1

我已经使用 VBA 几年了,但我正在切换到 VB 以利用更强大的编码实践。

我有以下 VB 代码将 Excel 工作簿附加到打开的实例:

Dim FullFilePath as String = "C:\Temp"
Dim WrkBk = as Excel.Workbook
WrkBk = System.Runtime.InteropServices.Marshal.BindToMoniker(FullFilePath)

这似乎需要工作簿的目录路径。

我有以下代码来循环遍历 Excel 进程。

FileName = "ABCD.xlsm"

For Each P As Process In System.Diagnostics.Process.GetProcessesByName("EXCEL")
    With P
        If .MainWindowTitle.ToLower.Contains(FileName.ToLower) Then

            'don't know the code to get the directory where the p process is located

            WrkBk = System.Runtime.InteropServices.Marshal.BindToMoniker(FilePath)

            Exit For
        End If
    End With
Next

对于我的应用程序,ABCD.xlsm 的路径并不总是相同的。我为获取进程目录而搜索的所有内容都返回 EXCEL.EXE 路径或返回 vb 项目工作目录的路径。我真的需要它返回类似的内容:“C:\Temp\Tools\ABCD.xlsm”,这样我就可以将 WrkBk 附加到进程中。

有任何想法吗?有没有更简单的方法来做到这一点?

4

2 回答 2

0
Dim xl As Excel.Application
xl = GetObject(, "Excel.Application")
For Each wb As Excel.Workbook In xl.Workbooks
  MsgBox(wb.FullName)
Next wb
xl = Nothing
于 2012-09-24T07:48:46.320 回答
0

我终于找到了。

视窗 API....

Private Delegate Function EnumWindowsProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean
Private Declare Function EnumChildWindows Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As IntPtr) As Boolean
Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Int32) As Int32
Private Const MAX_TITLE As Int32 = 256
Private Const S_OK As Int32 = &H0

Private Function GetClassName(ByVal hwnd As IntPtr) As String
    Dim name As New String(" "c, MAX_TITLE)
    Dim len = GetClassName(hwnd, name, MAX_TITLE)
    If len = 0 Then Return Nothing
    Return name.Remove(len)
End Function

Private Declare Function AccessibleObjectFromWindow Lib "OLEACC.dll" (ByVal hwnd As IntPtr, ByVal dwId As Int32, ByVal riid As Byte(), ByRef ppvObject As IntPtr) As Integer
Private Const OBJID_NATIVEOM As Int32 = &HFFFFFFF0
Private IID_IDispatch As New Guid("{00020400-0000-0000-C000-000000000046}")

功能...

Function EnumCWindows(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean
    Dim name = GetClassName(hwnd)
    If name = "EXCEL7" OrElse name = "EXCEL10" Then
        Dim ptr As IntPtr
        If AccessibleObjectFromWindow(hwnd, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), ptr) = S_OK Then
            Dim win = CType(Marshal.GetObjectForIUnknown(ptr), Excel.Window)
            Dim sheet = CType(win.ActiveSheet, Excel.Worksheet)
            Dim book = CType(sheet.Parent, Excel.Workbook)
            If book.FullName.ToLower.Contains("wpp tools") Then
                FoundTheFile = True
                WPPFilePath = book.FullName
                Exit Function
            End If
        End If
    End If
    Return True
End Function

然后在你的代码中......

For Each p In Process.GetProcesses
    If p.ProcessName = "EXCEL" Then
        EnumChildWindows(p.MainWindowHandle, AddressOf EnumCWindows, IntPtr.Zero)
        If FoundTheFile = True Then Exit For
    End If
Next
If FoundTheFile = False Then
    MsgBox("Targeted file was not found.", MsgBoxStyle.OkOnly, "File Find Error")
    End
End If

我希望这可以帮助其他人,因为我已经搜索了一周!

于 2012-09-25T03:30:37.707 回答