Hi,
First, I know there is a cumbersome way to do this contained in the post: http://visguy.com/vgforum/index.php?topic=3820.0 (http://visguy.com/vgforum/index.php?topic=3820.0)
The question is, though, does anyone know a way that I might iterate through a recordset to test each row for it being linked to a shape? I don't care where in the drawing the shape is, I just care that it is or is not linked. This will happen after a recordset refresh. For a fresh pull, I just drop all the shapes easily. The goal is to drop a new shape for only the rows that were added to the recordset.
I know that I can get the recordset row ID from a shape that is already existing. I am looking to come at it from the recordset direction. It just feels like there has to be a better way than the nested loop of shape/page traversal.
What I might be able populate an array of primary keys in the records set before the refresh and after then compare the two.
Any thoughts?
Michael.
Hi,
try this code:
Sub findUnlinkedData()
Dim drs As Visio.DataRecordset
Dim pge As Visio.Page
Dim dataRowIDs() As Long
Dim dataRowID As Long
Dim shapeIDs() As Long
Dim test As Long
Dim linked As Boolean
Dim i As Integer
For Each drs In ActiveDocument.DataRecordsets
dataRowIDs = drs.GetDataRowIDs("")
For i = LBound(dataRowIDs) To UBound(dataRowIDs)
linked = False
dataRowID = dataRowIDs(i)
For Each pge In ActiveDocument.Pages
pge.GetShapesLinkedToDataRow drs.id, dataRowID, shapeIDs
On Error Resume Next
test = UBound(shapeIDs) 'Causes an error if shapeIDs is not allocated
If err.Number Then
err.Clear
Else
linked = True
Exit For 'At least linked once
End If
On Error GoTo 0
Next pge
If (Not linked) Then
Debug.Print drs.name & ": ID: " & dataRowID & " > not linked"
Else
Debug.Print drs.name & ": ID: " & dataRowID & " > linked to " & pge.Shapes.ItemFromID(shapeIDs(0)).name
End If
Next i
Next drs
End Sub
Here is the original thread:
http://visguy.com/vgforum/index.php?topic=3960.msg15443
Regards,
Thomas
> The goal is to drop a new shape for only the rows that were added to the recordset.
If this is the goal, then it looks like you can achieve that by first getting the list of linked rows before refresh and then after refresh using the rs.GetDataRowIDs,
and then comparing the two.. if a row presents in in the new recordset, but does not present in the old one, that means it is new, right..?
oldRows = rs.GetDataRowIDs
rs.Refresh()
newRows = rs.GetDataRowIDs
addedRows = newRows - oldRows
I mean, if you only care about added rows, then it does not seem to matter if existing are linked or not, right?
In this case all you need is to implement "-" (set substraction) operation - not sure what is the easiest way to do it in VBA.
In normal languages you have something like "set_difference" built-in function for this purpose.
But anyways, the time will be linear.
We were thinking along the same lines with diffing before and after the refresh. I was going to work on doing that today but will check out the above provided code. After the refresh I have 3 goals:
1. Delete shapes that correspond to rows in the recordset that no longer exist. The shape conflict functionality that Visio has takes care of thiss
2. Update the data in the shapes to match the data in the recordset. I have a function that I use for that so I am covered there
3. dropping new shape. that is the subject of this post.
I was hoping that the conflict resolution functionality would deal with new rows but it doesn't seem to so I have to do that in code. I was thinking about doing the before/after comparison and divide the new recorder set into three groups: drop, update and delete the loop through the resulting sets and act.
For all the Visio does, it seems that the VBA support is half baked. It forces us to do more coding that we should have to. Anyway, I will leave an update on the suggestions above. Thank you, all
Michael.