Produkt(e): | MicroStation | ||
Version(en): | 08.11.09.829 | ||
Umgebung: | Windows 8 | ||
Produktbereich: | Programmierung | ||
Produktunterbereich: | VBA |
Zum Importieren von Koordinaten in eine Zeichnung steht in MicroStation das Tool xyzText zur Verfügung. Damit können unterschiedlich aufgebaute Textdateien importiert werden. Darüber hinaus gibt es aber noch weitere Anforderungen, die eine mehrfache Ausführung dieses Tools verlangen oder auch direkt nicht umsetzbar sind.
Mit VBA haben wir die Möglichkeit, gezielt auf die vorhandene Datenstruktur der Textdatei einzugehen und den Import entsprechend der eigenen Anforderung zu gestalten.
Ich möchte hier ein Beispiel aufzeigen, das eine Datenstruktur mit folgendem Aufbau einliest:
4359169.0287,5536492.1819,247.6100,26
4359157.2171,5536497.5796,241.8600,27
4359154.4723,5536494.7391,241.8600,28
4359160.8127,5536494.1052,241.8600,29
D.h. die Textdatei enthält pro Zeile eine Koodinate in den ersten 3 Spalten und in Spalte 4 noch eine Nummer. Sowohl die Koordinate (als Punkt) als auch die Nummer (als Text) soll in der Zeichnung platziert werden. Das Trennsymbol zwischen den Spalten ist das Komma.
Diese Eigenschaften werden nun in diesem VBA Beispiel berücksichtigt und können leicht auf andere Vorgaben angepasst werden.
Hier nun das Beispiel:
Sub importPunkte_und_Label() Dim pfad As String Dim zeile As String Dim l() As String Dim pOrigin As Point3d Dim pOffset As Point3d Dim oPoint As Element Dim oText As Element pOffset = Point3dFromXYZ(0.5, 0.5, 0) ' Verschiebung des Labels zur Koordinate pfad = "d:/import/import.txt" ' Ort für Ascii Datei zum Importieren Open pfad For Input As #1 Do While Not (EOF(1)) ' Ascii Datei vollständig einlesen Line Input #1, zeile ' zeilenweise einlesen l = Split(zeile, ",") ' es wird ein Komma als Trennzeichen für die Daten angenommen If UBound(l) - LBound(l) = 3 Then ' prüfen ob 4 Daten pro Zeile mit Komma getrennt vorliegen pOrigin.X = Val(l(LBound(l))) pOrigin.Y = Val(l(LBound(l) + 1)) pOrigin.Z = Val(l(LBound(l) + 2)) Set oPoint = CreateLineElement2(Nothing, pOrigin, pOrigin) ' Punkt an Koordinate erstellen ActiveModelReference.AddElement oPoint ' Punkt Platzieren pOrigin = Point3dAdd(pOrigin, pOffset) Set oText = CreateTextElement1(Nothing, l(LBound(l) + 3), pOrigin, Matrix3dIdentity) 'Label erstellen, an Koodinate + Offset ActiveModelReference.AddElement oText ' Label platzieren End If Loop Close #1 End Sub
Das vorige Beispiel ist insbesondere dann geeignet, wenn feste Dateinamen und Orte für die zu importierenden Ascii Dateien vorliegen, ebenso im Batchbetrieb ist dies geeignet, da für den Ablauf keine Interaktion mit dem Anwender notwendig ist.
Jedoch in der Praxis möchte der Anwender die importierende Datei oft direkt selber auswählen können, deshalb stelle ich hier noch eine weitere Variante vor, die dies unterstützt, und zwar konkret verwende ich hier den Dateidialog zur Auswahl einer Datei, wie sie in dem Beispielprojekt mdlexamples.mvba gezeigt wird.
Konkret handelt es sich um die MDL Funktion mdlDialog_fileopen,
Das Beispielprojekt mdlexamples.mvba wird mit MicroStation installiert und liegt im Workspace unter ..\system\vba\examples
Insgesamt sind zur vorigen Variante 3 Änderungen zu nennen:
- Auswahl einer Importdatei per Dialog
- Platzieren der aktuell festgelegten Zelle anstelle eines Punktes
- Angabe der insgesamt eingelesenen Punkte in der Nachrichtenzentrale.
Hier nun das Beispiel:
Private Declare Function mdlDialog_fileOpen Lib "stdmdlbltin.dll" (ByVal fileName As String, ByVal rFileH As Long, ByVal resourceId As Long, ByVal suggestedFileName As String, ByVal filterString As String, ByVal defaultDirectory As String, ByVal titleString As String) As Long ' Truncates a buffer to just contain the string that ' the C function returned. Function TruncateAtEOS(str As String) As String If str <> "" Then ' This test avoids exception on zero-length string TruncateAtEOS = Left$(str, InStr(1, str, vbNullChar) - 1) End If End Function Option Explicit Sub importPunkte_und_Label() Dim pfad As String Dim zeile As String Dim l() As String Dim pOrigin As Point3d Dim pOffset As Point3d Dim oCell As Element Dim oText As Element Dim cellName As String Dim counter As Long counter = 0 pOffset = Point3dFromXYZ(0.5, 0.5, 0) ' Verschiebung des Labels zur Koordinate ' Check aktive Zelle If Len(ActiveSettings.cellName) = 0 Then MsgBox "Keine aktive Zelle gewählt - Abbruch", vbCritical Exit Sub Else cellName = ActiveSettings.cellName End If pfad = Space(1024) If Not (mdlDialog_fileOpen(pfad, 0, 0, "import.txt", "*.txt", "c:\", "Datei wählen für Import")) = 0 Then MsgBox " Bitte Datei zum Import wählen - Abbruch", vbCritical Exit Sub End If Open pfad For Input As #1 Do While Not (EOF(1)) ' Ascii Datei vollständig einlesen Line Input #1, zeile ' zeilenweise einlesen l = Split(zeile, ",") ' es wird ein Komma als Trennzeichen für die Daten angenommen If UBound(l) - LBound(l) = 3 Then ' prüfen ob 4 Daten pro Zeile mit Komma getrennt vorliegen pOrigin.X = Val(l(LBound(l))) pOrigin.Y = Val(l(LBound(l) + 1)) pOrigin.Z = Val(l(LBound(l) + 2)) 'Set oPoint = CreateLineElement2(Nothing, pOrigin, pOrigin) ' Punkt an Koordinate erstellen Set oCell = CreateCellElement2(cellName, pOrigin, Point3dFromXYZ(1, 1, 1), True, Matrix3dIdentity) ActiveModelReference.AddElement oCell ' Zelle platzieren pOrigin = Point3dAdd(pOrigin, pOffset) Set oText = CreateTextElement1(Nothing, l(LBound(l) + 3), pOrigin, Matrix3dIdentity) 'Label erstellen, an Koodinate + Offset ActiveModelReference.AddElement oText ' Label platzieren counter = counter + 1 End If Loop Close #1 MessageCenter.AddMessage "Es wurden ingesamt " + str(counter) + " Koordinaten eingelesen" End Sub
Update: Für MicroStation CONNECT Edition sind an der VBA Routine minimale Änderungen vorzunehmen, um den Wechsel von 32 Bit auf 64 Bit zu unterstützen, das macht sich in diesem Beispiel nur in der Deklaration der benutzen MDL Funktion bemerkbar. Diese Funktion wird in diesem Beispiel zum Öffnen einer Dialogbox zur Dateiauswahl verwendet.
Hier das Beispiel für MicroStation CONNECT:
Private Declare PtrSafe Function mdlDialog_fileOpen Lib "stdmdlbltin.dll" (ByVal fileName As String, ByVal rFileH As LongPtr, ByVal resourceId As Long, ByVal suggestedFileName As String, ByVal filterString As String, ByVal defaultDirectory As String, ByVal titleString As String) As Long ' Truncates a buffer to just contain the string that ' the C function returned. Function TruncateAtEOS(str As String) As String If str <> "" Then ' This test avoids exception on zero-length string TruncateAtEOS = Left$(str, InStr(1, str, vbNullChar) - 1) End If End Function Option Explicit Sub importPunkte_und_Label() Dim pfad As String Dim zeile As String Dim l() As String Dim pOrigin As Point3d Dim pOffset As Point3d Dim oCell As Element Dim oText As Element Dim cellName As String Dim counter As Long counter = 0 pOffset = Point3dFromXYZ(0.5, 0.5, 0) ' Verschiebung des Labels zur Koordinate ' Check aktive Zelle If Len(ActiveSettings.cellName) = 0 Then MsgBox "Keine aktive Zelle gewählt - Abbruch", vbCritical Exit Sub Else cellName = ActiveSettings.cellName End If pfad = Space(1024) If Not (mdlDialog_fileOpen(pfad, 0, 0, "import.txt", "*.txt", "c:\", "Datei wählen für Import")) = 0 Then MsgBox " Bitte Datei zum Import wählen - Abbruch", vbCritical Exit Sub End If Open pfad For Input As #1 Do While Not (EOF(1)) ' Ascii Datei vollständig einlesen Line Input #1, zeile ' zeilenweise einlesen l = Split(zeile, ",") ' es wird ein Komma als Trennzeichen für die Daten angenommen If UBound(l) - LBound(l) = 3 Then ' prüfen ob 4 Daten pro Zeile mit Komma getrennt vorliegen pOrigin.x = val(l(LBound(l))) pOrigin.y = val(l(LBound(l) + 1)) pOrigin.z = val(l(LBound(l) + 2)) 'Set oPoint = CreateLineElement2(Nothing, pOrigin, pOrigin) ' Punkt an Koordinate erstellen Set oCell = CreateCellElement2(cellName, pOrigin, Point3dFromXYZ(1, 1, 1), True, Matrix3dIdentity) ActiveModelReference.AddElement oCell ' Zelle platzieren counter = counter + 1 pOrigin = Point3dAdd(pOrigin, pOffset) If Len(l(LBound(l) + 3)) > 0 Then ' Text nur platzieren, wenn nicht leer Set oText = CreateTextElement1(Nothing, l(LBound(l) + 3), pOrigin, Matrix3dIdentity) 'Label erstellen, an Koodinate + Offset ActiveModelReference.AddElement oText ' Label platzieren End If End If Loop Close #1 MessageCenter.AddMessage "Es wurden ingesamt " + str(counter) + " Koordinaten eingelesen" End Sub
Ursprünglicher Autor: | Artur Goldsweer |