Koordinaten plus Label importieren aus Ascii Datei


 Produkt(e):MicroStation
 Version(en):08.11.09.829
 Umgebung:Windows 8
 Produktbereich:Programmierung
 Produktunterbereich:VBA

 

Hintergrundinformation

 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.

Erforderliche Schritte

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