Mastershapes in einer Schablone

Sehr geehrter Herr Dr. René Martin,
[…] Ziel ist es die Visio Diagramme mit unserem SAP System zu verbinden.
Dazu müssen jedem Shape entsprechende Shape-Daten mitgeben werden.
Dabei haben mir Ihre Bücher
(Microsoft Visio 2010 Programmierung Microsoft Visio effizient anpassen und erweitern) und
(Visio 2013/2016 anpassen Das Handbuch für Entwickler),
wie auch Ihr Video-Training
(Visio 2010 Umfassend praxisorientiert, leicht verständlich) schon erheblich geholfen.
Da es das Ziel der Automatisierung ist dem Benutzer die Erstellung der Diagramme möglichst einfach zu machen,
soll er auch beim Anlegen neuer Shapes bestmöglich unterstützt werden.
Jetzt bin ich jedoch auf ein Problem gestoßen an welchem ich nicht weiter komme.
Ich benötige eine Möglichkeit einem neuerzeugten Shape die benötigten Shape-Daten mitzugeben, wenn es zu einer Schablone hinzugefügt und somit zum Mastershape wird.
Es gibt jedoch kein Event, welches auf dieses Ereignis anspricht.
Haben Sie vielleicht eine Idee wie sich dies umsetzen lässt?
 
Im Voraus schon mal vielen Dank für Ihre Hilfe
 
Mit freundlichen Grüßen
Hallo Herr B.,
 
ich verstehe den Workflow nicht ganz: der Anwender soll neue Shapes erstellen. Beim Abspeichern in einer Schablone sollen (automatisiert) Daten an diese Shapes angefügt werden.
* Warum erstellt der Anwender nicht selbst diese Daten?
* Oder: wenn es sich um immer die gleichen Daten handelt (und auch viele Daten) dann würde ich es nicht über ein Ereignis lösen, sondern über eine Schaltfläche, die der Anwender anklickt: entweder dem markierten Shape werden neue Daten hinzugefügt oder: alle Mastershapes einer Schablone werden mit diesen Daten versehen.
 
Der Grund: meines Wissens gibt es kein Ereignis: „ziehe ein Shape vom Zeichenblatt in die Schablone“. Und: nach meiner Erfahrung werden Shapes in die Schablone gezogen; dort manchmal bearbeitet. Manchmal werden sie auch wieder auf das Zeichenblatt gezogen, bearbeitet und wieder zurück in die Schablone gezogen; manchmal auch in der Schablone direkt bearbeitet (auf dem Zeichenblatt geht das manchmal besser).
 
Hilft Ihnen diese Antwort?

Dynamische Schaltflächen auf einem Zeichenblatt

Amüsant. Wenn man in Visio eine Befehlsschaltfläche auf ein Zeichenblatt legt, liegt das nächste Shape ÜBER der Befehlsschaltfläche. Schaltet man jedoch den Entwurfsmodus aus, liegt das Shape dahinter. Es gibt keine Möglichkeit, das Shape vor die Befehlsschaltfläche zu legen.
Auch die Zellen „NoShow“ oder „Transparency“ bewirken nicht, dass die Schaltfläche ausgeblendet wird. Man könnte sie per Programmierung auf Width = 0 und Height = 0 (vielleicht noch PinX und PinY auf 0) setzen – dann ist die Schaltfläche fast verschwunden. Natürlich kann man sie auch programmieren:
Dim shp As Shape
 
Dim DiagramServices As Integer
DiagramServices = ActiveDocument.DiagramServicesEnabled
ActiveDocument.DiagramServicesEnabled = visServiceVersion140 + visServiceVersion150
 
Set shp = Application.ActiveWindow.Page.InsertObject(„forms.Commandbutton.1“, visInsertAsControl + visInsertNoDesignModeTransition)
shp.Cells(„PinX“).FormulaU = „=100mm“
shp.Cells(„PinY“).FormulaU = „=150mm“
shp.Name = „Testbutton“
 
 
‚Restore diagram services
ActiveDocument.DiagramServicesEnabled = DiagramServices
 
Jedoch – es bleibt mühsam dynamische Schaltfläche auf dem Zeichenblatt zu erzeugen.

Die API-Hölle

Ich versuche API-Funktionen zu vermeiden. Das Problem sind die 32- und 64-Bit-Systeme.

Länge einer Linie: LengthIU

Folgende Zeilen Code berechnen die Länge einer Linie:

Sub LängeAnzeigen()

Const ShapeLinieAnzeigen As String = „Dynamischer Verbinder“

Dim i As Long

 

For i = 1 To ActivePage.Shapes.Count

If ActivePage.Shapes(i).Name Like „*“ & ShapeLinieAnzeigen & „*“ Then

ActivePage.Shapes(i).Text = Format(Application.ConvertResult(ActivePage.Shapes(i).LengthIU, „in“, „mm“), „0.00“)

End If

Next i

End Sub

Erklärung: Die Eigenschaft LengthIU liefert die Länge – allerdings in inch. Sie muss in cm oder m umgewandelt werden. Dies kann die Funktion Application.ConvertResult. Und dieses Ergebnis wird mit der Funktion Format auf zwei Stellen nach dem Komma formatiert: „0.00“. Und diese Ergebnis wird auf das Shape als Text geschrieben. Auf welches Shape?

 

Eine Schleife durchläuft alle Shapes und schreibt den Text jeweils auf die „Dynamischen Verbinder“.

 

Für Ihre Fluchtwege können Sie den Code anpassen. Erstellen Sie ein Mastershape „Fluchtweg“ in einer Schablone, ziehen es aufs Zeichenblatt (formatieren es, machen es transparent …). In Entwicklertools / Shape-Name befindet sich ja der Name – beispielsweise „Fluchweg“ oder „Fluchtweg.24“ Wenn die Konstante in „Fluchtweg“ geändert wurde, wenn Sie die Formatierung auf „m“ ändern, dann liefert der folgende Code:

Sub LängeAnzeigen()

Const ShapeLinieAnzeigen As String = „Fluchtweg“

Dim i As Long

 

For i = 1 To ActivePage.Shapes.Count

If ActivePage.Shapes(i).Name Like „*“ & ShapeLinieAnzeigen & „*“ Then

ActivePage.Shapes(i).Text = Format(Application.ConvertResult(ActivePage.Shapes(i).LengthIU, „in“, „m“), „0.00“)

End If

Next i

End Sub

 

die Länge des Fluchtwegs (hier: 77,13 – schließlich muss man noch nachsehen, wenn beim Billard gewonnen hat, bevor man in die Raucherecke geht)

Wechseln Sie zu VBA. Erstellen dort ein Modul. Und fügen den Code von oben ein. Sie können diese Datei als VSDM speichern – oder die Vorlage als VSTM (Mit Makros!). Das Programm wird von Visio über Ansicht / Makros ausgeführt.

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