[ABAP] Beispiel für Verwendung der Klasse cl_xlsx_document

* Workbook
PARAMETERS: p_wb RADIOBUTTON GROUP grp DEFAULT 'X'.
* Sharedstrings
PARAMETERS: p_str RADIOBUTTON GROUP grp.
* Sheetpart
PARAMETERS: p_sh RADIOBUTTON GROUP grp.
* Tablepart
PARAMETERS: p_tab RADIOBUTTON GROUP grp.

START-OF-SELECTION.

  TRY.
      DATA: lv_rc TYPE i.
      DATA: it_files TYPE filetable.
      DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
      cl_gui_frontend_services=>file_open_dialog( EXPORTING file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                  CHANGING  file_table  = it_files
                                                            rc          = lv_rc
                                                            user_action = lv_action ).

      IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
        IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
          DATA: lv_filesize TYPE w3param-cont_len.
          DATA: lv_filetype TYPE w3param-cont_type.
          DATA: it_bin_data TYPE w3mimetabtype.

* Excel-Datei auf Appl. Server hochladen (binary)
          cl_gui_frontend_services=>gui_upload( EXPORTING filename   = |{ it_files[ 1 ]-filename }|
                                                          filetype   = 'BIN'
                                                IMPORTING filelength = lv_filesize
                                                CHANGING  data_tab   = it_bin_data ).

* solix -> xstring
          DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

**********************************************************************
* Excel-Objekt
**********************************************************************
          DATA(o_excel) = cl_xlsx_document=>load_document( lv_bin_data ).

          DATA(o_workbook) = o_excel->get_workbookpart( ).
          DATA(lv_workbook_xstr) = o_workbook->get_data( ).

          DATA(o_sharedstrings) = o_workbook->get_sharedstringspart( ).
          DATA(lv_sharedstrings_xstr) = o_sharedstrings->get_data( ).

          DATA(o_sheets) = o_workbook->get_worksheetparts( ).
          IF o_sheets->get_count( ) > 0.
            DATA(o_sheet) = CAST cl_xlsx_worksheetpart( o_sheets->get_part( 0 ) ).

            DATA(lv_sheet_xstr) = o_sheet->get_data( ).

            DATA(o_tables) = o_sheet->get_tableparts( ).
            IF o_tables->get_count( ) > 0.
              DATA(o_table) = CAST cl_xlsx_tablepart( o_tables->get_part( 0 ) ).
              DATA(lv_table_xstr) = o_table->get_data( ).
            ENDIF.
          ENDIF.

* XML Doc
          DATA(o_doc) = NEW cl_xml_document( ).

* xstring --> xml
          CASE abap_true.
            WHEN p_wb.
              o_doc->parse_xstring( lv_workbook_xstr ).
            WHEN p_str.
              o_doc->parse_xstring( lv_sharedstrings_xstr ).
            WHEN p_sh.
              o_doc->parse_xstring( lv_sheet_xstr ).
            WHEN p_tab.
              o_doc->parse_xstring( lv_table_xstr ).
          ENDCASE.

* Inhalt des XML-Documents in string wandeln
          o_doc->render_2_string( EXPORTING pretty_print = abap_true
                                  IMPORTING retcode      = DATA(lv_rc2)
                                            size         = DATA(lv_size2)
                                            stream       = DATA(lv_xml) ).

          IF lv_rc2 = 0.
* XML-String anzeigen
            cl_soap_xml_helper=>xml_show( sdoc  = lv_xml
                                          html  = abap_true
                                          title = 'XML Anzeige' ).
          ENDIF.

        ENDIF.
      ENDIF.

    CATCH cx_root INTO DATA(e_text).
      MESSAGE e_text->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.

[ABAP] Transportauftrag als ZIP-Datei speichern

SELECTION-SCREEN BEGIN OF LINE.
  SELECTION-SCREEN COMMENT (20) lbl1 FOR FIELD p_trkorr.
  PARAMETERS: p_trkorr LIKE e070-trkorr OBLIGATORY.
SELECTION-SCREEN END OF LINE.

INITIALIZATION.

  lbl1 = 'Transport-Auftrag:'.

START-OF-SELECTION.
  TRY.
      DATA: lv_req TYPE trwbo_request.

