[ABAP] Text zu Wert in einem Datenbankfeld auslesen

Variante 1 (einzelner Feldwert)

DATA: lv_text TYPE text255.
DATA: lv_found TYPE flag_x.
DATA: it_identifier TYPE txid_t_text_identifier_result.

TRY.
    DATA(o_text) = NEW cl_text_identifier( ).
* Text für EBAN-STATU zu Feldwert 'B' holen
    o_text->read_text( EXPORTING
                         tabname    = 'EBAN'   " Tabelle
                         fieldname  = 'STATU'  " Feld
                         fieldvalue = 'B'      " Feldwert
                       IMPORTING
                         text                    = lv_text
                         text_for_value_read     = lv_found
                         text_identifier_results = it_identifier ).

    IF lv_found = abap_true.
* gefundenen Text ausgeben
      WRITE: / lv_text.

      LOOP AT it_identifier ASSIGNING FIELD-SYMBOL(<i>).
        WRITE: / <i>-tabname, <i>-fieldname, <i>-fieldvalue, <i>-text.
      ENDLOOP.
    ENDIF.
  CATCH cx_root INTO DATA(e_txt).
    WRITE: / e_txt->get_text( ).
ENDTRY.

Variante 2 (Datensatz)

PARAMETERS: p_banf TYPE eban-banfn OBLIGATORY.

START-OF-SELECTION.
* Datensatz holen
  DATA: lv_eban TYPE eban.
  SELECT SINGLE * FROM eban INTO lv_eban WHERE banfn EQ p_banf.

  IF sy-subrc = 0.
    DATA: lv_text TYPE text255.
    DATA: lv_found TYPE flag_x.
    DATA: it_identifier TYPE txid_t_text_identifier_result.

    TRY.
* Datensatz: Text zu Feld 'STATU' holen
        DATA(o_text) = NEW cl_text_identifier( ).
        o_text->read_text( EXPORTING
                             tabname          = 'EBAN'    " Tabelle
                             fieldname        = 'STATU'   " Feld
                             record           = lv_eban   " Struktur mit Wert für EBAN-STATU
                             record_specified = abap_true
                           IMPORTING
                             text                    = lv_text
                             text_for_value_read     = lv_found
                             text_identifier_results = it_identifier ).

        IF lv_found = abap_true.
* gefundenen Text ausgeben
          WRITE: / lv_text.

          LOOP AT it_identifier ASSIGNING FIELD-SYMBOL(<i>).
            WRITE: / <i>-tabname, <i>-fieldname, <i>-fieldvalue, <i>-text.
          ENDLOOP.
        ENDIF.
      CATCH cx_root INTO DATA(e_txt).
        WRITE: / e_txt->get_text( ).
    ENDTRY.
  ENDIF.

[SAP] SAP GUI Scripting per VBA

Voraussetzungen

  • System ab SAP NW 6.2
    • Präsentationsserver: SAP Menu (SAP Easy Access) -> Button „Lokales Layout anpassen“ -> Optionen… -> Barrierefreiheit und Scripting -> Skiptunterstützung aktivieren, die anderen Haken deaktivieren
    • Applikationsserver: Profilparameter: RZ11 -> Parameter sapgui/user_scripting = TRUE (in Großbuchstaben!) -> gilt nur ab dem nächsten Login und bis Serverneustart
      • weitere Profilparameter:
        • sapgui/user_scripting must be TRUE to use scripting functions
        • sapgui/user_scripting_disable_recording if it is TRUE then it is only possible to run scripts
        • sapgui/user_scripting_force_notification if it is TRUE a notification is always displayed at the frontend
        • sapgui/user_scripting_per_user if it is TRUE you need S_SCR authority to use scripting
        • sapgui/user_scripting_set_readonly if it is TRUE it is not allowed to change the state of SAP GUI

Skriptaufzeichnung und Hilfe

  • SAP Menu (SAP Easy Access) -> Button „Lokales Layout anpassen“ -> Skript-Aufzeichnung und -Playback
  • SAP Menu (SAP Easy Access) -> Button „Lokales Layout anpassen“ -> Hilfe zu SAP GUI Scripting

