Совместное использование переменных между несколькими экземплярами Excel - PullRequest
1 голос
/ 29 мая 2019

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

Моя текущая мысль - сохранить эти числа в менеджере имен главной рабочей книги и заставить основную рабочую книгу суммировать значение для каждого имени как общее число завершенных итераций. Я также попробовал ту же концепцию, ссылаясь на скрытое пространство имен в главном экземпляре Excel, как описано здесь Чипом Пирсоном: 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 Ответ

1 голос
/ 29 мая 2019

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