[ABAP] ABAP2XLSX: Interne Tabelle als Excel-Datei (*.xlsx) aufbereiten und mit Desktop Office Integration (DOI) als Excel inplace anzeigen

Variante 1 (Daten aus der Tabelle SFLIGHT anzeigen)

* Dummy-Screen für cl_gui_container=>default_screen deklarieren
SELECTION-SCREEN BEGIN OF SCREEN 100.
SELECTION-SCREEN END OF SCREEN 100.

START-OF-SELECTION.

* Daten holen
  SELECT * FROM sflight INTO TABLE @DATA(it_sflight).

  TRY.
* ABAP2XLSX
      DATA: o_xl TYPE REF TO zcl_excel.

* Converter itab->ABAP2XLSX
      DATA(o_converter) = NEW zcl_excel_converter( ).

      o_converter->convert( EXPORTING
                              it_table = it_sflight
                            CHANGING
                              co_excel = o_xl ).

* aktive Worksheet
      DATA(o_xl_ws) = o_xl->get_active_worksheet( ).
* oberste Zeile einfrieren -> beim Scrollen immer sichtbar
      o_xl_ws->freeze_panes( ip_num_rows = 1 ).

* Binärdaten (xstring) generieren
      DATA(o_xlwriter) = CAST zif_excel_writer( NEW zcl_excel_writer_2007( ) ).
      DATA(lv_xl_xdata) = o_xlwriter->write_file( o_xl ).

* Daten mit DOI (Excel inplace) anzeigen
      DATA: o_oic TYPE REF TO i_oi_container_control.
      DATA: o_oid TYPE REF TO i_oi_document_proxy.
      DATA: o_err TYPE REF TO i_oi_error.
      DATA: it_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY.

      c_oi_container_control_creator=>get_container_control( IMPORTING
                                                               control = o_oic
                                                               error   = o_err ).

      APPEND o_err TO it_errors.

      IF abap_true = o_err->has_succeeded.
        o_oic->init_control( EXPORTING
                               inplace_enabled     = abap_true
                               no_flush            = abap_true
                               r3_application_name = 'Flugverbindungen'
                               parent              = cl_gui_container=>default_screen
                             IMPORTING
                               error               = o_err ).

        APPEND o_err TO it_errors.

        IF abap_true = o_err->has_succeeded.
          o_oic->get_document_proxy( EXPORTING
                                       document_type  = soi_doctype_excel_sheet " 'Excel.Sheet'
                                     IMPORTING
                                       document_proxy = o_oid
                                       error          = o_err ).
          APPEND o_err TO it_errors.

          IF abap_true = o_err->has_succeeded.
            DATA(it_raw) = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_xl_xdata ).
            DATA(lv_rawlen) = xstrlen( lv_xl_xdata ).

* Binärdaten des *.xlsx im Hintergrund an DOI-Objekt senden und anzeigen
            o_oid->open_document_from_table( EXPORTING
                                               document_size  = lv_rawlen
                                               document_table = it_raw
                                               open_inplace   = abap_true
                                             IMPORTING
                                               error          = o_err ).

            APPEND o_err TO it_errors.

            IF abap_true = o_err->has_succeeded.

* leere Toolbar ausblenden
              cl_abap_list_layout=>suppress_toolbar( ).

* cl_gui_container=>default_screen erzwingen
              CALL SCREEN 100.

* Schließen eines Dokuments in der Office-Anwendung
              o_oid->close_document( IMPORTING error = o_err ).

              APPEND o_err TO it_errors.

              IF o_err->has_succeeded = abap_true.

* Schließen eines Visual-Basic-Dokuments
                o_oid->close_activex_document( IMPORTING error = o_err ).

                APPEND o_err TO it_errors.

                IF o_err->has_succeeded = abap_true.

* Freigabe des für das Dokument reservierten Speichers
                  o_oid->release_document( IMPORTING error = o_err ).

                  APPEND o_err TO it_errors.

                  IF o_err->has_succeeded = abap_true.
                    FREE: o_oid.
                  ENDIF.
                ENDIF.
              ENDIF.
            ENDIF.

* baut das Control ab
            o_oic->destroy_control( IMPORTING error = o_err ).

            APPEND o_err TO it_errors.

            IF o_err->has_succeeded = abap_true.
              FREE: o_oic.
            ENDIF.

          ENDIF.
        ENDIF.
      ENDIF.

