Suchen

Die Tastenkombination Strg + F zum Suchen ist hinlänglich bekannt. Sie funktioniert in allen Anwendungsprogrammen, die ich kenne, in allen Browsern, pdf-Programmen (allerdings leider nicht in Outlook). Aber in Visio.
Meistens werden Sie dort nach bestimmten Texten suchen.
Für die Programmierung ist es enorm wichtig, dass man auch nach Shape-Namen suchen kann. Also beispielsweise das Shape Sheet.18727. Der Name wird durch den (VBA-)Code ermittelt.

PinX und LocPinX

Gestern habe eine Visio-Zeichnung, aus der ich Informationen per Programmierung auslese, zurückgeschickt bekommen. Einige Informationen werden nicht gefunden, war der Vorwurf. Der Grund war schnell gefunden.
Der „Nachbarrtisch“ wurde nicht gefunden, weil ich davon ausgehe, dass der Pin sich immer in Mitte-Mitte des Shapes befindet. Wenn allerdings der Anwender (aus Versehen) den Pin verschiebt, so stimmen meine Programmierresultate nicht mehr.
Ich könnte nun die Position des LocPinX und LocPinY berechnen. Ich tendiere dazu in den Shapes die Funktion =Width*0.5 und Height*0.5 mit der Funktion GUARD zu sperren.

Pfeilrichtung

Ich lese per Programmierung die Laufrichtung von Gängen von Visio-Zeichnungen aus. Ich stutze, weil das Ergebnis nicht korrekt ist. Schaue mir die Zeichnungen genauer an: Warum zeigen einige Pfeile mit einem Winkel 90° nach links, während andere Pfeile mit dem Winkel -90° auch nach links zeigen? Die Lösung ist schnell gefunden: einige Pfeile wurden gespiegelt. Also muss man neben dem Winkel auch noch FlipY überprüfen. Dann findet man die Pfeilrichtung.

Nachbarshapes

Der Befehl
SpatialRelation
ist klasse: damit kann man überprüfen, ob ein Shape in der Nähe eines anderen liegt. Durchläuft man mit einer Schleife alle Shapes, kann man schnell die Nachbarn herausfinden.
Allerdings: ich suche die benachbarten „Regale“ zu den Spirituosen und finde drei Regale (ich suche nur nach den weißen Shapes). Was tun? Also doch ein bisschen x- und y-Rechnung:
For j = 1 To UBound(strShapeNameMitText)
If vsBlatt.Shapes(strShapeNameMitText(j)).Cells(„FillForegnd“).Result(„in“) = 1 Then
If Asc(Left(vsBlatt.Shapes(strShapeNameMitText(j)).Text, 1)) <> 63 Then
If vsBlatt.Shapes(strShapeNameMitText(i)).SpatialRelation(vsBlatt.Shapes(strShapeNameMitText(j)), dblTolerance, visSpatialIncludeHidden) > 0 Then
If CInt(vsBlatt.Shapes(strShapeNameMitText(j)).Cells(„Angle“).Result(„deg“)) = 0 Then ‚ — waagrecht
If (vsBlatt.Shapes(strShapeNameMitText(j)).Cells(„PinX“).Result(„cm“) >= vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„PinX“).Result(„cm“) – _
vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„Width“).Result(„cm“) / 2 And _
vsBlatt.Shapes(strShapeNameMitText(j)).Cells(„PinX“).Result(„cm“) <= vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„PinX“).Result(„cm“) + _
vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„Width“).Result(„cm“) / 2) Then
xlZelle.Offset(lngExcelZeile, 8).Value = vsBlatt.Shapes(strShapeNameMitText(j)).Text
xlZelle.Offset(lngExcelZeile, 9).Value = vsBlatt.Shapes(strShapeNameMitText(j)).Name
lngExcelZeile = lngExcelZeile + 1
blnRegalierung = True
End If
Else
If (vsBlatt.Shapes(strShapeNameMitText(j)).Cells(„PinY“).Result(„cm“) >= vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„PinY“).Result(„cm“) – _
vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„Width“).Result(„cm“) / 2 And _
vsBlatt.Shapes(strShapeNameMitText(j)).Cells(„PinY“).Result(„cm“) <= vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„PinY“).Result(„cm“) + _
vsBlatt.Shapes(strShapeNameMitText(i)).Cells(„Width“).Result(„cm“) / 2) Then
xlZelle.Offset(lngExcelZeile, 8).Value = vsBlatt.Shapes(strShapeNameMitText(j)).Text
xlZelle.Offset(lngExcelZeile, 9).Value = vsBlatt.Shapes(strShapeNameMitText(j)).Name
lngExcelZeile = lngExcelZeile + 1
blnRegalierung = True
End If
End If
End If
End If
End If
Next

Hyperlinks in Excel auf Visio-Dateien

Erstaunlich:
ein kleines VBA-Skript schreibt die Namen aller Dateien eines Ordners in eine Exceltabelle.
Sub AlleVisioZeichnungen()
Dim strPfad As String
Dim strDatei As String
Dim i As Integer

