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

11

问题

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

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

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

我尝试设置内置和自定义属性,但为了这个问题,我想设置标题主题类别

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

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


函数应该如何工作

这是函数应该做的简要概述,但是如果您发现检查完整函数更容易,下面是完整函数:

  1. 检查属性是否已经存在
    • 它已经存在并且是一个默认属性
      • 设置默认属性
      • PropertyTypeUsed变量设置为默认
    • 它已经存在并且是一个自定义属性
      • 设置自定义属性
      • PropertyTypeUsed变量设置为自定义
    • 它根本不存在
      • 创建一个新的自定义属性
      • 设置自定义属性
      • PropertyTypeUsed变量设置为自定义
  2. 检查是否成功设置了值
    • 应该设置了一个默认属性
      • 属性是否已成功设置?
    • 应该设置了一个自定义属性
      • 属性是否已成功设置?
  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

完整的项目代码

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

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

  1. 表单- frmChooseDocument
  2. 标签- lblChooseDocument (您要导出哪个新入职员工文件?)
  3. 下拉列表框- comChooseDocument
  4. 取消按钮- btnCancel
  5. 确定按钮- btnOK(最初为禁用状态)

实际上,我使用包含有关如何使用各种应用程序的详细说明的文档作为新入门者的“主”文档。

代码本身查找文档中格式为Heading 1的文本,并将其添加到表单中的下拉列表框中,允许用户选择要导出的部分。 然后创建一个新文档并另存为PDF格式。


更新

如评论中建议的那样,我已经检查了设置的值类型是否与传递给函数的值类型匹配,它确实匹配。

在上述所有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

9
哇,我希望所有的SO问题都能像这个一样简洁明了。 - RubberDuck
它确实在每个实例中返回false,但它实际上也没有设置属性(这是在检查是否成功之前完成的)。我现在会查看您的其他评论...谢谢。 - David Gard
@DickKusleika - 抱歉,属性现在已经被设置了(我猜之前可能有另一个错误阻止了它,没有意识到我已经修复了它),但是仍然返回false。根据您的评论,我更新了我的问题,并将非常感谢您进一步的想法。谢谢。 - David Gard
3
在函数SetProperties中,将结果赋初值True。 - ignotus
啊!!!我怎么会错过那个?!谢谢你,那的确是问题所在。与其给一个True的初始值,我实际上检查确保返回的值是True(这只是我的个人偏好),但这解决了问题。感谢你抽出时间来看一下,如果您愿意发布答案,我会接受它 :) - David Gard
显示剩余6条评论
2个回答

2

我成功地通过更改属性并保存文档来设置我的Word文档标题。我首先将“Saved”属性设置为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

抱歉,我重新阅读了上面的内容,现在感觉完全错过了重点。我以为问题是文档属性没有被更改。如果我的帖子与此无关,请忽略它! - TehJake

1

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

将该函数重写为Sub即可正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接