[ABAP] Beliebige Dateien zu einer Zipdatei hinzufügen

TYPES: BEGIN OF bin_file,                          " Typ für Binärdatei mit Meta-Infos für das Zipfile
         name TYPE string,
         size TYPE i,
         data TYPE solix_tab,
       END OF bin_file.

DATA: lv_filename TYPE string.                     " Dateiname für FileOpen/FileSave
DATA: wa_file TYPE bin_file.                       " Binärdatei mit Meta-Infos für das Zipfile
DATA: it_binfiles TYPE STANDARD TABLE OF bin_file. " unkomprimierter Stream (Tabelle mit Dateien zum Zippen)
DATA: lv_path TYPE string.

START-OF-SELECTION.
* ZIP-Objekt erzeugen
  DATA(o_zip) = NEW cl_abap_zip( ).

  DATA: it_sel_filetab TYPE filetable.
  DATA: ret_code TYPE i.
  DATA: lv_action TYPE i.
* FileOpen-Dialog für Dateiauswahl anzeigen
* Mehrfachselektion möglich
  cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                window_title   = 'Dateien zum Komprimieren auswählen'
                                                multiselection = abap_true
                                              CHANGING
                                                file_table     = it_sel_filetab
                                                rc             = ret_code    " Anzahl ausgewählte Dateien, -1 bei Fehler
                                                user_action    = lv_action ).

  IF lv_action = cl_gui_frontend_services=>action_ok.

* Ausgewählte Dateien durchgehen
    LOOP AT it_sel_filetab INTO DATA(wa_sel_file).

      WRITE: / |Datei hinzugefügt: { wa_sel_file-filename }|.

* Dateien auf den Appl.-Server hochladen
      cl_gui_frontend_services=>gui_upload( EXPORTING
                                              filename   = |{ wa_sel_file-filename }|
                                              filetype   = 'BIN'
                                            IMPORTING
                                              filelength = wa_file-size
                                            CHANGING
                                              data_tab   = wa_file-data ).

* Pfad + Dateinamen aufsplitten
      CALL FUNCTION 'SO_SPLIT_FILE_AND_PATH'
        EXPORTING
          full_name     = wa_sel_file-filename
        IMPORTING
          file_path     = lv_path
          stripped_name = wa_file-name
        EXCEPTIONS
          x_error       = 1
          OTHERS        = 2.

* Datei zum Stream hinzufügen
      APPEND wa_file TO it_binfiles.

    ENDLOOP.

    ULINE.

    DATA: lv_xstring TYPE xstring.
* unkomprimierte Daten zum Zip-File hinzufügen
    LOOP AT it_binfiles INTO wa_file.

* jeden Datei-Stream binär zu xstring wandeln
      CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
        EXPORTING
          input_length = wa_file-size
        IMPORTING
          buffer       = lv_xstring
        TABLES
          binary_tab   = wa_file-data.

      o_zip->add( name    = wa_file-name
                  content = lv_xstring ).

    ENDLOOP.

* Daten komprimieren
    DATA(lv_zip) = o_zip->save( ).

    DATA: lv_zip_size TYPE i.
    DATA: it_zip_bin_data TYPE STANDARD TABLE OF raw255.

* xstring mit Zip-Daten zu binär rückwandeln
    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer        = lv_zip
      IMPORTING
        output_length = lv_zip_size
      TABLES
        binary_tab    = it_zip_bin_data.

    DATA: lv_dest_filepath TYPE string.

* SaveFile-Dialog aufrufen
    cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                  window_title         = 'Zipdatei speichern'
                                                  file_filter          = '(*.zip)|*.zip|'
                                                CHANGING
                                                  filename             = lv_filename
                                                  path                 = lv_path
                                                  fullpath             = lv_dest_filepath ).

* Zipdatei vom Appl-Server auf den lokalen Pfad speichern
    cl_gui_frontend_services=>gui_download( EXPORTING
                                              filename                = lv_dest_filepath
                                              filetype                = 'BIN'
                                              bin_filesize            = lv_zip_size
                                            CHANGING
                                              data_tab                = it_zip_bin_data ).

    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ELSE.
      WRITE: / |Zipdatei erfolgreich unter { lv_dest_filepath } gespeichert.|.
    ENDIF.
  ENDIF.

[ABAP] Formeleditor

