[ABAP] PDF-Dokument per ADS (Adobe Document Service) in XML konvertieren

* https://www.berater-wiki.de/XML_aus_PDF_extrahieren_mit_Testprogramm_FP_PDF_TEST_03
* http://sapfirst.blogspot.com/2014/05/inbound-abap-proxy-with-pdf-attachment.html
* Paket:     SAFP
* Programme: FP_PDF_TEST_01 (PDF erzeugen)
*            FP_PDF_TEST_03 (Datenextraktion)
* XFD (XML Form Data): https://www.berater-wiki.de/XFD-Datei_(Values_of_PDF_form_fields_in_XML)
* XFT (XML Form Template)
* XDC (XML Printer Definitions)

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 }|
                                                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 ) > 0.
        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[ 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 ).

* Form Processor erzeugen
        DATA(o_form_processor) = cl_fp=>get_reference( ).
* PDF-Objekt erzeugen
        DATA(o_pdf) = o_form_processor->create_pdf_object( ).
* Binärdaten an PDF-Objekt übergeben
        o_pdf->set_document( pdfdata = lv_bin_data ).
* PDF-Daten extrahieren
        o_pdf->set_extractdata( ).
* ADS-Server rufen
        o_pdf->execute( ).
* extrahierte Daten holen (xstring)
        o_pdf->get_data( IMPORTING formdata = DATA(lv_pdf_formdata) ).

* xstring (binary) -> XML-string (UTF-8)
        DATA(lv_pdf_xml_str) = ||.
        DATA(o_conv) = cl_abap_conv_in_ce=>create( input    = lv_pdf_formdata
                                                   encoding = 'UTF-8' ).
        o_conv->read( IMPORTING data = lv_pdf_xml_str ).

* XML-Zugriff
        DATA(o_ixml) = cl_ixml=>create( ).

        DATA(o_sf) = o_ixml->create_stream_factory( ).
        DATA(o_doc) = o_ixml->create_document( ).
        DATA(o_stream) = o_sf->create_istream_string( lv_pdf_xml_str ).

* XML-Parser
        DATA(o_parser) = o_ixml->create_parser( stream_factory = o_sf
                                                istream        = o_stream
                                                document       = o_doc ).

* XML parsen
        IF o_parser->parse( ) = 0.

          DATA(o_root) = o_doc->get_root_element( ).

          ...

        ELSE.
* Fehlerauswertung
          DO o_parser->num_errors( ) TIMES.
            DATA(o_err) = o_parser->get_error( index = sy-index - 1 ).
            IF o_err IS BOUND.
              WRITE: / o_err->get_column( ), o_err->get_line( ), o_err->get_reason( ).
            ENDIF.
          ENDDO.
        ENDIF.

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

[ABAP] Google-API: QR-Code generieren und Bild herunterladen/speichern

* Dateiname der Bilddatei zum hochladen
PARAMETERS: p_fname TYPE file_table-filename OBLIGATORY.

START-OF-SELECTION.
* URL zur Google-API für die Erstellung des QR-Codes
  DATA(lv_url) = |http://chart.apis.google.com/chart?chs=200x200&cht=qr&chld=\|1&chl=viele%20lustige%20Zeichen/chart.png|.

  TRY.
      DATA: o_client TYPE REF TO if_http_client.
* Client-Objekt erzeugen
      cl_http_client=>create_by_url( EXPORTING
                                       url     = lv_url
                                     IMPORTING
                                       client  = o_client ).
      IF sy-subrc = 0.
* HTTP GET senden
        o_client->send( ).

* Response lesen
        o_client->receive( ).

        DATA: lv_http_status TYPE i.
        DATA: lv_status_text TYPE string.

* HTTP Return Code holen
        o_client->response->get_status( IMPORTING
                                          code   = lv_http_status
                                          reason = lv_status_text ).

* Wenn Status 200 (Ok)
        IF lv_http_status = 200.

* Binärdaten (QR-Code) auslesen
          DATA(lv_xdata) = o_client->response->get_data( ).

          o_client->close( ).

* xstring -> solix
          DATA(it_img_conv_data) = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_xdata ).

          WRITE: / |{ p_fname }.png|.

* Image lokal speichern
          cl_gui_frontend_services=>gui_download( EXPORTING
                                                    filename     = |{ p_fname }.png|
                                                    filetype     = 'BIN'
                                                    bin_filesize = xstrlen( lv_xdata )
                                                  CHANGING
                                                    data_tab     = it_img_conv_data ).

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

[ABAP] CONVERT_OTF: OTF-Format als PDF speichern und anzeigen (Beispiel Smart Forms-Formular)

