在 VBA 中将 Word 对象分配给 Variant 变量

Posted

技术标签:

【中文标题】在 VBA 中将 Word 对象分配给 Variant 变量【英文标题】:Assign Word Object to Variant Variable in VBA 【发布时间】:2020-01-18 02:15:37 【问题描述】:

我的目标是创建一个我在表格中定义的各种全局模板的数组。我的宏读取表格。如果名称指定了可用模板,我的数组应该保存该对象。如果找不到模板,则数组应包含无法处理的名称。 ThisDocument 是docm 类型。它默认分配给 Sfs(0)。这是我的代码的摘录。

Private Sub TestSetSfs()
    Dim Sfs() As Variant
    SetSfs Sfs
    Debug.Print Sfs(0).Name
    Debug.Print VarType(Sfs(0))             ' returns vbString
End Sub

Function SetSfs(Sfs() As Variant) As Long

    Dim Tbl As Table

    ReDim Sfs(20)                           ' max 20 references
    Set Sfs(0) = ThisDocument

    Debug.Print Sfs(0).Bookmarks.Count      ' works as expected
    Debug.Print VarType(Sfs(0))             ' returns vbString
    Debug.Print GetTextTbl(Tbl, Sfs(0), "SomeName")
End Function

Function GetTextTbl(Tbl As Table, Doc As Document, Tn As String) As Boolean
    GetTextTbl = True
End Function

我的问题在于 Set Sfs(0) = ThisDocument 行。在测试过程的下一行中,Sfs(0) 作为对象正常工作,允许 Bookmarks.Count。它还在“局部变量”窗口中显示为对象。但是,函数 GetTextTbl 将其拒绝为“ByRef 参数类型不匹配”,当在函数调用中替换为 ThisDocument 时它不会这样做。这促使我查看它的 VarType,它返回 VbString 而不是 vbObject。

让我补充一点,我已经有了在 Excel 中工作的想法(使用插件),但我需要 Word 中的等效项,我认为如果我可以将对象分配给 Sfs() 变体,全局模板将满足我的要求。知道该怎么做吗?

【问题讨论】:

删除您的 2 个 debug.print 行并改用它 - Debug.Print Sfs(0).Bookmarks.Count - 这应该证明它正在根据需要分配文档对象。 也许你是对的,但为什么 GetTextTbl(Tbl, Sfs(0), TnRef) - 在书签检查后的下一行(这也适用于我) - 给出“ByRef 参数类型不匹配”错误,而 GetTextTbl(Tbl, ThisDocument, TnRef) 没有?函数 GetTextTbl 需要 Doc As Document。正是这一点促使我研究 VarType。我会再做一些测试。谢谢鼓励。 我已经按照你的建议扩展了这个问题。 它可能需要从通用对象转换为实际的文档对象,但作为一种解决方法,您只需将函数定义更改为Function GetTextTbl(Tbl As Table, Doc As Variant, Tn As String) As Boolean 即可。这并不能完全回答您的问题,但是如果您将 MsgBox Doc.Bookmarks.Count 放入您的 GetTextTbl() 函数中,它就会起作用。 我找到了另一种解决方法 - 使用 Object 而不是 Variant - Dim Sfs() As ObjectFunction SetSfs(Sfs() As Object) As Long - 然后你可以使用 Function GetTextTbl(Tbl As Table, Doc As Document, Tn As String) As Boolean 【参考方案1】:

它的答案有点晚,但是解决您的问题的方法是使用集合而不是数组。集合(或 Scripting.Dictionaries)是处理对象的一种更自然的方式。

Private Sub TestSetSfs()
    Dim Sfs As Collection
    Set Sfs = New Collection
    SetSfs Sfs
    Debug.Print Sfs.Item(1).Name
    Debug.Print VarType(Sfs.Item(1))             ' returns vbString
End Sub

Function SetSfs(ByVal Sfs As Collection) As Long

    Dim Tbl As Table

    
    Sfs.Add ThisDocument

    Debug.Print Sfs.Item(1).Bookmarks.Count      ' works as expected
    Debug.Print VarType(Sfs.Item(1))             ' returns vbString
    Debug.Print GetTextTbl(Tbl, Sfs.Item(1), "SomeName")
End Function

Function GetTextTbl(Tbl As Table, Doc As Document, Tn As String) As Boolean
    GetTextTbl = True
End Function

【讨论】:

谢谢@freeflow。事实上,你的反应非常及时。我忘记了这个问题。甚至我的问题对我来说也很奇怪。但在过去 6 个月左右的时间里,我一直在努力完成这个 2018 年的项目,该项目一直在推动它,但我确实对更改 ActiveDocument 有疑问。所以,你的建议可能会派上用场。【参考方案2】:

它需要从Variant 转换为Object,但我在网上阅读的有关该主题的所有内容都表明您无法在VBA 中将Variant 转换为Object

您的替代方案是在所有地方坚持使用Variant(而不是Document 对象)或坚持在所有地方使用Object,因为它们似乎都提供了您在此所需的功能例子。

所以要么改成这个(使用变体方法):

Function GetTextTbl(Tbl As Table, Doc As Variant, Tn As String) As Boolean

或者将这两个都改成这个(使用对象方法):

Dim Sfs() As Object 

Function SetSfs(Sfs() As Object) As Long 

在所有情况下将其用作Object 对我来说最有意义,因为您可以将GetTextTbl 函数的原始声明用作:

Function GetTextTbl(Tbl As Table, Doc As Document, Tn As String) As Boolean

然后您的智能感知将在该函数内部工作。只要确保您没有向它传递一个不是 Word 文档的对象,否则您会收到错误。

【讨论】:

我想你已经详尽地回答了我的问题。谢谢。

以上是关于在 VBA 中将 Word 对象分配给 Variant 变量的主要内容,如果未能解决你的问题,请参考以下文章

用VBA中将Excel的数据写入Word文档,格式文本怎么传递?

在 c++ 中将对象分配给一个值时会发生啥 [关闭]

为啥在Javascript中将一个对象分配给另一个变量也会改变初始对象[重复]

从函数中将多个对象分配给 .GlobalEnv

如何在plsql中将对象类型属性的值分配给具有相同属性属性的不同对象类型?

MS Word 中的 VBA 影响整个文档,而不仅仅是选择