解决Visio使用Shape Replace方法显示OBJ的BUG

引言 许多Visio管理员在项目初期都会面临模具频繁更新的问题。由于Visio的机制,每当用户首次从模具库中拖拽模具至绘图页时,实际上是从该模具库中拷贝了模具的副本至文档模具中。这种机制无疑切断了文档模具与原模具库的联系,也造成管理更新模具库后无法将更新应用到已有的绘图上。当绘图上需要更新的形状数量较少时,可以使用Visio提供的更改形状功能手动更新。但是,当绘图页中存在大量的待更新形状时,使用使用程序进行批量更新。 程序批量更新的方法是遍历文档模具,并通过文档模具中模具的BaseID从模具库中找到源模具,再比较两者的UniqueID是否一致。若UniqueID一致,说明该模具没有更新,应跳过操作;若不一致,说明源模具发生了更新。然后在绘图页中找到所有与该模具关联的形状,然后删除文档模具中的旧模具,再执行Shape.Replace()方法使用新的模具替换形状。 这种方法通常是凑效的,但是在上一周中,我遇到了如下的BUG:更新后的形状显示Obj文本。仔细查看形状shapesheet,可以发现模具中已经定义好的TextField在形状中变成了空白,造成显示错误。 不幸的是,未能在Google中搜到类似的问题反馈。 问题排查 通过查看xml文件,发现该形状的Field节被替换为了<Row IX='0' Del='1'/>。对比未出现显示错误的形状的xml文件可以发现:当TextField取值为空时,Field节应该继承自模具,因此xml文档不应出现Field节;当TextField存在取值时,Row节点内应该有Cell节点。此时,如果手动删除Field节,显示的OBJ文字消失。由此可以推出Field节数据发生了异常。 但是,仍然无法确定该异常的产生是因为形状定义错误还是其他。 回到Visio应用程序中,在源模具中的形状树中删除发生该问题的子形状,再次执行更新程序,原本没有问题的子形状的TextField出现同样的问题。重复执行删除子形状并更新的操作,问题始终出现。当所有的子形状都被删除后,更新后的形状不再显示OBJ。但是,新的问题出现了:形状显示数字3。显然我们并没有在模具的任何形状或子形状中定义过这个数值。 由此可以推出,形状定义并没有问题,而是其他数据导致了Visio更新时的异常行为。 为了确定是哪一部分数据存在问题,我们清空了User、ShapeData等全部用于定义用户数据的Section,问题依然复现。现在,只剩模具的基础数据了(诸如PinX、PinY等Shape节点下的Cell节点)。由于Visio中不能删除基础数据,所以在XML文件中用其他正常模具的基础数据替换问题模具的基础数据。此后,再使用程序对绘图页的形状进行更新,数字3不再出现,也就是这个BUG被修复了。 通过文本对比工具,我们比较了问题模具与正常模具的基础数据。 (此处,因为重启电脑图丢了。。。。。) 比较两者的基础数据并没有特别的地方,除了尺寸和定位存在数值差异外,只有Cell的顺序存在区别。最终也无法确定这个问题到底是怎么产生的。 解决方法 尽管未能找到该问题形成的原因,但通过定位问题位置,我们找到了解决该问题的方法:即使用正常模具的基础数据覆盖问题模具。

September 26, 2023 · 1 min · 18 words · Snailya

解决Visio外部数据绑定失败:自定义形状ID属性