* https://www.tutorialspoint.com/sap_smart_forms/
* https://www.berater-wiki.de/Smart_Forms_Generierter_Funktionsbaustein
* https://mind-forms.de/sap-formulartechnologien/sapscript/sapscript-formulare-in-pdf-umwandeln/

* Tabelle STXFADM

PARAMETERS: p_form TYPE stxfadm-formname DEFAULT 'SF_EXAMPLE_01'.
PARAMETERS: p_open TYPE abap_bool DEFAULT abap_true.

START-OF-SELECTION.
  DATA(lv_control_parameters) = VALUE ssfctrlop( no_dialog = abap_true
                                                 preview   = space
                                                 getotf    = abap_true
                                                 langu     = sy-langu ).

  DATA: lv_devtype TYPE rspoptype.

* Smart Forms: Gerätetyp nach Sprache ermitteln
  CALL FUNCTION 'SSF_GET_DEVICE_TYPE'
    EXPORTING
      i_language             = lv_control_parameters-langu
    IMPORTING
      e_devtype              = lv_devtype
    EXCEPTIONS
      no_language            = 1
      language_not_installed = 2
      no_devtype_found       = 3
      system_error           = 4
      OTHERS                 = 5.

  IF sy-subrc = 0.
    DATA(lv_output_options) = VALUE ssfcompop( tddest    = 'LOCL'
                                               tdprinter = lv_devtype ).

* FuBa Name ermitteln
    DATA: lv_fm_name TYPE rs38l_fnam.

* Smart Forms: Name des Funktionsbausteins bestimmen
    CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
      EXPORTING
        formname           = p_form
      IMPORTING
        fm_name            = lv_fm_name
      EXCEPTIONS
        no_form            = 1
        no_function_module = 2
        OTHERS             = 3.

    IF sy-subrc = 0.

      DATA: lv_document_output_info TYPE ssfcrespd.
      DATA: lv_job_output_info TYPE ssfcrescl.
      DATA: lv_job_output_options TYPE ssfcresop.

* Zusatzparameter für Fuba für Formular 'SF_EXAMPLE_01'
      DATA: lv_customer TYPE scustom.
      DATA: it_bookings TYPE ty_bookings.
      DATA: it_connections TYPE ty_connections.

* FuBa der Form aufrufen und OTF-Daten erzeugen
      CALL FUNCTION lv_fm_name
        EXPORTING
          control_parameters   = lv_control_parameters
          output_options       = lv_output_options
          user_settings        = space
          customer             = lv_customer
          bookings             = it_bookings
          connections          = it_connections
        IMPORTING
          document_output_info = lv_document_output_info
          job_output_info      = lv_job_output_info
          job_output_options   = lv_job_output_options
        EXCEPTIONS
          formatting_error     = 1
          internal_error       = 2
          send_error           = 3
          user_canceled        = 4
          OTHERS               = 5.

      IF sy-subrc = 0.

        DATA(lv_bin_filesize) = 0.

        DATA: lv_pdf_xstring TYPE xstring.
        DATA: it_lines TYPE tline_t.

* Konvertieren von OTF-Format in verschiedene Formate (TLINE Tabelle)
        CALL FUNCTION 'CONVERT_OTF'
          EXPORTING
            format                = 'PDF' " ASCII, PDF
          IMPORTING
            bin_filesize          = lv_bin_filesize
*           bin_file              = lv_pdf_xstring             " PDF Binärdaten -> einkommentieren, wenn benötigt, sonst it_lines leer!
          TABLES
            otf                   = lv_job_output_info-otfdata " Input OTF
            lines                 = it_lines                   " Output
          EXCEPTIONS
            err_max_linewidth     = 1
            err_format            = 2
            err_conv_not_possible = 3
            err_bad_otf           = 4
            OTHERS                = 5.

        IF sy-subrc = 0.

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

          TRY.
* Speichern-Dialog
              cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                            default_file_name = |{ p_form }.pdf|
                                                            default_extension = 'pdf'
                                                            file_filter       = '(*.pdf)|*.pdf|'
                                                          CHANGING
                                                            filename          = lv_filename
                                                            path              = lv_path
                                                            fullpath          = lv_fullpath
                                                            user_action       = lv_action ).

              IF lv_action EQ cl_gui_frontend_services=>action_ok.
* Daten lokal speichern
                cl_gui_frontend_services=>gui_download( EXPORTING
                                                          bin_filesize = lv_bin_filesize
                                                          filename     = lv_fullpath
                                                          filetype     = 'BIN'
                                                        CHANGING
                                                          data_tab     = it_lines ).

                WRITE: / |Datei erfolgreich unter { lv_fullpath } gespeichert.|.

                IF abap_true = p_open.
* Datei anzeigen
                  cl_gui_frontend_services=>execute( document = lv_fullpath ).
                ENDIF.
              ENDIF.

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

        DATA: it_sf_errors TYPE tsferror.

