|
|
In der vergangenen Ausgabe unserer VBA-EinfĂŒhrung haben Sie ein wenig von der Entwicklungsumgebung kennen gelernt, einen Kreis vom Programm in AutoCAD zeichnen lassen und sogar ein erstes kleines MenĂŒ entwickelt. Wer sich
etwas ernsthafter mit der VBA-Programmierung beschĂ€ftigt, wird immer wieder vor der Aufgabe stehen, bereits vorhandene AutoCAD-Elemente zu verarbeiten. DafĂŒr gibt es verschiedene Möglichkeiten. Nachfolgend sollen zwei Wege
beschrieben werden, nĂ€mlich die Klassen Utility und Selectionset. Im letzten Teil der VBA-EinfĂŒhrung haben Sie bereits das Utility-Objekt zur interaktiven Koordinatenabfrage kennen gelernt. Neben verschiedenen anderen
Methoden stellt es auch die GetEntity-Funktion zur VerfĂŒgung. Sie wird dazu benutzt, um den Anwender ein Zeichnungsobjekt auswĂ€hlen zu lassen. Allerdings wirklich nur genau ein Element. Sollen mehrere Zeichnungsobjekte
selektiert werden, gibt es dafĂŒr das anschlieĂend etwas nĂ€her besprochene Selectionset. Um GetEntity zu testen, starten Sie AutoCAD, zeichnen einige Elemente (z.B. Kreise, Linien, Polylinien etc.) und rufen anschlieĂend VBA
mittels der Tastenkombination âAlt-F11â auf. Jetzt können Sie folgende kleine Prozedur schreiben, die Sie auffordert, ein Zeichnungselement zu selektieren und anschlieĂend dessen Namen ausgibt.
Public Sub zz1() Dim Auswahl As acadObject Dim Punkt As Variant
Utility.GetEntity Auswahl, Punkt, "WĂ€hlen Sie ein Element" MsgBox Auswahl.ObjectName
End Sub
In vielen FĂ€llen ist
allerdings mehr als ein Element in der Zeichnung auszuwÀhlen. In der Klasse AcadSelectionSets werden Ihnen vielfÀltig einsetzbare Methoden an die Hand gegeben, um Zeichnungselemente interaktiv oder auch im Hintergrund zu
selektieren. Um einen solchen Auswahlsatz anzulegen, sollte er zunÀchst mit einer Dim- oder Public-Anweisung deklariert werden.
Dim Sset as AcadSelectionset
Angelegt wird der Auswahlsatz mit folgender Programmzeile.
Set Sset1 = ThisDrawing.SelectionSets.Add("Auswahl1")
Nun können Sie Ihrem Auswahlsatz verschiedenste Elemente hinzufĂŒgen. Hier die
dafĂŒr am hĂ€ufigsten gebrauchten Methoden:
|
Select
|
Filtern von AutoCAD-Elementen im Hintergrund (also ohne Nutzereingabe).
|
|
SelectAtPoint
|
Auswahl eines Elements an einem bestimmten Punkt (Koordinate). Diese Anweisung Àhnelt (!) der GetEntity-Methode, allerdings ohne Abtasten einer Koordinate durch den Nutzer.
|
|
SelectByPolygon
|
Auswahl von Elementen die innerhalb eins Polygons liegen
|
|
SelectOnSrceen
|
Auswahl von Elementen durch den Anwender
|
Neben den Besonderheiten jeder einzelnen Methode, haben alle eines gemeinsam. Die Elemente können auch noch nach
verschiedenen Eigenschaften gefiltert werden. So ist es beispielsweise möglich, alle Polylinien der Zeichnung zu ermitteln, die
auf einem bestimmten Layer liegen, oder alle bestimmte Blöcke zu selektieren, die einen ganz bestimmten EinfĂŒgepunkt haben.
Zur Verdeutlichung ein erstes Beispiel, in dem Sie interaktiv mehrere Zeichnungselemente auswÀhlen und deren Objektnamen
in einer Message-Box zur Anzeige bringen. Zum Einstieg verzichten wir zunĂ€chst auf die genannte Filtermöglichkeit. Bevor Sie die Prozedur starten, sollten Sie natĂŒrlich erst verschiedene Elemente zeichnen.
Public Sub Elementliste() Dim Sset As AcadSelectionSet Dim Auswahl As acadObject Dim Liste As String
Set Sset = ThisDrawing.SelectionSets.Add("Elemente1") Sset.SelectOnScreen
For Each Auswahl In Sset Liste = Liste & vbCrLf & Auswahl.ObjectName Next MsgBox Liste Sset.Delete End Sub
Eingangs werden die erforderlichen Variablen deklariert. Mit âSet Sset=âŠâ erzeugen Sie einen zunĂ€chst noch leeren
Auswahlsatz. Die Zeile âSset.SelectOnScreenâ fĂŒhrt dann dazu, dass Sie in der AutoCAD-Kommandozeile aufgefordert
werden, Objekte am Bildschirm auszuwÀhlen. Bitte beachten Sie, dass diese Anweisung noch mit Filter-Parametern ergÀnzt werden kann, dazu gleich mehr.
Wenn Sie Ihre Auswahl am Bildschirm mit der rechten Maustaste oder der Eingabetaste abgeschlossen haben, wird in der
folgenden For-Next-Schleife der Auswahlsatz Element fĂŒr Element durchsucht. Mit jedem Schleifendurchlauf fĂŒllt sich die
Liste um ein weiteres Element. Wenn die Schleife abgearbeitet ist, wird die gefĂŒllte Liste in einer Messagebox zur Anzeige
gebracht. Vor dem AbschluĂ der Prozedur erzwingt âSset.Deleteâ das Löschen des Auswahlsatzes aus der Menge der
SelectionSets. Erfolgt das nicht, wĂŒrde beim nĂ€chsten Aufruf Ihres Programms eine Fehlermeldung erscheinen, die sagt, dass
der Auswahlsatz bereits existiert. Bitte die âDelete-Anweisungâ nicht mit der âErease-Anweisungâ verwechseln. Letztere
löscht den Inhalt des Auswahlsatzes (einschlieĂlich der Zeichnungselemente), lĂ€sst ihn aber als dann leeres Selectionset in der Zeichnung. Am einfachsten, Sie probieren es selbst einfach aus.
Wie eingangs angedeutet, bietet das Selectionset die Möglichkeit, Elemente bei der Auswahl zu filtern, was Àhnlich wie der
FILTER-Befehehl von AutoCAD zu verstehen ist. Die folgende Prozedur wird das verdeutlichen. Sie ist ein wenig komplexer
und arbeitet mit zwei Selectionsets. Zeichnen Sie zunĂ€chst jeweils mehrere Polylinie auf den beiden Layern âLayer1â und
Layer2â. Die Aufgabe des Programms besteht grundsĂ€tzlich darin, die GesamtlĂ€nge der Polylinien auf einem bestimmten
Layer zu berechnen. Ein grundsĂ€tzlicher Ablauf könnte nun so aussehen (viele Wege fĂŒhren zum Programm), dass alle Polylinien der Zeichnung gewĂ€hlt werden, und aus dieser Menge die von Layer2 zur Berechnung genommen werden.
Public Sub Tool_LenPoly() 'Ermittlung der LĂ€nge von Polylinien Dim Sset As AcadSelectionSet Dim fCode() as Integer Dim fWert as Variant Dim selOb as acadObject Dim Onam as String
Dim Gesamt as Double Dim POLin as AcadPolyline Dim LWLin as AcadLWPolyline
Set Sset = ThisDrawing.SelectionSets.Add("sset08") ReDim fCode(6): ReDim fWert(6)
fCode(0) = -4: fWert(0) = "<AND" fCode(1) = -4: fWert(1) = "<OR" fCode(2) = 0: fWert(2) = "lwpolyline" fCode(3) = 0: fWert(3) = "polyline"
fCode(4) = -4: fWert(4) = "OR>" fCode(5) = 8: fWert(5) = "Layer1" fCode(6) = -4: fWert(6) = "AND>"
Sset.Select acSelectionSetAll, , , fCode, fWert Gesamt = 0
For Each SelOb In Sset If SelOb.ObjectName = "AcDb2dPolyline" Then Set PoLin = SelOb
Gesamt = Gesamt + POLin.Length End If If SelOb.ObjectName = "AcDbPolyline" Then
Set LwLin = SelOb Gesamt = Gesamt + LWLin.Length End If Next AnzPoly = Sset.Count MsgBox (LaePol)
Sset.Delete End Sub
Hier nun die ErklĂ€rung einiger Besonderheiten. Nach der schon bekannten Erzeugung eines Auswahlsatzes mit âSet Sset =
ThisDrawing.SelectionSets.Add("Auswahl")â erfolgt die Definition des Filters. Er besteht immer aus zwei Komponenten.
Erstens dem so genannten DXF-Gruppencode und zweitens dem eigentlichen Filterwert. Der Gruppencode ist vom Typ Integer und der Filterwert vom Typ Variant (siehe Deklarationen). In jedem Fall mĂŒssen es Arrays sein, deren
Dimensionierung mit der Anzahl der Parameter identisch ist. Bitte beachten Sie, dass die ZĂ€hlung ĂŒblicherweise bei 0 beginnt.
Zum hoffentlich besseren VerstÀndnis sei die Filterdefinition hier erst mal in einer logischen Operation dargestellt:
Auswahl = ((Objekttyp=âPolylineâ ODER Objekttyp=âLWPolylineâ) AND Layer=âLayer2â)
Dementsprechend sieht Ihr Programm aus. Mit : âfWert(0) = "<AND"â öffnen Sie die UND-VerknĂŒpfung und in der
folgenden Zeile die ODER-VerknĂŒpfung. Der DXF-Code fĂŒr logische VerknĂŒpfungen ist in beiden FĂ€llen â-4â. Die beiden
nĂ€chsten Zeilen geben die Filterbedingungen fĂŒr die Linientypen an. Hier ist der Gruppencode â0â (fĂŒr die Bezeichnung des
AutoCAD-Elementtyps). Danach wird die ODER-VerknĂŒpfung geschlossen und es folgt die Layer-Bedingung. Layernamen sind vom Code â8â. Letztlich wird die UND-VerknĂŒpfung geschlossen.
Eine Ăbersicht ĂŒber alle Gruppencodes finden Sie in der DXF-Hilfe unter dem Abschnitt âGruppencodes in numerischer Reihenfolgeâ.
Nachdem Sie die Filterbedingung definiert haben, können Sie endlich alle Objekte auswĂ€hlen. Das erfolgt mit âSset.Select
acSelectionSetAll, , , fCode, fWertâ. Die allgemeine Syntax lautet âobject.Select Mode[, Point1][, Point2][, FilterType][,
FilterData]â. Nach der Select-Anweisung folgt als erster Parameter der Filtermodus, also der Mechanismus, nach dem
Objekte ausgewĂ€hlt werden. âacSelectionSetAllâ sagt, dass alle Elemente der Zeichung einbezogen werden sollen. Alternativ
könnten Sie den Bereich auch mit âacSelectionSetCrossingâ oder mit âacSelectionSetWindowâ auf einen durch die Punkte
Point1 und Point2 definierten Bereich einschrÀnken. In unserem Beispiel allerdings werden diese (optionalen) Parameter nicht
angegeben, denn es sollen ja alle Elemente in der Zeichnung untersucht werden. Die letzten beiden Parameter verweisen nun auf die vorstehend definierten Filterbedingungen.
Analog dazu hĂ€tten Sie ĂŒbrigens auch im vorstehenden Beispiel die Bildschirmauswahl (âSelectOnScreenâ) noch mit einem Filter einschrĂ€nken können.
Was nun folgt, ist die Auswertung des Selektionsergebnisses. In der For-Next-Schleife wird jedes im Auswahlsatz
enthaltenen Objekt weiter verarbeitet. Genauer gesagt, werden in einem Selectionset nicht die AutoCAD-Elemente selbst gespeichert, sondern nur Verweise auf diese Objekte.
Dazu muss zunÀchst der jeweilige Objektname bestimmt werden. Entsprechend dieses Namens unterscheidet die folgende
Select-Case-Anweisung, wie mit dem Objekt zu verfahren ist. Handelt es sich um eine Autocad-2D-Polylinie wird, mit âSet
POLin = selObâ zunĂ€chst ein entsprechendes Objekt erzeugt. Das ist erforderlich, um in der nĂ€chsten Zeile mit âPOLin.Lengthâ dessen LĂ€nge abzufragen und zu saldieren.
Analog dazu wird mit LWPolylinien verfahren, oder auch mit (im Beispiel nicht betrachteten) AutoCAD-Linien oder -3D-Polylinien.
Nachdem Sie das Ergebnis in einer Messagebox zur Anzeige gebracht haben, wird zum Schluss der Auswahlsatz wieder gelöscht.
Noch zwei letzte kleine Hinweise fĂŒr heute. Erstens empfiehlt es sich, die Namen der AuswahlsĂ€tze in einer Zeichenketten-Variable zu speichern. Das spart eine lĂ€stige Fehlersuche bei geringfĂŒgigen Schreibfehlern.
Zweitens kann es bei lÀngeren Programmen schon mal passieren, dass man das Löschen eines Auswahlsatzes vergisst. Dem
schafft folgende Funktion Abhilfe, die vor der Erzeugung eines Selectionset zunÀchst testet, ob es schon vorhanden ist. Wenn ja, wird es gelöscht. Am Ende der Funktion kann es dann erzeugt werden.
Public Function ssetGen(setName As String) As AcadSelectionSet Dim sCol As AcadSelectionSets Dim SS As AcadSelectionSet Set sCol = ThisDrawing.SelectionSets For Each SS In sCol
If SS.Name = setName Then sCol.Item(setName).Delete Exit For End If Next
Set SS = sCol.Add(setName) Set ssetGen = SS End Function
Der Funktionsaufruf wĂŒrde dann mit âSet Sset = ssetGen(âAuswahlâ) erfolgen. Viel SpaĂ beim ausprobieren.
Wird fortgesetzt
|