* (Nach-)Lesen von Einzelbestandteilen eines Auftrags
      CALL FUNCTION 'TR_READ_REQUEST'
        EXPORTING
          iv_read_e070     = abap_true
          iv_read_e07t     = abap_true
          iv_trkorr        = p_trkorr
        CHANGING
          cs_request       = lv_req
        EXCEPTIONS
          error_occured    = 1
          no_authorization = 2
          OTHERS           = 3.

      IF sy-subrc = 0.
*D Änderbar
*L Änderbar, geschützt
*O Freigabe gestartet
*R Freigegeben
*N Freigegeben (Importschutz für reparierte Objekte aktiv)
        IF lv_req-h-trstatus = 'R'.

          DATA: lv_trans_cofile_dir TYPE stpa-file.
          DATA: lv_trans_data_dir TYPE stpa-file.

* intern: Pfade der Transportverzeichnisse
          CALL FUNCTION 'TRINT_FI_GET_DIRECTORY_NAMES'
            EXPORTING
              iv_dir_type          = 'T'
            IMPORTING
              ev_data_dir          = lv_trans_data_dir
              ev_cofiles_dir       = lv_trans_cofile_dir
            EXCEPTIONS
              get_dir_trans_failed = 1
              build_path_failed    = 2
              OTHERS               = 3.

          IF sy-subrc = 0.
* Name
            DATA(lv_syst) = |{ p_trkorr(3) }|.
            DATA(lv_num) = |{ p_trkorr+4 }|.
            DATA(lv_name) = |{ lv_num }.{ lv_syst }|.

* Cofile lesen
            DATA: lv_xstr_cofile TYPE xstring.
            DATA(lv_cofile) = |{ lv_trans_cofile_dir }/K{ lv_name }|.

            OPEN DATASET lv_cofile FOR INPUT IN BINARY MODE.
            READ DATASET lv_cofile INTO lv_xstr_cofile.
            CLOSE DATASET lv_cofile.

* Data lesen
            DATA: lv_xstr_data TYPE xstring.
            DATA(lv_data) = |{ lv_trans_data_dir }/R{ lv_name }|.

            OPEN DATASET lv_data FOR INPUT IN BINARY MODE.
            READ DATASET lv_data INTO lv_xstr_data.
            CLOSE DATASET lv_data.

* Zip
            DATA(o_zip) = NEW cl_abap_zip( ).

            o_zip->add( name    = |K{ lv_name }|
                        content = lv_xstr_cofile ).

            o_zip->add( name    = |R{ lv_name }|
                        content = lv_xstr_data ).

            DATA(lv_xstr_zip) = o_zip->save( ).

* SOLIX
            DATA(it_raw_data) = cl_bcs_convert=>xstring_to_solix( EXPORTING iv_xstring = lv_xstr_zip ).

            DATA: lv_action TYPE i.
            DATA: lv_filename TYPE string.
            DATA: lv_fullpath TYPE string.
            DATA: lv_path TYPE string.

            DATA(lv_default) = |{ lv_req-h-as4text }_{ p_trkorr }|.

* alle Vorkommen, die nicht [a-zA-Z0-9_] entsprechen, durch '_' ersetzen
            REPLACE ALL OCCURRENCES OF REGEX '[^\w]+' IN lv_default WITH '_'.

* Save-Dialog
            cl_gui_frontend_services=>file_save_dialog( EXPORTING default_file_name = lv_default
                                                                  default_extension = 'zip'
                                                                  file_filter       = |{ cl_gui_frontend_services=>filetype_all }|
                                                        CHANGING  filename          = lv_filename
                                                                  path              = lv_path
                                                                  fullpath          = lv_fullpath
                                                                  user_action       = lv_action ).

            IF lv_action EQ cl_gui_frontend_services=>action_ok.

* Datei lokal speichern
              cl_gui_frontend_services=>gui_download( EXPORTING filename     = lv_fullpath
                                                                filetype     = 'BIN'
                                                                bin_filesize = xstrlen( lv_xstr_zip )
                                                      CHANGING  data_tab     = it_raw_data ).
            ENDIF.

          ELSE.
            WRITE: / |Systemverzeichnisse nicht gefunden.|.
          ENDIF.
        ELSE.
          WRITE: / |Auftrag { p_trkorr } nicht frei gegeben.|.
        ENDIF.

      ELSE.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO DATA(lv_msg).
        WRITE: / lv_msg.
      ENDIF.
    CATCH cx_root INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.

