0

在 Microsoft Visio Professional 2010 中,我已经隔离了我遇到的这个小代码片段的错误。页面上有一个包含 2 个形状的容器,我想在另一个循环中遍历这些形状。但我不断收到无效参数错误。

我对解决方案的尝试是顶部块,但它仅适用于内部循环的相同定义。在外循环的第二次迭代期间,似乎有些东西正在发生变化,但我不确定。我觉得这与定义 For Each 循环的方式有关。

Sub Nested_Loop_Error()

    Dim a As Variant
    Dim b As Variant
    Dim lngs() As Long

    'This Works
    lngs = ActiveDocument.Pages(1).Shapes.ItemFromID(1).ContainerProperties.GetMemberShapes(visContainerFlagsDefault)
    For a = 0 To 1
        For Each b In lngs
            'Do nothing
        Next b
    Next a


    'This does not work
    For a = 0 To 1
        For Each b In ActiveDocument.Pages(1).Shapes.ItemFromID(1).ContainerProperties.GetMemberShapes(visContainerFlagsDefault)
            MsgBox "In Loop for a=" & a
        Next b
    Next a

End Sub

编辑:我一直在玩它并让它工作,但我真正感兴趣的是它为什么工作。当 a=1 时,第二个代码块失败,在 docMyDoc.Pages... 行中给出无效参数

以下代码显示了使用变体或文档变量在循环中定义 ActiveDocument 的区别。使用调试器,我看不出 docMyDoc 或 varMyDoc 的定义方式有何不同。

Sub Nested_Loop_Error2()
    Dim a As Variant
    Dim b As Variant
    Dim docMyDoc As Visio.Document
    Dim varMyDoc As Variant

    'This works
    For a = 0 To 1
        Set varMyDoc = ActiveDocument
        For Each b In varMyDoc.Pages(1).Shapes.ItemFromID(1).ContainerProperties.GetMemberShapes(visContainerFlagsDefault)
            MsgBox "Using variant, a=" & a
        Next b
    Next a

    'This does not work
    For a = 0 To 1
        Set docMyDoc = ActiveDocument
        For Each b In docMyDoc.Pages(1).Shapes.ItemFromID(1).ContainerProperties.GetMemberShapes(visContainerFlagsDefault)
            MsgBox "Using document, a=" & a
        Next b
    Next a
End Sub
4

2 回答 2

1

使用 Variant 类型对编译器帮助不大:名为“b”的变量应该是 Long 类型,而“a”变量应该是 Integer 类型。

这就是说,您没有使用“a”变量,而是重复您在内部循环(Msgbox)中所做的两次,但没有其他任何变化。

此外,您需要引用 ID 为 b 的形状,而您没有这样做。

另一个提示:不要以变量的类型命名变量,而是根据它们的语义命名。

我认为您打算做的类似于MSDN 中 GetMemberShapes 方法参考中的示例:

Sub Nested_Loop()

    Dim lngMemberID as Long
    Dim vsoShape as Visio.Shape
    Dim j as Integer

    For j = 0 to 1
        For Each lngMemberID In ActiveDocument.Pages(1).Shapes(1).ContainerProperties.GetMemberShapes(visContainerFlagsDefault)
            Set vsoShape = ActivePage.Shapes.ItemFromID(memberID)
            Debug.Print vsoShape.ID
        Next lngMemberID
    Next j

 End Sub

在这里,您的 vsoShape 变量将首先引用一个,然后引用您的另一个形状。即使您的页面中有更多形状,它也会起作用。

这是集合和 For Each 循环的好处:集合是由其他对象列表组成的特殊对象。它们有自己的方法,如 Item 或 Count,以及快捷方式,如使用括号之间的数字从集合中检索单个对象(如在 Pages(1) 中)。

您对 For Each 所做的是遍历集合中的所有对象(或数组中的所有值)。

出于您的目的,我会尝试以下一般结构:

dim oPage as Visio.Page
dim oShape as Visio.Shape
dim oInnerShape as Visio.Shape

For each oPage In ActiveDocument.Pages
  For each oShape in oPage.Shapes
      If oShape.Master.Name = "xxx" Then       ' You can check the type of the shape
          For each oInnerShape In oShape
             ' set and compute width and height
          Next oInnerShape
          ' set and compute width and height of the containing shape
       End If
  Next oShape
  ' Rearrange shapes
Next oPage

您可以构造一个存储形状 ID、宽度和高度的数组,同时遍历形状,然后使用该数组重新排列形状。

问候,

于 2013-08-14T11:49:05.263 回答
0

我的计算机上没有 Visio,但您确定第一个嵌套循环有效吗?

我有lngs = ActiveDocument.Pages(1)...疑问Dim lngs() As Long

Excel VBA 将在尝试存储时抛出“类型不匹配”arr = Array(1,2)错误Dim arr() As LongDim lngs As Variant即使您知道它是返回的 Long 数组也会更好。

第二个嵌套循环在理论上有效。

于 2013-08-14T01:08:56.327 回答