Search code examples
excelvbasap-guiactivation

How to activate workbook exported from SAP?


I have a macro to process data from SAP.

When the workbook from SAP appears I am not able to activate it via VBA code below.

Even Workbooks("export.xlsx").activate does not work.

session.findById("wnd[0]/tbar[0]/okcd").Text = "/nFBL3N"
session.findById("wnd[0]").sendVKey 0
session.findById("wnd[0]/usr/btn%_SD_SAKNR_%_APP_%-VALU_PUSH").press
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,0]").Text = "179811"
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,1]").Text = "431311"
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,1]").SetFocus
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,1]").caretPosition = 6
session.findById("wnd[1]/tbar[0]/btn[0]").press
session.findById("wnd[1]/tbar[0]/btn[8]").press
session.findById("wnd[0]/usr/radX_AISEL").Select
session.findById("wnd[0]/usr/ctxtSO_BUDAT-LOW").Text = "01.03.2020"
session.findById("wnd[0]/usr/ctxtSO_BUDAT-HIGH").Text = "31.03.2020"
session.findById("wnd[0]/usr/ctxtSO_BUDAT-HIGH").SetFocus
session.findById("wnd[0]/usr/ctxtSO_BUDAT-HIGH").caretPosition = 10
session.findById("wnd[0]/tbar[1]/btn[16]").press
session.findById("wnd[0]/usr/ssub%_SUBSCREEN_%_SUB%_CONTAINER:SAPLSSEL:2001/ssubSUBSCREEN_CONTAINER2:SAPLSSEL:2000/ssubSUBSCREEN_CONTAINER:SAPLSSEL:1106/ctxt%%DYN009-LOW").Text = "L6"
session.findById("wnd[0]/usr/ssub%_SUBSCREEN_%_SUB%_CONTAINER:SAPLSSEL:2001/ssubSUBSCREEN_CONTAINER2:SAPLSSEL:2000/ssubSUBSCREEN_CONTAINER:SAPLSSEL:1106/ctxt%%DYN009-LOW").SetFocus
session.findById("wnd[0]/usr/ssub%_SUBSCREEN_%_SUB%_CONTAINER:SAPLSSEL:2001/ssubSUBSCREEN_CONTAINER2:SAPLSSEL:2000/ssubSUBSCREEN_CONTAINER:SAPLSSEL:1106/ctxt%%DYN009-LOW").caretPosition = 2
session.findById("wnd[0]/tbar[1]/btn[8]").press
session.findById("wnd[0]/mbar/menu[0]/menu[3]/menu[1]").Select
session.findById("wnd[1]/tbar[0]/btn[11]").press

Set session = Nothing
Set Connection = Nothing
Set SapGuiAuto = Nothing
Set WScript = Nothing
Set Application = Nothing

Dim wb As Workbook
Windows("export.XLSX").Activate

Solution

  • In order to check the existence of the workbook in all open Excel sessions, please use the next code, as I will explain

    Firstly copy the next code on top of your module (in the declarations part):

    Option Explicit
    
    #If VBA7 Then
      Private Declare PtrSafe Function AccessibleObjectFromWindow Lib "oleacc" ( _
        ByVal hWnd As LongPtr, ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
    
      Private Declare PtrSafe Function FindWindowExA Lib "user32" ( _
        ByVal hwndParent As LongPtr, ByVal hwndChildAfter As LongPtr, _
        ByVal lpszClass As String, ByVal lpszWindow As String) As LongPtr
    #Else
      Private Declare Function AccessibleObjectFromWindow Lib "oleacc" ( _
        ByVal hwnd As Long, ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
    
      Private Declare Function FindWindowExA Lib "user32" ( _
        ByVal hwndParent As Long, ByVal hwndChildAfter As Long, _
        ByVal lpszClass As String, ByVal lpszWindow As String) As Long
    #End If
    

    Then, use the next function to be called from your existing code (instead of Windows("export.XLSX").Activate):

    Private Function GetExcelSes() As Collection
        Dim g&(0 To 3), ppv As Object, hWnd, hWnd2, hWnd3
        g(0) = &H20400: g(1) = &H0
        g(2) = &HC0:    g(3) = &H46000000
    
        Dim AlreadyThere As Boolean, Xl As Application
        Set GetExcelSes = New Collection
        Do
            hWnd = FindWindowExA(0, hWnd, "XLMAIN", vbNullString)
            If hWnd = 0 Then Exit Do
            hWnd2 = FindWindowExA(hWnd, 0, "XLDESK", vbNullString)
            hWnd3 = FindWindowExA(hWnd2, 0, "EXCEL7", vbNullString)
            If AccessibleObjectFromWindow(hWnd3, &HFFFFFFF0, g(0), ppv) = 0 Then
                AlreadyThere = False
                For Each Xl In GetExcelSes
                    If Xl Is ppv.Application Then
                        AlreadyThere = True
                        Exit For
                    End If
                Next
                If Not AlreadyThere Then
                    GetExcelSes.aDD ppv.Application
                End If
            End If
        Loop
    End Function
    

    The above function can be called as in the following example (use it like it is instead of your last code line). The declarations are important:

    Sub TestSaveAWbFromAllSess()
       Dim Ex As Collection, El As Variant
       Dim wb As Workbook, expWb As Workbook
       Set Ex = GetExcelSes
    
       For Each El In Ex
            For Each wb In El.Workbooks
                Debug.Print wb.Name 'just to see all open wb names, confirming that the function works...
                If UCase(wb.Name) = "EXPORT.XLSX" Then
                    Set expWb = wb
                    'Do here whatever you need with the found workbook. For instance:
                    expWb.SaveCopyAs fileName:=ThisWorkbook.path & "\TestSAPExport.XLSX"
                End If
            Next
       Next
    End Sub