Search code examples
multiple-instancessave-assap-guiexcel-365

How to connect to OPEN workbook in another instance of Excel SAP Issue


I tried to follow up with the topic here: How to connect to OPEN workbook in another instance of Excel

But I ran into a problem, I am not able grab the new instance name or path.

However I know I have open Excel window in another instance (opened from a SAP system) and when I open VBA editor in that SAP generated Excel file and I type: ? Thisworkbook.Path in immediate window I get nothing, no path is given and thus this solutions does not get the instance path.

What can I do to make it work ?

My issue is that this: Set xlApp = GetObject("C:\Tmp\TestData2.xlsx") is not grabbing the workbook name (including This.workbook.name or activeworkbook.name)

Any idea how else I can make VBA code in instance 1 work with workbook in instance 2?

I only want to save it nothing more, I'm using Saveas option, or at least I try.

Have anyone had a similar issue?


Solution

  • Working with the Excel files downloaded from SAP is always problematic.

    You can use the module below and add before the xls.Close SaveChanges:=False this line xls.SaveAs Filename:='Any name that you want after that just place a call in your code after downloading the Excel File with

    Call Close_SAP_Excel("TestData2.xlsx")

    And it should work fine.

    Module:

    #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
    
    Sub Close_SAP_Excel(ParamArray FileNames())
        'Procedure to close files downloaded from SAP and at the same time close the Excel application instance that will be open with them.
    
        Dim ExcelAppSAP As Variant
        Dim ExcelFile As Variant
        Dim FinishedLoop As Boolean, TimeoutReached As Boolean, FileClosed As Boolean
        Dim ReTry As Long
        Dim i As Long, x As Long
        
        Set ExcelAppSAP = Nothing
        ReTry = 100000 'Used as Timeout 100000 = ~10 seconds
        i = 1
        
        'The following loop is executed until excel file is closed.
        'Inside of this, there is a For Loop for each Excel Instance and inside of that is another loop
        'for each excel inside the instance. If name matches, it is closed.
        Do While Not FinishedLoop
            If i > ReTry Then
                TimeoutReached = True
                Exit Do
            End If
            
            For Each ExcelFile In GetExcelInstances() 'Function to Get Excel Open Instances
                For Each xls In ExcelFile.Workbooks
                    For x = LBound(FileNames()) To UBound(FileNames())
                        If xls.Name = FileNames(x) Then
                        
                            Set ExcelAppSAP = ExcelFile 'Set Instance opened by SAP to variable
                            'Here add actions if needed. Reference to workbook as xls e.g.: xls.Sheets(1).Range("A1").Copy
                            xls.Close SaveChanges:=False
                            FileClosed = True
                        
                        End If
                    Next x
                Next
            Next
            
            If FileClosed Then
                FinishedLoop = True
            End If
            i = i + 1
        Loop
        
        ThisWorkbook.Activate
    
        If Not TimeoutReached Then
            If FileClosed Then
                On Error Resume Next
                If ExcelAppSAP.Workbooks.Count = 0 Then
                    ExcelAppSAP.Quit
                End If
            Else
                MsgBox "Excel application instance from SAP was not closed correctly. Please close it manually or try again.", , "Error"
            End If
        Else
            MsgBox "Max timeout reached", , "Error"
        End If
    
    End Sub
         
    Public Function GetExcelInstances() As Collection
      Dim guid&(0 To 3), acc As Object, hwnd, hwnd2, hwnd3
      guid(0) = &H20400
      guid(1) = &H0
      guid(2) = &HC0
      guid(3) = &H46000000
    
      Set GetExcelInstances = 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, guid(0), acc) = 0 Then
          GetExcelInstances.Add acc.Application
        End If
      Loop
    End Function