[ABAP] Binärdaten (HEX) in eine lokale Datei speichern

* HEX-Daten (Beispiel)
DATA(it_solix) = VALUE solix_tab(
                   ( line = '7639BD' )
                   ( line = '67326F' )
                 ).

TRY.
    DATA: lv_action TYPE i.
    DATA: lv_filename TYPE string.
    DATA: lv_fullpath TYPE string.
    DATA: lv_path TYPE string.

* Save-Dialog
    cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                  default_file_name = 'Data.bin'
                                                  default_extension = 'bin'
                                                  file_filter       = |Binärdaten (*.bin)\|*.bin\|{ cl_gui_frontend_services=>filetype_all }|
                                                CHANGING
                                                  filename          = lv_filename
                                                  path              = lv_path
                                                  fullpath          = lv_fullpath
                                                  user_action       = lv_action ).

    IF lv_action EQ cl_gui_frontend_services=>action_ok.
* XSTRING für Längenbestimung erzeugen
      DATA(lv_xstring) = cl_bcs_convert=>solix_to_xstring( it_solix ).

* Datei lokal speichern
      cl_gui_frontend_services=>gui_download( EXPORTING
                                                filename     = lv_fullpath
                                                filetype     = 'BIN'
                                                bin_filesize = xstrlen( lv_xstring )
                                              CHANGING
                                                data_tab     = it_solix ).

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

[ABAP] Excel-Version aus der Registry auslesen

DATA(lv_xl_current_version) = ||.

TRY.
    cl_gui_frontend_services=>registry_get_value( EXPORTING
                                                    root      = 0 " HKEY_CLASSES_ROOT
                                                    key       = 'EXCEL.APPLICATION\CURVER'
                                                  IMPORTING
                                                    reg_value = lv_xl_current_version ).

*Excel 97   = 8
*Excel 2000 = 9
*Excel 2002 = 10
*Excel 2003 = 11
*Excel 2007 = 12
*Excel 2010 = 14
*Excel 2013 = 15
*Excel 2016 = 16
    WRITE: / lv_xl_current_version.

  CATCH cx_root INTO DATA(e_txt).
ENDTRY.

[ABAP] Excel-Datei (*.xlsx) mit Desktop-Office-Integration (DOI) laden und 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.

  TRY.
      DATA: lv_rc TYPE i.
      DATA: it_files TYPE filetable.
      DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
      cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                    file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                  CHANGING
                                                    file_table  = it_files
                                                    rc          = lv_rc
                                                    user_action = lv_action ).

      IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
        IF lines( it_files ) > 0.

          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.

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

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

            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 ).

              IF abap_true = o_err->has_succeeded.
* URL muss für das Laden eines lokalen Files mit 'FILE://' beginnen
                DATA(lv_file) = 'FILE://' && it_files[ 1 ]-filename.
* *.xlsx von URL (File) laden und anzeigen
                o_oid->open_document( EXPORTING
                                        document_title = 'Excel'
                                        document_url   = CONV swk_url( lv_file )
                                        open_inplace   = abap_true
                                      IMPORTING
                                        error          = o_err ).

                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 ).
                  IF o_err->has_succeeded = abap_true.

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

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

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

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

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

                ENDIF.
              ENDIF.
            ENDIF.
          ENDIF.
        ENDIF.
      ENDIF.

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

[ABAP] Komplexbeispiel: Binärdaten Screenshot mit GZIP komprimieren, in Base64-String wandeln und zurück (CL_ABAP_GZIP, SSFC_BASE64_ENCODE, SSFC_BASE64_DECODE)

TRY.
    DATA: lv_mime_type TYPE string.
    DATA: lv_image_bytes TYPE xstring.

* Ein paar Bytes holen: Screenshot aufnehmen
    cl_gui_frontend_services=>get_screenshot( IMPORTING
                                                mime_type_str = lv_mime_type
                                                image         = lv_image_bytes ).

    DATA: lv_xstr_gzip TYPE xstring.