* Smart Forms: Lesen der Fehlertabelle nach Aufruf
        CALL FUNCTION 'SSF_READ_ERRORS'
          IMPORTING
            errortab = it_sf_errors.

        cl_demo_output=>display( it_sf_errors ).
      ENDIF.

    ELSE.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

  ELSE.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

[ABAP] PDF im Browserfenster anzeigen

TRY.
    DATA: it_sel_filetab TYPE filetable.
    DATA: ret_code TYPE i.
    DATA: lv_action TYPE i.

* FileOpen-Dialog für Dateiauswahl anzeigen
    cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                  window_title            = 'PDF-Datei öffnen'
                                                  multiselection          = abap_false
                                                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.
* Browserfenster erzeugen
      DATA(o_html) = NEW cl_gui_html_viewer( parent = cl_gui_container=>default_screen ).

* PDF im ABAP-Fenster anzeigen
      o_html->show_url( url      = it_sel_filetab[ 1 ]-filename
                        in_place = abap_true ).

* leere SAP-Toolbar ausblenden
      cl_abap_list_layout=>suppress_toolbar( ).

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

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

[ABAP] Screenshot speichern

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

TRY.
* Screenshot aufnehmen
    cl_gui_frontend_services=>get_screenshot( IMPORTING
                                                mime_type_str = lv_mime_type
                                                image         = lv_image_bytes ).

* MIME-Typ (PNG) ausgeben
    WRITE: / lv_mime_type.

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

* Savedialog anzeigen
    cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                  default_file_name = 'image.png'
                                                  default_extension = 'png'
                                                  file_filter       = '(*.png)|*.png|'
                                                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_image_bytes ).

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

    ENDIF.
  CATCH cx_root INTO DATA(e_txt).
ENDTRY.
ENDTRY.

[ABAP] Listenausgabe in Spool umleiten und als PDF ausgeben

DATA: it_print_params TYPE pri_params.

* Spool Druckparameter und Archivparameter lesen, bestimmen, ändern
CALL FUNCTION 'GET_PRINT_PARAMETERS'
  EXPORTING
    no_dialog              = abap_true
  IMPORTING
    out_parameters         = it_print_params
  EXCEPTIONS
    archive_info_not_found = 1
    invalid_print_params   = 2
    invalid_archive_params = 3
    OTHERS                 = 4.

IF sy-subrc = 0.
* Liste -> Spool (ID)
  NEW-PAGE PRINT ON PARAMETERS it_print_params NO DIALOG.
  WRITE: / 'Hello World'.
  NEW-PAGE PRINT OFF.

  COMMIT WORK.

  DATA: lv_bin_length TYPE i.
  DATA: lv_xstring_pdf TYPE xstring.

* Spool (ID) -> PDF
  CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
    EXPORTING
      src_spoolid              = CONV tsp01-rqident( sy-spono )
      no_dialog                = abap_true
      pdf_destination          = 'X' " xstring
      get_size_from_format     = abap_true
    IMPORTING
      pdf_bytecount            = lv_bin_length
      bin_file                 = lv_xstring_pdf
    EXCEPTIONS
      err_no_abap_spooljob     = 1
      err_no_spooljob          = 2
      err_no_permission        = 3
      err_conv_not_possible    = 4
      err_bad_destdevice       = 5
      user_cancelled           = 6
      err_spoolerror           = 7
      err_temseerror           = 8
      err_btcjob_open_failed   = 9
      err_btcjob_submit_failed = 10
      err_btcjob_close_failed  = 11
      OTHERS                   = 12.

  IF sy-subrc = 0.
    DATA: lv_action TYPE i.
    DATA: lv_filename TYPE string.
    DATA: lv_fullpath TYPE string.
    DATA: lv_path TYPE string.

    TRY.
* SaveDialog aufrufen
        cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                      default_extension   = 'pdf'
                                                      default_file_name   = 'ListOutput'
                                                      file_filter         = |PDF (*.pdf)\|*.pdf\|{ cl_gui_frontend_services=>filetype_all }|
                                                      prompt_on_overwrite = abap_true
                                                    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
          DATA(it_raw_data) = cl_bcs_convert=>xstring_to_solix( lv_xstring_pdf ).
* iTab (bytes) -> lokale Datei
          cl_gui_frontend_services=>gui_download( EXPORTING
                                                    filename     = lv_fullpath
                                                    filetype     = 'BIN'
                                                    bin_filesize = lv_bin_length
                                                  CHANGING
                                                    data_tab     = it_raw_data ).

* Browserfenster erzeugen
          DATA(o_html) = NEW cl_gui_html_viewer( parent = cl_gui_container=>default_screen ).