* Ausgabe Fehlerprotokoll
      DATA: lv_message_id TYPE sy-msgid.
      DATA: lv_message_number TYPE sy-msgno.
      DATA: lv_param1 TYPE sy-msgv1.
      DATA: lv_param2 TYPE sy-msgv2.
      DATA: lv_param3 TYPE sy-msgv3.
      DATA: lv_param4 TYPE sy-msgv4.

      LOOP AT it_errors ASSIGNING FIELD-SYMBOL(<e>).
        <e>->get_message( IMPORTING
                            message_id     = lv_message_id
                            message_number = lv_message_number
                            param1         = lv_param1
                            param2         = lv_param2
                            param3         = lv_param3
                            param4         = lv_param4
                        ).
        WRITE: / <e>->error_code, lv_message_id, lv_message_number, lv_param1, lv_param2, lv_param3, lv_param4.
      ENDLOOP.

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

Variante 2 (Daten aus der Tabelle SFLIGHT anzeigen, Styles festlegen)

* Dummy-Screen für cl_gui_container=>default_screen deklarieren
SELECTION-SCREEN BEGIN OF SCREEN 100.
SELECTION-SCREEN END OF SCREEN 100.

START-OF-SELECTION.

* Daten holen
  SELECT * FROM sflight INTO TABLE @DATA(it_sflight).

  TRY.
* ABAP2XLSX
      DATA(o_xl) = NEW zcl_excel( ).
* aktive Worksheet
      DATA(o_xl_ws) = o_xl->get_active_worksheet( ).
* Name der Sheet
      o_xl_ws->set_title( ip_title = 'Flights' ).

* Tabelle übergeben und Style festlegen
      o_xl_ws->bind_table( ip_table          = it_sflight
                           is_table_settings = VALUE #(
                                                        table_style      = zcl_excel_table=>builtinstyle_medium2
*                                                  show_row_stripes = abap_true
                                                      )
                         ).

* oberste Zeile einfrieren -> beim Scrollen immer sichtbar
      o_xl_ws->freeze_panes( ip_num_rows = 1 ).

* Binärdaten (xstring) generieren
      DATA(o_xlwriter) = CAST zif_excel_writer( NEW zcl_excel_writer_2007( ) ).
      DATA(lv_xl_xdata) = o_xlwriter->write_file( o_xl ).

* Daten mit DOI (Excel inplace) anzeigen
      DATA: o_oic TYPE REF TO i_oi_container_control.
      DATA: o_oid TYPE REF TO i_oi_document_proxy.
      DATA: o_err TYPE REF TO i_oi_error.
      DATA: it_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY.

      c_oi_container_control_creator=>get_container_control( IMPORTING
                                                               control = o_oic
                                                               error   = o_err ).

      APPEND o_err TO it_errors.

      IF abap_true = o_err->has_succeeded.
        o_oic->init_control( EXPORTING
                               inplace_enabled     = abap_true
                               no_flush            = abap_true
                               r3_application_name = 'Flugverbindungen'
                               parent              = cl_gui_container=>default_screen
                             IMPORTING
                               error               = o_err ).

        APPEND o_err TO it_errors.

        IF abap_true = o_err->has_succeeded.
          o_oic->get_document_proxy( EXPORTING
                                       document_type  = soi_doctype_excel_sheet " 'Excel.Sheet'
                                     IMPORTING
                                       document_proxy = o_oid
                                       error          = o_err ).

          APPEND o_err TO it_errors.

          IF abap_true = o_err->has_succeeded.
            DATA(it_raw) = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_xl_xdata ).
            DATA(lv_rawlen) = xstrlen( lv_xl_xdata ).

* Binärdaten des *.xlsx im Hintergrund an DOI-Objekt senden und anzeigen
            o_oid->open_document_from_table( EXPORTING
                                               document_size    = lv_rawlen
                                               document_table   = it_raw
                                               open_inplace     = abap_true
                                             IMPORTING
                                               error          = o_err ).

            APPEND o_err TO it_errors.

            IF abap_true = o_err->has_succeeded.

* leere Toolbar ausblenden
              cl_abap_list_layout=>suppress_toolbar( ).

* cl_gui_container=>default_screen erzwingen
              CALL SCREEN 100.

* Schließen eines Dokuments in der Office-Anwendung
              o_oid->close_document( IMPORTING error = o_err ).

              APPEND o_err TO it_errors.

              IF o_err->has_succeeded = abap_true.

* Schließen eines Visual-Basic-Dokuments
                o_oid->close_activex_document( IMPORTING error = o_err ).

                APPEND o_err TO it_errors.

                IF o_err->has_succeeded = abap_true.

* Freigabe des für das Dokument reservierten Speichers
                  o_oid->release_document( IMPORTING error = o_err ).

                  APPEND o_err TO it_errors.

                  IF o_err->has_succeeded = abap_true.
                    FREE: o_oid.
                  ENDIF.
                ENDIF.
              ENDIF.
            ENDIF.

