【问题标题】:How do you correctly set document properties using VBA?如何使用 VBA 正确设置文档属性?
【发布时间】:2015-03-15 04:36:41
【问题描述】:

问题

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

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

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

我正在尝试设置内置属性和自定义属性,但出于这个问题的目的,我想设置 title、subject 和 title强>类别。

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

有人知道我做错了什么吗?


函数应该如何工作

这里是函数应该做什么的简要总结,但如果你发现更容易检查的话,下面是完整的函数-

  1. 检查属性是否已经存在
    • 确实如此,它是一个default 属性
      • 设置默认属性
      • 将PropertyTypeUsed 变量设置为default
    • 确实如此,它是一个custom 属性
      • 设置自定义属性
      • 将PropertyTypeUsed 变量设置为custom
    • 根本不存在
      • 创建新的自定义属性
      • 设置自定义属性
      • 将PropertyTypeUsed 变量设置为custom
  2. 检查值是否设置成功
    • 应该设置了default 属性
      • 属性设置成功了吗?
    • 应该已经设置了custom 属性
      • 属性设置成功了吗?
  3. 返回结果

我认为是导致问题的函数

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

完整的项目代码

这个项目的完整代码可以在两个粘贴箱中找到-

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

  1. 表格 - frmChooseDocument
  2. 标签 - lblChooseDocument(您要导出哪个 New Starter 文档?)
  3. 组合框 - comChooseDocument
  4. 取消按钮 - btnCancel
  5. 确定按钮 - btnOK(最初禁用)

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

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


更新

按照 cmets 中的建议,我检查了设置的值的类型是否与传递给函数的值的类型匹配,并且确实如此。

在上述所有 3 个属性的情况下,我传递的值和存储在文档中的属性都是 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

【问题讨论】:

  • 伙计,我希望所有 SO 问题都像这样。
  • 问题是它返回 False,对吗?当我尝试设置布尔值时,我得到了相同的结果。它将 True 与 -1 进行比较并称之为不匹配。我没有将其设置为 True,而是将其设置为 -1。还是假的。现在它将 -1 与“-1”进行比较。检查 propertyvalue 和 doc.CustomeDocumentProperties(properyName).value 的 TypeName 并查看它们是否相同。对于标题、主题和类别等内容,我无法想象它们会有所不同,但这是一个开始。
  • 它确实在每个实例中都返回 false,但它实际上也没有设置属性(在检查它是否成功之前完成)。我现在就看看你的其他 cmets...谢谢。
  • @DickKusleika - 抱歉,现在正在设置属性(我猜是另一个错误在早些时候阻止了它,没有意识到我已经修复它),但是 false 仍然被返回。我已经根据您的 cmets 更新了我的问题,如果您有任何进一步的想法,我将不胜感激。谢谢。
  • @DavidGard 在函数 SetProperties 中,给结果一个初始值为 True

标签: vba ms-word word-2010


【解决方案1】:

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

【讨论】:

  • 抱歉,我重新阅读了上面的内容,现在觉得我完全错过了重点。我认为问题在于文档属性没有被更改。无关的请忽略我的帖子!
【解决方案2】:

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

将函数重写为 Sub,它应该可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多