Как сделать экземпляр Excel видимым, если нет открытых книг, использующих VBA - PullRequest
0 голосов
/ 21 апреля 2020

У меня запущено несколько экземпляров Excel, может быть до 4 экземпляров. Один из них (назовем в примере A) обычно не имеет открытой рабочей книги. Он используется одним из других экземпляров (назовем его экземпляром B), чтобы открыть книгу в экземпляре A, добавить, изменить данные, затем сохранить и закрыть эту книгу, таким образом, возвращается экземпляр, где эти изменения вносятся (экземпляр A) в состояние, когда нет открытых рабочих книг. Я делаю это так, потому что это намного быстрее, чем когда рабочая книга с кодом (экземпляр B) открывает рабочую книгу, выполняет эти задачи и затем закрывает рабочую книгу.

Моя проблема заключается в следующем: время от времени, в основном для целей отладки желательно сделать экземпляр A видимым, но я обнаружил, что экземпляр без открытой рабочей книги нельзя сделать видимым, или, по крайней мере, на этом я и заключаю. Я использую Excel 2016, 64 бит. Мой код для этого:

Private Sub cmdMakeSelectionVisible_Click()


Dim strng As String
Dim lCol As Long, lRow As Long
Dim oXLApp As Excel.Application
Dim bFoundInstance As Boolean
Dim wb_Actress As Workbook

With Me.lstXL '<--| refer to your listbox: change "ListBox1" with your actual listbox name
    For lRow = 0 To .ListCount - 1 '<--| loop through listbox rows
        If .Selected(lRow) Then '<--| if current row selected
            For lCol = 0 To .ColumnCount - 1 '<--| loop through listbox columns
                strng = strng & .List(lRow, lCol) & " | " '<--| build your output string

                If lCol = 1 Then
                    MsgBox .List(lRow, lCol)
                    bFoundInstance = GetReferenceToXLApp(.List(lRow, lCol), oXLApp)
                    MsgBox oXLApp.Caption
                    Set wb_Actress = oXLApp.Workbooks.Open("T:\-1996\Dummy Performer's Book.xlsm")
                    oXLApp.Visible = True
                    wb_Actress.Close
                End If

            Next lCol
            MsgBox "you selected" & vbCrLf & Left(strng, (Len(strng) - 1)) '<--| show output string (after removing its last character ("|"))
            Exit For '<-_| exit loop
        End If
    Next lRow
End With
End Sub

Внутри циклов For есть оператор If и в этом операторе If, если рассматриваемый экземпляр открывает рабочую книгу, то код работает. Если экземпляр не открывает рабочую книгу и не содержит дочерних элементов, он не работает. Если в этот момент я проверяю, имеет ли значение oXApp.Visible значение true, это правда, но экземпляр остается скрытым.

Вопрос в том, можно ли обойти это без открытия книги, сделать экземпляр видимым а потом закрывать книгу? Я все еще считаю себя новичком, когда дело доходит до VBA. Может быть совершенно другой подход, кроме использования дескриптора для нужного экземпляра.

Спасибо за внимание и помощь.

Редактировать:

Код для GetReferenceToXLApp:

    Public Function GetReferenceToXLApp(hWndXL As Long, oXLApp As Object) As Boolean

Dim hWinDesk         As Long
Dim hWin7            As Long

Dim obj              As Object
Dim iID              As GUID

'// Rather than explaining, go read
'// http://msdn.microsoft.com/en-us/library/windows/desktop/ms687262(v=vs.85).aspx
Call IIDFromString(StrPtr(IID_IDispatch), iID)

'// We have the XL App (Class name XLMAIN)
'// This window has a child called 'XLDESK' (which I presume to mean 'XL desktop')
'// XLDesk is the container for all XL child windows....
hWinDesk = FindWindowEx(hWndXL, 0&, "XLDESK", vbNullString)

'// EXCEL7 is the class name for a Workbook window (and probably others, as well)
'// This is used to check there is actually a workbook open in this instance.
hWin7 = FindWindowEx(hWinDesk, 0&, "EXCEL7", vbNullString)

'// Deep API... read up on it if interested.
'// http://msdn.microsoft.com/en-us/library/windows/desktop/dd317978(v=vs.85).aspx
If AccessibleObjectFromWindow(hWin7, OBJID_NATIVEOM, iID, obj) = RETURN_OK Then
    Set oXLApp = obj.Application
    GetReferenceToXLApp = True
End If

End Function    

А

Private Declare PtrSafe Function IIDFromString Lib "ole32" _
(ByVal lpsz As LongPtr, ByRef lpiid As GUID) As Long

А

Private Declare PtrSafe Function FindWindowEx Lib "User32" Alias "FindWindowExA" _
(ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long

1 Ответ

0 голосов
/ 21 апреля 2020

Кажется, работает ...

Dim oApp As Excel.Application


Sub TT()

    Set oApp = New Excel.Application
    'oApp.Workbooks.Add
    oApp.Visible = True

    Debug.Print oApp.HWnd, Application.HWnd
    Debug.Print oApp.Caption, Application.Caption

    Application.Wait Now + TimeSerial(0, 0, 2)
    AppActivate Application.Caption

    Application.Wait Now + TimeSerial(0, 0, 2)
    AppActivate oApp.Caption

End Sub
...