【问题标题】:Can you group shapes as they are created in Excel?您可以将在 Excel 中创建的形状分组吗?
【发布时间】:2020-07-17 09:55:40
【问题描述】:

我在 Excel 2016 中有一个用户表单,它将生成一组特定的形状(一个焊接符号,如果上下文有帮助的话),主要由线条、圆弧和文本框组成。其中一些在每次运行代码时都是相同的,而另一些则是由用户通过用户窗体确定的选项。最后,这些元素被组合成一个符号。我当前的代码按照目前的描述工作。

当我尝试第二次运行表单时出现问题(生成独立于第一组的第二组形状)。我将其设置为,在执行代码时,它会创建一个形状,适当地命名该形状,然后在最后对所有形状进行分组,并按名称引用它们。第二次运行代码时,它使用与第一次运行相同的名称。当它尝试形成第二组时,由于名称引用了两个不同的形状,我得到一个错误。

我的问题是:有没有办法在创建形状时将形状添加到组(或稍后分组的集合)?似乎命名形状不是要走的路,因为名称在代码结束后保留​​。我尝试通过形状索引进行引用,但由于我在页面上也有图像,因此很难准确确定特定形状的索引是什么。对于缺少代码,我深表歉意,因为我现在无法访问它。如果需要,我可以写一些简单的东西来理解这一点。非常感谢任何帮助!

【问题讨论】:

  • 嗨,Calvin,请向我们展示您为实现结果所做的尝试。 Edit your question,然后粘贴到您的代码中。

标签: excel vba


【解决方案1】:

您可以使用如下命令对形状进行分组:

Dim ws as Worksheet
Set ws = ActiveSheet   ' <-- Set to the worksheet you are working on
ws.Shapes.Range(Array("Heart 1", "Sun 2", "Star 3")).Group

(您可以通过名称或索引访问形状)。 group 命令的结果是添加到工作表的另一个形状。但请注意,分组形状仍然存在于工作表中,您可以使用 GroupItems-property 访问它们。

With ws.Shapes
    Dim shGroup As Shape, sh As Shape
    Set shGroup = .Range(Array("Heart 1", "Sun 2", "Star 3")).Group
    shGroup.Name = "MyNewGroup" & .Count
    For Each sh In shGroup.GroupItems
        Debug.Print sh.Name, sh.Type
    Next sh
End With

如您所见,单个形状元素不会更改其名称,因此分组不会解决您的命名问题。唯一的方法是在名称中添加后缀,例如一个数字(就像 Excel 在创建形状时所做的那样)。

更新:当然Array- 参数不需要是静态的。你可以声明一个足够大的数组(它是否包含一些空元素并不重要)。

Const maxShapes = 12
Dim myShapes(1 to maxShapes) as String

myShapes(1) = *Name of first shape you created*
myShapes(2) = *Name of second shape you created*
...
ws.Shapes.Range(myShapes).Group

或使用Redim 命令:

Dim myShapes() as String

Redim myShapes(1 to NumberOfShapesInYourNewGroup)
myShapes(1) = *Name of first shape you created*
myShapes(2) = *Name of second shape you created*
...
ws.Shapes.Range(myShapes).Group

要获得唯一的形状和组名,您可以实现各种方法。我不喜欢使用全局变量的尝试,因为它们可能会被重置 - 例如,当您在调试期间取消执行时。例如,您可以使用 Excel 在创建新形状时生成的后缀。或者将重命名语句放入一个循环中,在重命名之前放一个On error Resume Next(不要忘记在它后面放一个On error Goto 0)并循环直到重命名成功。或遍历工作表中的所有形状以查找下一个免费名称。

【讨论】:

  • 我对 .Range(Array(X,...,Xn)).Group 方法的问题是,有问题的数组可能包含 5 到 12 个形状以及一些不同的选项对于每个(即“心脏 2”而不是“心脏 1”)。可以清除这些名称以便重复使用吗?或者,如果需要后缀,那么添加每次运行代码时都可以引用的计数器的最佳方法是什么?全局变量?
【解决方案2】:

经过反复试验,我想出的解决方案类似于以下内容。

'Count shapes already on sheet
Shapesbefore=ActiveSheet.Shapes.Count

'Create new shapes

'Create array containing indexes of recently created shapes
Dim shparr() As Variant
Dim shprng  As ShapeRange
ReDim shparr(Shapestart + 1 To ActiveSheet.Shapes.Count)
For i = LBound(shparr) To UBound(shparr)
    shparr(i) = i
Next i


'Group shapes and format weight/color
Set shprng = ActiveSheet.Shapes.Range(shparr)

With shprng
    .Group
    .Line.Weight = 2
    .Line.ForeColor.RGB = 0
End With

这样我就不必担心创建和管理各种组和形状名称,因为我以后不需要返回并引用它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多