* Binärdaten mit GZIP komprimieren
    cl_abap_gzip=>compress_binary( EXPORTING raw_in   = lv_image_bytes
                                   IMPORTING gzip_out = lv_xstr_gzip ).

    DATA(lv_base64_data) = ||.

* Base64 codieren
    CALL FUNCTION 'SSFC_BASE64_ENCODE'
      EXPORTING
        bindata                  = lv_xstr_gzip
      IMPORTING
        b64data                  = lv_base64_data
      EXCEPTIONS
        ssf_krn_error            = 1
        ssf_krn_noop             = 2
        ssf_krn_nomemory         = 3
        ssf_krn_opinv            = 4
        ssf_krn_input_data_error = 5
        ssf_krn_invalid_par      = 6
        ssf_krn_invalid_parlen   = 7
        OTHERS                   = 8.
    IF sy-subrc = 0.

* Base64-String in der Listenausgabe darstellen
      DATA: it_text80 TYPE STANDARD TABLE OF text80 WITH DEFAULT KEY.
* formatierte Ausgabe (80 Zeichen Breite)
      CALL FUNCTION 'SWA_STRING_TO_TABLE'
        EXPORTING
          character_string = lv_base64_data
        IMPORTING
          character_table  = it_text80.

      LOOP AT it_text80 ASSIGNING FIELD-SYMBOL(<t>).
        WRITE: / <t>.
      ENDLOOP.

      DATA: lv_xstr_dec TYPE xstring.

* Base64 decodieren
      CALL FUNCTION 'SSFC_BASE64_DECODE'
        EXPORTING
          b64data                  = lv_base64_data
        IMPORTING
          bindata                  = lv_xstr_dec
        EXCEPTIONS
          ssf_krn_error            = 1
          ssf_krn_noop             = 2
          ssf_krn_nomemory         = 3
          ssf_krn_opinv            = 4
          ssf_krn_input_data_error = 5
          ssf_krn_invalid_par      = 6
          ssf_krn_invalid_parlen   = 7
          OTHERS                   = 8.

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

* Binärdaten mit GZIP dekomprimieren
        cl_abap_gzip=>decompress_binary( EXPORTING gzip_in = lv_xstr_dec IMPORTING raw_out = lv_pic_bytes ).

* freier Custom-Container innerhalb der Listenansicht
        DATA(o_cnt) = NEW cl_gui_custom_container( container_name = ''
                                                   repid          = 'SAPMSSY0'
                                                   dynnr          = '0120' ).

* Position des Containers setzen
        o_cnt->set_top( 50 ).
        o_cnt->set_left( 50 ).
        o_cnt->set_width( 640 ).
        o_cnt->set_height( 240 ).

* Bild über die URL laden und anzeigen
        DATA(o_pic) = NEW cl_gui_picture( parent = o_cnt ).
        o_pic->set_display_mode( display_mode = cl_gui_picture=>display_mode_stretch ).

* xstring -> solix
        DATA(it_bin_data) = cl_bcs_convert=>xstring_to_solix( lv_pic_bytes ).

        DATA: lv_url TYPE swk_url.

* temporäre URL für das Bild erzeugen
        CALL FUNCTION 'DP_CREATE_URL'
          EXPORTING
            type                 = 'image/jpeg' " https://wiki.selfhtml.org/wiki/MIME-Type/%C3%9Cbersicht
            subtype              = ''
          TABLES
            data                 = it_bin_data
          CHANGING
            url                  = lv_url
          EXCEPTIONS
            dp_invalid_parameter = 1
            dp_error_put_table   = 2
            dp_error_general     = 3
            OTHERS               = 4.

* Bild von URL laden
        o_pic->load_picture_from_url_async( lv_url ).

      ENDIF.
    ENDIF.

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

[ABAP] Interne Tabelle als Excel-Datei (*.xlsx) speichern (cl_fdt_xl_spreadsheet)

* Mit Hilfe der Klasse cl_fdt_xl_spreadsheet können über XML-Transformationen
* Daten aus SAP in XLSX-Dateien geschrieben werden
TRY.
* Testdaten lesen
    SELECT * FROM t001 INTO TABLE @DATA(it_t001).

    IF sy-subrc = 0.