引言 在 Visio 中,可以通过使用外部数据来创建和更新图标、图形和其它可视化元素。例如,可以通过外部数据绑定,建立形状与数据表之间的同步关系,实现当外部数据发生变化时,Visio 图形的自动更新。利用这个方法,既可以解决人工通过 Excel 批量修改形状数据的需求,又可以实现数据库自动更新数据的需求。 但是,目前针对外部数据功能的教程非常少,均是以组织架构图或时序图为例,以人工拖拽的方式实现数据链接到形状,鲜有如何自动将导入的数据连接到形状的教程。尽管 Microsoft 官方提供了自动链接向导将导入的数据连接到形状的支持文档,但是仅参照该文档并不能实现我们如下的需求: 通过数据导出功能导出形状的数据至 Excel 表格 通过数据导入及自动链接功能将修改后的 Excel 表格与 Visio 形状数据的自动绑定,实现形状数据的更新。 该需求应于我们的业务过程存在的批量修改某类设备型号、供应商的情况。面对大量的设备,如果通过 Visio 逐次去修改每个形状的数据,一是操作繁琐耗时,二是容易产生遗漏,以上两个问题均可以得到解决。 问题描述 借助数据库导出向导,我们可以将指定图层上的形状数据导出至数据库(或 Excel 文档),导出过程中将使用形状的 ID 作为数据表的 Key。因此,在将数据表导回 Visio 时,只需将 Key 值与形状的 ID 关联,理论上应该可以实现自动将数据链接至形状。 但是,在实际操作中,外部数据窗口中并没有出现链接符号,即绑定失败了。 此时,如果使用拖拽的方式将数据连接至形状,还会发现 Visio 并没有如期更新已有的属性,而是将表格中的属性作为新的属性写入形状。 也就是说,要实现我们的需求需要解决如下两个问题: 自动链接数据至形状数据 更新已有形状数据而不是新建数据 原因分析 针对问题一,使用录制宏功能,可以发现当设置形状的 ObjectID 与数据源中的 ShapeKey 匹配时,没有录制上任何有效代码,而其它选项均有代码被录制。因此推测 ID(Object Info)不是有效选项。 针对问题二,由于在导出数据时,允许重新定义属性的名称,因此推测属性名称在更新数据时起关联作用,即表格中的列名称应与属性的 Name 或 Label 一致。经过多次尝试,应设置列名称为属性的 Label。 解决方法 因此,要在 Visio 中实现外部数据绑定与自动更新,需要完成以下操作: 在 User Section 中添加新的 ShapeID 属性,并设置其公式为"=GUARD(ID())"。 在数据导出窗口中,依次修改导出属性的 Field Name 为其 Label。 在自动链接窗口中,选择 Shape Field 的值为 User....

June 25, 2023 · 1 min · 76 words · Snailya

修复Visio容器调整尺寸引发的意外的文件尾错误:正确的容器定义方法

引言 容器是 Visio 中一类可以帮助实现结构化组织和管理其它图形元素的特殊对象。通过容器,您可以将相关的子图形放置在一个框架内,以便更清晰地展示信息和关系。在管理员定义方面,与组合相比,容器可以实现更丰富的预定义内容:形状结构、外观样式、连接点定义等,以满足不同公司对图表样式的要求。在用户操作方面,用户可以通过将子图形拖拽在容器内或容器外轻松实现将子图形加入或移出容器,通过拖拽容器可以实现容器内子图形的一起移动。因此,容器尤其适用于图表、流程图、组织结构图的设计。 但是,容器作为 Visio2010 的新增特性,Visio 并没有提供关于自定义容器的相关教程及建议,这也使得当前 Visio 容器的定义存在极高的自由度。通常,若将一个对象定义为容器,只需要在该对象 Spreadsheet 中的 User Section 内增加msvStructureType属性,并设置其值为="Container"。 但是,这种简单的定义可能会在特定情况下引发意外的文件尾错误。 问题描述 星期一的时候,我的同事向我演示了他是如何引起这个错误的。首先,他将一条表示管路的线段放在了表示功能单元的容器内。由于这条管路表示外部进来的管路,所以他希望这条线段一端恰好贴在容器边框,另一端落在容器内。随后,他又删除了这条线段。在此之后,当他想要调整容器的尺寸时,出现了这个错误。 当我尝试复现这个错误时,我发现使用 Visio 预定义的容器并不会引发该现象。 原因分析 通过仔细对比我们自定义的容器和 Visio 预定义的容器,我们确定了以下两个前置条件: 线段一端必须吸附在容器的几何形状上。当线段被吸附至容器的几何形状上时,点击容器,连接处可以看到如图所示的高亮的连接点。 在默认状态下,拖拽线段至容器的边界不会引发吸附,除非文档模板中预定义或用户手动开启了该功能。该功能位于 View-Visual aids-Snap & Glue-General-Glue to节,勾选 Shape geometery 可以启用该功能。 被吸附的容器的几何形状必须定义在容器本身,而不是容器组合的子对象。也就是说,表示几何形状的 Geometry Section 位于容器的 Spreadsheet 内。 解决方法 要解决这个问题,我们需要将容器的几何形状定义在容器组合的子对象中。也就是说,在创建自定义容器时,不应在容器自身的 Spreadsheet 中定义 Geometry,而应将容器转换为组合,并将表示容器几何形状的对象作为容器组合的子对象。 以下给出了建议的自定义容器步骤: 插入表示容器造型的形状对象; 将这些形状对象使用 Ctrl+G组合成一个组合对象; 打开组合对象的 Spreadsheet,并在 User Section 内增加msvStructureType属性,并设置其值为="Container"。

June 1, 2023 · 1 min · 55 words · Snailya