* PDF im ABAP-Fenster anzeigen
          o_html->show_url( url      = CONV skwf_url( lv_fullpath )
                            in_place = abap_true ).

* leere SAP-Toolbar ausblenden
          cl_abap_list_layout=>suppress_toolbar( ).

* cl_gui_container=>default_screen erzwingen
          WRITE: / |Datei erfolgreich unter { lv_fullpath } gespeichert.|.
        ENDIF.

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

Links

[ABAP] Daten aus der Zwischenablage (Clipboard) importieren

* Datentyp mit ausreichend Länge für Zeilen der Clipboard-Daten
TYPES: ty_char4096 TYPE c LENGTH 4096.

DATA: it_clipboarddata TYPE STANDARD TABLE OF ty_char4096.
DATA: it_splitelements TYPE STANDARD TABLE OF string.
DATA: lv_line_count TYPE i.

cl_gui_frontend_services=>clipboard_import( IMPORTING
                                              data                 = it_clipboarddata
                                              length               = lv_line_count
                                            EXCEPTIONS
                                              cntl_error           = 1
                                              error_no_gui         = 2
                                              not_supported_by_gui = 3
                                              OTHERS               = 4 ).

IF sy-subrc = 0.
  WRITE: / 'Zeilen:', lv_line_count.

  SKIP.

* Zeilen der Clipboarddaten durchloopen
  LOOP AT it_clipboarddata ASSIGNING FIELD-SYMBOL(<fs_line>).

* die Zeilen am TAB spaltenweise aufsplitten
    SPLIT <fs_line> AT cl_abap_char_utilities=>horizontal_tab INTO TABLE it_splitelements.

* Zeilendaten verarbeiten -> neu zusammenbauen
    DATA(lv_line) = ||.

    LOOP AT it_splitelements ASSIGNING FIELD-SYMBOL(<fs_elem>).
      IF lv_line IS INITIAL.
        lv_line = <fs_elem>.
      ELSE.
        lv_line = |{ lv_line }\|{ <fs_elem> }|.
      ENDIF.
    ENDLOOP.

* Ausgabe
    WRITE: / lv_line.
  ENDLOOP.
ENDIF.

[ABAP] Interne Tabellen im Format Office Open XML (SpreadsheetML) speichern

Beispiel für die Nutzung des Office Open XML (SpreadsheetML) Formates zur Datenausgabe von Nutzdaten aus internen Tabellen.

Links

Wikipedia – Office Open XML
Wikipedia – SpreadsheetML
SAP ABAP Doku
Beispiel 1
Beispiel 2

Beispiel – Speicherung Daten beliebiger interner Tabellen in eine von Microsoft Office Excel lesbare XML-Datei

* Dateien können ab Microsoft Office Excel 2002 / 2003 geöffnet werden
DATA: it_spfli TYPE STANDARD TABLE OF spfli.
DATA: gv_company TYPE string VALUE 'codezentrale.de'.
DATA: gv_user TYPE string VALUE 'Testuser'.
DATA: gv_sheetname TYPE string VALUE 'SPFLI'.

INITIALIZATION.
* Daten holen
  SELECT * FROM spfli INTO TABLE @it_spfli.

START-OF-SELECTION.

  DATA: o_cell TYPE REF TO if_ixml_element.
  DATA: o_data TYPE REF TO if_ixml_element.

* Tabellenstruktur
  DATA(o_table_descr) = CAST cl_abap_tabledescr( cl_abap_tabledescr=>describe_by_data( it_spfli ) ).

* Struktur einer Tabellenzeile
  DATA(o_struct_descr) = CAST cl_abap_structdescr( o_table_descr->get_table_line_type( ) ).

* Komponenten (Spalten) einer Zeile
  DATA(it_comp_tab) = o_struct_descr->get_components( ).

* Anzahl Spalten
  DATA(lv_colcount) = lines( it_comp_tab ).

* ixml Factory
  DATA(o_ixml) = cl_ixml=>create( ).

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* DOM Object Model
  DATA(o_doc) = o_ixml->create_document( ).

* Processing Instructions setzen
* damit die XML-Datei gleich vom Windows als Excel-XML erkannt und korrekt geöffnet wird
  DATA(o_pi) = o_doc->create_pi_parsed( name = 'mso-application' ).
  o_pi->set_attribute( name = 'progid' value = 'Excel.Sheet' ).
  o_doc->append_child( o_pi ).