* Header erzeugen
      DATA: it_columns TYPE if_fdt_doc_spreadsheet=>t_column.
      DATA: lv_head TYPE t001.
      DATA(o_desc) = CAST cl_abap_structdescr( cl_abap_structdescr=>describe_by_data( lv_head ) ).

      LOOP AT o_desc->get_components( ) ASSIGNING FIELD-SYMBOL(<c>).
        IF <c> IS ASSIGNED.
          IF <c>-type->kind = cl_abap_typedescr=>kind_elem.
            APPEND VALUE #( id           = sy-tabix
                            name         = <c>-name
                            display_name = <c>-name
                            is_result    = abap_true
                            type         = <c>-type ) TO it_columns.
          ENDIF.
        ENDIF.
      ENDLOOP.

* itab + header -> XML -> xstring
* Achtung: Speicherintensiv und rel. langsam! Es sollten keine großen Datenmengen verarbeitet werden.
      DATA(lv_bin_data) = cl_fdt_xl_spreadsheet=>if_fdt_doc_spreadsheet~create_document( columns      = it_columns " optional
                                                                                         itab         = REF #( it_t001 )
                                                                                         iv_call_type = if_fdt_doc_spreadsheet=>gc_call_dec_table ).
      IF xstrlen( lv_bin_data ) > 0.
        DATA: lv_action TYPE i.
        DATA: lv_filename TYPE string.
        DATA: lv_fullpath TYPE string.
        DATA: lv_path TYPE string.

* Save-Dialog
        cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                      default_file_name = 'Excel.xlsx'
                                                      default_extension = 'xlsx'
                                                      file_filter       = |Excel-Datei (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                    CHANGING
                                                      filename          = lv_filename
                                                      path              = lv_path
                                                      fullpath          = lv_fullpath
                                                      user_action       = lv_action ).

        IF lv_action EQ cl_gui_frontend_services=>action_ok.
* XSTRING -> SOLIX (RAW)
          DATA(it_raw_data) = cl_bcs_convert=>xstring_to_solix( EXPORTING iv_xstring = lv_bin_data ).

* Datei lokal speichern
          cl_gui_frontend_services=>gui_download( EXPORTING
                                                    filename     = lv_fullpath
                                                    filetype     = 'BIN'
                                                    bin_filesize = xstrlen( lv_bin_data )
                                                  CHANGING
                                                    data_tab     = it_raw_data ).


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

[ABAP] Excel-Datei (*.xlsx) in interne Tabelle laden (cl_fdt_xl_spreadsheet)

Variante 1 (generische Ausgabe mit cl_demo_output)

* Mit Hilfe der Klasse cl_fdt_xl_spreadsheet können über XML-Transformationen
* aus XLSX-Dateien Daten extrahiert und in eine interne Tabelle konvertiert werden
TRY.
    DATA: lv_rc TYPE i.
    DATA: it_files TYPE filetable.
    DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                  file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                CHANGING
                                                  file_table  = it_files
                                                  rc          = lv_rc
                                                  user_action = lv_action ).

    IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
      IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
        DATA: lv_filesize TYPE w3param-cont_len.
        DATA: lv_filetype TYPE w3param-cont_type.
        DATA: it_bin_data TYPE w3mimetabtype.

* Bild auf Appl. Server hochladen (binary)
        cl_gui_frontend_services=>gui_upload( EXPORTING
                                                filename   = |{ it_files[ 1 ]-filename }|
                                                filetype   = 'BIN'
                                              IMPORTING
                                                filelength = lv_filesize
                                              CHANGING
                                                data_tab   = it_bin_data ).

* solix -> xstring
        DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

* Excel (itab) -> XML -> Ref-Objekt
* Achtung: Speicherintensiv und rel. langsam! Es sollten keine großen Datenmengen verarbeitet werden.
        DATA(o_excel) = NEW cl_fdt_xl_spreadsheet( document_name = CONV #( it_files[ 1 ]-filename )
                                                   xdocument     = lv_bin_data ).

        DATA: it_worksheet_names TYPE if_fdt_doc_spreadsheet=>t_worksheet_names.