* baut das Control ab
            o_oic->destroy_control( IMPORTING error = o_err ).

            APPEND o_err TO it_errors.

            IF o_err->has_succeeded = abap_true.
              FREE: o_oic.
            ENDIF.

          ENDIF.
        ENDIF.
      ENDIF.

* Ausgabe Fehlerprotokoll
      DATA: lv_message_id TYPE sy-msgid.
      DATA: lv_message_number TYPE sy-msgno.
      DATA: lv_param1 TYPE sy-msgv1.
      DATA: lv_param2 TYPE sy-msgv2.
      DATA: lv_param3 TYPE sy-msgv3.
      DATA: lv_param4 TYPE sy-msgv4.

      LOOP AT it_errors ASSIGNING FIELD-SYMBOL(<e>).
        <e>->get_message( IMPORTING
                            message_id     = lv_message_id
                            message_number = lv_message_number
                            param1         = lv_param1
                            param2         = lv_param2
                            param3         = lv_param3
                            param4         = lv_param4
                        ).
        WRITE: / <e>->error_code, lv_message_id, lv_message_number, lv_param1, lv_param2, lv_param3, lv_param4.
      ENDLOOP.

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

Variante 3 (Daten aus der Tabelle SFLIGHT anzeigen, Komplexbeispiel)

* Dummy-Screen für cl_gui_container=>default_screen deklarieren
SELECTION-SCREEN BEGIN OF SCREEN 100.
SELECTION-SCREEN END OF SCREEN 100.

START-OF-SELECTION.

* Daten holen
  SELECT * FROM sflight INTO TABLE @DATA(it_sflight).

  TRY.
* ABAP2XLSX
      DATA(o_xl) = NEW zcl_excel( ).
* aktive Worksheet
      DATA(o_xl_ws) = o_xl->get_active_worksheet( ).
* Name der Sheet
      o_xl_ws->set_title( ip_title = 'Flights' ).
* Gitterlinien ausschalten
      o_xl_ws->set_show_gridlines( i_show_gridlines = abap_false ).
* oberste zwei Zeilen einfrieren -> beim Scrollen immer sichtbar
      o_xl_ws->freeze_panes( ip_num_rows = 2 ).

* RTTS: Table: Beschreibung
      DATA(o_tdesc) = CAST cl_abap_tabledescr( cl_abap_tabledescr=>describe_by_data( it_sflight ) ).
* RTTS: Row: Beschreibung
      DATA(o_sdesc) = CAST cl_abap_structdescr( o_tdesc->get_table_line_type( ) ).
* RTTS: Col: Komponenten (Felder) -> DFIES: DD-Schnittstelle: Tabellenfelder für DDIF_FIELDINFO_GET
      DATA(it_com) = o_sdesc->get_components( ).

* Header einfügen
      LOOP AT it_com ASSIGNING FIELD-SYMBOL(<c>).
        DATA(lv_col_head) = sy-tabix.
* Prüfen, ob DDIC-Typ, damit die Metadaten ausgelesen werden können
        DATA(o_edesc_head) = CAST cl_abap_elemdescr( <c>-type ).
        IF o_edesc_head->is_ddic_type( ) EQ abap_true.
          DATA(lv_dfies_head) = o_edesc_head->get_ddic_field( ).
* technischer Name in die erste Zeile
          o_xl_ws->set_cell( ip_column = lv_col_head
                             ip_row    = 1
                             ip_value  = <c>-name ).
* Langtext des Feldes in die zweite Zeile
          o_xl_ws->set_cell( ip_column = lv_col_head
                             ip_row    = 2
                             ip_value  = lv_dfies_head-scrtext_l ).

* Spaltenbreite setzen
          o_xl_ws->get_column( lv_col_head )->set_width( strlen( lv_dfies_head-scrtext_l ) + 5 ).
        ENDIF.

      ENDLOOP.

* Daten einfügen
      LOOP AT it_sflight ASSIGNING FIELD-SYMBOL(<row>).
        DATA(lv_row) = sy-tabix + 2.

        LOOP AT it_com ASSIGNING FIELD-SYMBOL(<col>).
          DATA(lv_col) = sy-tabix.

* Prüfen, ob DDIC-Typ, damit die Metadaten ausgelesen werden können
          DATA(o_edesc) = CAST cl_abap_elemdescr( <col>-type ).
          IF o_edesc->is_ddic_type( ) EQ abap_true.
* wenn DDIC-Typ, dann Metainformationen auslesen
            DATA(lv_dfies) = o_edesc->get_ddic_field( ).
* anhand des Komponentennamens den akt. Zellinhalt einer Zeile lesen
            ASSIGN COMPONENT <col>-name OF STRUCTURE <row> TO FIELD-SYMBOL(<cell>).
            IF <cell> IS ASSIGNED.
              o_xl_ws->set_cell( ip_column = lv_col
                                 ip_row    = lv_row
                                 ip_value  = <cell> ).
            ENDIF.
          ENDIF.
        ENDLOOP.