* Workbook
  DATA(o_workbook) = o_doc->create_simple_element( name = 'Workbook' parent = o_doc ).
  o_workbook->set_attribute( name = 'xmlns' value ='urn:schemas-microsoft-com:office:spreadsheet' ).
  o_workbook->set_attribute_node( o_doc->create_namespace_decl( name = 'o' prefix = 'xmlns' uri = 'urn:schemas-microsoft-com:office:office') ).
  o_workbook->set_attribute_node( o_doc->create_namespace_decl( name = 'x' prefix = 'xmlns' uri = 'urn:schemas-microsoft-com:office:excel' ) ).
  o_workbook->set_attribute_node( o_doc->create_namespace_decl( name = 'ss' prefix = 'xmlns' uri = 'urn:schemas-microsoft-com:office:spreadsheet') ).
  o_workbook->set_attribute_node( o_doc->create_namespace_decl( name = 'html' prefix = 'xmlns' uri = 'http://www.w3.org/TR/REC-html40') ).

* DocumentProperties
* Zeitstempel erzeugen
  DATA: lv_tsl TYPE timestampl.
  GET TIME STAMP FIELD lv_tsl.
  DATA(lv_created) = |{ substring( val = |{ lv_tsl TIMESTAMP = ISO }| off = 0 len = 19 ) }Z|.

  DATA(o_prop) = o_doc->create_simple_element( name = 'DocumentProperties' parent = o_workbook ).
  o_prop->set_attribute( name = 'xmlns' value ='urn:schemas-microsoft-com:office:office' ).
  o_doc->create_simple_element( name = 'Author' value = gv_user parent = o_prop ).
  o_doc->create_simple_element( name = 'LastAuthor' value = gv_user parent = o_prop ).
  o_doc->create_simple_element( name = 'Created' value = lv_created parent = o_prop ).
  o_doc->create_simple_element( name = 'Company' value = gv_company parent = o_prop ).
  o_doc->create_simple_element( name = 'Version' value = '14.00' parent = o_prop ).

* OfficeDocumentSettings
  DATA(o_set) = o_doc->create_simple_element( name = 'OfficeDocumentSettings' parent = o_workbook ).
  o_set->set_attribute( name = 'xmlns' value ='urn:schemas-microsoft-com:office:office' ).
  o_doc->create_simple_element( name = 'AllowPNG' parent = o_set ).

* ExcelWorkbook
  DATA(o_excelwb) = o_doc->create_simple_element( name = 'ExcelWorkbook' parent = o_workbook ).
  o_excelwb->set_attribute( name = 'xmlns' value ='urn:schemas-microsoft-com:office:excel' ).
  o_doc->create_simple_element( name = 'ProtectStructure' value = 'False' parent = o_excelwb ).
  o_doc->create_simple_element( name = 'ProtectWindows' value = 'False' parent = o_excelwb ).

* Styles
  DATA(o_styles) = o_doc->create_simple_element( name = 'Styles' parent = o_workbook ).

* "Default" Style
  DATA(o_style_default) = o_doc->create_simple_element( name = 'Style' parent = o_styles ).
  o_style_default->set_attribute_ns( name = 'ID' prefix = 'ss' value = 'Default' ).
  o_style_default->set_attribute_ns( name = 'Name' prefix = 'ss' value = 'Normal' ).
  DATA(o_align) = o_doc->create_simple_element( name = 'Alignment' parent = o_style_default ).
  o_align->set_attribute_ns( name = 'Vertical' prefix = 'ss' value = 'Bottom' ).
  DATA(o_borders) = o_doc->create_simple_element( name = 'Borders' parent = o_style_default ).
  DATA(o_font) = o_doc->create_simple_element( name = 'Font' parent = o_style_default ).
  o_font->set_attribute_ns( name = 'FontName' prefix = 'ss' value = 'Arial' ).
  o_font->set_attribute_ns( name = 'Family' prefix = 'x' value = 'Swiss' ).
  o_font->set_attribute_ns( name = 'Size' prefix = 'ss' value = '11' ).
  o_font->set_attribute_ns( name = 'Color' prefix = 'ss' value = '#000000' ).
  DATA(o_interior) = o_doc->create_simple_element( name = 'Interior' parent = o_style_default ).
  DATA(o_numberformat) = o_doc->create_simple_element( name = 'NumberFormat' parent = o_style_default ).
  DATA(o_protection) = o_doc->create_simple_element( name = 'Protection' parent = o_style_default ).

* Bold Style "s62" für die Überschrift
  DATA(o_style_bold) = o_doc->create_simple_element( name = 'Style' parent = o_styles ).
  o_style_bold->set_attribute_ns( name = 'ID' prefix = 'ss' value = 's62' ).
  DATA(o_font_bold) = o_doc->create_simple_element( name = 'Font' parent = o_style_bold ).
  o_font_bold->set_attribute_ns( name = 'FontName' prefix = 'ss' value = 'Arial' ).
  o_font_bold->set_attribute_ns( name = 'Family' prefix = 'x' value = 'Swiss' ).
  o_font_bold->set_attribute_ns( name = 'Size' prefix = 'ss' value = '11' ).
  o_font_bold->set_attribute_ns( name = 'Color' prefix = 'ss' value = '#000000' ).
  o_font_bold->set_attribute_ns( name = 'Bold' prefix = 'ss' value = '1' ).

