Используйте Excel VBA для запуска файла в отдельном экземпляре Microsoft Excel - PullRequest
0 голосов
/ 24 июня 2019

(Минимальные требования: Excel 2010 и Windows 7) Мне удалось использовать ответ Билла Мэнвилла, найденный в MSDN , с небольшими изменениями.Предлагаемый рекурсивный код в основном использует файлы 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 уже работает какон создает новый экземпляр Excel и, если открывается новый файл Excel, он переходит к другому экземпляру Excel (выполняется до него).Но если файл с 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 при открытии новых файлов.Любой код должен быть связан внутри файла Excel с кодом Worbook_Open.Как можно включить код VBA в файл, чтобы он открывался в отдельном экземпляре Excel, даже если этот файл запускает Excel?

1 Ответ

0 голосов
/ 08 июля 2019

После исследования кода на уровне приложений было найдено рабочее решение.Я публикую это на тот случай, если это заинтересует кого-то другого.

Когда книга открывается в первый раз, она устанавливает подпрограмму события открытия книги на уровне приложения (а не на уровне книги).

Когда открывается новая книга, подпрограмма на уровне приложения открывает новыйэкземпляр с книгой, которая должна храниться отдельно по рекурсивности - закрывает эту книгу в экземпляре приложения, которая проверяет отдельность, таким образом удаляя обработчик событий из экземпляра приложения и устанавливает этот обработчик событий и код для вновь созданного экземпляра приложения.

Весь соответствующий код включен, и он должен быть в трех разных модулях.

1-a Модуль класса VBA с именем 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 Moduleвключает в себя:

'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-Весь код, необходимый для создания экземпляра на уровне рабочей книги. Событие открытия из класса, который заканчивается на уровне приложения, находится в стандартном модуле 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...