Глобальные переменные VBA, несколько рабочих книг

У меня есть приложение VB, которое использует некоторые глобальные переменные для хранения данных, которые требуются для нескольких форм и модулей, это прекрасно работает. Однако если пользователь открывает другую рабочую книгу с тем же приложением VBA, он получает доступ (и изменяет) к одним и тем же общедоступным переменным.

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

Это надстройка VBA, а глобальные переменные объявляются в стандартном модуле.

Ответы на вопрос(4)

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

 Sam Cogan24 сент. 2010 г., 09:29
Неудобно, что это должен быть учебник независимым дополнением. Придется искать другой вариант.
 Charles Williams24 сент. 2010 г., 11:57
Я понимаю, что это независимая надстройка. Вы выполняете эту работу, перехватывая события уровня приложения, так что код в вашем надстройке вызывается каждый раз, когда активируется рабочая книга, не являющаяся надстройкой. <br/> Затем ваш код проверяет книгу, которая была активирована для ваших скрытых имен, и, если они присутствуют. копирует свои настройки в ваши глобальные переменные. Вам также потребуется обработать хранение глобальных переменных в скрытых именах при деактивации рабочей книги.

Таким образом, коллекция, вероятно, сделает эту работу.

'//-- module --
Public var As Collection

Public Function SetVar(Value)
   If var Is Nothing Then
      Set var = New Collection
   End If
   var.Add Value, ThisWorkbook.Name
End Function

Public Function GetVar() As Variant
   If var Is Nothing Then
      GetVar = Null
   Else
      GetVar = var.Item(ThisWorkbook.Name)
   End If
End Function

Не уверен, что это сработает для вашего Addin.

 Oneide02 окт. 2010 г., 19:42
Кстати, я заметил недостаток в коде выше. Вы должны проверить, есть ли значение в коллекции, прежде чем устанавливать его (вы не можете добавить то, что уже есть). Может быть, есть и другие недостатки, но это должно быть легко заставить это работать.
Public myvar as Variant

объявленные как Public, попадают в рабочую книгу, в которой они находятся. Если у вас есть другая книга с myvar, изменение ее значения в одной не изменит ее в другой. Возможно, у вас есть событие, которое устанавливает эту переменную из активного листа, которая запускается в обоих проектах, и устанавливает переменные в одно и то же.

 Sam Cogan23 сент. 2010 г., 14:33
Эти переменные объявляются в стандартном модуле, а не в рабочей книге или объекте листа, что, я думаю, может быть причиной проблемы. Однако это то место, где они должны находиться, чтобы остальная часть кода получила к ним доступ. Это надстройка VBA, а не лист с кодом
 Dick Kusleika23 сент. 2010 г., 16:03
Правильно, я имел в виду область видимости проекта. Я только что проверил это с двумя идентичными книгами и глобальной переменной, затемненной в стандартном модуле, и изменение одной не изменило другую. Я предполагаю, что вы не установили ссылку между книгами.
Решение Вопроса

дж:

Public harry As Variant

Public Sub setHarry(x)
    harry = x
End Sub

Public Function getHarry()
    getHarry = harry
End Function

Я установил xla. Затем я создал Alice.xls с текстовым полем, которое вызывало setHarry, когда оно изменилось, и ячейку с = getHarry () в нем. Я держал это действительно простым:

Private Sub TextBox1_Change()
    Run "george.xla!setHarry", TextBox1
End Sub

Затем я сделал копию Alice.xls в виде Bob.xls и запустил их обоих. Как и ожидалось, если одна из книг изменит Гарри, обе книги увидят результат.

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

На мой взгляд, лучший способ исправить это - использовать модуль класса вместо обычного модуля. Таким образом, вы можете назначить каждой книге свой экземпляр класса и его переменные в событии Workbook_Open. Если переменные объявлены как публичные, вам не нужны свойства get и set, хотя вы можете использовать их, если в этом есть смысл.

 Marc Thibault29 сент. 2010 г., 16:40
Я предложил использовать событие Workbook_Open, потому что оно автоматическое. Вы можете так же легко использовать макрос клавиатуры или что-либо еще, что вы используете сейчас для запуска приложения. Просто добавьте код для создания экземпляра класса.
 Sam Cogan28 сент. 2010 г., 23:29
Спасибо, у меня было ощущение, что это то, что происходит. К сожалению, я не могу создать экземпляр класса в событии workbook_open, так как этот плагин должен работать для любой книги. Нужно будет найти другой способ сделать это.

Ваш ответ на вопрос