* Worksheet "SPFLI" einfügen
  DATA(o_sheet1) = o_doc->create_simple_element( name = 'Worksheet' parent = o_workbook ).
  o_sheet1->set_attribute_ns( name = 'Name' prefix = 'ss' value = gv_sheetname ).

* WorksheetOptions
  DATA(o_ws_opt) = o_doc->create_simple_element( name = 'WorksheetOptions' parent = o_sheet1 ).
  o_ws_opt->set_attribute( name = 'xmlns' value = 'urn:schemas-microsoft-com:office:excel' ).

  o_doc->create_simple_element( name = 'Selected' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'ProtectObjects' value = 'False' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'ProtectScenarios' value = 'False' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'SplitHorizontal' value = '1' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'TopRowBottomPane' value = '1' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'FreezePanes' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'FrozenNoSplit' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'Unsynced' parent = o_ws_opt ).
  o_doc->create_simple_element( name = 'ActivePane' value = '2' parent = o_ws_opt ).

* Page Setup
  DATA(o_ps) = o_doc->create_simple_element( name = 'PageSetup' parent = o_ws_opt ).
  DATA(o_ps_header) = o_doc->create_simple_element( name = 'Header' parent = o_ps ).
  o_ps_header->set_attribute_ns( name = 'Margin' prefix = 'x' value = '0.3' ).
  DATA(o_ps_footer) = o_doc->create_simple_element( name = 'Footer' parent = o_ps ).
  o_ps_footer->set_attribute_ns( name = 'Margin' prefix = 'x' value = '0.3' ).
  DATA(o_ps_margins) = o_doc->create_simple_element( name = 'PageMargins' parent = o_ps ).
  o_ps_margins->set_attribute_ns( name = 'Bottom' prefix = 'x' value = '0.7' ).
  o_ps_margins->set_attribute_ns( name = 'Left' prefix = 'x' value = '0.7' ).
  o_ps_margins->set_attribute_ns( name = 'Right' prefix = 'x' value = '0.7' ).
  o_ps_margins->set_attribute_ns( name = 'Top' prefix = 'x' value = '0.7' ).

* Splitter für Header / Data definieren
  o_doc->create_simple_element( name = 'x:Selected' parent = o_ps ).
  o_doc->create_simple_element( name = 'x:FreezePanes' parent = o_ps ).
  o_doc->create_simple_element( name = 'x:FrozenNoSplit' parent = o_ps ).
  o_doc->create_simple_element( name = 'x:Unsynced' parent = o_ps ).
  o_doc->create_simple_element( name = 'x:ProtectObjects' value = 'False' parent = o_ps ).
  o_doc->create_simple_element( name = 'x:ProtectScenarios' value = 'False' parent = o_ps ).
  o_doc->create_simple_element( name = 'x:SplitHorizontal' value = '1' parent = o_ps ).
  o_doc->create_simple_element( name = 'x:TopRowBottomPane' value = '1' parent = o_ps ).

* Named Range für Filter definieren
  DATA(o_names) = o_doc->create_simple_element( name = 'Names' parent = o_sheet1 ).
  DATA(o_named_range) = o_doc->create_simple_element( name = 'NamedRange' parent = o_names ).
  o_named_range->set_attribute_ns( name = 'Name' prefix = 'ss' value = '_FilterDatabase' ).
  o_named_range->set_attribute_ns( name = 'RefersTo' prefix = 'ss' value = |=Sheet1!R1C1:R1C{ lv_colcount }| ). " Spalte 1-x als Range "_FilterDatabase" definieren
  o_named_range->set_attribute_ns( name = 'Hidden' prefix = 'ss' value = '1' ).

* Autofilter aktivieren
  DATA(o_autofilter) = o_doc->create_simple_element( name = 'AutoFilter' parent = o_sheet1 ).
  o_autofilter->set_attribute_ns( name = 'Range' prefix = 'x' value = |R1C1:R1C{ lv_colcount }| ).              " Spalte 1-x als Filter-Range definieren
  o_autofilter->set_attribute_ns( name = 'xmlns' value = 'urn:schemas-microsoft-com:office:excel' ).