OCX-Bibliothek für VBA

  • VBA-Import über: Extras -> Verweise … -> Durchsuchen …
  • C:\Program Files\SAP\FrontEnd\SAPgui\sapfewse.ocx
    oder
    C:\Apps32\SAP\FrontEnd\SAPgui\sapfewse.ocx
  • Aktivieren: SAP GUI Scripting API

Windows Scripting Host (x64)

  • C:\Windows\SysWOW64\wscript.exe
  • Ausführen von vbs-Scripten: C:\Windows\SysWOW64\wscript.exe c:\test.vbs

Beispiel 1 (Alle Connections, Sessions, GUI-Elemente auflisten)

Option Explicit

Sub SAP()
    Dim oSapGui As Object
    ' Extras -> Verweise ... -> Durchsuchen ...
    ' C:\Program Files\SAP\FrontEnd\SAPgui\sapfewse.ocx
    ' Aktivieren: SAP GUI Scripting API
    Dim oApp As SAPFEWSELib.GuiApplication
    Dim oConn As SAPFEWSELib.GuiConnection
    Dim oSession As SAPFEWSELib.GuiSession
    Dim oSessionInfo As SAPFEWSELib.GuiSessionInfo
    Dim oWindow As SAPFEWSELib.GuiMainWindow
    Dim oComponent As SAPFEWSELib.GuiComponent
    Dim oSubComponent As SAPFEWSELib.GuiComponent
    
    Debug.Print "----------"
    
    ' Ref auf SAPGUI
    Set oSapGui = GetObject("SAPGUI")
    If IsObject(oSapGui) Then
        ' Ref auf ScriptingEngine
        Set oApp = oSapGui.GetScriptingEngine
        If IsObject(oApp) Then
            
            Debug.Print oApp.ID
            Debug.Print oApp.Name
            
            ' Liste Connections
            For Each oConn In oApp.Children
                Debug.Print "|--" & oConn.ConnectionString
                Debug.Print "|  " & oConn.Description
                Debug.Print "|  " & oConn.ID
                Debug.Print "|  " & oConn.Name
                
                ' Sessions sind nur verfügbar, wenn RZ11 Parameter sapgui/user_scripting = TRUE
                ' Liste Sessions
                For Each oSession In oConn.Children
                    Debug.Print "  |--" & oSession.ID
                    Debug.Print "  |  " & oSession.Busy
                    
                    ' Ref auf Session Info
                    Set oSessionInfo = oSession.Info
                    
                    If IsObject(oSessionInfo) Then
                        Debug.Print "    |--" & oSessionInfo.SystemSessionId
                        Debug.Print "    |  " & oSessionInfo.ApplicationServer
                        Debug.Print "    |  " & oSessionInfo.SystemName
                        Debug.Print "    |  " & oSessionInfo.Client
                        Debug.Print "    |  " & oSessionInfo.Transaction
                        Debug.Print "    |  " & oSessionInfo.User
                    End If
                    
                    ' Ref auf Fenster
                    For Each oWindow In oSession.Children
                        Debug.Print "      |--" & oWindow.ID
                        Debug.Print "      |  " & oWindow.Text
                        Debug.Print "      |  " & oWindow.Left
                        Debug.Print "      |  " & oWindow.Top
                        Debug.Print "      |  " & oWindow.Width
                        Debug.Print "      |  " & oWindow.Height
                        
                        ' Liste mit Komponenten im Fenster
                        For Each oComponent In oWindow.Children
                            Debug.Print "        |--" & oComponent.ID
                            Debug.Print "        |  " & oComponent.Name
                            Debug.Print "        |  " & oComponent.Type
                            Debug.Print "        |  " & oComponent.ContainerType
                            
                            ' Liste mit Unterkomponenten (können wiederum auch Unterkomponenten haben -> besser rekursiv aufrufen)
                            For Each oSubComponent In oComponent.Children
                                Debug.Print "          |--" & oSubComponent.ID
                                Debug.Print "          |  " & oSubComponent.Name
                                Debug.Print "          |  " & oSubComponent.Type
                                Debug.Print "          |  " & oSubComponent.ContainerType
                            Next
                        Next
                    Next
                Next
            Next
        End If
    End If
    
    Set oSubComponent = Nothing
    Set oComponent = Nothing
    Set oWindow = Nothing
    Set oSessionInfo = Nothing
    Set oSession = Nothing
    Set oConn = Nothing
    Set oApp = Nothing
    Set oSapGui = Nothing