* Zeilenhöhe
        o_xl_ws->get_row( ip_row = lv_row )->set_row_height( 15 ).
      ENDLOOP.

* Autofilter setzen
      DATA(o_autofilter) = o_xl->add_new_autofilter( io_sheet = o_xl_ws ).
      o_autofilter->set_filter_area( is_area = VALUE #( row_start = 2
                                                        col_start = 1
                                                        row_end   = o_xl_ws->get_highest_row( )
                                                        col_end   = o_xl_ws->get_highest_column( ) ) ).

* Binärdaten (xstring) generieren
      DATA(o_xlwriter) = CAST zif_excel_writer( NEW zcl_excel_writer_2007( ) ).
      DATA(lv_xl_xdata) = o_xlwriter->write_file( o_xl ).

* Daten mit DOI (Excel inplace) anzeigen
      DATA: o_oic TYPE REF TO i_oi_container_control.
      DATA: o_oid TYPE REF TO i_oi_document_proxy.
      DATA: o_err TYPE REF TO i_oi_error.
      DATA: it_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY.

      c_oi_container_control_creator=>get_container_control( IMPORTING
                                                               control = o_oic
                                                               error   = o_err ).

      APPEND o_err TO it_errors.

      IF abap_true = o_err->has_succeeded.
        o_oic->init_control( EXPORTING
                               inplace_enabled     = abap_true
                               no_flush            = abap_true
                               r3_application_name = 'Flugverbindungen'
                               parent              = cl_gui_container=>default_screen
                             IMPORTING
                               error               = o_err ).

        APPEND o_err TO it_errors.

        IF abap_true = o_err->has_succeeded.
          o_oic->get_document_proxy( EXPORTING
                                       document_type  = soi_doctype_excel_sheet " 'Excel.Sheet'
                                     IMPORTING
                                       document_proxy = o_oid
                                       error          = o_err ).

          APPEND o_err TO it_errors.

          IF abap_true = o_err->has_succeeded.
            DATA(it_raw) = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_xl_xdata ).
            DATA(lv_rawlen) = xstrlen( lv_xl_xdata ).

* Binärdaten des *.xlsx im Hintergrund an DOI-Objekt senden und anzeigen
            o_oid->open_document_from_table( EXPORTING
                                               document_size  = lv_rawlen
                                               document_table = it_raw
                                               open_inplace   = abap_true
                                             IMPORTING
                                               error          = o_err ).

            APPEND o_err TO it_errors.

            IF abap_true = o_err->has_succeeded.
* leere Toolbar ausblenden
              cl_abap_list_layout=>suppress_toolbar( ).

* cl_gui_container=>default_screen erzwingen
              CALL SCREEN 100.

* Schließen eines Dokuments in der Office-Anwendung
              o_oid->close_document( IMPORTING error = o_err ).

              APPEND o_err TO it_errors.

              IF o_err->has_succeeded = abap_true.

* Schließen eines Visual-Basic-Dokuments
                o_oid->close_activex_document( IMPORTING error = o_err ).

                APPEND o_err TO it_errors.

                IF o_err->has_succeeded = abap_true.

* Freigabe des für das Dokument reservierten Speichers
                  o_oid->release_document( IMPORTING error = o_err ).

                  APPEND o_err TO it_errors.

                  IF o_err->has_succeeded = abap_true.
                    FREE: o_oid.
                  ENDIF.
                ENDIF.
              ENDIF.
            ENDIF.

* baut das Control ab
            o_oic->destroy_control( IMPORTING error = o_err ).

            APPEND o_err TO it_errors.

            IF o_err->has_succeeded = abap_true.
              FREE: o_oic.
            ENDIF.

          ENDIF.
        ENDIF.
      ENDIF.

* Ausgabe Fehlerprotokoll
      DATA: lv_message_id TYPE sy-msgid.
      DATA: lv_message_number TYPE sy-msgno.
      DATA: lv_param1 TYPE sy-msgv1.
      DATA: lv_param2 TYPE sy-msgv2.
      DATA: lv_param3 TYPE sy-msgv3.
      DATA: lv_param4 TYPE sy-msgv4.

      LOOP AT it_errors ASSIGNING FIELD-SYMBOL(<e>).
        <e>->get_message( IMPORTING
                            message_id     = lv_message_id
                            message_number = lv_message_number
                            param1         = lv_param1
                            param2         = lv_param2
                            param3         = lv_param3
                            param4         = lv_param4
                        ).
        WRITE: / <e>->error_code, lv_message_id, lv_message_number, lv_param1, lv_param2, lv_param3, lv_param4.
      ENDLOOP.

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