strPfad = „D:\Eigene Dateien\Visio\contoso\“

strDatei = Dir(strPfad, vbNormal)
i = 2
Do While strDatei <> „“

If Right(strDatei, 4) = „.vsd“ Or Right(strDatei, 4) = „.vsdx“ Or Right(strDatei, 5) = „.vsdm“ Then
ActiveSheet.Cells(i, 1).Value = strDatei
Range(„A1“).Hyperlinks.Add Anchor:=ActiveSheet.Cells(i, 1), _
Address:=strPfad & strDatei, _
TextToDisplay:=strDatei
i = i + 1
End If

strDatei = Dir

Loop

End Sub

Nicht nur die Dateinamen, sondern erstellt auch einen Hyperlink auf die Datei.
20161127link01
Beim Aktivieren des Hyperlinks wird zwar die Datei geöffnet, allerdings nicht die Schablonen, die eigentlich mit dieser Datei verknüpft sind. Sehr ärgerlich!
20161127link02

Steuerelemente und Gruppen

Der Umgang mit den verschiedenen Koordinatensystemen in Visio ist nicht trivial:
Ein Shape besitzt einen PinX und PinY, die auf dem Zeichenblatt verortet sind. Ihre Position innerhalb des Shapes wird durch die Zellen LocPinX und LocPinY festgelegt. Darauf beziehen sich sowohl Textblöcke als auch andere Shapes, wenn das „Hauptshape“ eine Gruppe darstellt.
Gegeben sei eine solche Gruppe (Sheet.4) Liegt auf der Gruppe nun ein Steuerelement (ein Control), darf die Linie des inneren Shapes nicht auf
=Sheet.4!Controls.Row_1.Y
verweisen. Das Control bezieht sich auf die Geometrie der Gruppe. Man muss es auf
=Sheet.4!Controls.Row_1.Y-Sheet.4!Height/2
setzen. Der Faktor 0.5 kommt dadurch zustande, weil der LocPinY auf Height*0.5 liegt. Dann funktioniert es.
20161101controls01
20161101controls0220161101controls03

Verbindungspunkte

Kunde möchte auf einer Linie ganz viele Verbindungspunkte haben. Nun ein paar Zeilen Code und schon sind die 96 Verbindungspunkte im gleichen Abstand zueinander gesetzt. So etwas mache ich nicht per Hand!
20161018verbindungspunkte
Sub Verbindungspunkte()
 
Dim vsShape As Shape
Dim i As Integer
Set vsShape = ActivePage.Shapes(„Sheet.430“)
vsShape.AddRows visSectionConnectionPts, i, 0, 96
For i = 1 To 96
vsShape.Section(visSectionConnectionPts).Row(i).Cell(0).FormulaU = „=2 mm+2 mm*“ & (i – 1) * 2
Next
 
End Sub

Timer

20161104Uhr

Hallo Herr Martin,

danke für Ihre letzte Antwort.!
Um in der Angelegenheit große Schritte zu tun (oder sie bleiben zu lassen, was ich erst einmal bevorzugt habe) müssten wir wohl über das Schreiben hinausgehen.

Momentan treibt mich eine andere Angelegenheit um:
Inzwischen nutze ich ja das visio2010.
Ein Kollege, dem ich eine kleine Simulation zugeschickt habe, benutzt ein visio 2013.

Nun brauche ich für meine Routine einen genauen 20ms Zeittakt. (oder auch 30ms, …)
Die Rechnerzeit hole ich mir mit GetTime aus

Private Declare Function GetTime Lib „winmm.dll“ Alias „timeGetTime“ () As Long

Dabei überwache ich, ob mein Arbeitszyklus auch nicht länger als die 20ms ist.
Seit langem funktioniert bei mir die Routine. (auch gemütliche PC’s) Die Überwachung habe ich sichtbar gestaltet.

Jetzt, bei meinem Kollegen, braucht der PC, wie soll ich sagen, „mehr Zeit“ (auch 30ms reichen nicht)….

Frage:
– Ist Ihnen ein besserer Zugriff auf die Systemzeit des PC’s im Rahmen in visio bekannt?
– Hätten Sie ein Erklärung parat ?

zur Info das kleine Programmstück

If (M_GetTime – Ticker) > Taktzeit Then ‚ in Abstand von z.B. 20ms wird getaktet
Schleife = True ‚ für den Aufruf eines Programmes
If (M_GetTime – Ticker) > 2 * Taktzeit Then ‚ Kontrolle, ob Überlauf!
Taktueberlauf = Taktueberlauf + 1
End If
Normaltakt = Normaltakt + 1 ‚ Zähler für den Takt
Ticker = Ticker + Taktzeit
End If

….im Programm dann „Schleife = false“
####
Hallo Herr F.,
Hätten Sie mich gefragt, wie man einen Timer ansteuert , hätte ich Ihnen geantwortet – mit einer API-Funktion. Nein , Visio hat, anders als Word oder Access, keinen integrierten Timer.
Dass diese Funktion nicht richtig arbeitet, oder sich je nach Rechner oder Prozessor oder Betriebssystem unterschiedlich verhält – dazu kann ich nichts sagen .
Also doch Visual Studio als Überbau?
Sorry – da kann ich leider nicht weiterhelfen.
Schöne Grüße
Rene Martin
#####
Hallo Herr Martin,

