vba - VBA 可以跨 Excel 实例吗?

标签 vba excel

在一个 Excel 实例中运行的 Excel VBA 宏能否访问另一个正在运行的 Excel 实例的工作簿?例如,我想创建在任何正在运行的 Excel 实例中打开的所有工作簿的列表。

最佳答案

科尼利厄斯的回答部分正确。他的代码获取当前实例,然后创建一个新实例。 GetObject 只获取第一个实例,无论有多少实例可用。我认为的问题是如何从众多实例中获取特定实例。

对于 VBA 项目,创建两个模块,一个是代码模块,另一个是带有一个名为 Command1 的命令按钮的窗体。您可能需要添加对 Microsoft.Excel 的引用。

此代码在“立即”窗口中显示每个正在运行的 Excel 实例的每个工作簿的所有名称。

'------------- Code Module --------------

Option Explicit

Declare Function FindWindowEx Lib "User32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Declare Function GetClassName Lib "User32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare Function IIDFromString Lib "ole32" (ByVal lpsz As Long, ByRef lpiid As UUID) As Long
Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As Long, ByVal dwId As Long, ByRef riid As UUID, ByRef ppvObject As Object) As Long

Type UUID 'GUID
  Data1 As Long
  Data2 As Integer
  Data3 As Integer
  Data4(7) As Byte
End Type

'------------- Form Module --------------

Option Explicit

Const IID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}"
Const OBJID_NATIVEOM As Long = &HFFFFFFF0

'Sub GetAllWorkbookWindowNames()
Sub Command1_Click()
    On Error GoTo MyErrorHandler

    Dim hWndMain As Long
    hWndMain = FindWindowEx(0&, 0&, "XLMAIN", vbNullString)

    Do While hWndMain <> 0
        GetWbkWindows hWndMain
        hWndMain = FindWindowEx(0&, hWndMain, "XLMAIN", vbNullString)
    Loop

    Exit Sub

MyErrorHandler:
    MsgBox "GetAllWorkbookWindowNames" & vbCrLf & vbCrLf & "Err = " & Err.Number & vbCrLf & "Description: " & Err.Description
End Sub

Private Sub GetWbkWindows(ByVal hWndMain As Long)
    On Error GoTo MyErrorHandler

    Dim hWndDesk As Long
    hWndDesk = FindWindowEx(hWndMain, 0&, "XLDESK", vbNullString)

    If hWndDesk <> 0 Then
        Dim hWnd As Long
        hWnd = FindWindowEx(hWndDesk, 0, vbNullString, vbNullString)

        Dim strText As String
        Dim lngRet As Long
        Do While hWnd <> 0
            strText = String$(100, Chr$(0))
            lngRet = GetClassName(hWnd, strText, 100)

            If Left$(strText, lngRet) = "EXCEL7" Then
                GetExcelObjectFromHwnd hWnd
                Exit Sub
            End If

            hWnd = FindWindowEx(hWndDesk, hWnd, vbNullString, vbNullString)
            Loop

        On Error Resume Next
    End If

    Exit Sub

MyErrorHandler:
    MsgBox "GetWbkWindows" & vbCrLf & vbCrLf & "Err = " & Err.Number & vbCrLf & "Description: " & Err.Description
End Sub

Public Function GetExcelObjectFromHwnd(ByVal hWnd As Long) As Boolean
    On Error GoTo MyErrorHandler

    Dim fOk As Boolean
    fOk = False

    Dim iid As UUID
    Call IIDFromString(StrPtr(IID_IDispatch), iid)

    Dim obj As Object
    If AccessibleObjectFromWindow(hWnd, OBJID_NATIVEOM, iid, obj) = 0 Then 'S_OK
        Dim objApp As Excel.Application
        Set objApp = obj.Application
        Debug.Print objApp.Workbooks(1).Name

        Dim myWorksheet As Worksheet
        For Each myWorksheet In objApp.Workbooks(1).Worksheets
            Debug.Print "     " & myWorksheet.Name
            DoEvents
        Next

        fOk = True
    End If

    GetExcelObjectFromHwnd = fOk

    Exit Function

MyErrorHandler:
    MsgBox "GetExcelObjectFromHwnd" & vbCrLf & vbCrLf & "Err = " & Err.Number & vbCrLf & "Description: " & Err.Description
End Function

关于vba - VBA 可以跨 Excel 实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2971473/

相关文章:

c# - Excel 求解器 : Non linear least squares equivalent in C#

excel - Application.CommandBars.ExecuteMso ("PasteSourceFormatting") 在 powerpoint 中不起作用

windows - VBA - Windows 和 OSX 中的用户名

excel - VBA Shapes.AddTextbox 方法

c# - 使用 C# 中的 Open Xml SDK 将 DataTable 导出到 Excel

vba - VBA Transpose 数组长度限制的最佳解决方法?

excel - 如何使用 Excel VBA 从已关闭的工作簿中读取元数据信息?

VBA UDF 返回数组

excel - 将字符串转换为 Excel 日期和时间,具有特定的字符串格式

c# - EPPlus - 按索引而不是按字母顺序处理多列