[ABAP] CSS-Code als ABAP-INCLUDE speichern und laden

Über die Nutzung von Includes ist es möglich beliebigen Code im SAP abzulegen und darauf zuzugreifen. Folgende Schritte sind notwendig:

  • SE80 -> neues INCLUDE anlegen (Bsp.: ZCSSINCLUDE)
  • CSS-Code im INCLUDE eintragen
  • Aktvieren! (Ja, das funktioniert.)
  • CSS-Code (INCLUDE) im ABAP-Code lesen
* Name des INCLUDEs mit dem CSS-Code
CONSTANTS: co_cssinclude TYPE char12 VALUE 'ZCSSINCLUDE'.
* String für CSS-Daten
DATA: lv_css TYPE string.
	
* Prüfen, ob INCLUDE im System (TADIR) aktiv vorhanden
SELECT SINGLE obj_name
  INTO @DATA(lv_obj_name)
  FROM tadir
  WHERE obj_name = @co_w3css
    AND pgmid    = 'R3TR'
    AND object   = 'PROG'.

IF sy-subrc = 0.

* Stringtab für Code
  DATA: it_incl_code TYPE stringtab.

* Code des INCLUDEs lesen
  READ REPORT co_w3css INTO it_incl_code.

  IF sy-subrc = 0.
