在自己单独的 Microsoft Excel 实例中使用 Excel VBA 到 运行 文件
Use Excel VBA to run file in own separate instance of Microsoft Excel
(最低要求:Excel 2010 和 Windows 7)
我已设法使用在 MSDN 中找到的 Bill Manville 的答案并稍作改动。建议的递归代码基本上使用文件的 Workbook_Open 来创建一个单独的实例,并且 taht 实例将文件打开为可编辑的,没有只读访问提示。
Private Sub Workbook_Open()
Dim oXcl As Excel.Application
If Workbooks.Count > 1 Then
ThisWorkbook.Saved = True
ThisWorkbook.ChangeFileAccess xlReadOnly
Set oXcl = CreateObject("Excel.Application")
oXcl.ScreenUpdating = False
oXcl.Visible = True
oXcl.Workbooks.Open fileName:=ThisWorkbook.FullName, ReadOnly:=False
AppActivate oXcl.Caption
ThisWorkbook.Close SaveChanges:=False
Else
Call Continue_Open
End If
End Sub
代码在 Excel 已经 运行ning 时工作得很好,因为它创建了一个新的 Excel 实例,如果打开了一个新的 Excel 文件,它转到另一个 Excel 实例(运行ning 在它之前)。但是,如果带有 Workbook_Open 的文件是 Excel 开头的文件,则通过在该 Excel 实例中双击打开可以打开任何其他 Excel 文件,因为它是最早的 运行 实例因此不再分离。
我已经能够通过使用
来判断(Windows)该文件是否开始Excel
Function NumberOfExcelInstances()
strComputer = "."
Set objWMI = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\" & strComputer & "\root\cimv2")
Set proc = objWMI.ExecQuery("Select * from Win32_Process Where Name = 'Excel.exe'")
NumberOfExcelInstances = proc.Count
End Function
但我无法找到一种方法来告诉在打开新文件时不要使用 Excel 实例。任何代码都应与 Worbook_Open 代码捆绑在 Excel 文件中。
我怎么可能在文件中包含 VBA 代码,以便它在单独的 Excel 实例中打开,即使该文件是触发 Excel?
的文件
在对应用程序级别的代码进行研究之后,找到了一个可行的解决方案。我正在发布它,以防其他人感兴趣。
第一次打开工作簿时,它会在应用程序级别(而不是工作簿级别)设置一个工作簿打开事件子例程。
当打开一个新工作簿时,应用程序级别的子程序会打开一个新实例,其中工作簿将通过递归保持分离 - 关闭应用程序实例中检查分离的工作簿,从而从应用程序实例中删除事件处理程序并在新创建的应用程序实例上设置该事件处理程序和代码。
包含所有相关代码,并且需要在三个不同的模块中。
1-a VBA Class 使用以下代码创建名为 cXlEvents 的模块:
'VBA Class Module named cXlEvents
Public WithEvents appWithEvents As Application
'Instance variables
Dim sEventSetterPath As String
Dim sEventSetterName As String
Private Sub appWithEvents_WorkbookOpen(ByVal Wb As Workbook)
Call NewAppInstance(Wb, sEventSetterPath, sEventSetterName)
End Sub
2-ThisWorkbook 模块包括:
'1-ThisWorkbook VBA Module calling events at
'Workbook level.
'2-At Workbook Open set Application level event
'handler and then instance code by calling subs
'held in VBA standard module.
Private Sub Workbook_Open()
Call SetEventHandler
Call NewAppInstance(Me)
End Sub
'Code to call "undo" special settings upon opening
'when file closes
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call UndoSettings
End Sub
3-从 class 将在应用程序级别结束的工作簿级别打开事件创建实例所需的所有代码都在标准 VBA 模块中:
'In a VBA standard Module
Dim oXlEvents As New cXlEvents
Sub SetEventHandler()
If oXlEvents.appWithEvents Is Nothing Then
Set oXlEvents.appWithEvents = Application
End If
End Sub
Sub NewAppInstance(wbWbook As Workbook, Optional sEventSetterPath As String, Optional sEventSetterName As String)
Dim oXcl As Excel.Application
Dim wbEventSet As Workbook
Dim lCaseNum As Long
Dim sResetMacro As String: sResetMacroName = "UndoSettings"
'Set instance variables
sEventSetterPath = ThisWorkbook.FullName
sEventSetterName = ThisWorkbook.Name
If wbWbook.ReadOnly And wbWbook.FullName = sEventSetterPath Then
MsgBox "Already open - please use open file.", , "WARNING"
wbWbook.Close False
Exit Sub
End If
If Workbooks.Count > 1 Then
If wbWbook.FullName <> sEventSetterPath Then
lCaseNum = 1
Set wbEventSet = Workbooks(1)
wbEventSet.Save
Application.Run "'" & sEventSetterName & "'!'" & sResetMacro & "'"
Else
lCaseNum = 2
Set wbEventSet = wbWbook
wbEventSet.Saved = True
End If
wbEventSet.ChangeFileAccess xlReadOnly
Set oXcl = CreateObject("Excel.Application")
oXcl.Workbooks.Open Filename:=sEventSetterPath, ReadOnly:=False
oXcl.Visible = True
Set oXlEvents.appWithEvents = Nothing
Select Case lCaseNum
Case Is = 1
AppActivate Application.Caption
Case Is = 2
AppActivate oXcl.Caption
End Select
wbEventSet.Close False
Else
Call Continue_Open
End If
End Sub
Sub Continue_Open()
'Code with special settings and procedures required for the workbook
End Sub
Sub UndoSettings()
'Code to "undo" any special settings when workbook opened
End Sub
(最低要求:Excel 2010 和 Windows 7) 我已设法使用在 MSDN 中找到的 Bill Manville 的答案并稍作改动。建议的递归代码基本上使用文件的 Workbook_Open 来创建一个单独的实例,并且 taht 实例将文件打开为可编辑的,没有只读访问提示。
Private Sub Workbook_Open()
Dim oXcl As Excel.Application
If Workbooks.Count > 1 Then
ThisWorkbook.Saved = True
ThisWorkbook.ChangeFileAccess xlReadOnly
Set oXcl = CreateObject("Excel.Application")
oXcl.ScreenUpdating = False
oXcl.Visible = True
oXcl.Workbooks.Open fileName:=ThisWorkbook.FullName, ReadOnly:=False
AppActivate oXcl.Caption
ThisWorkbook.Close SaveChanges:=False
Else
Call Continue_Open
End If
End Sub
代码在 Excel 已经 运行ning 时工作得很好,因为它创建了一个新的 Excel 实例,如果打开了一个新的 Excel 文件,它转到另一个 Excel 实例(运行ning 在它之前)。但是,如果带有 Workbook_Open 的文件是 Excel 开头的文件,则通过在该 Excel 实例中双击打开可以打开任何其他 Excel 文件,因为它是最早的 运行 实例因此不再分离。
我已经能够通过使用
来判断(Windows)该文件是否开始ExcelFunction NumberOfExcelInstances()
strComputer = "."
Set objWMI = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\" & strComputer & "\root\cimv2")
Set proc = objWMI.ExecQuery("Select * from Win32_Process Where Name = 'Excel.exe'")
NumberOfExcelInstances = proc.Count
End Function
但我无法找到一种方法来告诉在打开新文件时不要使用 Excel 实例。任何代码都应与 Worbook_Open 代码捆绑在 Excel 文件中。 我怎么可能在文件中包含 VBA 代码,以便它在单独的 Excel 实例中打开,即使该文件是触发 Excel?
的文件在对应用程序级别的代码进行研究之后,找到了一个可行的解决方案。我正在发布它,以防其他人感兴趣。
第一次打开工作簿时,它会在应用程序级别(而不是工作簿级别)设置一个工作簿打开事件子例程。
当打开一个新工作簿时,应用程序级别的子程序会打开一个新实例,其中工作簿将通过递归保持分离 - 关闭应用程序实例中检查分离的工作簿,从而从应用程序实例中删除事件处理程序并在新创建的应用程序实例上设置该事件处理程序和代码。
包含所有相关代码,并且需要在三个不同的模块中。
1-a VBA Class 使用以下代码创建名为 cXlEvents 的模块:
'VBA Class Module named cXlEvents
Public WithEvents appWithEvents As Application
'Instance variables
Dim sEventSetterPath As String
Dim sEventSetterName As String
Private Sub appWithEvents_WorkbookOpen(ByVal Wb As Workbook)
Call NewAppInstance(Wb, sEventSetterPath, sEventSetterName)
End Sub
2-ThisWorkbook 模块包括:
'1-ThisWorkbook VBA Module calling events at
'Workbook level.
'2-At Workbook Open set Application level event
'handler and then instance code by calling subs
'held in VBA standard module.
Private Sub Workbook_Open()
Call SetEventHandler
Call NewAppInstance(Me)
End Sub
'Code to call "undo" special settings upon opening
'when file closes
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call UndoSettings
End Sub
3-从 class 将在应用程序级别结束的工作簿级别打开事件创建实例所需的所有代码都在标准 VBA 模块中:
'In a VBA standard Module
Dim oXlEvents As New cXlEvents
Sub SetEventHandler()
If oXlEvents.appWithEvents Is Nothing Then
Set oXlEvents.appWithEvents = Application
End If
End Sub
Sub NewAppInstance(wbWbook As Workbook, Optional sEventSetterPath As String, Optional sEventSetterName As String)
Dim oXcl As Excel.Application
Dim wbEventSet As Workbook
Dim lCaseNum As Long
Dim sResetMacro As String: sResetMacroName = "UndoSettings"
'Set instance variables
sEventSetterPath = ThisWorkbook.FullName
sEventSetterName = ThisWorkbook.Name
If wbWbook.ReadOnly And wbWbook.FullName = sEventSetterPath Then
MsgBox "Already open - please use open file.", , "WARNING"
wbWbook.Close False
Exit Sub
End If
If Workbooks.Count > 1 Then
If wbWbook.FullName <> sEventSetterPath Then
lCaseNum = 1
Set wbEventSet = Workbooks(1)
wbEventSet.Save
Application.Run "'" & sEventSetterName & "'!'" & sResetMacro & "'"
Else
lCaseNum = 2
Set wbEventSet = wbWbook
wbEventSet.Saved = True
End If
wbEventSet.ChangeFileAccess xlReadOnly
Set oXcl = CreateObject("Excel.Application")
oXcl.Workbooks.Open Filename:=sEventSetterPath, ReadOnly:=False
oXcl.Visible = True
Set oXlEvents.appWithEvents = Nothing
Select Case lCaseNum
Case Is = 1
AppActivate Application.Caption
Case Is = 2
AppActivate oXcl.Caption
End Select
wbEventSet.Close False
Else
Call Continue_Open
End If
End Sub
Sub Continue_Open()
'Code with special settings and procedures required for the workbook
End Sub
Sub UndoSettings()
'Code to "undo" any special settings when workbook opened
End Sub