Шаг 47 - Свойства документов MSOffice

Аналогично свойству 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.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем.