[ABAP] Open SQL: Dynamische WHERE-Condition

Variante 1 (Werteliste / Filter)

* Liste mit Benutzernamen
DATA(lv_users) = |'USER1', 'USER2'|.
* WHERE-Condition zusammenbauen
DATA(lv_where_condition) = |bname IN ({ lv_users })|.

TRY.
    DATA: it_usr TYPE STANDARD TABLE OF usr02 WITH DEFAULT KEY.

    SELECT * FROM usr02 INTO TABLE @it_usr WHERE (lv_where_condition).

    IF sy-subrc = 0.
      SORT: it_usr BY trdat DESCENDING bname ASCENDING.

      WRITE: / |USER         \| DATE       \| TIME     \| CREATED|.
      WRITE: / |-------------------------------------------------|.

      LOOP AT it_usr ASSIGNING FIELD-SYMBOL(<usr>).
        WRITE: / <usr>-bname, '|', <usr>-trdat, '|', <usr>-ltime, '|', <usr>-erdat.
      ENDLOOP.
    ENDIF.
  CATCH cx_root INTO DATA(e_txt).
    WRITE: / e_txt->get_text( ).
ENDTRY.

Variante 2 (Mehrzeilige WHERE-Bedingung)

* Liste mit Benutzernamen
DATA(lv_users) = |'USER1', 'USER2'|.
* Erstelldatum
DATA(lv_erdat) = |20100101|.

* WHERE-Condition zusammenbauen
DATA(it_where_condition) = VALUE stringtab( ( |bname IN ({ lv_users })| )
                                            ( |AND erdat > '{ lv_erdat }'| ) ).

TRY.
    DATA: it_usr TYPE STANDARD TABLE OF usr02 WITH DEFAULT KEY.

    SELECT * FROM usr02 INTO TABLE @it_usr WHERE (it_where_condition).

    IF sy-subrc = 0.
      SORT: it_usr BY trdat DESCENDING bname ASCENDING.

      WRITE: / |USER         \| DATE       \| TIME     \| CREATED|.
      WRITE: / |-------------------------------------------------|.

      LOOP AT it_usr ASSIGNING FIELD-SYMBOL(<usr>).
        WRITE: / <usr>-bname, '|', <usr>-trdat, '|', <usr>-ltime, '|', <usr>-erdat.
      ENDLOOP.
    ENDIF.
  CATCH cx_root INTO DATA(e_txt).
    WRITE: / e_txt->get_text( ).
ENDTRY.

[ABAP] OLE2: VBScript-Code über MSScriptControl ausführen

* VBS-Code einfügen
DATA(it_vbs_code) = VALUE stringtab( ( |Option Explicit| ) " Alle Variablen im VBS müssen mit Dim deklariert werden
                                     ( || )
                                     ( |Function Add(val1, val2)| )
                                     ( |  Add = val1 + val2| )
                                     ( |End Function| )
                                     ( || )
                                     ( |Function ShowMsgBox(InfoText)| )
                                     ( |  Dim msg| )
                                     ( |  msg = MsgBox(InfoText, vbOkOnly, "Info")| )
                                     ( |End Function| )
                                     ( || )
                                     ( |Function Run(FileName)| )
                                     ( |  Dim wshell| )
                                     ( |  Set wshell = CreateObject("Wscript.Shell")| )
                                     ( |  wshell.Run FileName, 1, False| )
                                     ( |End Function| )
                                     ( || )
                                     ( |Function Input()| )
                                     ( |  Input = InputBox("Namen:", "Namen eingeben", "Horst")| )
                                     ( |End Function| )
                                     ( || )
                                     ( |Function GenerateXLSX(FileName)| )
                                     ( |  Dim oXL| )
                                     ( |  Set oXL = CreateObject("Excel.Application")| )
                                     ( |  oXL.Visible = True| )
                                     ( |  oXL.Workbooks.Add| )
                                     ( |  oXL.Cells(1, 1).Value = "Test"| )
                                     ( |  oXL.ActiveWorkbook.SaveAs(FileName)| )
                                     ( |  oXL.Quit| )
                                     ( |  oXL = Nothing| )
                                     ( |End Function| )
                                   ).

DATA: lv_vbscode TYPE string.

* VBA-Code in String wandeln
LOOP AT it_vbs_code ASSIGNING FIELD-SYMBOL(<fs_codeline>).
  DATA(lv_codeline) = condense( <fs_codeline> ).
  IF lv_vbscode IS INITIAL.
    lv_vbscode = lv_codeline.
  ELSE.
    lv_vbscode = |{ lv_vbscode }{ cl_abap_char_utilities=>cr_lf }{ lv_codeline }|.
  ENDIF.
ENDLOOP.

DATA: o_scr TYPE ole2_object.

* Scriptcontrol-Objekt erzeugen
CREATE OBJECT o_scr 'MSScriptControl.ScriptControl'.

* wenn Erzeugung ok
IF sy-subrc = 0 AND o_scr-handle <> 0 AND o_scr-type = 'OLE2'.
* GUI anzeigen
  SET PROPERTY OF o_scr 'AllowUI' = 1.
