如何使用 VBA 正确设置文档属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27986234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-12 05:51:37  来源:igfitidea点击:

How do you correctly set document properties using VBA?

vbaword-vbaword-2010

提问by David Gard

The problem

问题

I'm having some trouble setting document properties using VBA in Word 2010.

我在 Word 2010 中使用 VBA 设置文档属性时遇到了一些问题。

I have a document containing several Heading 1sections and I use a macro to extract a selected section (along with it's contents) and paste it to a new document.

我有一个包含多个Heading 1部分的文档,我使用宏来提取选定的部分(及其内容)并将其粘贴到新文档中。

This part works fine, but at the end I need to set several document properties, but none of them are being set.

这部分工作正常,但最后我需要设置几个文档属性,但没有设置它们。

I'm trying to set both built-in and custom properties, but for the purpose of this question I'd like to set title, subjectand, category.

我正在尝试设置内置和自定义属性,但出于这个问题的目的,我想设置titlesubjectcategory

I've created a function to set the properties I desire (as below), and VBA is throwing no error (even when I remove error handling in the function).

我创建了一个函数来设置我想要的属性(如下所示),并且 VBA 没有抛出任何错误(即使我删除了函数中的错误处理)。

Does anybody know what I am doing wrong?

有谁知道我做错了什么?



How the function should work

函数应该如何工作

Here is a brief summary of what the function should do, but the full function is below should you find it easier to check that -

这是该函数应该做什么的简短摘要,但如果您发现更容易检查,完整的函数如下 -

  1. Check to see if the property already exists
    • It does and it is a defaultproperty
      • Set the default property
      • Set the PropertyTypeUsedvariable to default
    • it does and it is a customproperty
      • Set the custom property
      • Set the PropertyTypeUsedvariable to custom
    • It does not exist at all
      • Create a new custom property
      • Set the custom property
      • Set the PropertyTypeUsedvariable to custom
  2. Check whether or not a value has successfully been set
    • A defaultproperty should have been set
      • Was the property set successfully?
    • A customproperty should have been set
      • Was the property set successfully?
  3. Return the result
  1. 检查属性是否已经存在
    • 它确实是一个default财产
      • 设置默认属性
      • PropertyTypeUsed变量设置为default
    • 它确实是一个custom财产
      • 设置自定义属性
      • PropertyTypeUsed变量设置为custom
    • 它根本不存在
      • 创建新的自定义属性
      • 设置自定义属性
      • PropertyTypeUsed变量设置为custom
  2. 检查是否已成功设置值
    • default应该设置一个属性
      • 属性设置成功了吗?
    • custom应该设置一个属性
      • 属性设置成功了吗?
  3. 返回结果


The function I believe is causing the issue

我认为导致问题的功能

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


Full project code

完整的项目代码

The full code for this project can be found in two Paste Bins -

该项目的完整代码可以在两个 Paste Bins 中找到 -

I'm not sure if it's possible to get the code for actually creating the form (short of exporting it, but I have no where to put it), but in any case it's very simple -

我不确定是否有可能获得用于实际创建表单的代码(没有导出它,但我没有把它放在哪里),但无论如何它非常简单 -

  1. The form - frmChooseDocument
  2. The label - lblChooseDocument(Which New Starter document would you like to export?)
  3. The combobox - comChooseDocument
  4. The cancel button - btnCancel
  5. The OK button - btnOK(Initially disabled)
  1. 表格 - frmChooseDocument
  2. 标签 - lblChooseDocument(您要导出哪个新的 Starter 文档?)
  3. 组合框 - comChooseDocument
  4. 取消按钮—— btnCancel
  5. 确定按钮 - btnOK(最初禁用)

In reality I'm using the document that houses this code as a 'master' document for new startes, containing detailed instructions on how to use variouse applications.

实际上,我将包含此代码的文档用作新手的“主”文档,其中包含有关如何使用各种应用程序的详细说明。

The code itself looks for Heading 1formatted text within the document and adds them to the combobox in the form, allowing the user to select a section to export. A new document is then created and saved as a PDF.

代码本身会Heading 1在文档中查找格式化文本并将它们添加到表单中的组合框,从而允许用户选择要导出的部分。然后创建一个新文档并将其保存为 PDF。



Update

更新

As suggested in the comments, I have checked that the type of value being set matches that of the value being passed to the function and it does.

正如评论中所建议的,我已经检查过设置的值的类型是否与传递给函数的值的类型相匹配,并且确实如此。

In the case of all 3 properties described above, both the value that I am passing and the property as stored against the document are of type string.

在上述所有 3 个属性的情况下,我传递的值和针对文档存储的属性都是类型string

I've added a couple of lines to output the type and value where I am setting the result and all looks well, but obviously it is not!

我添加了几行来输出我设置结果的类型和值,一切看起来都很好,但显然不是!

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

Here is the output -

这是输出 -

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

回答by TehJake

I managed to set my word document title by saving the document after changing the property. I set the "Saved" property to false first to make sure that Word registers the change in state.

我设法通过在更改属性后保存文档来设置我的 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

Immediate Window:

即时窗口:

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

回答by tpkaplan

Permanent object properties cannot be set by functions. In other words, VBA does not allow functions to have side effects that persist after the function is finished running.

永久对象属性不能由函数设置。换句话说,VBA 不允许函数具有在函数完成运行后持续存在的副作用。

Re-write the function as a Sub and it should work.

将该函数重新编写为 Sub 并且它应该可以工作。