End Sub

Beispiel 2 (Transaktion SE16 starten und Inhalt des ALV-Grids in Excel kopieren)

Option Explicit

Sub SAP()
    Dim oSapGui As Object
    ' Extras -> Verweise ... -> Durchsuchen ...
    ' C:\Program Files\SAP\FrontEnd\SAPgui\sapfewse.ocx
    ' Aktivieren: SAP GUI Scripting API
    Dim oApp As SAPFEWSELib.GuiApplication
    Dim oConn As SAPFEWSELib.GuiConnection
    Dim oSession As SAPFEWSELib.GuiSession
      
    ' Ref auf SAPGUI
    Set oSapGui = GetObject("SAPGUI")
    If IsObject(oSapGui) Then
        ' Ref auf ScriptingEngine
        Set oApp = oSapGui.GetScriptingEngine
        If IsObject(oApp) Then
            ' Sind Connections vorhanden?
            If oApp.Children.Count > 0 Then
                ' 1. Connection der App
                Set oConn = oApp.Children(0)
                ' 1. Session der Connection
                Set oSession = oConn.Children(0)
                
                ' Fenster minimieren
                oSession.FindById("wnd[0]").Iconify
                
                ' SE16 starten
                oSession.StartTransaction ("SE16")
                               
                ' Selektionsbild
                ' Tabelle MARA
                oSession.FindById("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").Text = "MARA"
                ' Button "Tabelleninhalt (F7)"
                oSession.FindById("wnd[0]/tbar[1]/btn[7]").Press
                ' max. 10 Einträge
                oSession.FindById("wnd[0]/usr/txtMAX_SEL").Text = "10"
                ' Button "Ausführen (F8)"
                oSession.FindById("wnd[0]/tbar[1]/btn[8]").Press
                
                ' ALV-Ansicht aktivieren
                ' Menü suchen
                Dim oMenu As GuiComponent
                Set oMenu = oSession.FindById("wnd[0]/mbar")
                
                ' Menüpunkt "Einstellungen"
                Dim oOptions As GuiComponent
                Set oOptions = oMenu.FindByName("Einstellungen", "GuiMenu")
                
                ' Menüpunkt "Benutzerparameter ..."
                Dim oUserPar As GuiComponent
                Set oUserPar = oOptions.FindByName("Benutzerparameter...", "GuiMenu")
                oUserPar.Select
                
                ' Databrowser -> Ausgabeliste -> ALV-Grid-Darstellung
                Dim oALVParam As GuiComponent
                Set oALVParam = oSession.FindById("wnd[1]/usr/tabsG_TABSTRIP/tabp0400/ssubTOOLAREA:SAPLWB_CUSTOMIZING:0400/radRSEUMOD-TBALV_GRID")
                
                ' wenn ALV-Ansicht noch nicht ausgewählt, dann anhaken
                If oALVParam.Selected = vbFalse Then
                    oALVParam.Select
                End If
                
                ' Einstellungen übernehmen
                oSession.FindById("wnd[1]/tbar[0]/btn[0]").Press
                
                Set oUserPar = Nothing
                Set oOptions = Nothing
                Set oMenu = Nothing
                
                ' ALV-Grid holen
                Dim oALV As GuiComponent
                Set oALV = oSession.FindById("wnd[0]/usr/cntlGRID1/shellcont/shell")
                
                ' Zeilen
                Dim iRows As Integer
                iRows = oALV.RowCount() - 1
                ' Spalten
                Dim iCols As Integer
                iCols = oALV.ColumnCount() - 1
                
                ' Spaltentitel lesen
                Dim oColumns
                Set oColumns = oALV.ColumnOrder
                
                Dim c As Integer
                Dim r As Integer
                
                ' Überschriften einfügen
                For c = 0 To iCols
                    ActiveWorkbook.ActiveSheet.Cells(1, c + 1) = oColumns(c)
                Next
                
                ' Daten einfügen
                For r = 0 To iRows
                
                    ' ALV-Grid weiterscrollen, damit ein Update des Inhalts erfolgt
                    oALV.FirstVisibleRow = r
                    
                    For c = 0 To iCols
                        ActiveWorkbook.ActiveSheet.Cells(r + 2, c + 1) = oALV.GetCellValue(r, CStr(oColumns(c)))
                    Next
                Next
                
                ' Fenster maximieren
                oSession.FindById("wnd[0]").Maximize
            Else
                MsgBox "Bitte an einem SAP-System anmelden."
            End If
        End If
    End If
    
    Set oSession = Nothing
    Set oConn = Nothing
    Set oApp = Nothing
    Set oSapGui = Nothing
