1

工作表的形状集合中形状的索引是否总是与其 ZOrderPosition 相同?(原则上不能直接查询给定形状的索引)。

我已经证实在少数情况下这是正确的(最多 3000 个形状),但我没有找到关于此的文档。

我遍历了整个集合,询问 Index 和 ZOrderPosition 之间可能存在的差异:

Sub dump_shapes()
' Dump information on all shapes in a Shapes collection
    Dim shc As Shapes
    Set shc = ActiveSheet.Shapes
    Dim shp As Shape
    For Each shp In shc
      Dim sh2 As Shape
      Set sh2 = sh2idxzosh_shc(shp)
      Dim zoidx As Long
      ' The second argument is not actually the Index, but since we are traversing the 
      ' whole collection, and Index and ZOrderPosition are at most permutations, we are
      ' covering all of the possible Indexes.
      zoidx = idx2zo_shc(shc, shp.ZOrderPosition)
    Next shp
End Sub

用于查询的函数如下所示。由于 MsgBox 中的警告从未弹出,这意味着对于评估的案例,Index=ZOrderPosition。

' Functions between the set of shapes S and the set of natural numbers N.
' O=ZOrderPosition : S -> N  (function exists)
' D=From Index : N -> S  (function exists)
' D^-1=Index : S -> N  (function does not exist)
' f=OoD : N -> N  (can be constructed; this is expected to be only a permutation, 
'  i.e., bijective)
' g=DoO : S -> S  (can be constructed)

Function sh2idxzosh_shc(ByRef sh As Shape) As Shape
    Dim shc As Shapes
    Set shc = sh.Parent.Shapes
    Dim zo As Long
    zo = sh.ZOrderPosition
    Dim sh2 As Shape
    Set sh2 = shc(zo)
    ' g=DoO : S -> S
    ' Test Shape : g(S)=S for all s? If so, g=DoO=I ; D=O^-1 ; D^-1=O. Thus, the Index 
    '  is equal to the ZOrderPosition.
    ' Use ZOrderPosition to test Shape : O(g(s))=O(s) for all s? I.e., OoDoO=O? If so, 
    '  given that O is bijective, OoD=I ; D=O^-1 ; D^-1=O. Thus, the index is equal to 
    '  the ZOrderPosition.
    Dim zo2 As Long
    zo2 = sh2.ZOrderPosition
    If (zo2 <> zo) Then
      MsgBox ("Compound ZOrderPosition: " & zo2 & ", ZOrderPosition: " & zo)
    End If
    Set sh2idxzosh_shc = sh2
    'Set sh2 = Nothing
End Function

Function idx2zo_shc(ByRef shc As Shapes, idx As Long) As Integer
    Dim sh As Shape
    Set sh = shc(idx)
    Dim zo As Long
    zo = sh.ZOrderPosition
    ' f=OoD : N -> N
    ' Test index : f(i)=i for all i? If so, f=OoD=I ; D=O^-1 ; D^-1=O. Thus, the Index is 
    '  equal to the ZOrderPosition.
    If (zo <> idx) Then
      MsgBox ("Index: " & idx & ", ZOrderPosition: " & zo)
    End If
    idx2zo_shc = zo
End Function

PS:我已经对Worksheet的ChartObjects集合的函数进行了适配,也验证了等价Index=ZOrder。

PS2:有人可能会问,这是否是任何收藏的典型(甚至是保证)。在Excel VBA:Shapes 集合中 ZOrderPosition 的非连续编号我报告了一种情况,不仅这是不正确的,而且 Index 和 ZOrderPosition 甚至都不是排列(请注意,它是与 ChartObject 关联的 Shape 的 Shapes 集合,a情况与上述不同)。

编辑:请参阅Excel VBA 中的编辑:如何从 ChartObject 获取对形状的引用

4

1 回答 1

2

如果您制作一组形状,则 Excel 工作表形状的规则“ZOrderPosition = index”是 ** NOT ** true。例如,如果您在 Zorder 1 到 6 中有形状“A”、“B”、“C”、“D”、“E”、“F”,然后将形状“B”、“C”、“D”分组一起,您将打破形状“E”和“F”的“ZOrderPosition = index”规则。如果列出形状(i),您将获得以下信息:

index Z订单名称
 1 1 "A"        
 2 2“第 1 组”   
 3       *6*      "E"        
 4       *7*      "F"        

这是获取先前信息的代码:

Sub DebugListInfoOfShapes()
    Dim i As Long
    Debug.Print "Index   ZOrder   Name"
    For i = 1 To ActiveSheet.Shapes.Count
        Debug.Print i & "         " _
                      & ActiveSheet.Shapes(i).ZOrderPosition _
                      & "      " _
                      & ActiveSheet.Shapes(i).Name
    Next i
End Sub

希望这能澄清你的问题!

问候, 安德烈斯

PD:如果您想查看形状“B”、“C”、“D”,您必须在组内循环使用例如:ActiveSheet.Shapes(2).GroupItems(i)对于上述情况。

于 2013-10-03T16:01:56.263 回答