Visio Guy

Visio Discussions => Programming & Code => Topic started by: M.G.Ford on March 30, 2016, 03:23:40 PM

Title: determining if a row in a recordset is linked to a shape
Post by: M.G.Ford on March 30, 2016, 03:23:40 PM
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.
Title: Re: determining if a row in a recordset is linked to a shape
Post by: Thomas Winkel on March 30, 2016, 10:57:41 PM
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
Title: Re: determining if a row in a recordset is linked to a shape
Post by: Nikolay on March 31, 2016, 01:05:11 AM
> 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.
Title: Re: determining if a row in a recordset is linked to a shape
Post by: M.G.Ford on March 31, 2016, 12:24:07 PM
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.