在多个Excel实例之间共享变量

时间:2019-05-28 22:58:17

标签: excel vba

我有多个Excel实例来计算问题的不同部分,我希望能够随着每个实例完成的迭代次数来跟踪总进度。如何在Excel实例之间共享变量?

我目前的想法是将这些数字存储在主工作簿的名称管理器中,并让主工作簿将每个名称的值汇总为迭代完成总数的总数。我还尝试通过引用Excel主实例中的隐藏命名空间来尝试相同的概念,如Chip Pearson在此处所述:http://www.cpearson.com/excel/hidden.htm。最终,我努力将跨实例的进度号保存在内存中。我不想写入主Excel实例引用的文件,因为那样会使事情放慢速度。

在Excel的工作实例内部将类似于以下代码,以将其当前进度传送回主工作簿的名称空间:

Dim xlApp As Excel.Application
Set xlApp = GetObject(MasterPath).Application
'The MasterPath is defined as the full path of the master instance: ActiveWorkbook.FullName
With xlApp
    .Workbooks(MasterName).Activate
    .ActiveWorkbook.Names("Thread_" & i & "_iter").RefersTo = "=" & CStr(i - seqFrom + 1)
End With

上面的代码是给我错误的。它陷入无限循环。当我删除它时,一切都会按预期执行。

在主工作簿中,将显示以下内容,以显示所有实例的总体进度:

For thread = 1 To cThreads
    progress_Arr(thread) = CLng(Right(ThisWorkbook.Names("Thread_" & thread & "_iter").RefersTo, Len(ThisWorkbook.Names("Thread_" & thread & "_iter").RefersTo) - 1))
    progress = progress + progress_Arr(thread)
    Debug.Print "Thread " & thread & ": " & progress_Arr(thread)
Next thread

我最终希望能够在Excel的主实例中编译所有迭代。

1 个答案:

答案 0 :(得分:1)

好吧,在我的评论中扩展这里是我准备的粗略测试代码:旋转几个“从属” Excel实例,加载“驱动程序”工作簿的副本(作为只读),然后为每个从属工作簿提供对主工作簿,他们可以用来在LogProgress对象上调用公用的ThisWorkbook方法。

在常规模块中:

Option Explicit

Dim col As Collection '<< In the master, stores references to slave application instances
                      '    Not really used here though

'For "slave" workbooks - dummy "do some work" long-running 
'   routine which periodically reports back
Public Sub DoWork()
    Dim n As Long
    'kick something off...
    For n = 1 To 20
        Application.Wait Now + TimeSerial(0, 0, 1)
        ThisWorkbook.ReportWork n '<< update master
    Next n
End Sub

'Creates slave instances loaded with copies of this workbook
'  and a reference to the master workbook, and loads them into "col"
Sub InitSlaves()
    Dim x As Long, app
    ThisWorkbook.Save
    Debug.Print "Master instance", Application.Hwnd
    Set col = New Collection
    For x = 1 To 5
        col.Add XlInstance(ThisWorkbook.FullName)
    Next x
End Sub

'Set up and return a new Excel instance
Function XlInstance(wb As String)
    Dim app, wkb
    Set app = CreateObject("excel.application")
    app.Visible = True
    Debug.Print "Slave instance", app.Hwnd
    Set wkb = app.Workbooks.Open(wb, ReadOnly:=True)
    Set wkb.Master = ThisWorkbook
    wkb.StartWork
    Set XlInstance = app
End Function

ThisWorkbook模块中:

Option Explicit

Dim masterWb As Object '<< in a slave workbook, a reference to the master wb

'In a slave workbook, gets a reference to the master workbook
'  Note: you *must* use 'As Object' here or you can't call the custom
'        methods later (because a "WorkBook"-type doesn't have them)
Public Property Set Master(wb As Object)
    Set masterWb = wb
End Property

'Gets called on the slave workbooks from the master
Public Sub StartWork()
   Application.OnTime Now, "DoWork"
End Sub

'From a slave, send a message back to the master workbook
Public Sub ReportWork(msg)
    masterWb.LogProgress Application.Hwnd, msg
End Sub

'In the master, get a message from a slave workbook
Public Sub LogProgress(id, msg)
    Dim m
    m = Application.Match(id, Sheet1.Columns(1), 0)
    If IsError(m) Then
        m = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row + 1
        Sheet1.Cells(m, 1).Value = id
    End If
    Sheet1.Cells(m, 2).Value = msg
End Sub