2010-09-23 2 views
1

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

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

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

ответ

1

Я был в состоянии воспроизвести проблему с помощью простой XLA называется Джордж:

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's, поскольку в памяти есть только одна копия; что, по-видимому, включает в себя глобальные переменные, что имеет смысл. Я просто хотел проверить теорию.

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

+0

Спасибо, у меня было ощущение, что это происходит. К сожалению, я не могу создать экземпляр класса в событии workbook_open, так как этот addin должен работать для любой книги. Должен найти другой способ сделать это. –

+0

Я предложил использовать событие Workbook_Open, потому что оно автоматическое. Вы можете легко использовать клавиатурный макрос или все, что вы сейчас используете для запуска приложения. Просто добавьте код для создания экземпляра класса. –

1
Public myvar as Variant 

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

+0

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

+0

Правильно, я имел в виду охват проекта. Я просто тестировал его с двумя идентичными книгами, а глобальная переменная затухала в стандартном модуле, а изменение одного не меняло другого. Я полагаю, вы не установили ссылку между книгами. –

1

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

+0

Unfortuantley это должна быть независимая от книги книга. Придется искать другой вариант. –

+0

Я понимаю, что это отдельная надстройка. Вы делаете эту работу путем захвата событий на уровне приложения, чтобы код в вашем добавлении вызывался каждый раз, когда активирована книга без добавления.
Затем ваш код проверяет книгу, которая была активирована для ваших скрытых имен, и, если они присутствуют, копирует свои настройки в глобальные переменные. Вам также потребуется обработать сохранение глобальных переменных в именах hiddeen при отключении рабочей книги. –

1

Я думаю, вы могли бы получить название книги во время выполнения.

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

'//-- 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.

+0

Кстати, я заметил недостаток в коде выше. Вы должны проверить, находится ли это значение в коллекции до его установки (вы не можете добавить что-то, что уже есть). Возможно, есть и другие недостатки, но должно быть легко заставить его работать. – Oneide

Смежные вопросы