* Sprache ist 'VBScript'
  SET PROPERTY OF o_scr 'Language' = 'VBScript'.

* Code hinzufügen und Syntaxcheck
  CALL METHOD OF o_scr 'AddCode'
    EXPORTING
      #1 = lv_vbscode.

* wenn Syntax ok
  IF sy-subrc = 0.
* einfacher Funktionsaufruf mit Übergabeparametern
    DATA: lv_res_i TYPE i.

    CALL METHOD OF o_scr 'Eval' = lv_res_i
      EXPORTING
        #1 = 'Add(1, 2)'.

    WRITE: / '1 + 2 =', lv_res_i.

* Eingabefeld mit Rückgabestring
    DATA: lv_res_s TYPE string.

    CALL METHOD OF o_scr 'Eval' = lv_res_s
      EXPORTING
        #1 = 'Input()'.

    DATA(lv_txt) = |ShowMsgBox("Hallo { lv_res_s }!")|.
* MessageBox anzeigen
    CALL METHOD OF o_scr 'Eval'
      EXPORTING
        #1 = lv_txt.

* Exe-Datei ausführen
    CALL METHOD OF o_scr 'Eval'
      EXPORTING
        #1 = 'Run("cmd.exe")'.

* Excel-Datei generieren
    CALL METHOD OF o_scr 'Eval'
      EXPORTING
        #1 = 'GenerateXLSX("c:\temp\test.xlsx")'.
  ELSE.
    WRITE: / 'Fehler im Code: ', sy-subrc.
  ENDIF.

* Objekt zerstören
  FREE OBJECT o_scr.
ENDIF.

Weiterführende Infos: Link, Link und Link

[ABAP] Listenausgabe mit Zeilennummern (Integer-Werte) – führende Nullen auffüllen

DATA(it_text_lines) = VALUE stringtab( ( |Heinz| )
                                       ( |Udo| )
                                       ( |Horst| )
                                       ( |Gerda| )
                                       ( |Hilde| )
                                       ( |Ulf| )
                                       ( |Marianne| )
                                       ( |Bertram| )
                                       ( |Eduart| )
                                       ( |Marianne| ) ).

DATA(lv_width) = strlen( |{ lines( it_text_lines ) }| ).

LOOP AT it_text_lines ASSIGNING FIELD-SYMBOL(<fs_line>).
  DATA(lv_cnt) = |{ sy-tabix }|.

  WRITE: / |{ lv_cnt WIDTH = lv_width ALPHA = IN }: { <fs_line> }|.
ENDLOOP.

[ABAP] IDoc als XML-Datei speichern

PARAMETERS: p_idoc TYPE edi_docnum.

START-OF-SELECTION.

  TRY.
      DATA(o_idoc_xml) = NEW cl_idoc_xml1( docnum = p_idoc ).

      DATA: lv_xml TYPE string.

      o_idoc_xml->get_xmldata_as_string( IMPORTING data_string = lv_xml ).

      DATA(it_xml) = VALUE stringtab( ( |{ lv_xml }| ) ).

      DATA: lv_temp_dir TYPE string.

* Temp-Directory holen
      cl_gui_frontend_services=>get_desktop_directory( CHANGING desktop_directory = lv_temp_dir ).
* Note 1442303, sonst ist lv_temp_dir leer
      cl_gui_cfw=>flush( ).

* Dateinamen zusammenbauen
      DATA(lv_filename) = |{ lv_temp_dir }\\my_xml.xml|.

* Datei im Zielverzeichnis erzeugen
      cl_gui_frontend_services=>gui_download( EXPORTING
                                                filename = lv_filename
                                                filetype = 'ASC'
                                              CHANGING
                                                data_tab = it_xml ).

      WRITE: / lv_filename.
    CATCH cx_root INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.

[ABAP] VBA-Code ausführen

* VBA-Code
DATA(it_vba_code) = VALUE stringtab( ( |Dim app| )
                                     ( |Set app = CreateObject("Access.Application")| )
                                     ( |Dim msg| )
                                     ( |msg = MsgBox ("My Message.", 0, "Warning")| ) ).

DATA: lv_temp_dir TYPE string.

* Temp-Directory holen
cl_gui_frontend_services=>get_desktop_directory( CHANGING desktop_directory = lv_temp_dir ).
* Note 1442303, sonst ist lv_temp_dir leer
cl_gui_cfw=>flush( ).

* Dateinamen zusammenbauen
DATA(lv_filename) = |{ lv_temp_dir }\\my_script.vbs|.

* Datei im Zielverzeichnis erzeugen
cl_gui_frontend_services=>gui_download( EXPORTING
                                          filename = lv_filename
                                          filetype = 'ASC'
                                        CHANGING
                                          data_tab = it_vba_code ).

LOOP AT it_vba_code ASSIGNING FIELD-SYMBOL(<fs_line>).
  WRITE: / <fs_line>.
ENDLOOP.

SKIP.

WRITE: / lv_filename.

