Veni, Vidi, VISIO
Veröffentlicht: 18. Dez 2002 | Aktualisiert: 21. Jun 2004
Von Senaj Lelic
VISIO ist vielen Benutzern als vielseitiges und komfortables Programm für die Erstellung von Diagrammen und Zeichnungen bekannt. Erst zusammen mit einigen Zeilen VBA-Code aber lässt sich die volle Funktionalität von VISIO ausnutzen. Unter anderem die automatische Generierung von Zeichnungen, Verbindung mit Office-Anwendungen und die Visualisierung von Prozessen.
Auf dieser Seite
Das Visio-Objektmodell
Einer nach dem anderen
Gruppenarbeit
Aktiv werden
Ab in die Zelle
Den Meister gefunden
Kleb' Dir eine
Properties im Dutzend
Netze malen
Gemeinsam stark
Das Visio-Objektmodell
Die Benutzung von Visio-Objekten folgt dem üblichen OLE-Schema: zuerst benötigen Sie einen Verweis auf ein Objekt, dann kann mit den Methoden und Eigenschaften des Objekts gearbeitet werden.
Einen Verweis auf ein Objekt erhalten Sie in der Regel durch die Nutzung einer Eigenschaft eines Objektes, welches in der Hierarchie des Visio-Objektmodells höher angesiedelt ist. Ein Objektmodell ist die Auflistung aller Objekte, welche eine Anwendung über die Automatisierungsschnittstelle zur Verfügung stellt.
In VBA ist das grundlegende Objekt VISIO, die VISIO-Anwendung selbst. So kann mit dem Ausdruck Visio.Documents auf die einzelnen Dokumente innerhalb der laufenden Anwendung zugegriffen werden.
Abbildung 1 zeigt einen Ausschnitt aus dem Objektmodell von VISIO, das vollständige Modell finden Sie in der Online-Hilfe zu VISIO und als Datei im Verzeichnis VISIO\DVS.
Bild 1 (ObjModel.wmf): Klar und strukturiert: das Objektmodell von VISIO.
Einer nach dem anderen
Einer der Vorteile des Objektmodells von VISIO gegenüber anderen OLE-Servern ist der klare Aufbau des Objektmodells. Basis für viele Elemente ist immer eine Collection mit dem Namen im Plural, welche dann die einzelnen Elemente des Namens enthält.
Ein Visio-Dokument kann aus mehreren Seiten bestehen (ähnlich den Arbeitsblättern in Excel), daher heißt die entsprechende Eigenschaft des Document-Objektes auch Pages. Diese liefert eine Collection von Page-Objekten. Auf einer Seite liegen mehrere Shapes, weshalb über die Eigenschaft Shapes eines Page-Objektes auf die Collection der Shape- Objekte zugegriffen werden kann.
Einige Methoden und Eigenschaften liefern keine Collections, sondern ein Array von Werten auf einmal. Ein Beispiel hierfür ist die Methode GetNames der Masters-Collection. Um die Namen aller MasterShapes eines Dokumentes auszulesen, können Sie folgendermaßen vorgehen:
Sub GetMasters() Dim MasterNames() As String Visio.Documents( _ "Clipart.vss").Masters.GetNames _ MasterNames For i = LBound(MasterNames) _ To UBound(MasterNames) Debug.Print MasterNames(i) Next i End Sub
Gruppenarbeit
Grundbestandteil einer VISIO-Zeichnung sind Shapes. Im einfachsten Fall besteht ein Shape aus einer Linie mit einem Anfangs- und einem Endpunkt. Allerdings wird auf komplexe Shapes genauso einfach zugegriffen wie auf die einfachsten Shapes: jedes Shape.Objekt besitzt die Möglichkeit, mit anderen zu einer Gruppe kombiniert zu werden. Das Ergebnis ist wieder ein Shape.Objekt, nämlich die gerade erzeugte Gruppe. Daher besitzt jedes Shape.Objekt auch selbst eine Eigenschaft Shape, welche bei einer Gruppe die einzelnen Shape-Objekte enthält, aus denen die Gruppe besteht.
Aktiv werden
Zur Erleichterung der Programmentwicklung existieren in VBA bei Visio einige Objekte, welche den Zugriff auf gerade aktive Dokumente und Seiten sehr erleichtern. Dies sind ActiveWindow, ActiveDocument und ActivePage.
Der Vorteil dieser Objekte liegt darin, dass Sie sich beim Programmieren sehr einfach auf die jeweils aktive Seite bzw. das gerade aktive Dokument beziehen können. Geben Sie zum Testen das folgende Kommando im Direktfenster des VBA-Editors ein:
Print ActiveDocument.Name, _ ActiveDocument.Title
Damit erhalten Sie sowohl den Dateinamen als auch den Titel (der Dokumenteneigenschaften) des aktiven Dokumentes.
Ab in die Zelle
Einer der Gründe für die Vielseitigkeit von VISIO ist das zugrunde liegende Design der Shapes. Intern werden alle notwendigen Daten in einem so genannten ShapeSheet gespeichert, das ist eine Art von Kalkulationsblatt für die Zeichnungselemente. Damit lässt sich beispielsweise ohne eine Zeile Programmierung festlegen, dass ein Shape immer doppelt so breit wie hoch dargestellt werden soll. Auch Datenfelder, Farben und alles andere sind letztlich nur Formeln im ShapeSheet. Natürlich können Sie mit VBA auf diese Zellen und Zeilen zugreifen und so auch Datenfelder hinzufügen oder das Verhalten von Shapes ändern.
Um das Shape mit dem Namen Anfang blau einzufärben, benötigen Sie zuerst eine Referenz auf das Shape:
Dim vShape as Visio.Shape vShape = ActivePage.Shapes("Anfang")
Jetzt wird aus dem ShapeSheet ein Verweis auf die Zelle mit dem Namen FillForeGnd geholt, welche die Farbe des Füllvordergrundes steuert:
Dim vCell As Visio.Cell Set vCell = vShape.Cells("FillForeGnd") vCell.Formula = "RGB(51;152;204)"
Wie Sie sehen, ist neben der Angabe der Farbnummer für die vordefinierten Farben auch die Verwendung der Funktion RGB zulässig, um jede Farbe im 24Bit-Farbraum zu definieren.
Eine Auflistung aller Zellen und ihrer Namen sowie der Abschnitte des ShapeSheets erhalten Sie aus der Online-Hilfe.
Den Meister gefunden
Um die Erstellung von Zeichnungen aus standardisierten Komponenten zu beschleunigen, stellt VISIO so genannte MasterShapes in eigenen Dateien zur Verfügung. Ein MasterShape ist eine Gruppe von Zeichnungselementen, welche einfach per Drag & Drop auf die Zeichenfläche gezogen wird und dadurch eine Kopie oder eine Instanz von sich erzeugt. Andere Programme besitzen unter dem Namen Symbolbibliothek oder Vorlagen ein ähnliches Konzept.
In VBA erfordert das Plazieren eines solchen Shapes über einen Master nur drei Zeilen:
Set vMasters = Visio.Documents( _ "Basic Network Shapes.vss").Masters set vMaster = vMasters( _ "Desktop PC") set vShape = _ ActivePage.Drop(vMaster,10.0,2.0)
Zuerst wird in einer Objektvariablen das Objekt mit der Masters-Collection gespeichert. Diese Collection enthält alle MasterShapes der angegebenen Datei (diese Dateien werden in VISIO als 'Stencils' oder 'Schablonen' bezeichnet und haben die Erweiterung .VSS).
Als zweiter Schritt wird eine Objektvariable erzeugt, welche auf ein ganz bestimmtes MasterShape zeigt, hier das mit dem Namen "Desktop PC".
Schließlich wird mit der Methode Drop eines Page-Objektes (hier der aktiven Seite) eine Instanz des Masters auf der Zeichenfläche platziert.
VISIO bietet für das Umrechnen von Werten, welche das System liefert, eine ganze Reihe Einheiten, von Inches über Millimeter bis zu Pixeln.
Beim Ablegen eines neuen Shapes auf dem Zeichenblatt aber akzeptiert die Methode Drop nur Werte in der Einheit Inches, also werden zwei Routinen für die Umrechnung in das metrische System benötigt:
' Umrechnung mm in Inches Function mm2inch( _ ByVal mm As Double) As Double mm2inch = mm / 25.4 End Function ' Umrechnung Inches in mm Function inch2mm( _ ByVal inch As Double) As Double inch2mm = inch * 25.4 End Function
Besonders leistungsfähig ist VISIO aber dadurch, dass die Verbindung eines so erzeugten Shapes zu seinem Master erhalten bleibt. Beim Ablegen des Masters auf der Zeichenfläche werden Ereignisse ausgelöst, auf die ein VBA-Modul reagieren kann.
Zusätzlich lassen sich über das Konzept des ShapeSheets jederzeit sowohl Master als auch 'normale' Shapes durch benutzerdefinierte Datenfelder erweitern. So ist es beispielsweise kein Problem, das ShapeSheet um ein Datenfeld für die IP-Adresse eines Computers zu ergänzen und dann per VBA darauf zuzugreifen:
set vShape = _ ActivePage.Shapes("HP9000") Set vCell = vShape.Cells("Prop.IP") vShape.text = vCell.Formula
Kleb' Dir eine
Verschiedene Shapes lassen sich in VISIO durch so genannte Verbinder dauerhaft 'verkleben'. Wird nach einer solchen Operation eines der verbundenen Shapes bewegt, so ändert sich der Verbinder entsprechend mit.
Für diese Funktionalität existiert in VBA die Methode GlueTo:
set vArrow = _ ActivePage.Shapes("Result") set vShape = _ ActivePage.Shapes("Process.4") vArrow.Cells("EndX").GlueTo _ vShape.Cells("Connections.X3")
Dies verbindet den Endpunkt des Verbinders mit dem Namen Result und dem dritten Verbindungspunkt des Shapes. Des Weiteren wird er mit dem Namen Process.4 verbunden, wobei eine evtl. bereits vorher bestehende Verbindung des Pfeils gelöst wird.
Properties im Dutzend
Viele VISIO-Zeichnungen, die als Dokumentation begonnen wurden, leiden daran, dass nach einiger Zeit die eine oder andere Eigenschaft oder Beschriftung fehlt. Dem lässt sich für eine beliebige Anzahl von Shapes auf einer Seite ganz leicht mit ein paar Zeilen VBA-Code abhelfen.
Im ShapeSheet besteht wie bereits erwähnt die Möglichkeit, eigene Zellen zu erstellen und dort Daten zu einzelnen Shapes abzulegen. Genau dies soll unser Programm erledigen: bei allen Shapes einer Seite, welche noch keine benutzerdefinierte Eigenschaft Inventarnummer haben, soll dies ergänzt werden.
Sub MakeProperties() Dim vShape As Visio.Shape Dim i, j As Integer For i = 1 To _ ActivePage.Shapes.Count Set vShape = _ ActivePage.Shapes(i) If Not vShape.CellExists( _ "Prop.Inventarnummer", _ True) Then If Not _ vShape.SectionExists( _ visSectionProp, True) Then j = vShape.AddSection( _ visSectionProp) End If j = vShape.AddNamedRow( _ visSectionProp, _ "Inventarnummer", 0) vShape.Cells( _ "Prop.Inventarnummer.Prompt" _ ).Formula = "=" & Chr(34) _ & "Bitte Inv.-Nr. eingeben " _ & Chr(34) vShape.Cells( _ "Prop.Inventarnummer.Type" _ ).Formula = 0 End If Next i End Sub
Nach dem Durchlaufen dieser Prozedur besitzt jedes Shape einen Eintrag im ShapeSheet, der in der Zeichnung über das Kontextmenü und die Option Shape / Custom Properties bzw. Shape / Datenfelder ... aufgerufen werden kann.
Bild 2 (screenshot2.tif): Verwendung von Custom Properties / Datenfeldern
Netze malen
Als ein letztes, praktisch einsetzbares Beispiel für die VBA-Programmierung von VISIO werden wir Inventurdaten eines Netzwerkes aus einer Datenbank auslesen und per Programm eine Zeichnung dieses Netzwerks in VISIO generieren.
Natürlich ist dies noch kein Ersatz für professionelle Software, aber bereits ein ganz guter Ausgangspunkt für eine automatisierte Dokumentation 'on demand'.
Die Daten liegen für unser Beispiel in einer MS Access Datenbank mit dem Namen machines.mdb und besitzen den in Tabelle 1 gezeigten Aufbau:
Bild 3 (Tabelle1.tif): Aufbau der Datenbank für die Inventardaten
Die Daten werden mit einer SQL-Abfrage ausgelesen und enthalten unter anderem eine Spalte Type, in der das gewünschte MasterShape angegeben wird. So enthält die Zeichnung später gleich die richtigen Bildsymbole für Server und Arbeitsplatzrechner.
Dazu wird eine Reihe von Deklarationen benötigt, um die entsprechenden Variablen zu erhalten:
' der SQL-String für die Abfrage Dim sSQL As String sSQL = "SELECT * FROM machines" ' für den Zugriff aus die MDB-Datei Dim rs As Recordset Dim db As Database ' Visio-Variablen Dim vShape As Visio.Shape Dim vMasters As Visio.Masters Dim vMaster As Visio.Master Dim vDoc As Visio.Document ' Hilfsvariablen Dim xpos as Integer Dim ypos as Integer Dim sMasterName As String Dim sText As String
Um die entsprechende Datei mit den MasterShapes zu laden, die als Vorlage dienen, wird mit der Methode OpenEx die Datei geöffnet und als angedocktes Fenster und schreibgeschützt neben unserem Zeichnungsfenster dargestellt.
Danach wird in der Variablen vMasters der Verweis auf die Collection mit den MasterShapes gespeichert.
Jetzt können wir darangehen, die Abfrage der Datenbank durchzuführen und die Zeichnung dynamisch zu erzeugen.
Alles was noch erledigt werden muss, ist die Definition des Beginns der Zeichenoperation auf der Seite. VISIO verwendet ein 'normales' Koordinatensystem, das heißt der Nullpunkt einer Seite liegt links unten. Über die Eigenschaft PaperHeight ist es ein Leichtes, diese Daten zu erhalten und die Position für das erste Shape festzulegen:
Set vDoc = Visio.Documents.OpenEx( _ "Basic Network Shapes.VSS", _ visOpenRO + visOpenDocked) Set vMasters = Visio.Documents( _ "Basic Network Shapes.vss").Masters Set db = _ OpenDatabase("machines.mdb", , True) Set rs = db.OpenRecordset(sSQL) ypos = ActiveDocument.PaperHeight( _ "mm") - 40 ' 4 cm vom oberen Rand xpos = 20 ' 2 cm vom linken Rand rs.MoveFirst
Jetzt wird in einer Schleife durch das RecordSet gelaufen und jedes Mal ein Satz aus der Tabelle der Datenbank gelesen. Der Name für das benötigte MasterShape steht in der Spalte Type (in einem Programm für den tatsächlichen Einsatz wird man diese Information nicht immer so einfach erhalten, sondern unter Umständen über eine Umsetzung den Namen des Mastershapes erst errechnen müssen).
Mit der Methode ActivePage.Drop wird eine Instanz des Mastershapes auf der Zeichenfläche platziert und dann die Beschriftung (die Eigenschaft Text eines Shapes) aus den restlichen Spalten der Tabelle erzeugt.
Jetzt muss nur noch der Zeiger im RecordSet weiterbewegt werden, bis das Ende der Tabelle erreicht wurde.
Do sMasterName = _ rs.Fields("Type").Value Set vMaster = _ vMasters.Item(sMasterName) Set vShape = _ ActivePage.Drop(vMaster, _ mm2inch(xpos), mm2inch(ypos)) sText = _ rs.Fields("Manufacturer").Value _ & " " & _ rs.Fields("ModelNumber").Value sText = sText & Chr(13) & Chr(10) _ & rs.Fields("IPAddr").Value vShape.Text = sText xpos = xpos + _ vShape.Cells("Width").Result("mm") _ + 15 rs.MoveNext Loop Until rs.EOF
Alles, was jetzt noch zu tun bleibt, ist das Schließen der Verbindung zur Datenbank und sicherheitshalber das Setzen der Objektvariablen auf Nothing.
rs.Close db.Close Set rs = Nothing Set db = Nothing
Als Ergebnis erhalten wir dann die in der Abbildung gezeigte Ausgabe, aktuell aus der Datenbank generiert.
Bild 4 (screenshot1.tif): Das Ergebnis: eine programmerzeugte Ansicht der LAN-Datenbank.
Gemeinsam stark
Das Geheimnis erfolgreicher VBA-Programmierung für VISIO ist also gar kein solches. Alles, was Sie benötigen, finden Sie bereits vor: ein gut strukturiertes und leicht erfassbares Objektmodell, eine große Menge von bereits mit Zusatzfeldern versehenen MasterShapes und dazu das extrem flexible Konzept des ShapeSheets.
Viele Dinge lassen sich zwar bereits entweder mit VBA- Makros oder über das ShapeSheet erledigen, aber erst die Kombination der beiden Konzepte erlaubt es, VISIO beispielsweise als Online-Netzwerkvisualisierungstools zu benutzen.
Natürlich kann im Rahmen eines Artikels nicht das gesamte Objektmodell und schon gar nicht jede Zeile des ShapeSheets vorgestellt werden, aber Sie haben sicherlich bereits jetzt einen Einblick in die grenzenlosen Möglichkeiten von VISIO erhalten.
Anmerkung
Die Beispiel- Quellcodes gehen von einem englischen VISIO aus, werden aber genauso unverändert auf einer deutschen VISIO- Version laufen.