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.

Neues Shape

Natürlich kann man Shapes in Schablonen abspeichern. Aber vielleicht möchte ich nicht, dass Anwender solche Shapes sehen und sich dann fragen, zu welchem Zwecke sie in der Schablone liegen. Und wo sie benötigt werden.
Manchmal ist es einfacher ein Shape per Code zu erzeugen. Beispielsweise diese „Kreuzug“, die jemand haben wollte. Ein paar Zeilen Code und fertig ist das Shape:
Dim vsShapeNeu As Shape
 
Set vsShapeNeu = ActivePage.DrawRectangle(100, 200, 300, 400)
 
vsShapeNeu.Cells(„LineWeight“).FormulaU = „=1.5 pt“ ‚ Linienstärke
vsShapeNeu.Cells(„Geometry1.Y1“).FormulaU = „=Height*0.5“
vsShapeNeu.Cells(„Geometry1.Y2“).FormulaU = „=Height*0.5“
vsShapeNeu.Cells(„Geometry1.Y3“).FormulaU = „=Height*0.5“
vsShapeNeu.Cells(„Geometry1.Y4“).FormulaU = „=Height*0.5“
 
vsShapeNeu.AddSection visSectionFirstComponent + 1
vsShapeNeu.AddRow visSectionFirstComponent + 1, visRowComponent, visTagComponent
vsShapeNeu.AddRow visSectionFirstComponent + 1, visRowVertex, visTagLineTo
vsShapeNeu.AddRow visSectionFirstComponent + 1, visRowVertex, visTagMoveTo
 
vsShapeNeu.Cells(„Geometry2.X1“).FormulaU = „=Width*0.5“
vsShapeNeu.Cells(„Geometry2.Y1“).FormulaU = „=Height*0“
vsShapeNeu.Cells(„Geometry2.X2“).FormulaU = „=Width*0.5“
vsShapeNeu.Cells(„Geometry2.Y2“).FormulaU = „=Height*1“
 
vsShapeNeu.AddSection visSectionFirstComponent + 2
vsShapeNeu.AddRow visSectionFirstComponent + 2, visRowComponent, visTagComponent
vsShapeNeu.AddRow visSectionFirstComponent + 2, visRowVertex, visTagLineTo
vsShapeNeu.AddRow visSectionFirstComponent + 2, visRowVertex, visTagLineTo
vsShapeNeu.AddRow visSectionFirstComponent + 2, visRowVertex, visTagLineTo
vsShapeNeu.AddRow visSectionFirstComponent + 2, visRowVertex, visTagLineTo
vsShapeNeu.AddRow visSectionFirstComponent + 2, visRowVertex, visTagMoveTo
 
vsShapeNeu.Cells(„Geometry3.X1“).FormulaU = „=Width*0.5“
vsShapeNeu.Cells(„Geometry3.Y1“).FormulaU = „=Height*0.25“
vsShapeNeu.Cells(„Geometry3.X2“).FormulaU = „=Width*0.75“
vsShapeNeu.Cells(„Geometry3.Y2“).FormulaU = „=Height*0.5“
vsShapeNeu.Cells(„Geometry3.X3“).FormulaU = „=Width*0.5“
vsShapeNeu.Cells(„Geometry3.Y3“).FormulaU = „=Height*0.75“
vsShapeNeu.Cells(„Geometry3.X4“).FormulaU = „=Width*0.25“
vsShapeNeu.Cells(„Geometry3.Y4“).FormulaU = „=Height*0.5“
vsShapeNeu.Cells(„Geometry3.X5“).FormulaU = „=Width*0.5“
vsShapeNeu.Cells(„Geometry3.Y5“).FormulaU = „=Height*0.25“

Form20151208

Daten in Visio

Hallo Herr Dr. Martin,
ich hätte nochmal ein paar spezielle Fragen zu Visio.
Ich kann über VBA auf die Shape-Daten meiner Shapes auf dem Zeichenblatt zugreifen … ABER … Wie kann ich auf Shape-Daten von Schablonen über VBA zugreifen?
Und: Gibt es eine Möglichkeit die Shape-Daten eines Shapes auf einen Schlag komplett zu löschen?
Z.Zt. kann ich immer nur die einzelnen Elemente löschen aber nicht alle auf einmal.
###
Hallo Herr S.,
* Sie müssen auf alle offenen Dokumente in Visio zugreifen, überprüfen, ob es sich dabei um eine Schablone handelt, die Mastershapes auslesen und von ihnen die Daten auslesen.
 
