Как предотвратить использование переменных VBA в документах Word? - PullRequest
0 голосов
/ 26 января 2012

У меня есть проект шаблона VBA, который запускается автоматически при открытии документа Word. Однако, если я открываю несколько документов, все они имеют общие значения переменных. Как объявить эти переменные связанными только с активным окном или активным документом?

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

Любой вклад приветствуется ...

Это то, что у меня есть в моем модуле:

Option Private Module
  Dim CurrentCommand As String

  Public Function SetCurrentCommand(command)
    CurrentCommand = command
  End Function

  Public Function GetCurrentCommand()
    GetCurrentCommand = CurrentCommand
  End Function

Подробнее: Код / макрос начинаются с AutoExec следующим образом:

Public Sub Main()      
  Set oAppClass.oApp = Word.Application
  If PollingRate <> "" Then Application.OnTime Now + TimeValue(PollingRate), "CaptureUserViewState"
End Sub

А CaptureUserViewState - это Sub, который находится в другом Модуле и выполняет все проверки (сравнивая новые значения с последними записанными) и вот как этот Sub выполняет проверку:

If WL_GetterAndSetter.GetLastPageVerticalPercentage <> pageVerticalPercentScrolled Then
  'Update the last value variable
   WL_GetterAndSetter.SetLastPageVerticalPercentage (pageVerticalPercentScrolled)
  'log change
End If

Ответы [ 3 ]

3 голосов
/ 26 января 2012

Вы не предоставляете нам много информации, но я предполагаю, что вы объявили публичные переменные на уровне модуля, например:

Public myString As String
Public myDouble As Double

Из документации VBA:

Переменные, объявленные с использованием оператора Public, доступны для всех процедур во всех модулях во всех приложениях , если не действует Option Private Module; в этом случае переменные являются общедоступными только в рамках проекта, в котором они находятся.

Ответ должен использовать Option Private Module.

При использовании в хост-приложениях, которые разрешают ссылки для нескольких проектов, Option Private Module предотвращает ссылки на содержимое модуля вне его проекта.

[...] Если используется, оператор Option Private должен появляться на уровне модуля, перед любыми процедурами.

РЕДАКТИРОВАТЬ Вы пояснили, что объявляете свои переменные, используя Dim на уровне модуля. В этом случае Option Private Module не имеет значения.

Переменные, объявленные с Dim на уровне модуля, доступны для всех процедур в модуле.

т.е. независимо от того, используете ли вы Option Private Module или нет.

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

EDIT

В вашем модуле класса вместо Dim CurrentCommand As String попробуйте Private CurrentCommand As String. Без дополнительной информации сложно отладить вашу программу. Я просто делаю случайные выстрелы здесь.

0 голосов
/ 22 августа 2014

Возможно, вы захотите сохранить детали документа, используя Свойство Document.CustomDocumentProperties http://msdn.microsoft.com/en-us/library/office/aa212718(v=office.11).aspx

Это возвращает DocumentProperties Collection Какие вы можете добавить новые свойства в Использование

Document.CustomDocumentProperties.Add(PropertyName, LinkToContent, Value, Type)

А затем прочитать с помощью

Document.CustomDocumentProperties.Item(PropertyName)

Недостатком или бонусом является то, что свойства будут сохраняться в документе, пока вы не удалите их.

Это может быть хорошо или плохо

0 голосов
/ 04 сентября 2013

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

В модуле класса (MyData), помеченном как общедоступный:

Public data1 as String
Public data2 as Integer

В модуле с обработчиками событий:

Dim c as new Collection 'module global declaration

Sub AddData()
  Dim d as new MyData 'Your data set
  d.data1 = "Some value"
  d.data2 = 42
  c.add Value:=d, Key:=ActiveDocument.name
End Sub

Затем, когда вы вводите обработчик событий, вы извлекаете данные и используете конкретный набор для текущего активного документа.

Sub EventHandler()
  Dim d as MyData
  set d = c.item(ActiveDocument.name)
  'use data
  'd.data1...
End Sub

Пожалуйста, обратите внимание, что этот код только на концептуальном уровне. Это не работает, вы должны применить это к вашей проблеме, но это должно дать вам некоторое представление о том, что вам нужно делать. Вам нужно будет добавить множество обработчиков ошибок, проверять, находится ли элемент в коллекции и т. Д., Но я надеюсь, что вы понимаете концепцию продолжать попытки самостоятельно.

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

С другой стороны, если каждый документ будет иметь свой собственный код / ​​обработчик событий, а значит, запускать несколько версий скрипта, вам не нужно решение, представленное выше. Вместо этого вам нужно быть осторожным, на какой экземпляр документа вы ссылаетесь в своем скрипте. Всегда используя «ThisDocument» вместо «ActiveDocument», вы можете добиться изоляции, если код размещен в каждом открытом документе.

Однако, насколько я понял, у вас работает только одна версия скрипта, отдельная от открытых документов, поэтому применимо первое решение.

Удачи!

...