End Sub

Beispiel 3 (System-Logon)

Option Explicit

Sub SAP()
    Dim oSapGui As Object
       
    ' Extras -> Verweise ... -> Durchsuchen ...
    ' C:\Program Files\SAP\FrontEnd\SAPgui\sapfewse.ocx
    ' Aktivieren: SAP GUI Scripting API
    Dim oApp As SAPFEWSELib.GuiApplication
    Dim oConn As SAPFEWSELib.GuiConnection
    Dim oSession As SAPFEWSELib.GuiSession
      
    ' Ref auf SAPGUI
    Set oSapGui = GetObject("SAPGUI")
    If IsObject(oSapGui) Then
        ' Ref auf ScriptingEngine
        Set oApp = oSapGui.GetScriptingEngine
        If IsObject(oApp) Then

            ' Zu System verbinden, wobei <SYSTEM> == vollst. (!) Systemname aus SAP Logon Pad -> Verbindungen
            Set oConn = oApp.OpenConnection("<SYSTEM>")

            If IsObject(oConn) Then
                ' 1. Session der Connection
                Set oSession = oConn.Children(0)
  
                ' Username und Passwort setzen
                oSession.FindById("wnd[0]/usr/txtRSYST-BNAME").Text = "<USER>"
                oSession.FindById("wnd[0]/usr/pwdRSYST-BCODE").Text = "<PASS>"
                ' Enter-Taste
                oSession.FindById("wnd[0]").SendVKey 0
  
                ' SE16 starten
                oSession.StartTransaction ("SE16")
            End If
        End If
    End If
    
    Set oSession = Nothing
    Set oConn = Nothing
    Set oApp = Nothing
    Set oSapGui = Nothing
End Sub

Links

[ABAP] Spoolaufträge (OTF, OTFHPL2, SMART, LIST, TEXT) in PDF wandeln

Variante 1 (cl_rspo_spoolid_to_pdf)

* Nr. des Spoolauftrags
PARAMETERS: p_spool TYPE rspoid OBLIGATORY.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_spool.

  SELECT rqident, rqtitle, rqdest, rqpaper, rqdoctype
    INTO TABLE @DATA(it_spool)
    FROM tsp01
    ORDER BY rqident.

  DATA: it_return TYPE TABLE OF ddshretval.

* eigene Suuchhilfe für Auswahl der Spooljobs anzeigen
  CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      retfield        = 'RQIDENT'     " Spalte der internen Tabelle bei value_tab
      dynpprog        = sy-repid
      dynpnr          = sy-dynnr
      dynprofield     = 'P_SPOOL'     " Name des Dynpro-Feldes für die automatische Werterückgabe
      value_org       = 'S'           " Werteübergabe: C: zellenweise, S: strukturiert
      window_title    = 'Auswahl'
    TABLES
      value_tab       = it_spool      " Übergabe-Tabelle mit Werten für die Anzeige und Auswahl
      return_tab      = it_return     " Rückgabe-Tabelle mit den ausgewählten (geklickten) Elementen
    EXCEPTIONS
      parameter_error = 1
      no_values_found = 2
      OTHERS          = 3.

  IF sy-subrc = 0.
    IF lines( it_return ) > 0.
      MESSAGE it_return[ 1 ]-fieldval TYPE 'S'.
    ENDIF.
  ENDIF.

