Einige kleine Makrobeispiele
Ich arbeite bei den Städtischen Werken in einer Abteilung zur Leitungsdokumentation. Es gibt also einen riesigen homogenen Datenbestand, den es gilt mit MicroStation zu beherrschen. Dazu bastele ich mir mit MicroStation-Basic, VBA und VB 6 kleine Helfer.
NameMix ist ein VB6-Progamm bei dem mit der FileSystemObject und der File-Klasse gearbeitet wurde. Die Dateien werden in eine Liste geschrieben. Anschließend werden Zufallszahlen in dem vorgegebenem Bereich erzeugt. Dies geschieht so lange, bis eine Zahl gefunden wird, die noch nicht vergeben wurde. Jetzt kann die Datei umbenannt werden.
Loop While Dir
(Dir1.Path & "\" & NewName) <> ""
Set Dat = FS.GetFile
(Dir1.Path & "\" & FileList(j))
Dat.Name = NewName
j = j + 1
Txt2html sind meine ersten Gehversuche in .net C#. Das Programm liest eine Textdatei und schreibt eine html-Datei. Dabei werden die Umlaute, einige Sonderzeichen sowie die Zeilenumbrüch durch die entsprechende HTML-Syntax ersetzt. Die Zeichen, die umgesetzt werden, sind in einer ASCII-Datei aufgelistet, die natürlich ergänzt werden kann. Einige Probleme bereitete mir das Einstellen des richtigen Zeichensatztes. Dies geschieht durch einen Parameter beim Erzeugen des Reader-Objektes.
FileStream objTxtFile = new FileStream(strTxtFile, FileMode.Open);
StreamReader objReader = new StreamReader(objTxtFile,
System.Text.Encoding.GetEncoding("iso-8859-1"));
Für jede Zeile der Textdatei wird die Datei mit den zu ändernden Zeichen einmal durchlaufen. Dabei wird schrittweise die neue Zeile erzeugt.
while ((lstLine = LstReader.ReadLine()) != null)
{
///Schleife, bis Zeichen in der Zeile nicht mehr vorkommt
testStr=lstLine.Substring(1,(lstLine.Length)-1);
newLine=newLine.Replace(lstLine.Substring(0,1),
lstLine.Substring(1,(lstLine.Length)-1));
}
LstReader.Close();
objWriter.WriteLine(newLine + "<br>");
DXF_Text durchsucht eine DXF-Datei auch Teexten und schreibt diese in eine Textdatei. Da ja DXF-Datien auch nur ASCII-Dateien sind, sind solche Auswertungen mit ihnen relativ einfach umzusetzen.
Nach dem Programmstart ist eine DXF-Datei
auszuwählen, sowie eine TXT-Datei anzugeben. Die Vorgabeverzeichnisse hierfür können in der INI-Datei angegeben werden. Der nächste Punkt in der INI-Datei ist der Masterkey. Er beschreibt den Geometrietyp in der DXF-Datei und muss auf TEXT stehen. Unter DezZeich bzw. TrennZeich werden Dezimal- bzw. das Trennzeichen der Spalten in der Ausgabedatei angegeben. Für die weiteren Zeilen der INI-Datei sind Kenntnisse über den Aufbau von DXF-Dateien nötig. Jede Elementeigenschaft wird in einer DXF-Datei durch eine Schlüsselzahl eingeleitet. In der INI-Datei gibt es unter [Spalten] mehrere Zeilen, z.B. 8|4|Ebene. Der erste wert ist die Schlüsselzahl in der DXF-Datei, der zweite Wert gibt die Spalte in der Ausgabedatei an. Ist er Null, wird der Wert nicht ausgegeben. Der dritte Wert steht für den Spaltennamen im Ergebnis. Die Ausgabedatei kann folgendermaßen aussehen:
Text,RW_Lu,HW_Lu,Ebene,RW_Fa,HW_Fa,Farbe,Index
Autobus,-38.556675,-0.576831,0,,,7,1
Autobus,-25.150845,3.771006,0,,,12,2
Bahnhof,-31.49144,-8.823225,0,,,9,3
Wasserwerk,-43.810311,5.669564,0,,,3,4
Durch das einheitliche Trennzeichen können die Dateien einfach in Excel, Access oder ein GIS importiert werden.
Text RW_Lu HW_Lu Ebene RW_Fa HW_Fa Farbe Index
Autobus -38.556675 -0.576831 0 7 1
Autobus -25.150845 3.771006 0 12 2
Bahnhof -31.49144 -8.823225 0 9 3
Wasserwerk -43.810311 5.669564 0 3 4
In den Spalten RW_Fa und HW_Fa werden Koordinaten angegeben, wenn sich der Fangpunkt vom Fußpunkt unterscheidet. Die Spalte Index beinhaltet einen Zähler und wird automatisch angefügt.
dxfread plaziert Punktnummern, die aus einer DXF-Datei gelesen werden in der geöffneten DGN-Datei. Die Punktnummern werden an einem Sachdateneintrag in den DXF-Daten erkannt. Da sich dieser Eintrag im Elementblock nach den Koordinaten und dem Text befindet, wird ein zwanzigzeiliges Feld erzeugt, in dem jeweils alle nötigen Daten vorhanden sind.
open dxfFile for Input Access Read Shared As #1
do while not eof(1)
line input #1,kette(20) 'Zeile zur Liste hinzufügen
i% = 0
do while i < 20
kette(i) = kette(i+1) 'Liste neu ordnen
i = i + 1
loop
if kette(19)="POINTNUMBER" and kette(17)="AcDbAttribute" then
mPoint.x = val(kette(7)) 'Koordinaten auslesen
mPoint.y = val(kette(9)) 'Koordinaten auslesen
pktNr = kette(15) 'Text auslesen
MbeSendCommand "PLACE DIALOGTEXT ICON"
MbeSetAppVariable "", "msToolSettings.placeText.type", 0&
MbeSendAppMessage "TEXTEDIT", "FirstLine " & pktNr
MbeSendDataPoint mPoint, 1% 'Text plazieren
end if
loop
close #1
Bemassung.mvba ist ein VBA-Programm für MicroStation 2005. Es handelt sich um einen ungebundenen Dialog, der auf Mausklicks reagiert. Als erstes muss eine Basislinie abgesetzt werden. Später werden zu dieser Linie rechtwinklig Maßpunkte abgesetzt.
Das Programm besteht aus zwei Schleifen, die durch jeweils einen Rechtsklick verlassen werden. Durch die Zeicheneinstellung msdDrawingModeTemporary können Bezugslinien temporär dargestellt werden.
Set nLine = CreateLineElement2(Nothing, Point1, Point2)
nLine.Redraw msdDrawingModeTemporary
Die Richtungen und Strecken werden durch algebraische Formeln ermittelt.
'Richtung x1x2
tt = 1 / Sqr((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
'Länge P1-Pf
a = Sqr((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2))
b = ((x1 - x2) * (x3 - x2) + (y1 - y2) * (y3 - y2)) / (a * c)
h = a * Sqr(1 - (b * b))
p = c - b * a
'Fußpunkt P4
Point4.X = x1 + tt * (x2 - x1) * p
Point4.Y = y1 + tt * (y2 - y1) * p
Point4.Z = 0
Abschließend werden die entsprechenden Maßzahlen plaziert.
Set nText = CreateTextElement1(Nothing, x2point(rText, dezTr), Point3, rotMatrixZ(r))
ActiveModelReference.AddElement nText
nText.Redraw
Durch das MicroStation 95 Makro eleproper können Elementeigenschaften von Elementen einer DGN-Datei geändert werden.
filePos = element.fromFile(0)
Do While filePos >= 0 and chkSum > 0
if element.level>0 and element.color>-1 and element.weight>-1 then
MbeWriteStatus "props " & cstr(element.properties) & " --> " & cstr(optSum)
element.properties = optSum
status = element.rewrite()
element.display MBE_NormalDraw
end if
filePos = element.fromFile (filePos + element.fileSize)
Loop
Die Do-Schleife durchläuft alle Elemente der DGN-Datei. Durch die If-Bedingung wird sichergestellt, dass es sich um ein dargestelltes Element handelt.
Die folgenden Darstellungseigenschaften werden als Summe durch die Eigenschaft properties des Elements eingestellt.
Die Makros delCell und delpoint diehnen zum Bereinigen von DGN-Dateien. Bei delpoint werden alle Elemente der DGN-DAtei durchlaufen. Wird eine Linie (Typ 3) gefunden, wird geteste, ob sie eine mindeslänge hat. Ist dies nicht der Fall, wird sie auf eine seprate Ebene verschoben.
'Einlesen der Endpunktkoordinaten
if element.getPoints (gpoint) = MBE_Success Then
'Test, ob das Element eine Linie ist
if ((element.type = 3) and (element.level < 63)) then
'Koordinaten auslesen
xx0# = gpoint(0).x
xx1# = gpoint(1).x
yy0# = gpoint(0).y
yy1# = gpoint(1).y
'Test, ob die Länge kleiner als (hier) 1mm ist
if (sqr(((xx0-xx1)*(xx0-xx1))+((yy0-yy1)*(yy0-yy1)))<0.001) then
'neue Ebene und Farbe zuweisen
element.color = 1
element.level = 4
stat = element.rewrite ()
end if
end if
end if
emtykill löscht leere DGN-Dateien. Ich benutzte ein anderes Makro, um eine DGN-Datei in Gauss-Krüger-Index-große Dateien zu zerlegen. Dabei können auch leere Dateien entstehen.
Emtykill öffnet nacheinander die DGN-Dateien eines Verzeichnisses und durchläuft sie. Wird ein grafisches Element gefunden, wird die nächste Datei geöffnet. Wird kein Element gefunden, wird die Datei gelöscht.
sub main
Dim Element as New MbeElement
Dim FilePos as Long
Dim flag as integer
dgnDummy$ = MbeDgnInfo.dgnFileName 'Name der geöffneten Datei
dgnPath$ = FileParse$(dgnDummy,2) & "\" 'Pfad der geöffneten Datei
dgnfile$ = LCase$(Dir$(dgnPath & "*.dgn"))
while (dgnfile <> "")
mbeSendCommand ("NEWFILE " & dgnPath & dgnFile) 'neue DGN öffnen
flag = 0
filePos = element.FromFile (0)
do while filePos >= 0 'DGN durchsuchen
if element.level > 0 and element.color > 0 then
flag = 1
exit do
end if
FilePos = element.FromFile (filePos + Element.FileSize)
loop
if flag = 0 then
mbeSendCommand ("NEWFILE " & dgnDummy)
kill dgnPath & dgnFile 'Datei löschen
end if
dgnFile$ = LCase$(Dir$()) 'nächsten Dateinamen lesen
wend
end sub
Durchsucht wird das Verzeichnis, in dem sich die geöffnete DGN-Datei befindet. Außerdem sollte die geöffnete Datei nicht leer und nicht zu groß sein, da sie, wenn einen andere Datei gelöscht wird, zwischenzeitig geöffnet wird.
Die beiden Makros text2txt und textchange zeigen Zugriffsmöglichkeiten auf Texte in DGN-Dateien. Das Makro text2txt schreibt Texte und die dazugehörigen Koordinaten aus einer MicroStation-Datei in eine Textdatei. Es wird benutzt, um in ArcView Punktobjekte zu erhalten, bei denen der Text ein Attribut ist. In diesem Beispiel werden alle Texte berücksichtigt, die einen definierten Teiltext enthalten, dieser Text (fText$) muss im Quelltext eingetragen werden. Es können aber auch ein Filter verwendet werden, die nach den grafischen Ausprägungen selektieren. Zentraler Bestandteil des Makros ist wieder eine DO-Schleife, in der alle Elemente der DGN-Datei durchlaufen werden. Anschließend werden über folgende Schleife Textknoten (mehrzeilige Texte) in einfache Texte umgeformt:
do
status = element.getString(OrgText)
EleText = EleText & OrgText
OrgText = ""
status = element.nextComponent
loop while status = MBE_Success
Die einzelnen Komponenten des Textknotens werden nacheinander gelesen und zu einem neuen einfachen Text zusammengesetzt.
Anschließend wird der Teiltext kontrolliert (instr gibt die Position im Text an) und die Textkoordinaten ausgelesen.
xx% = Instr(EleText,fText) 'Test, ob Teiltext enthalten ist
'xx% = 1 'zum Auslesen aller Texte auskommentieren
element.getOrigin(origin) 'Koordinaten an die Variable origin übergeben
Das Makro textchange ersetzt bestimmte Texte, durch andere Texte. Dabei werden keine Textknoten verarbeitet. Diese Funktion ist bereits unter dem Punkt Bearbeiten - Suchen/Ersetzten vorhanden. Das Makro durchsucht aber alle Dateien in einem ausgewähltem Verzeichnis. Zum Abfragen der Texte wird mit einem bunutzerdefinierten Dialog gearbeitet, dessen Layout in der ba-Datei gespeichert ist. Er hat den Index 1 und wird mit
status = mbeOpenModalDialog (1)
aufgerufen. Wird der Dialog abgebrochen, wird das Makro durch
if status <> MBE_BUTTON_OK then exit sub
beendet. Nach der Eingabe der Quell- und Zieltexte muss das zu bearbeitende Verzeichnis ausgewählt werden. Durch eine while-Schleife werden die DGN-Dateien nacheinander geöffnet.
DesignFile$ = Dir$(Directory$ & "*.dgn")
While DesignFile <> ""
MbeSendCommand "NEWFILE " & Directory & DesignFile 'Datei öffnen
....
DesignFile = Dir$
Wend
Durch die drei Zeilen
MbeSendCommand "FIT VIEW EXTENDED 1"
MbeSetAppVariable "VIEWCTRL", "dialogInfo.p.zoomRatio", 2#
MbeSendCommand "ZOOM OUT EXTENDED 1"
wird in Ansicht eins auf den gesamten Inhalt der DGN-Datei gezoomt. Anschließend werden wieder die einzelnen Elemente der DGN-Datei durchlaufen. Für jedes Textelement (Typ 17) werden folgende Zeilen ausgeführt:
if element.Type = 17 then
status = element.getString(DgnText) 'Zeichenfolge auslesen
if DGNText = OrgText then 'Zeichenfolge vergleichen
if element.setString (NewText) = MBE_Success then 'neue Folge zuweisen
status = element.rewrite () 'Änderungen übernehmen
else
MbeWriteError ("Zeichenfolge kann nicht geändert werden")
end if
end if
end if
Abschließend wird zum nächsten Element gewechselt. Diese beiden Makros wurden unter MicroStation 95 geschrieben.
Zur Zeit setzte ich mich besonders mit html, ... und .net C# auseinander. Demnächst kommt noch ArcGis mit Phyton.
|