Daten in einer Zeichnung mit VBA suchen und auswerten, Teil 7 – allgemeine komplexe Elemente auswer


Wir wollen jetzt allgemeine komplexe Struktturen auswerten, als Beipiele sollen zunächst Zellen dienen. Zellen sind vom Typ 2 und haben im Normalfall einen Namen, über den man Zellen identifizieren kann, ähnlich wie das bei den Knotennummern bei Textknoten war.
Allerings gibt es auch Zellen ohne Namen, das können Elemente sein, die man über den Befehl "Gruppe erstellen" zu einer Gruppe zusammengefasst hat.
Die Auswertung solcher Strukturen sind gleich, nur sollte man nicht unbedingt erwarten, dass alle Typ 2 Elemente auch einen Namen haben.

Ein erstes Auswertungsbeispiel soll eine Auflistung alle Zellen mit der Anzahl der enthaltenen Unterelemente sein.
Dazu variiere ich ein wenig den dafür benötigten Befehl .GetSubElements durch Konvertierung dieses Auswahlsatzes in ein Array, um direkt die Anzahl der Elemente auslesen zu können.
Auswerten möchte ich zunächst diese beiden optisch identischen Zellen. 
Die linke Zelle ist als Gruppe der einzelnen Elemente entstanden, rechts daneben optisch identisch eine platzierte Zelle aus einer Zellbibliothek, der Name der Zelle lautet Zelle1:

Die Auswertung leite ich hier wie bisher wieder in eine .csv Datei, hier eine mögliche Vorgehensweise:

Sub elementinfo()
Dim ele As Element
Dim ee As ElementEnumerator
Dim startpunkt, endpunkt As Point3d
Dim kopfZeile, Zeile As String
Dim oL() As Element
Dim Zellname As String
Dim datei As String
If ActiveWorkspace.IsConfigurationVariableDefined("MeineAusgabeDatei") Then
datei = ActiveWorkspace.ConfigurationVariableValue("MeineAusgabeDatei")
Else
MsgBox "Die Variable MeineAusgabeDatei ist nicht definiert, Verarbeitung abgebrochen", vbCritical
Exit Sub
End If
Open datei For Append As #1
Set ee = ActiveModelReference.GraphicalElementCache.Scan()
Do While ee.MoveNext
Set ele = ee.Current
If ele.IsCellElement Then
oL = ele.AsCellElement.GetSubElements.BuildArrayFromContents
Zellname = ele.AsCellElement.Name
If Len(Zellname) = 0 Then Zellname = "Ohne Namen"
Zeile = "Zelle < " & Zellname & "> mit " & UBound(oL) - LBound(oL) + 1 & " Elementen"
Print #1, Zeile
End If
Loop
Close #1
End Sub

Mit den beiden Elementen aus dem Screenshot ergibt dies für mich folgende Ausgabe:

Das Ergebnis stimmt soweit, neben den 3 Texten gibt es noch einen Kreis und ein Rechteck.
Man beachte hierbei, dass die Anzahl 3 wäre, wenn die 3 Texte in einem Textknoten zusammengefasst wären, optisch ist das nicht zu unterscheiden, das bemerkt man nur bei der Auswertung oder beim Elementinfo buw beim älteren Keyin "analyze element".
Den Keyin "analyze element" kann ich in dem Zusammenhang gut empfehlen, der zeigt viele Details an, die einem helfen, die richtige Vorgehensweise für eine Auswertung zu verwenden.

Bei der obigen Routine habe ich zum ersten Mal diesen Befehl zum Auslesen verwendet:


oL = ele.AsCellElement.GetSubElements.BuildArrayFromContents

Also nach dem Anwenden des .GetSubElements noch eine Umwandlung des Auswahlsatzes in ein Array. Dadurch kann ich sofort die Anzahl der Elemente auslesen mit dem Ausdruck "ubound(oL) - lbound(oL) + 1"

Ubound steht für Upper boundary und
LBound for Lower Boundary des mit Elementen gefüllten Arrays.

Als nächsten Schritt werden wir jetzt noch in der Ausgabe die einzelnen Elemente der jeweiligen Zelle auflisten, das könnte dann folgendermaßen erweitert werden:

Sub elementinfo()
Dim ele As Element
Dim ee As ElementEnumerator
Dim startpunkt, endpunkt As Point3d
Dim kopfZeile, Zeile As String
Dim oL() As Element
Dim Zellname As String
Dim datei As String
If ActiveWorkspace.IsConfigurationVariableDefined("MeineAusgabeDatei") Then
datei = ActiveWorkspace.ConfigurationVariableValue("MeineAusgabeDatei")
Else
MsgBox "Die Variable MeineAusgabeDatei ist nicht definiert, Verarbeitung abgebrochen", vbCritical
Exit Sub
End If
Open datei For Append As #1
Set ee = ActiveModelReference.GraphicalElementCache.Scan()
Do While ee.MoveNext
Set ele = ee.Current
If ele.IsCellElement Then
oL = ele.AsCellElement.GetSubElements.BuildArrayFromContents
Zellname = ele.AsCellElement.Name
If Len(Zellname) = 0 Then Zellname = "Ohne Namen"
Zeile = "Zelle < " & Zellname & "> mit " & UBound(oL) - LBound(oL) + 1 & " Elementen"
Print #1, Zeile
For i = LBound(oL) To UBound(oL)
Zeile = TypeName(oL(i))
Print #1, Zeile
Next
End If
Loop
Close #1
End Sub

Die Ausgabe erweitert sich bei mir dann folgendermaßen:

Bei dieser Ausgabe habe ich jetzt anstatt der Typnummer den Namen des Typs ausgegeben den ich über die Funktion TypeName erhalten habe.
Wie vorher schon angesprochen, ist der Kreis nur eine spezielle Ellipse, deshalb die Angabe des EllipseElement.
Will man hier konkret unterscheiden, kann man den .PrimaryRadius und SecondaryRadius auslesen und vergleichen, der bei Kreisen gleich sein sollte.

Bei vielen Daten reicht diese Form der Analyse sicher aus, allerdings können wir nicht sicher sein, ob die zu untersuchenden Zellen nicht vielleicht noch verschachtelt sind, also ob sich in den Zellen nicht wiederum Zellen und darin wieder Zellen befinden usw..
Grundsätzlich gibt es hier keine Einschränkung in der Verschachtelungstiefe, bei der wir dann aber ein neues bislang nicht verwendetes Mittel einsetzen sollten, nämlich die Rekursion zum Auslesen von Daten, dies aber im nächsten Teil.