* VBA über Scripting Host ausführen
* "" für lv_filename ergänzen, sonst wird der Pfad unter parameter nicht korrekt übergeben,
* da Leerzeichen im Pfad als Trennung in einzelne Parameter erkannt wird
cl_gui_frontend_services=>execute( application = 'WSCRIPT.EXE'
                                   parameter   = |"{ lv_filename }"| ).

[ABAP] Transienter Code / Dynamisch ABAP-Code generieren und ausführen

DATA: progname TYPE program.
DATA: msg TYPE string.
DATA: lin TYPE i.
DATA: wrd TYPE string.
DATA: off TYPE i.
DATA: mid TYPE trmsg_key.
DATA: sid TYPE string.

DATA(it_code) = VALUE stringtab( ( |PROGRAM SUBPOOL.| )
                                 ( |CLASS main DEFINITION.| )
                                 ( |  PUBLIC SECTION.| )
                                 ( |    CLASS-METHODS show| )
                                 ( |      IMPORTING| )
                                 ( |        i_txt TYPE string| )
                                 ( |      RETURNING VALUE(ret_val) TYPE string.| )
                                 ( |ENDCLASS.| )
                                 ( |CLASS main IMPLEMENTATION.| )
                                 ( |  METHOD show.| )
                                 ( |    WRITE: / i_txt.| )
                                 ( |    ret_val = \|\{ i_txt \} - Return value.\|.| )
                                 ( |  ENDMETHOD.| )
                                 ( |ENDCLASS.| ) ).

* Subroutinen-Pool im ABAP-Speicher des akt. Programms erzeugen
* it_code wird übergeben, Programmname wird temporär vom System vergeben
GENERATE SUBROUTINE POOL it_code NAME progname MESSAGE msg LINE lin WORD wrd OFFSET off MESSAGE-ID mid SHORTDUMP-ID sid.

CASE sy-subrc.
  WHEN 0. " ok
    TRY.
* dynamischen Klassennamen ermitteln
        DATA(lv_class) = |\\PROGRAM={ progname }\\CLASS=MAIN|.
        DATA: ret TYPE string.

        WRITE: / 'Programm:', progname.
        WRITE: / 'Class:', lv_class.
        SKIP.

* statischer Methodenaufruf
        CALL METHOD (lv_class)=>show
          EXPORTING
            i_txt   = 'Static call'
          RECEIVING
            ret_val = ret.

        WRITE: / ret.

* dynamischer Methodenaufruf
        DATA o_ref TYPE REF TO object.
        CREATE OBJECT o_ref TYPE (lv_class).
        CALL METHOD o_ref->('SHOW')
          EXPORTING
            i_txt   = 'Dynamic call'
          RECEIVING
            ret_val = ret.

        WRITE: / ret.

      CATCH cx_root INTO DATA(e_text).
        MESSAGE e_text->get_text( ) TYPE 'I'.
    ENDTRY.

  WHEN 4. " Syntaxfehler
    WRITE: / msg.
  WHEN 8. " Laufzeitfehler
    WRITE: / sid.
  WHEN OTHERS.
    MESSAGE 'Unbekannter Fehler.' TYPE 'I'.
ENDCASE.

Weiterführende Infos: Link

[ABAP] Interne Tabelle mit Strings definieren

* Variante 1: unsortiert, ohne Schlüssel
DATA(it_names) = VALUE stringtab( ( |Horst| )
                                  ( |Udo| )
                                  ( |Heinz| ) ).

* Variante 2: sortiert, mit Schlüssel
TYPES: ty_sorted TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line.

* strings dürfen nicht doppelt auftreten, sonst Duplicate-Key-Exception.
DATA(it_sorted) = VALUE ty_sorted( ( |Horst| )
                                   ( |Udo| )
                                   ( |Heinz| ) ).

[ABAP] Stringarray (interne Tabelle) zu einem String mit Separator verbinden (analog zu PHP implode)

Variante 1 (stringtab)

DATA(it_strings) = VALUE stringtab( ( |Horst| )
                                    ( |Udo| )
                                    ( |Heinz| ) ).

DATA(ret) = concat_lines_of( table = it_strings sep = ';' ).

WRITE: / ret.

Variante 2 (TYPES)

TYPES: ty_names TYPE STANDARD TABLE OF string WITH EMPTY KEY.

START-OF-SELECTION.

  DATA(it_strings) = VALUE ty_names( ( |Horst| )
                                     ( |Udo| )
                                     ( |Heinz| ) ).

  DATA(ret) = concat_lines_of( table = it_strings sep = ';' ).

  WRITE: / ret.

[ABAP] Strings aufsplitten

Variante 1 (beliebige Anzahl Splitelemente)

DATA: lv_satz TYPE string VALUE 'Horst;Udo;Heinz;Ede'.
DATA(it_elem) = VALUE stringtab( ).

SPLIT lv_satz AT ';' INTO TABLE it_elem.

Variante 2 (vordefinierte Anzahl Splitelemente)

DATA: lv_satz TYPE string VALUE 'abc,def,ghi'.
DATA: t11 TYPE string.
DATA: t22 TYPE string.
DATA: t33 TYPE string.
  
SPLIT satz AT ',' INTO t11 t22 t33.

WRITE: / t11, t22, t33.