*ich würde nicht auf die Shape-Datensätze zugreifen. Erstes weiß ich nicht, wo Visio diese abspeichert, zweites ist es mir zu unsicher und drittens vermute ich einen Bug darin (das an anderer Stelle). Ich würde auf Abschnitt und Zeilen der Shapes per Schleife zugreifen.
 
* Sie können den Abschnitt visSectionProp löschen – aber dann zickt er manchmal – oder besser: jede Zeile dieses Abschnittes.
Spitzer20151123
Beispielsweise so:
Public Sub cmdDaten1(ByRef control As IRibbonControl)
Dim strDateien As String
Dim strSchablonen As String
Dim vsSchablone() As Document
Dim strMaster() As String
Dim vsMastershape As Master
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim m As Integer
Dim strSpapeDatenzeile As String
ReDim vsSchablone(0)
For i = 1 To Application.Documents.Count
‚ — durchlaufe alle offenen Dokumente
strDateien = strDateien & Application.Documents(i).Name & vbCr
If Application.Documents(i).Type = visTypeStencil Then
‚ — wenn du eine Schablone bist
ReDim Preserve vsSchablone(UBound(vsSchablone) + 1)
strSchablonen = strSchablonen & Application.Documents(i).Name & vbCr
Set vsSchablone(UBound(vsSchablone)) = Application.Documents(i)
End If
Next i
MsgBox „Liste der offenen Dateien:“ & vbCr & strDateien
MsgBox „Liste der offenen Schablonen:“ & vbCr & strSchablonen
For j = 1 To UBound(vsSchablone)
vsSchablone(j).Masters.GetNames strMaster
‚ — alle Mastershapes der Schablone
MsgBox „Liste der Mastershapes der Schablone “ & vsSchablone(j) & vbCr & Join(strMaster, vbCr)
For k = 0 To UBound(strMaster)
Set vsMastershape = Application.Documents(vsSchablone(j).Name).Masters(strMaster(k))
strSpapeDatenzeile = „“
If vsMastershape.Shapes(1).SectionExists(visSectionProp, False) = True Then
‚ — wenn Shapedaten im Mastershape vorhanden sind.
For m = 0 To vsMastershape.Shapes(1).Section(visSectionProp).Count – 1
strSpapeDatenzeile = strSpapeDatenzeile & vsMastershape.Shapes(1).Section(visSectionProp).Row(m).Cell(0).Name & vbCr
‚###############
‚ Cell(0): Value
‚ Cell(1): Prompt
‚ Cell(2): Label
‚ Cell(3): Format
‚ Cell(4): SortKey
‚ Cell(5): Type
‚ Cell(6): Invisible
‚ Cell(7): Verify
‚ Cell(8): DateLinked
‚###############
Next
MsgBox „Mastershape „““ & vsMastershape.Name & „““ hat folgende Daten:“ & vbCr & strSpapeDatenzeile
End If
Next
Next
End Sub
 
 
 
 
Public Sub cmdDaten3(ByRef control As IRibbonControl)
Dim i As Integer
If ActiveWindow.Selection.Count = 0 Then
MsgBox „Sie haben kein Shape ausgewählt!“
ElseIf ActiveWindow.Selection.Count > 1 Then
MsgBox „Bitte markieren Sie nur ein Shape!“
Else
For i = ActiveWindow.Selection(1).Section(visSectionProp).Count – 1 To 0 Step -1
ActiveWindow.Selection(1).DeleteRow visSectionProp, i
Next
MsgBox „Alle Zeilen der Shape-Daten wurden gelöscht!“
 
End If
 
End Sub
 
Public Sub cmdDaten2(ByRef control As IRibbonControl)
If ActiveWindow.Selection.Count = 0 Then
MsgBox „Sie haben kein Shape ausgewählt!“
ElseIf ActiveWindow.Selection.Count > 1 Then
MsgBox „Bitte markieren Sie nur ein Shape!“
Else
If ActiveWindow.Selection(1).SectionExists(visSectionProp, False) = True Then
ActiveWindow.Selection(1).DeleteSection visSectionProp
MsgBox „Abschnitt „“Shape-Daten““ wurde gelöscht!“
End If
End If
End Sub