* Worksheetnamen ermitteln
        o_excel->if_fdt_doc_spreadsheet~get_worksheet_names( IMPORTING worksheet_names = it_worksheet_names ).

        IF lines( it_worksheet_names ) > 0.
* erste Worksheet holen und -> REF to itab erstellen
          DATA(o_worksheet_itab) = o_excel->if_fdt_doc_spreadsheet~get_itab_from_worksheet( it_worksheet_names[ 1 ] ).

* Referenz auf generisches Feldsymbol mappen
          ASSIGN o_worksheet_itab->* TO FIELD-SYMBOL(<worksheet>).

* Datenausgabe
          cl_demo_output=>write_data( <worksheet> ).

* HTML-Daten aus itab generieren
          DATA(lv_html) = cl_demo_output=>get( ).

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

* cl_gui_container=>default_screen erzwingen
          WRITE: space.
        ENDIF.
      ENDIF.
    ENDIF.

  CATCH cx_root INTO DATA(e_text).
    MESSAGE e_text->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

Variante 2 (generische Listausgabe)

TYPES : BEGIN OF ty_s_col_width,
          width TYPE i,
        END OF ty_s_col_width.

TYPES: ty_it_col_width TYPE STANDARD TABLE OF ty_s_col_width WITH DEFAULT KEY.

* Spaltenbreiten für Tabellenausgabe
DATA(it_col_width) = VALUE ty_it_col_width(
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                            ( width = 30 )
                                          ).

* Mit Hilfe der Klasse cl_fdt_xl_spreadsheet können über XML-Transformationen
* aus XLSX-Dateien Daten extrahiert und in eine interne Tabelle konvertiert werden
TRY.
    DATA: lv_rc TYPE i.
    DATA: it_files TYPE filetable.
    DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                  file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                CHANGING
                                                  file_table  = it_files
                                                  rc          = lv_rc
                                                  user_action = lv_action ).

    IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
      IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
        DATA: lv_filesize TYPE w3param-cont_len.
        DATA: lv_filetype TYPE w3param-cont_type.
        DATA: it_bin_data TYPE w3mimetabtype.

* Bild auf Appl. Server hochladen (binary)
        cl_gui_frontend_services=>gui_upload( EXPORTING
                                                filename   = |{ it_files[ 1 ]-filename }|
                                                filetype   = 'BIN'
                                              IMPORTING
                                                filelength = lv_filesize
                                              CHANGING
                                                data_tab   = it_bin_data ).

* solix -> xstring
        DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

* Excel (itab) -> XML -> Ref-Objekt
* Achtung: Speicherintensiv und rel. langsam! Es sollten keine großen Datenmengen verarbeitet werden.
        DATA(o_excel) = NEW cl_fdt_xl_spreadsheet( document_name = CONV #( it_files[ 1 ]-filename )
                                                   xdocument     = lv_bin_data ).

        DATA: it_worksheet_names TYPE if_fdt_doc_spreadsheet=>t_worksheet_names.

* Worksheetnamen ermitteln
        o_excel->if_fdt_doc_spreadsheet~get_worksheet_names( IMPORTING worksheet_names = it_worksheet_names ).

        IF lines( it_worksheet_names ) > 0.
* erste Worksheet holen und -> REF to itab erstellen
          DATA(o_worksheet_itab) = o_excel->if_fdt_doc_spreadsheet~get_itab_from_worksheet( it_worksheet_names[ 1 ] ).

* Referenz auf generisches Feldsymbol mappen
          FIELD-SYMBOLS: <worksheet> TYPE ANY TABLE.
          ASSIGN o_worksheet_itab->* TO <worksheet>.

* Tabellen-Zeile erzeugen
* muss hier erfolgen, damit man ein "greifbares" Tabellen-Zeilen-Objekt
* für die Strukturermittlung (describe_by_data) hat
          DATA: o_row TYPE REF TO data.
          CREATE DATA o_row LIKE LINE OF <worksheet>.
          ASSIGN o_row->* TO FIELD-SYMBOL(<row>).

* Komponenten (Spalten) einer Tabellenzeile ermitteln
          DATA(o_struct) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_data( <row> ) ).
          DATA(it_comp_tab) = o_struct->get_components( ).

