【问题标题】:Assign Word Object to Variant Variable in VBA在 VBA 中将 Word 对象分配给 Variant 变量
【发布时间】: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

标签: vba object ms-word variant


【解决方案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 文档的对象,否则您会收到错误。

【讨论】:

  • 我想你已经详尽地回答了我的问题。谢谢。
猜你喜欢
  • 2016-06-15
  • 2012-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
相关资源
最近更新 更多