Как правильно установить свойства документа с помощью VBA?

Проблема

У меня возникли проблемы с настройкой свойств документа с помощью VBA в Word 2010.

У меня есть документ, содержащий несколько разделов Heading 1, и я использую макрос, чтобы извлечь выделенный раздел (вместе с ним) и вставить его в новый документ.

Эта часть работает нормально, но в конце мне нужно установить несколько свойств документа, но ни один из них не установлен.

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

Я создал функцию для установки желаемых свойств (как показано ниже), а VBA не вызывает ошибок (даже когда я удаляю обработку ошибок в функции).

Кто-нибудь знает, что я делаю неправильно?


Как должна работать функция

Вот краткий обзор того, что должна делать функция, но полная функция ниже, если вам будет проще проверить, что -

  • Проверить, существует ли свойство
    • Это значит, что это свойство default
      • Задайте свойство по умолчанию
      • Задайте для переменной PropertyTypeUsed значение default
    • и это свойство custom
      • Задайте настраиваемое свойство
      • Задайте для переменной PropertyTypeUsed значение custom
    • Это вообще не существует
      • Создать новое настраиваемое свойство
      • Задайте настраиваемое свойство
      • Задайте для переменной PropertyTypeUsed значение custom
  • Проверить, было ли задано значение
    • A default должно быть установлено
      • Было ли свойство успешно установлено?
    • A custom должно быть установлено
      • Было ли свойство успешно установлено?
  • Вернуть результат

Функция, которая, как мне кажется, вызывает проблему

Function UpdateDocumentProperty(ByRef doc As Document, _
                                ByVal propertyName As String, _
                                ByVal propertyValue As Variant, _
                                Optional ByVal propertyType As Office.MsoDocProperties = 4)

    '** Set the result to 'False' by default '*
    Dim result As Boolean
    result = False

    '** A property to hold whether or not the property used is default or custom *'
    Dim propertyTypeUsed As String

    '** Check to see if the document property already exists *'
    If PropertyExists(doc, propertyName) Then                           ' A default property exists, so use that
        doc.BuiltInDocumentProperties(propertyName).value = propertyValue
        propertyTypeUsed = "default"
    ElseIf PropertyExists(doc, propertyName, "custom") Then             ' A custom property exists, so use that
        doc.CustomDocumentProperties(propertyName).value = propertyValue
        propertyTypeUsed = "custom"
    Else                                                                ' No property exists, so create a custom property
        doc.CustomDocumentProperties.Add _
            name:=propertyName, _
            LinkToContent:=False, _
            Type:=propertyType, _
            value:=propertyValue
        propertyTypeUsed = "custom"
    End If

    '** Check whether or not the value has actually been set *'
    On Error Resume Next
    If propertyTypeUsed = "default" Then
        result = (doc.BuiltInDocumentProperties(propertyName).value = propertyValue)
    ElseIf propertyTypeUsed = "custom" Then
        result = (doc.CustomDocumentProperties(propertyName).value = propertyValue)
    End If
    On Error GoTo 0

    UpdateDocumentProperty = result

End Function

Полный код проекта

Полный код для этого проекта можно найти в двух вставках для вставки -

Я не уверен, возможно ли получить код для фактического создания формы (если не экспортировать ее, но у меня нет места, где ее можно разместить), но в любом случае это очень просто -

  • Форма - frmChooseDocument
  • Метка - lblChooseDocument (Какой документ нового стартера вы хотите экспортировать?)
  • Сопоставление - comChooseDocument
  • Кнопка отмены - btnCancel
  • Кнопка OK - btnOK (первоначально отключена)

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

Сам код ищет текстовый текст Heading 1 в документе и добавляет его в поле со списком в форме, позволяя пользователю выбрать раздел для экспорта. Затем создается и сохраняется новый документ в формате PDF.


Update

Как было предложено в комментариях, я проверил, что тип устанавливаемого значения соответствует значению, передаваемому функции, и оно делает.

В случае всех трех свойств, описанных выше, как значение, которое я передаю, так и свойство, хранящееся у документа, имеют тип string.

Я добавил пару строк для вывода типа и значения, где я устанавливаю результат, и все выглядит хорошо, но, очевидно, это не так!

Debug.Print "My value:        (" & TypeName(propertyValue) & ")" & propertyValue
Debug.Print "Stored property: (" & TypeName(doc.BuiltInDocumentProperties(propertyName).value) & ")" & doc.BuiltInDocumentProperties(propertyName).value

Вот результат -

My value:        (String)New Starter Guide - Novell
Stored property: (String)New Starter Guide - Novell
My value:        (String)New starter guide
Stored property: (String)New starter guide
My value:        (String)new starters, guide, help
Stored property: (String)new starters, guide, help

Ответ 1

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

Перезапишите функцию как Sub, и она должна работать.

Ответ 2

Мне удалось установить заголовок документа Word, сохранив документ после изменения свойства. Сначала я установил свойство "Сохранено" в false, чтобы убедиться, что Word регистрирует изменение состояния.

Function ChangeDocumentProperty(doc As Document, sProperty As String, sNewValue As String)

    Debug.Print "Initial Property, Value: " & sProperty & ", " & doc.BuiltInDocumentProperties(sProperty)

    doc.BuiltInDocumentProperties(sProperty) = sNewValue

    doc.Saved = False
    doc.Save

    ChangeDocumentProperty = (doc.Saved = True And doc.BuiltInDocumentProperties(sProperty) = sNewValue)

    Debug.Print "Final Property, Value: " & sProperty & ", " & doc.BuiltInDocumentProperties(sProperty)

End Function

Немедленное окно:

? ThisDocument.ChangeDocumentProperty(ThisDocument, "Title", "Report Definitions")
Initial Property, Value: Title, Report Glossary
Final Property, Value: Title, Report Definitions
True