START-OF-SELECTION.
  TRY.
      DATA: lv_xstring_pdf TYPE xstring.
      DATA: lv_size TYPE int4.
      DATA: lv_jobname TYPE btcjob.
      DATA: lv_jobcount TYPE btcjobcnt.

* SPOOL-ID -> PDF
      cl_rspo_spoolid_to_pdf=>get_spool_pdf( EXPORTING
                                               iv_rqident       = p_spool
                                               iv_no_background = abap_true
                                             IMPORTING
                                               ev_pdf           = lv_xstring_pdf
                                               ev_size          = lv_size
                                               ev_jobname       = lv_jobname
                                               ev_jobcount      = lv_jobcount
                                           ).

      WRITE: / 'Size:', lv_size.
      WRITE: / 'Jobname:', lv_jobname.
      WRITE: / 'Jobcount', lv_jobcount.

      DATA: lv_action TYPE i.
      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_file_name = 'test.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.

* xstring -> solix
        DATA(it_raw_data) = cl_bcs_convert=>xstring_to_solix( lv_xstring_pdf ).

* PDF lokal speichern
        cl_gui_frontend_services=>gui_download( EXPORTING
                                                  filename     = lv_fullpath
                                                  filetype     = 'BIN'
                                                  bin_filesize = lv_size
                                                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).
  ENDTRY.

Variante 2 (CONVERT_OTFSPOOLJOB_2_PDF, CONVERT_ABAPSPOOLJOB_2_PDF)

* Nr. des Spoolauftrags
PARAMETERS: p_spool TYPE rspoid OBLIGATORY.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_spool.

  DATA: it_return TYPE TABLE OF ddshretval.

  SELECT rqident, rqtitle, rqdest, rqpaper, rqdoctype
    INTO TABLE @DATA(it_spool)
    FROM tsp01
    ORDER BY rqident.

* eigene Suuchhilfe für Auswahl der Spooljobs anzeigen
  CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      retfield        = 'RQIDENT'     " Spalte der internen Tabelle bei value_tab
      dynpprog        = sy-repid
      dynpnr          = sy-dynnr
      dynprofield     = 'P_SPOOL'     " Name des Dynpro-Feldes für die automatische Werterückgabe
      value_org       = 'S'           " Werteübergabe: C: zellenweise, S: strukturiert
      window_title    = 'Auswahl'
    TABLES
      value_tab       = it_spool      " Übergabe-Tabelle mit Werten für die Anzeige und Auswahl
      return_tab      = it_return     " Rückgabe-Tabelle mit den ausgewählten (geklickten) Elementen
    EXCEPTIONS
      parameter_error = 1
      no_values_found = 2
      OTHERS          = 3.

  IF sy-subrc = 0.
    IF lines( it_return ) > 0.
      MESSAGE it_return[ 1 ]-fieldval TYPE 'S'.
    ENDIF.
  ENDIF.

START-OF-SELECTION.

  SELECT SINGLE rqclient, rqo1name
    INTO @DATA(lv_tsp01_sel)
    FROM tsp01
    WHERE rqident = @p_spool.

  IF sy-subrc = 0.
* Dummys für Aufruf von RSPO_RETURN_SPOOLJOB
    DATA: it_otf TYPE STANDARD TABLE OF soli.
    DATA: it_pdf TYPE STANDARD TABLE OF tline.

