[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

[MS Excel] BAPI-Zugriff aus Excel (VBA) heraus

Option Explicit

Sub GetMATNR()
    ' Verbindung zu SAP herstellen
    Dim oSAP As Object
    Set oSAP = CreateObject("SAP.Functions")
    ' Verbindungsdaten vorbelegen
    oSAP.Connection.ApplicationServer = "1.1.1.1" ' IP des Appl-Servers (SM51->Details)
    oSAP.Connection.SystemNumber = "01"           ' Systemnummer, meißt im Namen des Appl-Servers enthalten
    oSAP.Connection.System = "XD1"                ' Entwicklungs-, Test-, Produktivsystem
    oSAP.Connection.Client = "100"                ' Mandant
    oSAP.Connection.Language = "DE"               ' Sprache "EN", "DE" ...
    
    ' RFC-Login: Logon-Fenster anzeigen
    If oSAP.Connection.Logon(0, False) = True Then
        ' BAPI_MATERIAL_GET_DETAIL abfragen
        Dim oFuBa As Object
        Set oFuBa = oSAP.Add("BAPI_MATERIAL_GET_DETAIL")
        
        ' EXPORTING
        Dim e_material As Variant
        Set e_material = oFuBa.Exports("MATERIAL")
        e_material.Value = ActiveWorkbook.ActiveSheet.Cells(1, 2) ' MATNR in B1
        
        ' IMPORTING
        Dim i_material_general_data As Variant
        Set i_material_general_data = oFuBa.Imports("MATERIAL_GENERAL_DATA")
        
        Dim i_return As Variant
        Set i_return = oFuBa.Imports("RETURN")
        
        ' Wenn Fuba-Aufruf ok
        If oFuBa.Call = True Then
            ' RETURN auswerten
            If i_return.Value("TYPE") = "E" Then
                ' Bei Fehler: Fehlermessage ausgeben in B2
                ActiveWorkbook.ActiveSheet.Cells(2, 2) = i_return.Value("MESSAGE")
            Else
                ' Wenn OK: Materialkurztext in B2
                ActiveWorkbook.ActiveSheet.Cells(2, 2) = i_material_general_data.Value("MATL_DESC")
            End If
        End If
    End If
End Sub

[ABAP] Excel-Daten in interne Tabelle einlesen

* alternative Funktionsbausteine:
* ALSM_EXCEL_TO_INTERNAL_TABLE -> nur Zellen mit 32 Zeichen Länge
* KCD_EXCEL_OLE_TO_INT_CONVERT -> nur Zellen mit 50 Zeichen Länge
* UPLOAD_XLS_FILE_2_ITAB
* FILE_READ_AND_CONVERT_SAP_DATA
* IMPORT_FROM_SPREADSHEET

TYPES: BEGIN OF ty_data,
         name    TYPE char255,
         gewicht TYPE f,
       END OF ty_data.

DATA: it_raw TYPE truxs_t_text_data.

PARAMETERS: p_file TYPE file_table-filename OBLIGATORY.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  DATA: lv_rc TYPE i.
  DATA: it_files TYPE filetable.
  DATA: lv_action TYPE i.

* File-Tabelle leeren, da hier noch alte Einträge von vorherigen Aufrufen drin stehen können
  CLEAR it_files.

* FileOpen-Dialog aufrufen
  TRY.
      cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                    file_filter = |TXT (*.txt)\|*.txt\|XLS (*.xls)\|*.xls\|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
          p_file = it_files[ 1 ]-filename.
        ENDIF.
      ENDIF.

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

START-OF-SELECTION.

  DATA: it_datatab TYPE STANDARD TABLE OF ty_data.

* Import von Excel-Daten in interne Tabelle über die Ole-Schnittstelle
* Format der Tabelle ist in ty_data definiert
* Unterstützte Dateiformate: *.csv (*.txt), *.xls, *.xlsx
* Das Format der Fließkommazahlen bei CSV muß dem Gebietsschema
* von Excel entsprechen: 1,23 (Dezimalseparator = ',')
  CALL FUNCTION 'TEXT_CONVERT_XLS_TO_SAP'
    EXPORTING
      i_field_seperator    = ';'                            " Trennzeichen für CSV-Datei
      i_line_header        = abap_true                      " Überschrift in der Tabelle
      i_tab_raw_data       = it_raw
      i_filename           = CONV rlgrap-filename( p_file ) " i_filename -> nur 128 Zeichen für Dateinamenlänge erlaubt
    TABLES
      i_tab_converted_data = it_datatab
    EXCEPTIONS
      conversion_failed    = 1
      OTHERS               = 2.

  IF sy-subrc = 0.
    LOOP AT it_datatab ASSIGNING FIELD-SYMBOL(<fs_line>).
      WRITE: / <fs_line>-name, <fs_line>-gewicht.
    ENDLOOP.
  ELSE.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

Weiterführende Infos: Link