Beispielprogramm        Bedeutung

SFBE_EXAMPLE1           Beispielprogramm FoBuEv: Einfachst-Aufruf 
SFBE_EXAMPLE2           Beispielprogramm FoBuEv: Aufruf mit eigenen Feldern 
SFBE_EXAMPLE3           Beispielprogramm FoBuEv: Aufruf mit Typprüfung, eigenem GUI-Status und TraceDer Trace wird im Menü eingeschaltet! 
SFBE_EXAMPLE4           Beispielprogramm FoBuEv: Aufruf mit eigenen Funktionen 
SFBE_EXAMPLE5           Beispielprogramm FoBuEv: Implementierung einer Methode per FoBuEv 
SFBE_EXAMPLE6           Beispielprogramm FoBuEv: Aufruf mit eigenen Drucktasten und IF-Funktion 
SFBE_EXAMPLE8           Beispielprogramm FoBuEv: Rechnen mit Währungsbeträgen, Mengen und Preisen
RS_FOBU_METHOD_EXAMPLE  Beispielprogramm für Formula Builder Methoden

wichtige Klassen:

cl_fobu_formula
cl_foev_formula
cl_fobu_connector

Weiterführende Infos: Link

[ABAP] Enumerator definieren

Variante 1 (einfaches Beispiel, mit impliziter Aufzählungskonstante 0..n)

TYPES:
  BEGIN OF ENUM e_drive_mode,
    forward,
    backward,
  END OF ENUM e_drive_mode.

DATA: lv_drivemode TYPE e_drive_mode.
lv_drivemode = forward.

DATA(lv_num) = CONV i( lv_drivemode ).

* FORWARD, 0
WRITE: / lv_drivemode, lv_num.

Variante 2 (explizite Aufzählungskonstante mit BASE TYPE)

TYPES:
  BEGIN OF ENUM e_drive_mode BASE TYPE symsgty,
    unknown  VALUE IS INITIAL,
    forward  VALUE 'F',
    backward VALUE 'B',
  END OF ENUM e_drive_mode.

DATA: lv_drivemode TYPE e_drive_mode.
lv_drivemode = forward.

DATA(lv_char) = CONV symsgty( lv_drivemode ).

* FORWARD, F
WRITE: / lv_drivemode, lv_char.

Variante 3 (Klassenbasiert, explizite Aufzählungskonstante mit BASE TYPE)

CLASS lcl_drive_mode DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES: BEGIN OF ENUM e_drive_mode BASE TYPE symsgty,
             unknown  VALUE IS INITIAL,
             forward  VALUE 'F',
             backward VALUE 'B',
           END OF ENUM e_drive_mode.

    CLASS-METHODS:
      check_mode
        IMPORTING
                  i_drive_mode TYPE symsgty
        RETURNING VALUE(rv_ok) TYPE abap_bool.
ENDCLASS.

CLASS lcl_drive_mode IMPLEMENTATION.
  METHOD check_mode.
    rv_ok = abap_false.

    TRY.
* gibt es den übergebenen ENUM-Wert?
        DATA(lv_type) = CONV e_drive_mode( i_drive_mode ).
        rv_ok = abap_true.

      CATCH cx_root INTO DATA(e_txt).
    ENDTRY.

  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
* F
  DATA(lv_fwd) = CONV symsgty( lcl_drive_mode=>forward ).
  WRITE: / lv_fwd.

* lcl_drive_mode=>forward
  DATA(lv_type) = CONV lcl_drive_mode=>e_drive_mode( 'F' ).
  WRITE: / lv_type.

* Funktion zum Prüfen von ENUM-Werten
  IF abap_true = lcl_drive_mode=>check_mode( 'X' ).
    WRITE: / 'Enum-Wert vorhanden.'.
  ELSE.
    WRITE: / 'Enum-Wert nicht vorhanden.'.
  ENDIF.

Variante 4 (CL_ABAP_ENUMDESCR)

TYPES: BEGIN OF ENUM e_drive_mode BASE TYPE symsgty,
         unknown  VALUE IS INITIAL,
         forward  VALUE 'F',
         backward VALUE 'B',
       END OF ENUM e_drive_mode.

DATA(lv_mode) = VALUE e_drive_mode( ).