vielen Dank für Ihre Antwort!
Und Sie waren eigentlich meine einzige große Hoffnung, etwas Licht in die Dunkelheit zu bringen!

Es ist schon verrückt! Ich habe zu Hause 2 PC’s , einen zum Arbeiten und einen alten, der nur noch herumsteht. Und einen kleinen Laptop.
Auf allen 3 Rechnern (ob W7 oder XP) läuft die genannte Routine (quasi unabhängig von der Leistungsfähigkeit) recht ähnlich.
Das Nutzerprogramm braucht halt ein paar Millisekunden. Der Hauptanteil dürfte aber für VB-visio bei der Bildschirmbehandlung (Verschieben von Rechtecken) verschwendet werden. Hat man z.B einen bunten Hintergrund braucht die Routine mehr Zeit…

Nun mache ich die Erfahrung, dass mit einem (sicher) leistungsfähigem Rechner, aber eben mit visio 2013, das gleiche Programm erheblich mehr Zeit kostet.
Nun, ich werde auf die Ferne mit den Kollegen einige Test’s versuchen , um der Sache etwas näher zu kommen.
Gern informiere ich Sie über das Ergebnis. Vielleicht gibt es auch noch andere Nutzer, die ähnliche Erfahrungen brauchen könnten. Und Sie sind ja der wohl einzige Fachmann, der sich mit visio voll auskennt.

Aus meiner Sicht ist es eigentlich schade, dass MS das Produkt „visio“ so verkommen lässt. ( oder so modernisiert…)
In meiner frühen Zeit habe ich noch maschinennahe Programme geschrieben (Z80). Da es Mangel an Speicher gab, war es oft das Ziel, überlegt zu programmieren…..
Noch bin ich begeistert, dass man z.B. mit 300kB visio-Programm bewegte Bilder mit wichtigem techn. Hintergrund zusammenstellen kann.
Allerdings ist für Viele das meist gar kein Argument… – eben schade!

Eingebettete Objekte

Ich gestehe – es hat mich etwas Mühe gekostet.
Das Einbetten eines Objektes (Exceltabelle) nach Visio ist per Programmierung nicht sehr schwierig – der Makrorekorder hilft dabei:
vsBlattDaten.InsertFromFile Dateiname, visInsertAsEmbed
oder
vsBlattDaten.InsertFromFile Dateiname, visInsertAsEmbed + visInsertIcon
Das kann man leicht mit Hilfe des Makrorekorders herausfinden.
Objekte
20160313Objekte02 Objekte
Der umgekehrte Weg jedoch: wie kann man dieses Objekt auf die Festplatte speichern oder: wie kann man auf die Daten zugreifen, ohne sie zu öffnen, ist etwas kniffliger. Es geht folgendermaßen:
1. ActiveDocument.Pages(Blattname).OLEObjects(1).Object.SaveAsDateiname
Will man die Exceldatei mit Makros speichern, muss man noch einen Parameter hinzufügen:
ActiveDocument.Pages(Blattname).OLEObjects(1).Object.SaveAsDateiname, xlOpenXMLWorkbookMacroEnabled
2. Der Zugriff funktioniert analog:
ActiveDocument.Pages(Blattname).OLEObjects(1).Object.Sheets(1).Range(„A1“).Value
Wenn man es weiß, ist es ganz einfach.

Zeichenblattlayout

Layout - geändert
Layout – geändert

Sehr geehrte Damen und Herren, ich habe mit großem Interesse die Schulung über Visio 2010 Programmierung angesehen. Dabei habe ich leider nicht gefunden, wie man per VBA die untergeordneten Elemente eines Shapes neu anordnet. Wenn ich programmtechnisch „user.thislayoutstyle“ auf einen anderen Wert ändere, ist dies im Shape-Sheet zwar sichtbar, aber die Anordnung ändert sich trotz eines doevents nicht. Was muss ich programmieren, damit sich die Anordnung sichtbar ändert? Vielen Dank für Ihre Hilfe und freundliche Grüße aus Berlin
####
Hallo Herr V.,

der Makrorekorder verrät es 😉 (ich hätte es auch nicht
gewusst).

Wenn Sie in die Zellen des ShapeSheets des Blattes beispielsweise folgende Formeln eintragen :
ActivePage.PageSheet.Cells(„PlaceStyle“).FormulaU = „3“
ActivePage.PageSheet.Cells(„RouteStyle“).FormulaU = „1“
müssen Sie diese mit der Methode Layout beenden – sonst werden sie nicht
durchgeführt:
ActivePage.Layout

schöne Grüße und viel Spaß mit Visio

Rene Martin

PS: Das habe ich einige Mal „per Hand“ programmiert: das manuelle Platzieren von Shapes – fürchterliche Rechenarbeit – aber das wissen Sie sicherlich selbst.