i'm not sure how this has been overlooked in probably the most widely used network diagramming tool in the world.
is there no built-in way to attach/assign things like IP and MAC addresses to connection points? preferably as searchable/sortable/customizable attribute fields rather than a just a text box, but a text box would be a start at least.
is there any way with VBA to make this happen?
thanks,
Leon
Hi Leon,
Connection points don't have any built-in data structures that you can exploit.
You can, however, name connection point rows in the ShapeSheet.
Add Shape Data (Custom Property) fields to shapes. This data could be associated with the CPs by a system of your devise.
Same with User-defined cells or Scratch cells in the ShapeSheet.
Shapes can hold XML data, and you can write just about any kind of string-data into ShapeSheet cells. So there is plenty of flexibility, just nothing really built-in and ready to go.
It's an interesting challange.
At it's most basic you should start out with how will an individual port be identified within an enterprise. The starting point of course is a unique name for the port and the component that it is a part of. The stumbling point here of course is that the component name is often not the same as the network name that at first blush would be assumed. Consider the issue of a large router (such as the Cisco 6500 series), with multiple ethernet cards and each having a possible 48 ports. The next issue comes with how much information you may need to keep track of. The IP address and Mac addresses may only be the start (speed, utilization, technology, connector type, wwwnid, etc.)
I use a two part name for a port that is based on the concept of "slots" and "ports". A "slot" is where a component may be plugged into. Examples : A router into a rack, a power supply / blade into switch, a blade into a chassis, a gbic into a switch. The key point here is that within visio almost all of these are handled as 1D shapes. So for a switch card being installed into a router's (rtrABC) first slot, the component name is rtrABC_1. I use the underscore as the delimiter. Slot connection points are explicitly defined by me in the master shapes as well. I found this out the hard way because all the vendor shapes don't necessarily start at point 1 and move incrementally (some vendor racks start at the bottom, others at the top). A slot obviously has two points (side 1 and side 2) and can be horizontal or vertical. I use point 1 as the left (or bottom) and side 2 as right (or top). Slot connection points then might be "slot_1_1"
For a port on the switch, the connection point is explicitly named port_X_Y, where X is a named port and Y is a technology. As an example port_cons_31 in my implementation is the console port and uses ethernet (31). This naming standard allows me to validate the shapes using vba for "slots" and "ports". Since my drawings are created from an external database, I can validate and datamine using standard tools.
The nice thing about this is that when you're analyzing cables with the shapesheet
=PAR(PNT(rtrABC_5!Connections.port_1_32.X,rtrABC_5!Connections.port_1_32.Y))
it becomes fairly straight forward.
Data schemas for this type of enterprise implementation can get complex.
al
ps Sorry for the long posting
When working with collections and vba it is possible to lose sight of some of the things you might be able to do. This demo code shows how a vba user might build and save collections in a visio shapesheet cell as a complex string.
Have fun,
al
Option Explicit
Public Sub demoStringStuff()
Dim strIn As String
Dim strOut As String
Dim colA As collection
Set colA = New collection
Dim colB As collection
Set colB = New collection
Dim colC As collection
Set colC = New collection
With colA
.Add "CompA"
.Add "PortA"
.Add "127.0.0.1"
.Add "0123456789ab"
End With
strIn = BuildCsvString(colA)
MsgBox strIn
Set colB = BuildCsvCollection(strIn)
strOut = ""
strOut = strOut & colB.Item(1) & "= component" & vbCrLf
strOut = strOut & colB.Item(2) & "= port" & vbCrLf
strOut = strOut & colB.Item(3) & "= ipaddr" & vbCrLf
strOut = strOut & colB.Item(4) & "= macaddr" & vbCrLf
MsgBox strOut
Dim intX As Integer
intX = ParseItemsToCollection(colB.Item(3), colC, ".", "integer")
strOut = "IpAddress " & vbCrLf
strOut = strOut & colC.Item(1) & " first byte" & vbCrLf
strOut = strOut & colC.Item(2) & " second byte " & vbCrLf
strOut = strOut & colC.Item(3) & " third byte " & vbCrLf
strOut = strOut & colC.Item(4) & " final byte " & vbCrLf
MsgBox strOut
Dim blnTrueFalse As Boolean
blnTrueFalse = memberStringOfCollection(colB, "127.0.0.1")
If blnTrueFalse = True Then
MsgBox "We found a loopback address"
Else
MsgBox "loopback not in use"
End If
End Sub
'***************************************************************************
'
' simple collection handlers
'
'***************************************************************************
'
' test for case neutral member
'
Private Function memberStringOfCollection _
(ByVal colStrings As collection, _
ByVal strMember As String) _
As Boolean
Dim intX As Integer
Dim blnReturn As Boolean
blnReturn = False
For intX = 1 To colStrings.Count
If LCase(strMember) = LCase(colStrings.Item(intX)) Then
blnReturn = True
GoTo ExitHandler
End If
Next intX
ExitHandler:
memberStringOfCollection = blnReturn
End Function
'
'
'
Private Sub removeStringFromCollection _
(ByRef colStrings As collection, _
ByVal strRemove As String)
Dim intX As Integer
For intX = colStrings.Count To 1 Step -1
If LCase(colStrings.Item(intX)) = LCase(strRemove) Then
colStrings.Remove intX
End If
Next intX
Exit Sub
ErrHandler:
Debug.Print "removestringfromcollection " & Err.Description
End Sub
'
'
'
Private Sub addStringToCollection _
(ByRef colStrings As collection, _
ByVal strNew As String, _
Optional ByVal blnUnique As Boolean = True)
Dim intX As Integer
Dim blnFound As Boolean
blnFound = False
'
' blnUnique ensures that the result is a list of unique names
'
If blnUnique = True Then
For intX = 1 To colStrings.Count
If colStrings.Item(intX) = strNew Then
blnFound = True
GoTo Found
End If
Next intX
End If
Found:
If blnFound = False Then
colStrings.Add strNew
End If
End Sub
Private Function ParseItemsToCollection _
(ByVal s As String, _
ByRef colA As collection, _
ByVal Delim As String, _
Optional ByVal strType As String = "string") _
As Integer
'
Dim p As Long
Dim I As Long
'
' Check for valid delimiter
'
If Delim = "" Then
ParseItemsToCollection = -1
Exit Function
End If
'
' Copy Items
'
p = InStr(1, s, Delim, vbTextCompare)
Do While p > 0
Select Case strType
Case "string"
colA.Add Left$(s, p - 1)
Case "integer"
colA.Add CInt(Left$(s, p - 1))
Case "double"
colA.Add CDbl(Left$(s, p - 1))
Case "long"
colA.Add CLng(Left$(s, p - 1))
End Select
s = Mid$(s, p + 1)
p = InStr(1, s, Delim, vbTextCompare)
Loop
'
' Copy Last Item
'
Select Case strType
Case "string"
colA.Add s
Case "integer"
colA.Add CInt(s)
Case "double"
colA.Add CDbl(s)
Case "long"
colA.Add CLng(s)
End Select
'
ParseItemsToCollection = colA.Count
Exit Function
ErrHandler:
Debug.Print "ParseItemsToCollection " & Err.Description
ParseItemsToCollection = colA.Count
End Function
'
' create a csv string with end brackets from a collection
'
Private Function BuildCsvString _
(ByVal colA As collection) _
As String
Dim intX As Integer
Dim intY As Integer
On Error GoTo ErrHandler
Dim strCsv As String
strCsv = ""
If (colA Is Nothing) _
Or (colA.Count = 0) Then
strCsv = "[]"
GoTo ExitHandler
End If
If colA.Count = 1 Then
strCsv = "[" & CStr(colA.Item(1)) & "]"
GoTo ExitHandler
End If
With colA
' start bracket
strCsv = "["
For intY = 1 To colA.Count
strCsv = strCsv & CStr(colA.Item(intY))
If intY <> colA.Count Then
strCsv = strCsv & ","
End If ' test for last position
Next intY
' end bracket
strCsv = strCsv & "]"
End With
ExitHandler:
BuildCsvString = strCsv
Exit Function
ErrHandler:
BuildCsvString = strCsv
Debug.Print "BuildCsvString " & Err.Description
End Function
'
' pass in a bracketed string of csv separated items and pass back a collection
' strType allows the user to define what the collection is composed of
'
Private Function BuildCsvCollection _
(ByVal strCsv As String, _
Optional ByVal strType As String = "string") _
As collection
On Error GoTo ErrHandler
Dim colReturn As collection
Set colReturn = New collection
Dim intX As Integer
' get rid of first bracket
If InStr(1, strCsv, "[") Then
strCsv = Replace(strCsv, "[", "")
Else
GoTo ExitHandler
End If
' get rid of second bracket
If InStr(1, strCsv, "]") Then
strCsv = Replace(strCsv, "]", "")
Else
GoTo ExitHandler
End If
intX = ParseItemsToCollection(strCsv, colReturn, ",", strType)
ExitHandler:
Set BuildCsvCollection = colReturn
Exit Function
ErrHandler:
Set BuildCsvCollection = colReturn
Debug.Print "BuildCsvCollection " & Err.Description
End Function