* String-Tabelle mit CSS-Code in String wandeln, Trennzeichen ist CRLF
    lv_css = REDUCE string( INIT s = ||
                            FOR <s> IN it_incl_code
                            NEXT s = COND #( WHEN s IS INITIAL THEN |{ <s> }| ELSE |{ s }{ cl_abap_char_utilities=>cr_lf }{ <s> }| ) ).
  ENDIF.
ENDIF.

* HTML mit CSS-INCLUDE
DATA(lv_html) = '<!DOCTYPE html>' &&
                '<html>' &&
                '<title>Lagermaterialkatalog</title>' &&
                '<meta name="viewport" content="width=device-width, initial-scale=1">' &&
                '<style>' && lv_css && '</style>' &&
                '<body>' &&
                '</body>' &&
                '</html>'.

[ABAP] Zugriff auf die Metainformationen einer internen Tabelle

* Daten holen
SELECT carrid, connid, fldate, price, currency, planetype
  INTO TABLE @DATA(it_sflight)
  FROM sflight .

* Table: Beschreibung
DATA(o_tdesc) = CAST cl_abap_tabledescr( cl_abap_tabledescr=>describe_by_data( it_sflight ) ).
* Row: Beschreibung
DATA(o_sdesc) = CAST cl_abap_structdescr( o_tdesc->get_table_line_type( ) ).
* Col: Komponenten (Felder) -> DFIES: DD-Schnittstelle: Tabellenfelder für DDIF_FIELDINFO_GET
DATA(it_com) = o_sdesc->get_components( ).

* Header
LOOP AT it_com ASSIGNING FIELD-SYMBOL(<c>).
* Prüfen, ob DDIC-Typ, damit die Metadaten ausgelesen werden können
  DATA(o_edesc) = CAST cl_abap_elemdescr( <c>-type ).
  IF o_edesc->is_ddic_type( ) EQ abap_true.
    DATA(lv_dfies) = o_edesc->get_ddic_field( ).
* technischer Name
*    WRITE: |{ <c>-name WIDTH = lv_dfies-scrlen3 }|.
* Langtext des Feldes
    WRITE: |{ lv_dfies-scrtext_l WIDTH = lv_dfies-scrlen3 }|.
  ENDIF.
ENDLOOP.

ULINE.

* Daten zellenweise auslesen
LOOP AT it_sflight ASSIGNING FIELD-SYMBOL(<row>).

  LOOP AT it_com ASSIGNING FIELD-SYMBOL(<col>).
* Prüfen, ob DDIC-Typ, damit die Metadaten ausgelesen werden können
    DATA(o_edesc2) = CAST cl_abap_elemdescr( <col>-type ).
    IF o_edesc2->is_ddic_type( ) EQ abap_true.
* wenn DDIC-Typ, dann Metainformationen auslesen
      DATA(lv_dfies2) = o_edesc2->get_ddic_field( ).
* anhand des Komponentennamens den akt. Zellinhalt einer Zeile lesen
      ASSIGN COMPONENT <col>-name OF STRUCTURE <row> TO FIELD-SYMBOL(<cell>).
      WRITE: |{ <cell> WIDTH = lv_dfies2-scrlen3 }|.
    ENDIF.
  ENDLOOP.

  WRITE: /.

ENDLOOP.

[ABAP] HTML im Browser-Fenster anzeigen

* Variante 1 (cl_abap_browser)
* Dummy Screen
SELECTION-SCREEN BEGIN OF SCREEN 100.
SELECTION-SCREEN END OF SCREEN 100.

* Daten holen
SELECT * FROM mara INTO TABLE @DATA(it_mara).

* Browserfenster mit HTML-Code im cl_gui_container=>default_screen anzeigen
cl_abap_browser=>show_html( html_string = cl_demo_output=>get( it_mara )
                            container   = cl_gui_container=>default_screen ).

* Toolbar ausblenden
cl_abap_list_layout=>suppress_toolbar( ).

* leeres Dynpro anzeigen und Ausgabe von cl_gui_container=>default_screen erzwingen
CALL SELECTION-SCREEN 100.

[ABAP] Archivobjekte lesen

* Archiv-ID aus Tabelle TOAAR
PARAMETERS: p_arc TYPE toaar-archiv_id.
* Dokumentart, in TOADV (SM30) gepflegt
PARAMETERS: p_aro TYPE toadv-ar_object DEFAULT 'SDOINVOICE'.
* Dateinamenerweiterung
PARAMETERS: p_dtype TYPE toaom-doc_type DEFAULT 'PDF'.
* SAP ArchiveLink: Objekt-Id (Objektidentifikator)
* SAP Objekt-Ident
* bei VBRK       - '0070000000                    0000000100'
* bei BUS1001006 - '0000000011000011111'
* Beispiele in TOA01, TOA02 oder TOA03
PARAMETERS: p_oid TYPE saeobjid DEFAULT '0070000000                    0000000100'.
* SAP ArchiveLink: Objekttyp des Business Objekts
* VBRK       - Kundeneinzelfaktura
* BUS1001006 - Standard Material
PARAMETERS: p_sobj TYPE tojtb-name DEFAULT 'VBRK'.

START-OF-SELECTION.

  DATA: it_connect_info TYPE STANDARD TABLE OF toav0 WITH DEFAULT KEY.

* Alle verkn?pften Archivobjekte zum Objekt anhand der Selektionskriterien ermitteln
* SAP ArchiveLink: Ermitteln von Ablage-Id und Dok.-Id zu Anwendungsobject
  CALL FUNCTION 'ARCHIV_CONNECTINFO_GET_META'
    EXPORTING
      archiv_id             = p_arc
      ar_object             = p_aro
      doc_type              = p_dtype
      object_id             = p_oid
      sap_object            = p_sobj
    TABLES
      connect_info          = it_connect_info
    EXCEPTIONS
      error_connectiontable = 1
      OTHERS                = 2.

  IF sy-subrc = 0.

* Liste der Verkn?fpungen durchgehen und Bin?rdaten aus Archiv holen
    LOOP AT it_connect_info ASSIGNING FIELD-SYMBOL(<ci>).

      WRITE: / <ci>-archiv_id, <ci>-sap_object, <ci>-object_id, <ci>-arc_doc_id, <ci>-reserve.

      DATA(lv_length) = 0.
      DATA: it_bin_data TYPE STANDARD TABLE OF tbl1024 WITH DEFAULT KEY.

      CLEAR: it_bin_data.

* Bin?rdaten des AO lesen
* CMS: AO API Dokument bereitstellen Tabelle
      CALL FUNCTION 'SCMS_AO_TABLE_GET'
        EXPORTING
          arc_id       = <ci>-archiv_id
          doc_id       = <ci>-arc_doc_id
        IMPORTING
          length       = lv_length
        TABLES
          data         = it_bin_data
        EXCEPTIONS
          error_http   = 1
          error_archiv = 2
          error_kernel = 3
          error_config = 4
          OTHERS       = 5.

      IF sy-subrc = 0.
        DATA: lv_xstring TYPE xstring.

* Bin?rdaten in xstring konvertieren
        CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
          EXPORTING
            input_length = CONV i( lv_length )
          IMPORTING
            buffer       = lv_xstring
          TABLES
            binary_tab   = it_bin_data
          EXCEPTIONS
            failed       = 1
            OTHERS       = 2.

        IF sy-subrc = 0.
          ...
        ENDIF.
      ELSE.
        WRITE: / 'Error:', sy-subrc.
      ENDIF.
    ENDLOOP.
  ELSE.
    WRITE: / 'Verbindungsdaten nicht gefunden:', sy-subrc.
  ENDIF.

[ABAP] Nützliche ABAP-Datentypen, Domänen, Tabellentypen

* Datentypen
* DD04L
* DD04T
* DD04V

Name          Typ         Länge   Beschreibung
---------------------------------------------------------------------------
MANDT         CLNT        3       Mandant

DEC_16_01_S   DEC         16,1    Dezimalwert mit 1 Nachkommastelle
DEC_16_02_S   DEC         16,2    Dezimalwert mit 2 Nachkommastellen
DEC_16_03_S   DEC         16,3    Dezimalwert mit 3 Nachkommastellen
DEC_16_04_S   DEC         16,4    Dezimalwert mit 4 Nachkommastellen
DEC_16_05_S   DEC         16,5    Dezimalwert mit 5 Nachkommastellen
DEC_16_06_S   DEC         16,6    Dezimalwert mit 6 Nachkommastellen
DEC20_2       DEC         20,2    Dezimalwert mit 2 Nachkommastellen
DEC20_3       DEC         20,3    Dezimalwert mit 3 Nachkommastellen
DECIMAL21_7   DEC         21,7    Dezimalwert mit 7 Nachkommastellen
DEC23_2       DEC         23,2    Dezimalwert mit 2 Nachkommastellen
DEC31_14      DEC         31,14   Dezimalwert mit 14 Nachkommastellen

SURL          CHAR        255     URL Länge 255
SWK_URL       CHAR        2048    URL Länge 2048
SKWF_URL      CHAR        4096    URL Länge 4096
USS_Y_URL     CHAR        255     URL Länge 255
VBC_URL2      CHAR        1024    URL Länge 1024

BAPI_MSG      CHAR        220     Meldungstext
ERR_TEXT      CHAR        60      Fehlertext
TEXT255       CHAR        255     Text Lowercase
TWB_S_TXT     CHAR        200     Groß / Kleinschreibung berücksichtigt
TXT50         CHAR        50      Text
VBC_TEXT      CHAR        255     Beschreibung Lowercase
VBI_TEXT      CHAR        255     Beschreibung Lowercase
VEPTEXT       CHAR        255     Kurzbeschreibung Lowercase

SYSUUID_C     CHAR        32      UUID in Character-Darstellung

EDPLINE       CHAR        72      EDIC Programm-Editor Zeile

TABNAME       CHAR        30      Tabellenname

ERNAM         CHAR        12      Name des Benutzers
XUANAME       CHAR        12      Anleger des Benutzerstamms
XUBNAME	      CHAR        12      Benutzername im Benutzerstamm
XUMODIFIER    CHAR        12      Letzter Änderer

AWKGR         CURR        15,2    Betrag
BELWER        CURR        15,2    Betrag
KWERT         CURR        13,2    Konditionswert

ABBDT         DATS        8       Beginndatum des Zeitabschnitts
ABDATUM       DATS        8       Beginn eines Zeitraumes
ADATU         DATS        8       Datum Gültigkeitsbeginn
BEGDATUM      DATS        8       Beginndatum
BEGINDATE     DATS        8       Beginndatum
ERSDA         DATS        8       Erstellungsdatum (JJJJMMDD)
LAEDA         DATS        8       Datum der letzten Änderung (JJJJMMDD)
XULDATE       DATS        8       Letzes Login-Datum (JJJJMMDD)
XUERDAT       DATS        8       Anlegedatum des Benutzerstamms (JJJJMMDD)
XUMODDATE     DATS        8       Modifikationsdatum (JJJJMMDD)

BEGINUZ       TIMS        6       Beginnuhrzeit
BEGUZ         TIMS        6       Beginnuhrzeit
XULTIME       TIMS        6       Letzte Anmeldeuhrzeit (HHMMSS)
XUMODTIME     TIMS        6       Modifikationszeit (HHMMSS)

TIMESTAMP     DEC         15      UTC-Zeitstempel in Kurzform (JJJJMMTThhmmss)
TIMESTAMPL    DEC         21,7    UTC-Zeitstempel in Langform (JJJJMMTThhmmssmmmuuun)

* Domänen
* DD01L
* DD01T
* DD01V

Name          Typ         Länge   Beschreibung
---------------------------------------------------------------------------
RSDSSELOPT    CHAR        45      Zeilentyp für RANGE-Tabelle
FUNCNAME      CHAR        30      Unterprogrammname
TDSFNAME      CHAR        30      Smart Forms: Formularname

* Strukturen
* DD02L
* DD03L
* DD03T


* Tabellentypen
* DD40L
* DD40T

Typ            Zeilentyp   Länge   Beschreibung
----------------------------------------------------------------------------
BAPIRETTAB     BAPIRET2            Tabelle mit BAPI Return Informationen
BAPIRET2_T     BAPIRET2            Returntabelle
BDCDATA_TAB    BDCDATA     309     Tabelle für Batchdaten
SOTR_TXTS      CHAR        255     Texttabelle
TTTEXT255      CHAR        255     Texttabelle
HTML_TABLE     W3HTML      255     Texttabelle für HTML
W3_HTMLTAB     W3_HTML     255     Texttabelle für HTML
INT4_TABLE     INT4        10      Standard Table of INT4
W3MIMETABTYPE  RAW         255     Tabelle für RAW-Daten
XML_RAWDATA    RAW         255     Tabelle für RAW-Daten
WD_OBJECTS     REF                 Tabelle zur Speicherung von REF TO OBJECT
RSEC_T_SPOPLI  SPOPLI      67      Auswahl von Werten
RSELOPTION     RSDSSELOPT  93      SELECT-OPTIONS Tabelle
STRINGTAB      STRING              Tabelle mit Strings
STRING_TABLE   STRING              Tabelle mit Strings
TLINE_T        TLINE               Tabelle mit TLINE
ICL_THEAD_TAB  THEAD               tabelle mit THEAD

[ABAP] Daten effizient zu internen Tabellen hinzufügen

Variante 1 (HASHED TABLE)

TYPES: BEGIN OF ty_msgnr,
         msgnr TYPE t100-msgnr,
       END OF ty_msgnr.

DATA: it_t100 TYPE HASHED TABLE OF t100 WITH UNIQUE KEY sprsl arbgb msgnr.

SELECT * FROM t100
  INTO TABLE @it_t100
  UP TO 100000 ROWS.

DATA: it_msgnr TYPE HASHED TABLE OF ty_msgnr WITH UNIQUE KEY msgnr.

DATA(o_timer) = cl_abap_runtime=>create_hr_timer( ).
DATA(usec_start) = o_timer->get_runtime( ).

LOOP AT it_t100 ASSIGNING FIELD-SYMBOL(<s>).
* jedes Element auf Vorhandensein Prüfen und ggf. zur Liste hinzufügen
  IF NOT line_exists( it_msgnr[ msgnr = <s>-msgnr ] ).
    INSERT VALUE ty_msgnr( msgnr = <s>-msgnr ) INTO TABLE it_msgnr.
  ENDIF.
ENDLOOP.

DATA(usec_end) = o_timer->get_runtime( ).
DATA(usec) = CONV decfloat16( usec_end - usec_start ).
DATA(sec) = usec / 1000000.

WRITE: / 'Laufzeit:', sec, 's'.

Variante 2 (GROUP BY)

TYPES: BEGIN OF ty_msgnr,
         msgnr TYPE t100-msgnr,
       END OF ty_msgnr.

*DATA: it_t100 TYPE HASHED TABLE OF t100 WITH UNIQUE KEY sprsl arbgb msgnr.
DATA: it_t100 TYPE STANDARD TABLE OF t100 WITH DEFAULT KEY.

SELECT * FROM t100
  INTO TABLE @it_t100
  UP TO 100000 ROWS.

DATA: it_msgnr TYPE STANDARD TABLE OF ty_msgnr WITH DEFAULT KEY.

DATA(o_timer) = cl_abap_runtime=>create_hr_timer( ).
DATA(usec_start) = o_timer->get_runtime( ).

LOOP AT it_t100 ASSIGNING FIELD-SYMBOL(<s>) GROUP BY <s>-msgnr ASCENDING.
* jedes Element auf Vorhandensein Prüfen und ggf. zur Liste hinzufügen
  APPEND VALUE ty_msgnr( msgnr = <s>-msgnr ) TO it_msgnr.
ENDLOOP.

DATA(usec_end) = o_timer->get_runtime( ).
DATA(usec) = CONV decfloat16( usec_end - usec_start ).
DATA(sec) = usec / 1000000.

WRITE: / 'Laufzeit:', sec, 's'.

Variante 3 (am schnellsten: COLLECT)

TYPES: BEGIN OF ty_msgnr,
         msgnr TYPE t100-msgnr,
       END OF ty_msgnr.

* Messages lesen
SELECT * FROM t100
  INTO TABLE @DATA(it_t100)
  UP TO 100000 ROWS.

DATA: it_msgnr TYPE STANDARD TABLE OF ty_msgnr WITH DEFAULT KEY.

DATA(o_timer) = cl_abap_runtime=>create_hr_timer( ).
DATA(usec_start) = o_timer->get_runtime( ).

LOOP AT it_t100 ASSIGNING FIELD-SYMBOL(<s>).
* jedes Element auf Vorhandensein Prüfen und ggf. zur Liste hinzufügen
* COLLECT verwendet intern HASHED TABLES
  COLLECT VALUE ty_msgnr( msgnr = <s>-msgnr ) INTO it_msgnr.
ENDLOOP.

DATA(usec_end) = o_timer->get_runtime( ).
DATA(usec) = CONV decfloat16( usec_end - usec_start ).
DATA(sec) = usec / 1000000.

WRITE: / 'Laufzeit:', sec, 's'.