First time user of VBA coding with Visio here!
I am using Visio 2010 Pro
I am trying to automate a the drawing of a system architecture diagram using VBA. The data source is an Excel sheet. Hopefully this is the result...
I have written VBA to read the Excel sheet, and can create the shapes on the page with a bit of help from the internet (thanks everyone!)
The path I was looking to take was:
- Drop Objects for each of the systems first
- Using autoconnect, loop through the recordset and draw the links (showing the integration) between systems
- From the Excel data, the links know the name of the shapes they are connecting (and I assign the shape.name when I drop the shapes on the page).
I do not know how to use the shape name to identify a unique shape object (which could be used as parameters for the autoconnect method)
Is there a better or easier way to do this?
I have seen the Autoconnect example (http://msdn.microsoft.com/en-us/library/office/ms427221%28v=office.12%29.aspx); which works fine if I have a handle on the objects created at run time (I.e. a variable for each object created. In my case, I am not storing that anywhere. I gave thought to storing this info in an array and then looping through same to find the object.
I’d like some thoughts as to the best way to do this. Given I am a Visio newbie, some sample (working?) code would be very well received.
The code I am particularly interested in sorting out is commented with "connect the shapes..."
One other little issue I have; is that a new stencil is created every time that I run the VBA. How can I still choose a master without doing this?
Many thanks!
I wasn’t sure how much info people would need to get an idea as to what I am trying to achieve and so have attached the code I’ve written/hacked/plagiarised to date
Public Sub DrawSystem()
Dim strConnection As String
Dim strCommand As String
Dim vsoDataRecordset As Visio.DataRecordset
strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;" _
& "User ID=Admin;" _
& "Data Source=" + "b:\visio\Objects2;" _
& "Mode=Read;" _
& "Extended Properties=""HDR=YES;IMEX=1;MaxScanRows=0;Excel 12.0;"";" _
& "Jet OLEDB:Engine Type=34;"
strCommand = "SELECT * FROM [Sheet1$]"
' load the data ...
Set vsoDataRecordset = ActiveDocument.DataRecordsets.Add(strConnection, strCommand, 0, "Objects")
'Stencil document that contains master
Dim stnObj As Visio.Document
'Master to drop
Dim mastObj As Visio.Master
'Pages collection of document
Dim pagsObj As Visio.Pages
'Page to work in
Dim pagObj, activePageObj As Visio.Page
'Instance of master on page
Dim shpObj As Visio.Shape
Dim shpFrom As Variant
Dim shpTo As Variant
Set stnObj = Documents.Add("Basic Shapes.vss")
' create a new page in the document
Set pagObj = ThisDocument.Pages.Add
pagObj.Name = "Page-" & Pages.Count
' -------------------------------------------------------
' LOOP THROUGH THE RECORDSET
' -------------------------------------------------------
Dim lngRowIDs() As Long
Dim lngRow As Long
Dim lngColumn As Long
Dim varRowData As Variant
' process the ENTITY records
Debug.Print "PROCESSING ENTITY RECORDS"
lngRowIDs = vsoDataRecordset.GetDataRowIDs("")
' draw rectangles for systems
Set mastObj = stnObj.Masters("Rectangle")
'Iterate through all the records in the recordset.
For lngRow = LBound(lngRowIDs) To UBound(lngRowIDs)
varRowData = vsoDataRecordset.GetRowData(lngRow)
If varRowData(2) = "ENTITY" Then
' draw a new object on the created page with the correct details
' TODO - work out how to programmatically draw them in an appropriate location
Set shpObj = pagObj.Drop(mastObj, lngRow / 2, lngRow / 2)
' set the appropriate attributes on the new object from the dataset
shpObj.Name = varRowData(3)
shpObj.Text = varRowData(7)
shpObj.data1 = varRowData(3)
shpObj.data2 = varRowData(7)
shpObj.Data3 = varRowData(8)
shpObj.Cells("Width") = 0.75
shpObj.Cells("Height") = 0.5
Debug.Print ("Created Object: " & varRowData(3) & " : ID = " & shpObj.ID)
Else
Debug.Print ("SKIPPED:" & varRowData(2) & " : " & varRowData(0))
End If
Next lngRow
' process the LINK records
Debug.Print "PROCESSING LINK RECORDS"
lngRowIDs = vsoDataRecordset.GetDataRowIDs("")
Set mastObj = stnObj.Masters("Dynamic Connector")
'Iterate through all the records in the recordset.
For lngRow = LBound(lngRowIDs) To UBound(lngRowIDs)
' only process LINK records
If varRowData(2) = "LINK" Then
Debug.Print ("Joining! " & varRowData(4) & " - " & varRowData(5) & " with " & varRowData(6))
Set shpObj = pagObj.Drop(mastObj, 2 + lngRow * 3, 0 + lngRow * 3)
varRowData = vsoDataRecordset.GetRowData(lngRow)
shpObj.Name = varRowData(6)
shpObj.Text = varRowData(7)
' connect the shapes ...
shpFrom = activePageObj.Shapes(varRowData(4))
shpTo = activePageObj.Shapes(varRowData(5))
shpFrom.AutoConnect shpTo, visAutoConnectDirNone
Else
Debug.Print ("LINK SKIPPED:" & varRowData(2) & " : " & varRowData(0))
End If
Next lngRow
End Sub
Here is the data file that I have been using to test ... (copy and paste into Excel)
1,,ENTITY,A,,,1,1: A,ONE
2,,ENTITY,B,,,2,2: B,TWO
3,,ENTITY,C,,,3,3: C,THREE
13,1,LINK,LINK1,A,B,13.1,13.1: LINK1,LINK1
13,2,LINK,LINK2,A,C,13.2,13.2: LINK2,LINK2
13,2,LINK,LINK2,C,B,13.2,13.2: LINK2,LINK2