Аналогично свойству Tag форм и элементов управления, свойства документа позволяют программисту сохранять необходимую информацию (о возможности использования свойств, точнее их значений, для поиска документов здесь упоминать не будем - это пользовательская возможность). При необходимости эту информацию можно легко извлечь и использовать.
В VBA для MSOffice определены два типа свойств документов: встроенные (BuiltIn) и пользовательские (Custom). Оба типа свойств организованы в коллекции, соответственно BuiltInDocumentProperties и CustomDocumentProperties, относящиеся к объекту(ам) Document и Template. Нумерация элементов коллекций начинается с единицы.
Встроенные свойства документов автоматически поддерживаются соответствующими приложениями, и без необходимости модифицировать их не стоит, можно считывать и использовать.
Гораздо больший интерес для программиста представляют Custom свойства документа - именно их можно использовать для хранения нужной информации, связанной с документом. Достаточно удобно то, что можно использовать разные типы свойств: строки, числа, даты, и логические поля.
Добавить нужное свойство (здесь и далее будем полагать, что работаем со свойствами активного документа) можно, использовав метод Add:
ActiveDocument.CustomDocumentProperties.Add _ Name:=PropertyName, _ LinkToContent:=False, _ Value:="", _ Type:=msoPropertyTypeString
В этой инструкции:
Обязательными элементами являются имя, тип и LinkToContent, значение можно не задавать.
Для считывания некоторого свойства просто пишем:
varProperty = ActiveDocument.CustomDocumentProperties.Item(Name)
где Name имя свойства или номер в коллекции.
Все было бы так просто, если бы не одна маленькая неприятность (по крайней мере, в MSOffice97 это так, а с ним еще долго будут работать пользователи). Неприятность заключается в том, что нет возможности прямо проверить, создано ли уже свойство с некоторым именем, а обращение к пустому свойству или попытка создания свойства с именем, совпадающим с именем уже определенного, вызывает ошибку (коды соответственно 5 и -2147467259 - не удивляйтесь, а распечатайте err.number!). Но такое поведение можно с легкостью использовать, написав свой обработчик ошибок.
Итак, необходимо присвоить пользовательскому свойству Test значение переменной strString, при этом не известно, существует ли в данный момент пользовательское свойство (даже если вы его уже когда-то определили, то ведь пользователь мог его удалить, значит такая ситуация является общей, а не частной). Вот фрагмент кода для решения такой задачи.
Dim strString as String strString = "тестовое значение пользовательского свойства Test" On Error GoTo AddCustomProperty ' устанавливаем обработчик ошибок ActiveDocument.CustomDocumentProperties.Item("Test") = strString On Error GoTo 0 ' или туда, куда он был установлен ранее Exit Sub ' ОБРАБОТЧИК(И) ОШИБОК AddCustomProperty: Select Case Err.Number Case 5 ' Этот номер ошибки возникает, если пытаемся писать ' в свойство, которое пока не создано ActiveDocument.CustomDocumentProperties.Add _ Name:=PropName, LinkToContent:=False, Value:="", Type:=msoPropertyTypeString Resume ' возвращаем управление в оператор присвоения значения Case Else ' Вывод сообщений о других ошибках и прерывание программы MsgBox(Err.Number & Chr(13) & Chr(13) & Err.Description) Exit Sub End Sub
Аналогично, считывание значения пользовательского свойства производится так (тоже ведь никогда нельзя быть уверенным в том, что свойство существует):
Dim varProperty as Variant ' Явное указание типа Variant On Error GoTo ReadCustomProperty ' устанавливаем обработчик ошибок strString = ActiveDocument.CustomDocumentProperties.Item("Test") On Error GoTo 0 ' или туда, куда он был установлен ранее ...... Exit Sub ' ОБРАБОТЧИК(И) ОШИБОК ReadCustomProperty: Select Case Err.Number Case 5 ' Этот номер ошибки возникает, если пытаемся читать ' свойство, которое пока не создано varProperty = "" ' или "Null" или "NoProperty" - как нравится Resume Next ' возвращаем управление следующему оператору ' кстати, вместо возврата строки можно и свойство создать... Case Else ' Вывод сообщений о других ошибках и прерывание программы MsgBox(Err.Number & Chr(13) & Chr(13) & Err.Description) Exit Sub End Sub
Существенно, что при считывании значения свойства производится автоматическое приведение типа (если оно возможно), и считывание, например, числа в стоковую переменную не приводит к ошибке.
Если задан номер пользовательского свойства, то легко можно узнать все его свойства (извините за каламбур), для этого достаточно написать (пример цикла для всех свойств):
For Each prop In ActiveDocument.CustomDocumentProperties With prop MsgBox .Name & "= " & .Value & Chr(13) & _ "Application" & " = " & .Application & _ "Creator" & " = " & .Creator & _ "Parent" & "= " & .Parent End With Next
Для всей коллекции пользовательских свойств легко получить число определенных свойств:
ActiveDocument.CustomDocumentProperties.Count
Очевидно, что индекс в цикле перебора всех свойств может пробегать от 1 до этого значения.
Для ситуации, когда надо создать свойство, можно тоже написать обработчик ошибок, но логика его работы уже будет сильно зависеть от функциональности программы, в которой он используется. Поэтому он здесь не приводится, однако информации для его написания достаточно. Повторим, что код ошибки для ситуации повторного определения свойства с некоторым именем, равен -2147467259 (знак минус!, впрочем, "правильный" код 440).
Написал и прислал шаг Dmitri Drozdov.