* Table für Header und Daten
  DATA(o_table) = o_doc->create_simple_element( name = 'Table' parent = o_sheet1 ).
  o_table->set_attribute_ns( name = 'FullColumns' prefix = 'x' value = '1' ).
  o_table->set_attribute_ns( name = 'FullRows' prefix = 'x' value = '1' ).
  o_table->set_attribute_ns( name = 'DefaultColumnWidth' prefix = 'x' value = '66' ).
  o_table->set_attribute_ns( name = 'DefaultRowHeight' prefix = 'x' value = '14.25' ).
  o_table->set_attribute_ns( name = 'DefaultColumnWidth' prefix = 'ss' value = '66' ).
  o_table->set_attribute_ns( name = 'DefaultRowHeight' prefix = 'ss' value = '14.25' ).

* Header (Tabellenüberschriften) einfügen
  DATA(o_hrow) = o_doc->create_simple_element( name = 'Row' parent = o_table ).

  LOOP AT it_comp_tab ASSIGNING FIELD-SYMBOL(<fs_comp>).
    o_cell = o_doc->create_simple_element( name = 'Cell' parent = o_hrow ).
    o_cell->set_attribute_ns( name = 'StyleID' prefix = 'ss' value = 's62' ). " Style Bold
* nur elementare Datentypen zulassen
    IF <fs_comp>-type->kind = cl_abap_typedescr=>kind_elem.
      o_doc->create_simple_element( name = 'Data' value = <fs_comp>-name parent = o_cell )->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    ELSE.
* alle anderen Spalten mit Strukturen, INCLUDES usw. einfach als DEEP kennzeichnen, Inhalt bleibt leer
      o_doc->create_simple_element( name = 'Data' value = 'DEEP' parent = o_cell )->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ).
    ENDIF.
* Named Range "_FilterDatabase" für Filter setzen
    o_doc->create_simple_element( name = 'NamedCell' parent = o_cell )->set_attribute_ns( name = 'Name' prefix = 'ss' value = '_FilterDatabase' ).
  ENDLOOP.

* Daten einfügen
  LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<fs_line>).
    DATA(o_row_data) = o_doc->create_simple_element( name = 'Row' parent = o_table ).

    o_struct_descr ?= cl_abap_structdescr=>describe_by_data( <fs_line> ).

    LOOP AT o_struct_descr->get_components( ) ASSIGNING FIELD-SYMBOL(<fs_comp2>).

      o_cell = o_doc->create_simple_element( name = 'Cell' parent = o_row_data ).

* nur elementare Datentypen zulassen, andernfalls gibts Exceptions bei der String-Konvertierung
* die Spalten mit kennzeichnung "DEEP" bleiben in der Ausgabe somit leer
      IF <fs_comp2>-type->kind = cl_abap_typedescr=>kind_elem.
        ASSIGN COMPONENT <fs_comp2>-name OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_cell>).

        IF <fs_cell> IS ASSIGNED.
          DATA: lv_data_type TYPE string.
          DATA(lv_typekind) = cl_abap_elemdescr=>get_data_type_kind( <fs_cell> ).

          CASE lv_typekind.
            WHEN cl_abap_typedescr=>typekind_time OR cl_abap_typedescr=>typekind_date OR cl_abap_typedescr=>typekind_string OR cl_abap_typedescr=>typekind_char.
              lv_data_type = 'String'.
            WHEN cl_abap_typedescr=>typekind_num OR cl_abap_typedescr=>typekind_packed OR cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_float.
              lv_data_type = 'Number'.
            WHEN OTHERS.
              lv_data_type = 'String'.
          ENDCASE.

          o_data = o_doc->create_simple_element( name = 'Data' value = |{ <fs_cell> }| parent = o_cell ).
          o_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = lv_data_type ).
        ENDIF.
      ENDIF.

    ENDLOOP.
  ENDLOOP.

* XML-Dokument rendern
  DATA(o_sf) = o_ixml->create_stream_factory( ).

  DATA: lv_xml TYPE string.

  DATA(o_stream) = o_sf->create_ostream_cstring( lv_xml ).
  o_stream->set_encoding( encoding = o_encoding ).
  o_stream->set_pretty_print( pretty_print = abap_true ).

  DATA(o_render) = o_ixml->create_renderer( ostream  = o_stream
                                            document = o_doc ).

* XML-String in lv_xml generieren
  DATA(lv_rc) = o_render->render( ).

* Dateigröße in Bytes
  DATA(lv_size) = o_stream->get_num_written_raw( ).

* Stream schließen
  o_stream->close( ).

  IF lv_rc = 0 AND lv_size > 0.
* XML-String in XML-Document wandeln
    DATA(o_xml_doc) = NEW cl_xml_document( ).
    o_xml_doc->parse_string( lv_xml ).

* Ausgabe-Datei, "\" müssen quotiert werden
    DATA(lv_fullpath) = |c:\\temp\\test.xml|.