* Anzahl Spalten der Tabellen-Zeile holen
          DATA(lv_colcnt) = lines( it_comp_tab ).

* Worksheet durchloopen
          LOOP AT <worksheet> ASSIGNING <row>.

* Spalten der akt. Zeile durchgehen
            DO lv_colcnt TIMES.
* Zelle: n-tes Element der akt. Zeile holen
              ASSIGN COMPONENT sy-index OF STRUCTURE <row> TO FIELD-SYMBOL(<cell>).

* Trennzeichen vor die Spalte einfügen, wenn nicht 1. Spalte
              IF sy-index > 1.
                WRITE: '|'.
              ENDIF.

* Achtung: Zell-Typ beachten! Es können hier nur flache Typen (Keine Strukturen, Tabellen) ausgegeben werden, der Rest muss gesondert behandelt werden
              IF CAST cl_abap_elemdescr( it_comp_tab[ sy-index ]-type )->kind = cl_abap_elemdescr=>kind_elem.
* Ausgabe Zellinhalt mit vordefinierter Spaltenbreite
                WRITE: |{ <cell> WIDTH = it_col_width[ sy-index ]-width }|.
              ENDIF.
            ENDDO.

            NEW-LINE.
          ENDLOOP.
        ENDIF.
      ENDIF.
    ENDIF.

  CATCH cx_root INTO DATA(e_text).
    MESSAGE e_text->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

Variante 3 (generische Ausgabe im SALV-Grid)

* Mit Hilfe der Klasse cl_fdt_xl_spreadsheet können über XML-Transformationen
* aus XLSX-Dateien Daten extrahiert und in eine interne Tabelle konvertiert werden
TRY.
    DATA: lv_rc TYPE i.
    DATA: it_files TYPE filetable.
    DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                  file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }|
                                                CHANGING
                                                  file_table  = it_files
                                                  rc          = lv_rc
                                                  user_action = lv_action ).

    IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
      IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
        DATA: lv_filesize TYPE w3param-cont_len.
        DATA: lv_filetype TYPE w3param-cont_type.
        DATA: it_bin_data TYPE w3mimetabtype.

* Bild auf Appl. Server hochladen (binary)
        cl_gui_frontend_services=>gui_upload( EXPORTING
                                                filename   = |{ it_files[ 1 ]-filename }|
                                                filetype   = 'BIN'
                                              IMPORTING
                                                filelength = lv_filesize
                                              CHANGING
                                                data_tab   = it_bin_data ).

* solix -> xstring
        DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

* Excel (itab) -> XML -> Ref-Objekt
* Achtung: Speicherintensiv und rel. langsam! Es sollten keine großen Datenmengen verarbeitet werden.
        DATA(o_excel) = NEW cl_fdt_xl_spreadsheet( document_name = CONV #( it_files[ 1 ]-filename )
                                                   xdocument     = lv_bin_data ).

        DATA: it_worksheet_names TYPE if_fdt_doc_spreadsheet=>t_worksheet_names.

* Worksheetnamen ermitteln
        o_excel->if_fdt_doc_spreadsheet~get_worksheet_names( IMPORTING worksheet_names = it_worksheet_names ).

        IF lines( it_worksheet_names ) > 0.
* erste Worksheet holen und -> REF to itab erstellen
          DATA(o_worksheet_itab) = o_excel->if_fdt_doc_spreadsheet~get_itab_for_alv_update( ).

* Referenz auf generisches Feldsymbol mappen
          ASSIGN o_worksheet_itab->* TO FIELD-SYMBOL(<worksheet>).

          TRY.
* SALV-Table
              DATA: o_salv TYPE REF TO cl_salv_table.

              cl_salv_table=>factory( IMPORTING
                                        r_salv_table   = o_salv
                                      CHANGING
                                        t_table        = <worksheet> ).

* Grundeinstellungen
              o_salv->get_functions( )->set_all( abap_true ).
              o_salv->get_columns( )->set_optimize( abap_true ).
              o_salv->get_display_settings( )->set_list_header( 'Worksheet' ).
              o_salv->get_display_settings( )->set_striped_pattern( abap_true ).
              o_salv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ).

