Daten in einer Zeichnung mit VBA suchen und auswerten, Teil 8 – verschachtelte komplexe Elemente aus


Im vorigen Teil haben wir einfache Zellen untersucht, allerdings haben wir bislang die Verschachtelung noch nicht beachtet, das wollen wir jetzt als Nächstes angehen.

Aus dem Beispiel der Zelle und Gruppe vom vorigen Teil 7 habe ich neue Zellen generiert und jeweils die bisherigen Zellen mit einbezogen, daraus habe ich dann letztlich eine Zelle mit Namen Zelle2 bis Zelle6 generiet, dessen Struktur hier mit dem „Analyze element“ Tool angedeutet wird, die Struktur ist dabei absichtlich verschachtelt und unübersichtlich:

Mit diesem Beispiel einer unübersichtlichen Zelle möchte ich demonstrieren, dass der bisherige Weg Zellen auszuwerten seine Grenzen erreicht hat. Um Zellen wie diese etwas komplexere Zelle6 wie bisher auszuwerten, müssten wir eine Menge an Programmzeilen generieren.

Stattdessen möchte ich einen Weg zeigen, wie man dies mit rekursiven Routinen angehen kann. Und zwar neben der bisherigen Subroutine Elementinfo, mit der die Auswertung weiterhin gestartet wird, lagere ich die Analyse der Zellen in eine weitere Subroutine aus, die ich einmal "zerlegen" nennen möchte.
Das Besondere an dieser Routine ist, dass sie immer wieder selbst aufgerufen wird, und das ist die angesprochene Rekursion

Folgenden Vorschlag habe ich dafür einmal zusammengestellt:

Public datei As String

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
If ActiveWorkspace.IsConfigurationVariableDefined("MeineAusgabeDatei") Then
     datei = ActiveWorkspace.ConfigurationVariableValue("MeineAusgabeDatei")
Else
     MsgBox "Die Variable MeineAusgabeDatei ist nicht definiert, Verarbeitung abgebrochen", vbCritical
Exit Sub
End If
Set ee = ActiveModelReference.GraphicalElementCache.Scan()
Do While ee.MoveNext
     Call zerlegen(ee.Current, 1)
Loop
End Sub

Sub zerlegen(ele As Element, tiefe As Integer)
Dim oL() As Element
Dim zeile As String
If ele.IsCellElement Then
     oL = ele.AsCellElement.GetSubElements.BuildArrayFromContents
     Open datei For Append As #1
     zeile = ""
For i = 2 To tiefe
     zeile = zeile & " ;"
Next
zeile = zeile + "Tiefe: " & tiefe & ";Zelle < " & ele.AsCellElement.Name & "> mit "
zeile = zeile & UBound(oL) - LBound(oL) + 1 & " Elementen"
Print #1, zeile
Close #1
For i = LBound(oL) To UBound(oL)
     Call zerlegen(oL(i), tiefe + 1)
Next
Else
     Open datei For Append As #1
     zeile = ""
For i = 2 To tiefe
     zeile = zeile & " ;"
Next
zeile = zeile + TypeName(ele)
Print #1, zeile
Close #1
End If
End Sub

In der bisherigen Sub elementinfo lese ich eigentlich nur noch den Namen der Datei aus, in die die Daten geschrieben werden sollen. Den Namen speichere ich in eine public Variable datei, die außerhalb der Sub elementinfo deklariert wird - Vorsicht, unbedingt die Deklaration der Variablen datei aus der Sub elementinfo entfernen, da sich sonst die Gültigkeitsbereiche der VAriablen überschneiden mit der Folge, dass in der Sub zerlegen kein Dateiname ankommt.  

Die eigentliche Analyse der Daten liegt ketzt bei der Sub zerlegen.
Die Sub elementinfo ruft jetzt die Sub zerlegen für jedes Element der Zeichnung auf.

Die Routine zerlegen prüft nur, ob das Element, mit dem die Routine aufgerufen wird, selber eine Zelle ist oder nicht.
Wenn ja, dann wird die Sub zerlegen jeweils mit allen Unterelementen erneut aufgerufen, ansonsten werden die Details in die Datei geschrieben.

Um die Verschachtelungstiefe deutlich zu machen, gebe ich die Tiefe mit der gleichnamigen Variable jeweils mit und stelle dies in der Ausgabedatei durch ein Einrücken um eine Spalte optisch deutlicher da.

Dazu stelle ich den Daten dies voran:

zeile = ""
For i = 2 To tiefe
     zeile = zeile & " ;"
Next

Damit erreiche ich ein Einrücken der Daten nach rechts ab der 2. Verschachtelungstiefe.
Die resultierende .csv Datei sieht in Excel dann etwa so aus, wie dieser Ausschnitt es andeutet:

Dies ist natürlich nur ein Vorschlag, wie man dies Problem angehen kann und dient mehr zur optischen Präsentation der ausgelesenen Daten. Oftmals sind nicht alle Daten von Interesse, sondern man sucht ganz spezielle Daten wie z.B. Texte innerhalb von Zellen, die man auslesen oder ändern möchte. Das Ändern der Daten werden wir später noch behandeln, im nächsten Teile beschäftigen wir uns mit dem sogenannten Propertyhandler, der eine weitere Möglichkeit bietet, Daten auszulesen.