* XML-Document als Datei speichern
    o_xml_doc->export_to_file( CONV #( lv_fullpath ) ).

* lokale Datei im Excel aufrufen
* parameter muss wegen möglicher Leerzeichen im Pfad mit "" quotiert werden
    cl_gui_frontend_services=>execute( application = 'excel.exe'
                                       parameter = |"{ lv_fullpath }"| ).
  ELSE.
    WRITE: / 'Fehler beim Erzeugen der XML-Datei.'.
  ENDIF.

[ABAP] XML-Daten in eine Datei (*.xml) schreiben

Variante 1 (lokal über XML-String)

* ixml Factory
  DATA(o_ixml) = cl_ixml=>create( ).

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* DOM Object Model
  DATA(o_doc) = o_ixml->create_document( ).

  ...

* XML-Dokument rendern
  DATA(o_sf) = o_ixml->create_stream_factory( ).

* XML-String
  DATA: lv_xml TYPE string.

* Stream für Ausgabe in XML-String
  DATA(o_stream) = o_sf->create_ostream_cstring( lv_xml ).
  o_stream->set_encoding( encoding = o_encoding ).
  o_stream->set_pretty_print( pretty_print = abap_true ).

* Render-Objekt
  DATA(o_render) = o_ixml->create_renderer( ostream  = o_stream
                                            document = o_doc ).

* XML-String in lv_xml generieren
  DATA(lv_rc) = o_render->render( ).

* Dateigröße in Bytes
  DATA(lv_size) = o_stream->get_num_written_raw( ).
  
* Stream schließen
  o_stream->close( ).

* Wenn alles ok
  IF lv_rc = 0 AND lv_size > 0.
  * XML-String in XML-Document wandeln
    DATA(o_xml_doc) = NEW cl_xml_document( ).
    o_xml_doc->parse_string( lv_xml ).

  * XML-Document als Datei speichern
    o_xml_doc->export_to_file( 'c:\temp\test.xml' ).
  ENDIF.

Variante 2 (lokal über XML-iTab)

* ixml Factory
  DATA(o_ixml) = cl_ixml=>create( ).

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* DOM Object Model
  DATA(o_doc) = o_ixml->create_document( ).

  ...

* XML-Dokument rendern
  DATA(o_sf) = o_ixml->create_stream_factory( ).

* XML-iTab
  DATA: it_xml_out TYPE STANDARD TABLE OF char255 WITH DEFAULT KEY.

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* Stream für Ausgabe in XML-iTab
  DATA(o_stream) = o_sf->create_ostream_itable( table = it_xml_out ).
  o_stream->set_encoding( encoding = o_encoding ).

* Render-Objekt
  DATA(o_render) = o_ixml->create_renderer( ostream  = o_stream
                                            document = o_doc ).

  o_render->set_normalizing( is_normalizing = space ).

* XML-String in it_xml_out generieren
  DATA(lv_rc) = o_render->render( ).

* Dateigröße in Bytes
  DATA(lv_size) = o_stream->get_num_written_raw( ).
  
* Stream schließen
  o_stream->close( ).

* Wenn alles ok
  IF lv_rc = 0 AND lv_size > 0.
* Tabelle als Binär-Daten herunterladen
    cl_gui_frontend_services=>gui_download( EXPORTING
                                              filename = 'c:\temp\test.xml'
                                              filetype = 'BIN'
                                              bin_filesize = lv_size
                                            CHANGING
                                              data_tab = it_xml_out ).
  ENDIF.

Variante 3 (Applikationsserver)

* ixml Factory
  DATA(o_ixml) = cl_ixml=>create( ).

* DOM Object Model
  DATA(o_doc) = o_ixml->create_document( ).
  
  ...
  
* XML-Dokument rendern
  DATA(o_sf) = o_ixml->create_stream_factory( ).

* Encoding UTF-8
  DATA(o_encoding) = o_ixml->create_encoding( character_set = 'UTF-8'
                                              byte_order = if_ixml_encoding=>co_none ).

* Stream für Ausgabe in Datei '/tmp/test/test.xml' auf dem Applikationsserver
  DATA(o_stream) = o_sf->create_ostream_uri( system_id = '/tmp/test/test.xml' ).
  o_stream->set_encoding( encoding = o_encoding ).
  o_stream->set_pretty_print( pretty_print = abap_true ).

* Render-Objekt
  DATA(o_render) = o_ixml->create_renderer( ostream  = o_stream
                                            document = o_doc ).

* XML-String in Datei auf Applikationsserver generieren
  DATA(lv_rc) = o_render->render( ).

* Dateigröße in Bytes
  DATA(lv_size) = o_stream->get_num_written_raw( ).
  
* Stream schließen
  o_stream->close( ).

* Wenn alles ok
  IF lv_rc = 0 AND lv_size > 0.
    ...
  ENDIF.