使用VBA将标签与Excelstream程图中的箭头进行匹配

我在Excel中使用VBA编写了一个代码生成工具(不要问为什么长的故事)。 我需要能够“parsing”一个stream程图。

问题是,Excel允许形状包含文本,但连接器除外:线条和箭头不能包含文本。 要标记一个箭头,你只需要在上面放一个文本框,但是这个盒子不能以VBA可以轻易捕捉的方式“附加”到箭头上。

例如,用户可能会画这样的东西:

示例流程图:三个方框,两个箭头,另外两个方框作为箭头标签

在我的VBA代码中,我可以使用ActiveSheet.Shapes来查找stream程图包含七个形状:有五个框(两个标签只是没有边框的框)和两个箭头。 然后Shape.TextFrame2会告诉我每个框里面写的是什么, Shape.ConnectorFormat会告诉我每个箭头的开始和结束处是哪个盒子。

我需要的是可以推导出的代码:

  • 标签A属于从方框1到方框2的箭头
  • 标签B属于从方框1到方框3的箭头

我可以想到三种方法,没有一种令人满意。

  1. 要求用户使用相应的箭头将每个标签分组。

  2. 找出每个箭头端点的坐标,然后计算哪些箭头通过哪些标签。

  3. 找出每个盒子angular落的坐标,然后计算哪些盒子之间有哪些标签。

方法1使程序员变得更容易,但用户更难。 这为用户错误开辟了很大的潜力。 我不认为这是一个可以接受的解决scheme。

方法2将相当容易实现,除了我不知道如何找出坐标!

方法3是可行的( Shape.Left等将给出坐标),但计算相当混乱。 它也有潜在的歧义(取决于放置,相同的标签可能与多个箭头相关联)。

请注意,方法2和3都涉及试图将每个标签与每个箭头进行匹配:复杂性是二次的。 典型的应用将有10-50个箭头,所以这种方法是可行的,如果有点不雅。

有没有人有更好的主意? 理想情况下,这将不涉及坐标几何和复杂的逻辑,并不涉及要求用户改变他们绘制stream程图的方式。


编辑补充说:例2是对Tim Williams的回应

带有一个方框,两个箭头和边界框与两个箭头的边界框相交的标签的流程图

这是一个标签,其边框与两个箭头的边框相交,并且其中点不在任一个箭头的边框内。 从视觉上来看,人类很容易看到它属于左箭头,但在编程上很难处理。 如果我能找出箭头端点的坐标,那么我可以计算出一个箭头通过标签的方框,而另一个箭头不通过。 但是,如果我拥有的是箭头的边界矩形,那么它不起作用。

有趣的问题。 如果考虑到箭头所覆盖的范围和文本框所覆盖的范围,并根据最重叠的方式进行匹配,会出现什么情况呢?

 Sub ListShapes() Dim shp As Shape Dim shpArrow As Shape Dim vaArrows As Variant Dim i As Long Dim rIntersect As Range Dim aBestFit() As String Dim lMax As Long vaArrows = Split("Straight Arrow Connector 7,Straight Arrow Connector 9", ",") ReDim aBestFit(LBound(vaArrows) To UBound(vaArrows)) For i = LBound(vaArrows) To UBound(vaArrows) Set shpArrow = Sheet1.Shapes(vaArrows(i)) lMax = 0 For Each shp In Sheet1.Shapes If shp.Name Like "Label*" Then Set rIntersect = Intersect(Sheet1.Range(shp.TopLeftCell, shp.BottomRightCell), _ Sheet1.Range(shpArrow.TopLeftCell, shpArrow.BottomRightCell)) If Not rIntersect Is Nothing Then If rIntersect.Count > lMax Then lMax = rIntersect.Count aBestFit(i) = shp.Name End If End If End If Next shp Next i For i = LBound(vaArrows) To UBound(vaArrows) Debug.Print vaArrows(i), aBestFit(i) Next i End Sub 

我testing了这个五盒二箭头设置,没有什么更复杂的。 我把我的两个箭头放在一个数组中,但是我认为你有办法识别箭头。 我还把我的不受限制的盒子命名为“Label x”,以便我可以识别它们,但是我又认为你有更复杂的东西。

代码遍历每个箭头。 在循环内部,它循环遍历每一个形状。 如果它是一个标签,那么它将计算这两个范围相交处的单元格。 无论哪一个都是最适合的arrays。

如果你有一个合理的stream程图来testing这个问题,看看陷阱在哪里,那将会很好。 我认为这不一定比使用坐标更好,只是一种不同的方法。

您可以按如下方式find箭头端点的坐标。

首先,如Tim Williams指出的, .Height.Top.Width.Height属性描述了箭头的边界矩形。

接下来,检查.Horizo​​ntalFlip和.VerticalFlip属性。 如果两者都是错误的,那么箭头在其边界矩形中从左上angular到右下angular。 也就是说,箭头的起点有坐标(.Left,.Top) ,最后有坐标(.Left+.Width,.Top+.Height)

如果* .Flip是真的,则坐标需要在适当的时候交换。 例如,如果.HorizontalFlip为true,但.VerticalFlip false,则箭头从(.Left+.Width,.Top)(.Left,.Top+.Height)

据我所知,这是不loggingMSDN上的任何地方。 感谢Andy Pope在excelforums.com上提到它。

鉴于此,方法2似乎是最好的方法。