关于将形状链接到数据
注意
数据连接功能仅适用于 Microsoft Visio Professional 2013 的授权用户。
Visio 中包括四个方面的数据连接:
- 连接至数据源
- 将形状链接至数据
- 以图形方式显示链接的数据
- 刷新已在数据源中更改的链接数据,更新链接形状,并解决可能引发的任何后续冲突
通常情况下,是按这些数据连接的列出顺序来对其进行访问的。也就是说,首先将 Visio 绘图连接到某数据源,然后将绘图中的形状链接到数据源中的数据,以图形方式显示链接形状中的数据,并在必要时刷新链接数据。
这些方面中的每一种在 Visio 对象模型中都有对象以及与其关联的成员。 本主题将介绍这些方面中的第二种,将 Visio 绘图中的形状链接到数据。 有关数据连接其他方面的详细信息,请参阅下列主题:
若要以编程方式将 Visio 绘图连接到数据源,可使用 Visio API 进行数据连接,其中包括下列对象及其关联成员:
- DataRecordsets 集合
- DataRecordset 对象
- DataConnection 对象
- DataRecordsetChangedEvent 对象
- DataColumns 集合
- DataColumn 对象
将 Visio 绘图连接到外部数据源之后,可以通过编程方式将绘图中的形状链接到该源中的数据。 您可以将一个或多个形状链接到一个数据记录集中的单行数据,也可以链接到不同数据记录集中的多行数据。 但是,不能将形状链接到同一记录集中的多行数据。
您可以一次一个形状或按组向数据链接现有形状;或者,也可以创建形状,再将其同时链接到数据。 您可以在知道的情况下指定形状与数据行之间的对应关系,或者,也可以由 Visio 根据现有形状数据与数据记录集中数据的比较关系自动确定对应关系。
将形状链接到数据后,可以通过向形状添加数据图形以图形形式显示这些数据。 有关数据图形的详细信息,请参阅关于以图形形式显示数据。
DataRecordset 和 DataColumn 对象以及 DataColumns 集合公开多个便于数据链接的属性、方法和事件。 此外,Visio 对象模型中的其他对象(包括 Application、Document、Page、Selection、Shape 和 Window 对象)的多个成员也与数据链接有关。
数据链接和形状数据
将形状链接到数据的前提是您可为所有 Visio 形状指定形状数据。 在早于 Visio 2007 的 Visio 版本中,形状数据称为自定义属性。
若要在 Visio UI 中访问和指定形状数据,请右键单击一个形状,指向“数据”,然后单击“形状数据”。 或者,您也可以在 Visio ShapeSheet 电子表格中手动或以编程方式访问和指定形状数据。 若要显示所选形状的 ShapeSheet 电子表格 (ShapeSheet),请右键单击该形状,再单击“显示 ShapeSheet”。 若要查看此命令,必须以开发人员模式运行 Visio。 若要以开发人员模式运行 Visio,请单击“文件”选项卡,单击“选项”,再单击“高级”,然后在“常规”下选中“以开发人员模式运行”。
在 ShapeSheet 中,形状数据包含在“形状数据”部分(以前称为“自定义属性”部分)内。 为维护向后兼容性,现有对象成员在其名称中保留了“自定义属性”。 如果没有为给定形状分配形状数据,则 ShapeSheet 中不会显示“形状数据”部分。 通过按上述操作显示 ShapeSheet,右键单击“ShapeSheet”窗口中的任意位置,然后单击“插入内容”,选择“形状数据”,再单击“确定”,可以向 ShapeSheet 中添加“形状数据”部分。
将形状链接到数据后,“形状数据”部分的许多列都严格地对应于 DataColumn 对象的不同属性。 例如,“形状数据”部分的“标签”列(提供“形状数据”对话框中的特定形状数据项的显示标签)与 DataColumn.DisplayName 属性(控制“外部数据”窗口中的相关联数据列的显示名称)对应。 有关使用 DataColumn 对象的详细信息,请参阅获取和设置数据列属性。
标识形状、数据记录集和数据行
Visio 使用唯一的 ID 编号来标识形状、记录集和数据行。 形状 ID 仅在形状所在页面范围内是唯一的。 在您确定这些编号后,可以将其传入 Visio 的数据相关对象的不同方法,以精确指定图表中的形状应如何链接到可用数据记录集中的数据行。
若要确定形状的 ID,请获取 Shape.ID 属性值。 此外,Visio 还提供了形状唯一 ID 或 GUID。 Page.ShapeIDsToUniqueIDs 方法将采用形状 ID 的数组以及 VisUniqueIDArgs(指定是获取、获取或建立还是删除形状 GUID)中的枚举值。 Page.ShapeIDsToUniqueIDs 方法还返回传入形状的唯一 ID 的数组。 反过来,如果您知道一组形状的唯一 ID,则可以使用 Page.UniqueIDsToShapeIDs 方法获取这些形状的形状 ID。 对于所选的形状,可以使用 Selection.GetIDs 方法获取这些形状的形状 ID。
若要确定向 DataRecordsets 集合添加的 DataRecordset 对象的 ID,请获取 DataRecordset.ID 属性值。 若要确定数据记录集中每一行的 ID,请调用 DataRecordset.GetDataRowIDs 方法,该方法可返回行 ID 的数组。 有关详细信息,请参阅关于在 Visio 中连接数据中的“以编程方式访问数据记录集中的数据”部分。
创建链接到数据的形状
当您要在绘图页(其中不包含任何形状,或包含除了要链接的形状之外的形状)上创建已链接到数据的形状时,可以使用 Page.DropLinked 和 Page.DropManyLinkedU 方法创建一个或多个已链接到数据的其他形状。 这些方法与 Page.Drop 和 Page.DropManyU 方法类似,相似之处在于它们都在页面上的指定位置创建其他形状;此外它们还在新建形状与指定的数据记录集中的指定数据行之间创建链接。
DropLinked 方法将返回新的链接 Shape 对象并采用下列参数:
- ObjectToDrop - 要创建的特定形状(例如矩形形状)。
- x - 新建形状的中心在页面上的 x 坐标。
- y - 新建形状的中心在页面上的 y 坐标。
- DataRecordsetID - DataRecordset 对象的 ID 属性值,该对象包含要链接到的数据行。
- DataRowID - 要链接到的数据行的 ID 属性值。
- ApplyDataGraphicAfterLink 一个 Boolean 值,在形状已具有数据图形时指定是否自动应用数据图形,或者在形状不具有数据图形时指定是否应用最近使用的数据图形。 默认设置是不应用数据图形。 有关数据图形的详细信息,请参阅关于以图形形式显示数据。
以下示例代码说明如何使用 DropLinked 方法在活动绘图页上创建一个链接到数据行的形状,该形状的中心位于页坐标 (2, 2) 处。 该示例将采用传入的 DataRecordset 对象,获取其 ID,再将该 ID 与所链接到的数据行的 ID 一起传入 DropLinked 方法。 放置的形状是该代码打开的 Basic_U.VSS 模具内一个停靠在 Visio 绘图窗口中的简单矩形。
在此示例中,数据行的 ID 设置为 1;在运行代码之前,请确保具有该 ID 的行已存在,或在代码中更改 ID 值。
Public Sub DropLinkedShape(vsoDataRecordset As Visio.DataRecordset)
Dim vsoShape As Visio.Shape
Dim vsoMaster As Visio.Master
Dim dblX As Double
Dim dblY As Double
Dim lngRowID As Long
Dim lngDataRecordsetID As Long
lngDataRecordsetID = vsoDataRecordset.ID
Set vsoMaster = Visio.Documents.OpenEx("Basic_U.VSS", 0).Masters("Rectangle")
x = 2
y = 2
lngRowID = 1
Set vsoShape = ActivePage.DropLinked(vsoMaster, dblX, dblY, lngDataRecordsetID, lngRowID, True)
End Sub
DropManyLinkedU 方法可同样创建一组链接形状,并返回形状 ID 的数组。 该方法采用要放置的形状的数组、坐标和要链接到的数据行作为参数。 对应数组索引位置的条目确定形状与数据行之间如何相关以及各个形状在页面上的放置位置。
将现有形状链接到数据
如果您精确地知道 Visio 绘图中的一个或多个现有形状与数据记录集中的一行或多行之间如何相互对应,则可通过下列方式将现有形状链接到数据:
- 将单个形状链接到单个数据行
- 将所选的形状链接到一个或多个数据行
- 将多个形状链接到多个数据行
此外,如果不知道形状与数据之间的精确映射,则可指示 Visio 根据所提供的有限匹配信息进行最佳匹配。
将单个形状链接到单个数据行
若要将单个形状链接到单个数据行,请使用 Shape.LinkToData 方法。 此方法采用数据记录集 ID 和数据行 ID 以及一个可选的 Boolean 标记(指定是否在数据图形中显示链接的数据)。 默认设置是显示数据图形。
将多个形状链接到数据
使用 Selection 对象的两个成员 Selection.LinkToData 和 Selection.AutomaticLink 方法,以及 Page.LinkShapesToDataRows 方法,可以将所选的一个或多个现有形状链接到数据。
Selection.LinkToData 方法的作用与 Shape 对象的同一方法非常类似,不过前者是将选定的多个形状(而不是单个形状)链接到单个数据行。
如果您不确定形状与数据行之间的对应关系,但知道每一个形状的某个特定属性均与数据记录集中一个列内的数据之间存在匹配关系,则可使用 Selection.AutomaticLink 方法将所选的一组现有形状链接到多行数据。 请注意,它必须是所有形状的相同属性。 有关此方法的详细信息,请参阅自动链接到数据。
Page.LinkShapesToDataRows 方法与 Selection.LinkToData 方法的类似之处在于链接的是多个形状。 但是,使用此方法向数据链接的是同一页中的形状,而不是所选范围内的形状。 LinkShapesToDataRows 方法用于将多个形状链接到多个数据行,而 LinkToData 方法用于将多个形状链接到单个行。 若要链接多个形状,请向 LinkShapesToDataRows 方法传入一对数组:一个用于形状,另一个用于数据行。 请注意,匹配的数组位置必须相互对应。 这样,举例来说,形状数组中位置为 1 的形状就可链接到数据行数组中位置为 1 的数据。 另外,在调用该方法时仍然可以可选地指定是否向链接形状应用现有的数据图形。
自动链接到数据
使用 Selection.AutomaticLink 方法,将所选形状(即为选择对象分配的形状)的形状数据值自动链接到数据记录集中的数据行。也就是说,无须指定所有形状和数据行之间的精确对应关系。 但是,若要向 Visio 提供创建链接需的足够信息,至少必须提供一组匹配的数据:数据库中列的名称、形状属性类型以及形状值(如果需要),这些数据都位于传递给该方法的相应数组的同一索引位置处。
形状属性类型指示匹配所基于的形状的属性。 该属性可以是形状数据项的值(以前称为自定义属性值)、形状文本或 VisAutoLinkFieldTypes 枚举中指定的其他值。
注意
例如,假设您的绘图中包含一组代表不同员工的所选形状。 这些形状用形状文本(这种情况下可能是相应员工的姓名)来标识。 (可以使用 Visio 附带的OrgData.xls工作簿中的某些员工姓名,然后连接到该数据源。默认情况下,OrgData.xls安装在以下路径上:C:\Program Files\Microsoft Office\Office15\Visio Content[ langID],其中 langID 因国家或地区而异。) 在某些计算机上,路径可能包括“Program Files (x86) ”而不是“Program Files”。
若要将这些形状连接到数据库(其中每个员工的数据构成一行),可以向 AutomaticLink 方法传入下列参数:
- DataRecordsetID - DataRecordset 对象的 ID 属性值,该对象包含要链接到的数据行。 在以下示例中,将为该过程传入一个现有数据记录集并获取其 ID。
- ColumnNames() 一个字符串数组,该数组由数据库中各列的名称组成。 在该数组中,必须至少有一个位置所包含的值与 AutoLinkFieldTypes 和 FieldNames 数组中同一位置处的值一致。 在以下示例中,将传入在数组位置 0 包含“Name”列名称的数组。
- AutoLinkFieldTypes() 一个由 VisAutoLinkFieldTypes 枚举中的值(Long 类型)组成的数组,该枚举由形状属性类型组成。 在该数组中,必须至少有一个位置所包含的值与 ColumnNames 和 FieldNames 数组中同一位置处的值一致。 在以下示例中,将传入在数组位置 0 的枚举值 visAutoLinkShapeText。
- FieldNames() 一个由形状值组成的字符串数组。 在 FieldNames 数组中,至少必须有一个位置所包含的值与 ColumnNames 和 AutoLinkFieldTypes 数组中同一位置处的值相对应。
- 对于 AutoLinkFieldTypes 的大多数值(如 visAutoLinkShapeText),不必指定 FieldNames 值;可改为传入一个空值。 本例中情况正是如此,因此传入的是空字符串。 但是,如果您传入 AutoLinkFieldTypes 的 visAutoLinkCustPropsLabel、visAutoLinkUserRowName、visAutoLinkPropRowNameU 或 visAutoLinkUserRowNameU 值,则只有传入完整指定形状数据项的 FieldNames 值,才能与数据列名进行比较。
- AutoLinkBehavior VisAutoLinkBehaviors 枚举中的一个值。 通过这些枚举值,可以自定义该方法,例如使用新链接替换现有链接。 以下示例将传入默认值 0。
- ShapeIDs() 该方法在返回时用链接形状的 ID 填充的一个数组。
以下示例显示了使用 AutomaticLink 方法自动链接形状和数据的方法。 该示例假定您已按照以上说明将绘图连接到 OrgData.xls 示例工作簿。 请注意,代码要求数据的第一列应命名为“Name”,OrgData.xls 即属于此种情况。 还请注意,要链接到数据的绘图中每种形状的形状文本都必须与 OrgData.xls 中“Name”列的某一名称匹配。
Public Sub LinkToDataAutomatically(vsoDataRecordset As Visio.DataRecordset)
Dim vsoSelection As Visio.Selection
Dim columnNames(1) As String
Dim fieldTypes(1) As Long
Dim fieldNames(1) As String
Dim shapesLinked() As Long
columnNames(0) = "Name"
fieldTypes(0) = Visio.VisAutoLinkFieldTypes.visAutoLinkShapeText
fieldNames(0) = ""
ActiveWindow.DeselectAll
ActiveWindow.SelectAll
Set vsoSelection = ActiveWindow.Selection
vsoSelection.AutomaticLink vsoDataRecordset.ID, _
columnNames, _
fieldTypes, _
fieldNames, 0, shapesLinked
End Sub
搜索形状和数据之间的链接
使用下列方法可确定向数据链接了哪些形状。 了解形状如何链接到数据有助于防止冲突和链接断开:
- Page.GetShapesLinkedToData
- Page.GetShapesLinkedToDataRow
- Shape.GetLinkedDataRow
- Shape.GetCustomPropertyLinkedColumn
- Shape.GetCustomPropertiesLinkedToData
- Shape.IsCustomPropertyLinked
断开形状和数据之间的链接
顾名思义,使用 Shape.BreakLinkToData 和 Selection.BreakLinkToData 方法可以通过编程方式断开形状和数据之间的现有链接。 此外,UI 中的各种更改可能会破坏这些链接。 例如,如果用户删除数据记录集、链接行或链接形状,或者,如果用户单击形状快捷菜单上的“取消行链接”或单击行快捷菜单上的“取消链接”,则可断开链接。
除非用户从 UI 中删除数据记录集、行或形状,否则所有这些操作都会触发 Shape.ShapeLinkDeleted 事件。 您还可以使用上一部分中列出的方法来确定链接状态。
获取和设置数据列属性
每个 DataRecordset 对象都包含与 DataRecordset 对象关联的所有 DataColumn 对象的 DataColumns 集合。 这些对象允许您将数据列映射到 ShapeSheet 的“形状数据”部分中的单元格。
以下示例说明如何获取传递给该方法的数据记录集第一列“形状数据”部分中“标签”单元格的值,并在“即时”窗口中显示该值。 然后,该示例对该值进行设置并显示新值。
对于链接到该数据记录集各行的所有形状来说,更改这个值也就是在“形状数据”对话框中更改形状数据项的标签。 为获取和设置“标签”单元格的值,该示例将 visDataColumnPropertyDisplayName 值从 VisDataColumnProperties 枚举传递给 DataColumn.GetProperty 和 DataColumn.SetProperty 方法。
Public Sub ChangeColumnProperties(vsoDataRecordset As Visio.DataRecordset)
Dim strPropertyName As String
Dim strNewName As String
Dim vsoDataColumn As Visio.DataColumn
strNewName = "New Property Name"
Set vsoDataColumn = vsoDataRecordset.DataColumns(1)
strPropertyName = vsoDataColumn.GetProperty(visDataColumnPropertyDisplayName)
Debug.Print strPropertyName
vsoDataColumn.SetProperty visDataColumnPropertyDisplayName, strNewName
strPropertyName = vsoDataColumn.GetProperty(visDataColumnPropertyDisplayName)
Debug.Print strPropertyName
End Sub
刷新链接数据和解决冲突
当绘图连接到的数据源中的数据发生更改时,您可以刷新 Visio 绘图中的数据以反映这些更改。 通过设置 DataRecordset.RefreshInterval 属性,可以指定 Visio 按指定的时间间隔自动刷新数据。 通过调用 DataRecordset.Refresh 方法,可以以编程方式刷新数据。
此外,您可以解决形状和数据行之间关系中的任何冲突。 例如,当您刷新数据记录集,而由于数据源的更改,形状在刷新操作之前链接到的某些数据行已不再存在时,就会发生冲突。 如果刷新的记录集中的两个或更多行具有相同的主关键字,也可能会发生冲突。
自动刷新链接数据
当您创建 DataRecordset 对象时,其 RefreshInterval 属性值将设置为默认值 0。 此设置指示不会自动刷新数据。 通过将 DataRecordset.RefreshInterval 设置为正的 Long 类型的值,可以指定自动刷新的时间间隔(以分钟为单位)。 可以指定的最小时间间隔是一分钟。 此设置对应于用户可以在“配置刷新”对话框中设置的值。
若要确定上一次刷新操作的日期和时间,请获取 DataRecordset.TimeRefreshed 属性。
此外,使用 DataRecordset.RefreshSettings 属性可以自定义数据的自动刷新。 通过将此属性设置为 VisRefreshSettings 枚举中的值组合,可以指定是发生下列任一种情况还是同时发生这两种情况:
- 禁用协调刷新冲突的 UI(“刷新冲突”任务窗格)。 (有关详细信息,请参阅下一部分。)
- 刷新操作自动覆盖在 UI 中对数据所做的更改。 此属性的默认值为 0,表示这两种情况均不发生。
标识数据记录集行以进行刷新操作
由于形状按其形状 ID 链接到特定数据行,因此当 Visio 刷新链接数据时,它必须确定自上次刷新数据以来添加、更改或删除了所链接的一个或多个数据记录集中的哪些行。 为了标识这些行,Visio 使用分配给数据记录集中行的行 ID。 根据您在创建数据记录集时是否为其指定了主关键字,Visio 可以按两种方式分配这些行 ID。
刷新不具有主键的数据记录集
在您创建数据记录集时,Visio 会根据数据源中现有的行顺序,向该记录集内的所有行分配行 ID。 记录集中的第一行通常会相应地分配行 ID 1,第二行通常会分配行 ID 2,依此类推。
这样,您就可向原始数据源添加数据行或从中删除数据行。 然后,当您刷新数据时,数据记录集将会反映这些更改。 这可能会导致数据记录集中的行顺序发生更改。
例如,在一个五行的数据记录集中,如果数据源中的第四行被删除,则当 Visio 刷新连接到该数据源的数据记录集时,该数据记录集中的第五行将成为新的第四行,并会分配行 ID 4。 行 ID 为 5 的行将从该数据记录集中删除。
因此,链接到行 ID 为 5 的行的形状将会断开其链接,而链接到行 ID 为 4 的行的形状现在将获得以前第五个位置的行中的数据。 这样,您可以看到,创建数据记录集时不指定主关键字可能会导致形状和数据之间的链接断开,也可能导致 Visio 将形状链接到不希望链接的行。
刷新具有主关键字的数据记录集
通过为数据记录集指定主关键字,可以帮助防止链接断开或不匹配。 主关键字标识包含每一行的唯一标识符的数据列的名称。 每一行的主关键字列中的值都唯一地标识数据记录集内的该行。 主关键字通常是 ID 值,但您也可将任意列或列组合设置为主关键字。 但是,为了在刷新数据时获得一致的结果,有必要将每行的主关键字列值(或多个主关键字列的值集)设置为唯一。
因此,当您或 Visio 刷新包含主关键字的数据记录集时,其中的行将保留与刷新操作之前相同的行 ID。 由于 Visio 按 ID(形状 ID 到行 ID)将形状链接到数据行,并且行 ID 在刷新操作之后保持不变,因此数据链接形状仍会链接到正确的行。 请注意,对于给定的数据记录集来说,行 ID 绝不会重复使用。
使用 DataRecordset.GetPrimaryKey 方法确定数据记录集的现有主键(如果已指定一个)。 此方法将数据记录集的主键设置作为 VisPrimaryKeySettings 枚举中的一个值返回。 使用单一或符合主键。 单一主键根据单个列中的值标识行。 复合主键使用两个或多个列唯一地标识一行。
如果主关键字设置是 visKeySingle 或 visKeyComposite,该方法还会返回主关键字列名字符串组成的数组。 如果主关键字设置是 visKeyRowOrder(默认值),则该方法返回一个空主关键字数组。
同样,可以使用 DataRecordset.SetPrimaryKey 方法指定数据记录集的主关键字设置以及要设置为主关键字列的列的名称。 另外,在设置主关键字时,请确保要选作主关键字列的列在每一行中都包含唯一值(或值集)。
以编程方式刷新链接数据
若要以编程方式刷新连接的数据记录集,请调用 DataRecordset.Refresh 方法。
调用此方法将执行与数据记录集关联的查询字符串,并使用该查询返回的数据更新链接的形状。 对特定的 DataRecordset 对象调用 Refresh 方法将导致刷新与同一个 DataConnection 对象关联的所有其他 DataRecordset 对象(即,这些对象的 DataConnection 属性具有相同值)。 DataRecordset 对象共享的相同 DataConnection 属性值被称为已处理的数据记录集。
如果调用 Refresh 时产生冲突,Visio 将在 UI 中显示“刷新冲突”任务窗格,除非将 RefreshSettings 属性设置为包括 visRefreshNoReconciliationUI 枚举值。
在刷新链接数据之前,如果希望更改 Visio 用来检索数据的查询,以查询相同数据库中的不同表,请将 DataRecordset.CommandString 属性设置为新值。 若要连接到全新的数据源,请同时设置 DataRecordset.CommandString 和 DataConnection.ConnectionString 属性值。
DataRecordset.GetLastDataError 方法可获取 Active X 数据对象 (ADO) 错误代码、ADO 说明和数据记录集 ID,它们与添加新数据记录集或刷新现有数据记录集中的数据时生成的最新错误相关联。
确定和解决冲突
如果在您或 Visio 刷新数据时出现冲突,可以使用 DataRecordset.GetAllRefreshConflicts 和 DataRecordset.GetMatchingRowsForRefreshConflict 方法来确定发生冲突的原因。 GetAllRefreshConflicts 方法将返回由形状组成的数组,这些形状中的数据与形状所链接到的数据记录集行中的数据之间存在冲突。 若要确定哪些数据记录集行产生了冲突,可以将每个形状传递给 GetMatchingRowsForRefreshConflict 方法,该方法将返回由存在冲突的行组成的数组。
当数据记录集中的两个或更多个行具有相同主关键字并且可能链接到同一个形状时,这些行可能存在冲突。 出现这种情况时,GetMatchingRowsForRefreshConflict 将返回至少包含两个行 ID 的数组。
在从数据记录集中删除以前的数据链接行时,也可能发生冲突。 出现这种情况时,该方法将返回空数组。
若要消除冲突,请将相应的形状传递给 DataRecordset.RemoveRefreshConflict 方法,该方法将从当前文档中删除冲突信息。
支持和反馈
有关于 Office VBA 或本文档的疑问或反馈? 请参阅 Office VBA 支持和反馈,获取有关如何接收支持和提供反馈的指南。