* Beispiel: Spooljob als iTabs holen
    CALL FUNCTION 'RSPO_RETURN_SPOOLJOB'
      EXPORTING
        rqident              = p_spool
        desired_type         = 'RAW' " RAW, ALI, OTF, PDF
      TABLES
        buffer               = it_otf
        buffer_pdf           = it_pdf
      EXCEPTIONS
        no_such_job          = 1
        job_contains_no_data = 2
        selection_empty      = 3
        no_permission        = 4
        can_not_access       = 5
        read_error           = 6
        type_no_match        = 7
        OTHERS               = 8.

    IF sy-subrc <> 0.
      WRITE: 'Spoolauftrag nicht vorhanden: ', sy-subrc.
    ELSE.
      SELECT SINGLE rqdoctype FROM tsp01 INTO @DATA(lv_objtype) WHERE rqident = @p_spool.

      IF sy-subrc <> 0.
        WRITE: 'Fehler beim Lesen des Doctypes.', sy-subrc.
      ELSE.
        DATA: lv_numbytes TYPE i.
        DATA: lv_pdfspoolid LIKE tsp01-rqident.
        DATA: lv_jobname TYPE tbtcjob-jobname.
        DATA: lv_jobcount TYPE tbtcjob-jobcount.
        DATA: lv_xstring_pdf TYPE xstring.

* Konvertierung anhand des Typs vornehmen
* OTF, SMART
        CASE lv_objtype.
          WHEN 'OTF' OR 'OTFHPL2' OR 'SMART'.
            CALL FUNCTION 'CONVERT_OTFSPOOLJOB_2_PDF'
              EXPORTING
                src_spoolid              = p_spool
                no_dialog                = abap_true
                pdf_destination          = 'X' " xstring
                no_background            = abap_false
              IMPORTING
                pdf_bytecount            = lv_numbytes
                pdf_spoolid              = lv_pdfspoolid
                btc_jobname              = lv_jobname
                btc_jobcount             = lv_jobcount
                bin_file                 = lv_xstring_pdf
              EXCEPTIONS
                err_no_otf_spooljob      = 1
                err_no_spooljob          = 2
                err_no_permission        = 3
                err_conv_not_possible    = 4
                err_bad_dstdevice        = 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.

            IF sy-subrc <> 0.
              WRITE: / 'Fehler bei der OTF->PDF Konvertierung:', sy-subrc.
            ELSE.

            ENDIF.
* ALI
          WHEN 'LIST' OR 'TEXT'.
            CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
              EXPORTING
                src_spoolid              = p_spool
                no_dialog                = abap_true
                pdf_destination          = 'X' " xstring
                no_background            = abap_false
              IMPORTING
                pdf_bytecount            = lv_numbytes
                pdf_spoolid              = lv_pdfspoolid
                btc_jobname              = lv_jobname
                btc_jobcount             = lv_jobcount
                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.

            IF sy-subrc <> 0.
              WRITE: / 'Fehler bei der TEXT->PDF Konvertierung: ', sy-subrc.
            ELSE.

            ENDIF.

          WHEN 'ADSP'.
            WRITE: / 'Adobe Forms derzeit nicht implementiert.'.
          WHEN OTHERS.
            WRITE: / 'Verarbeitungsschritt derzeit nicht implementiert:', lv_objtype.
        ENDCASE.

* wenn erfolgreich -> PDF speichern
        IF lv_numbytes > 0 AND xstrlen( lv_xstring_pdf ) > 0.
          DATA: lv_action TYPE i.
          DATA: lv_filename TYPE string.
          DATA: lv_fullpath TYPE string.
          DATA: lv_path TYPE string.

          TRY.
* SaveDialog
              cl_gui_frontend_services=>file_save_dialog( EXPORTING
                                                            default_file_name = |{ p_spool }|
                                                            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.
* xstring -> solix
                DATA(it_raw_data) = cl_bcs_convert=>xstring_to_solix( lv_xstring_pdf ).

* PDF lokal speichern
                cl_gui_frontend_services=>gui_download( EXPORTING
                                                          filename     = lv_fullpath
                                                          filetype     = 'BIN'
                                                          bin_filesize = lv_numbytes
                                                        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_text).          " Oberklasse für Exceptions abfangen und Kurztext übergeben
              WRITE: / e_text->get_text( ).
          ENDTRY.

        ENDIF.
      ENDIF.
    ENDIF.
  ELSE.
    WRITE: / |Spoolauftrag { p_spool } nicht vorhanden.|.
  ENDIF.