DATA(o_desc) = CAST cl_abap_enumdescr( cl_abap_typedescr=>describe_by_data( lv_mode ) ).

cl_demo_output=>write_data( o_desc->kind ).
cl_demo_output=>write_data( o_desc->type_kind ).
cl_demo_output=>write_data( o_desc->base_type_kind ).
cl_demo_output=>write_data( o_desc->members ).

* HTML-Code vom Demo-Output holen
DATA(lv_html) = cl_demo_output=>get( ).

* Daten im Inline-Browser im SAP-Fenster anzeigen
cl_abap_browser=>show_html( EXPORTING title       = 'ENUM'
                                      html_string = lv_html
                                      container   = cl_gui_container=>default_screen ).

* cl_gui_container=>default_screen erzwingen
WRITE: space.

Variante 5 (bis Release 750)

CONSTANTS: BEGIN OF e_status,
             open      TYPE i VALUE 0,
             close     TYPE i VALUE 1,
             undefined TYPE i VALUE 2,
           END OF e_status.

Links

[ABAP] Referenzen, Dereferenzierung, Feldsymbole, Typecast

* allg. Referenz auf irgendwas (data)
DATA: lo_data TYPE REF TO data.

* Referenz auf den allg. Typ object
DATA: lo_obj TYPE REF TO object.

* allg. Feldsymbol
FIELD-SYMBOLS: <fs_any> TYPE ANY.

* dynamic Typecast
lo_obj ?= <fs_any>.

IF lo_obj IS BOUND. " != null
  " lo_obj ist instanziiert

  " Dereferenzierung, Wert an der Stelle der Referenz
  lo_obj->* ...
ELSE.
  " lo_obj ist nicht instanziiert
ENDIF.

[ABAP] SALV-Table – technische Namen der Spalten anzeigen

Variante 1 (kurz)

DATA: o_salv TYPE REF TO cl_salv_table.

...

LOOP AT o_salv->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<c>).
  <c>-r_column->set_short_text( |{ <c>-r_column->get_columnname( ) }| ).
  <c>-r_column->set_medium_text( |{ <c>-r_column->get_columnname( ) }| ).
  <c>-r_column->set_long_text( |{ <c>-r_column->get_columnname( ) }| ).
ENDLOOP.

Variante 2 (RTTS, RTTI)

DATA: o_alv TYPE REF TO cl_salv_table.

...

* Datendescriptor für Tabellenzeile (z.B.: Struct "ls_spfli") holen
DATA: o_struct TYPE REF TO cl_abap_structdescr.
o_struct ?= cl_abap_typedescr=>describe_by_data( ls_spfli ).

DATA: o_comp_tab TYPE abap_component_tab.
o_comp_tab = o_struct->get_components( ).

* Spalten der SALV-Table holen
DATA(lo_columns) = o_salv->get_columns( ).
DATA: lv_col TYPE REF TO cl_salv_column.
            
LOOP AT o_comp_tab INTO DATA(ls_comp).
  lv_col ?= lo_columns->get_column( |{ ls_comp-name }| ).

* Spaltennamen auf Structnamen ändern
  lv_col->set_short_text( | { ls_comp-name } | ).
  lv_col->set_medium_text( | { ls_comp-name } | ).
  lv_col->set_long_text( | { ls_comp-name } | ).
ENDLOOP.

[ABAP] Interne Tabelle mit NEW-Operator erstellen / Zugriff über Feldsymbole und Table Expressions

* Zeile
TYPES: BEGIN OF ty_data,
         kunnr TYPE i,
         name TYPE string,
         ort TYPE string,
       END   OF ty_data.
* Tabellentyp
TYPES: it_itab TYPE STANDARD TABLE OF ty_data WITH DEFAULT KEY.
* Feldsymbol für Zugriff
FIELD-SYMBOLS: <lt_text> TYPE it_itab.

* neue interne Tabelle mit Inhalt erstellen
DATA(dref) = NEW it_itab( ( kunnr = '123' name = 'ABCD' ort = 'LV' )
                          ( kunnr = '456' name = 'XYZ'  ort = 'LA' ) ).

* Zuweisung Feldsymbol
ASSIGN dref->* TO <lt_text>.

* Zugriff auf Inhalt der internen Tabelle über Feldsymbol und Table Expression
WRITE: / <lt_text>[ 1 ]-ort.