* Spaltenüberschriften: technischer Name und Beschreibungstexte
              LOOP AT o_salv->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL(<c>).
                DATA(o_col) = <c>-r_column.
                o_col->set_short_text( || ).
                o_col->set_medium_text( || ).
                o_col->set_long_text( |{ o_col->get_columnname( ) }| ).
              ENDLOOP.

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

  CATCH cx_root INTO DATA(e_text).
    MESSAGE e_text->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

[ABAP] PDFs mittels Klasse CL_RSPO_PDF_MERGE zusammenfügen (mergen)

* siehe auch RSPO_TEST_MERGE_PDF_FILES (Beispielreport zum Aufruf des PDF-Merge ABAP-Interfaces)
* benötigt KEIN ADS (Adobe Document Service)
TRY.
    DATA: lv_rc TYPE i.
    DATA: it_files TYPE filetable.
    DATA: lv_action TYPE i.

* FileOpen-Dialog aufrufen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                  file_filter    = |pdf (*.pdf)\|*.pdf\|{ cl_gui_frontend_services=>filetype_all }|
                                                  multiselection = abap_true
                                                CHANGING
                                                  file_table  = it_files
                                                  rc          = lv_rc
                                                  user_action = lv_action ).

    IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn mind. zwei Dateien ausgewählt worden sind
      IF lines( it_files ) > 1.
* PDF-Merge Objekt
        DATA(o_pdf_merger) = NEW cl_rspo_pdf_merge( ).

* Dateiliste durchgehen
        LOOP AT it_files ASSIGNING FIELD-SYMBOL(<f>).

          DATA(lv_filesize) = CONV w3param-cont_len( '0' ).
          DATA(it_bin_data) = VALUE w3mimetabtype( ).

* Datei auf Appl. Server hochladen (binary)
          cl_gui_frontend_services=>gui_upload( EXPORTING
                                                  filename   = |{ it_files[ sy-tabix ]-filename }|
                                                  filetype   = 'BIN'
                                                IMPORTING
                                                  filelength = lv_filesize
                                                CHANGING
                                                  data_tab   = it_bin_data ).

* solix -> xstring
          DATA(lv_bin_data) = cl_bcs_convert=>solix_to_xstring( it_solix = it_bin_data ).

* Binärdaten der PDF-Datei als xstring zum Merger-Objekt hinzufügen
          o_pdf_merger->add_document( lv_bin_data ).

          WRITE: / |Hinzugefügt: { it_files[ sy-tabix ]-filename } ({ lv_filesize } Bytes)|.
        ENDLOOP.

* PDF-Dokumente mergen
        o_pdf_merger->merge_documents( IMPORTING merged_document = DATA(lv_merged_pdf)
                                                 rc              = lv_rc ).

        IF lv_rc = 0.
          DATA: lv_filename TYPE string.
          DATA: lv_fullpath TYPE string.
          DATA: lv_path TYPE string.

* SaveDialog
          cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                        default_extension   = 'pdf'
                                                        default_file_name   = 'merged.pdf'
                                                        file_filter         = |pdf (*.pdf)\|*.pdf\|{ cl_gui_frontend_services=>filetype_all }|
                                                        prompt_on_overwrite = abap_true
                                                      CHANGING
                                                        filename          = lv_filename     " Dateiname
                                                        path              = lv_path         " Pfad
                                                        fullpath          = lv_fullpath     " Pfad + Dateiname
                                                        user_action       = lv_action ).    " Benutzeraktion

          IF lv_action EQ cl_gui_frontend_services=>action_ok.
* xstring -> solix
            DATA(it_bin_data_merged) = cl_bcs_convert=>xstring_to_solix( lv_merged_pdf ).

            DATA(lv_size_merged) = xstrlen( lv_merged_pdf ).

* Datei lokal speichern
            cl_gui_frontend_services=>gui_download( EXPORTING
                                                      filename                = lv_fullpath
                                                      filetype                = 'BIN'
                                                      bin_filesize            = lv_size_merged
                                                    CHANGING
                                                      data_tab                = it_bin_data_merged ).

            WRITE: / |Gespeichert: { lv_fullpath } ({ lv_size_merged } Bytes)|.

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

Links