VB Studio Express 2012, Zeilen in Textfile finden und Werte Variablen zuweisen? Anfänger verzweifelt

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    VB Studio Express 2012, Zeilen in Textfile finden und Werte Variablen zuweisen? Anfänger verzweifelt

    Moin moin,

    jetzt habe ich mir gerade angemeldet und möchte auch gleich eine Frage an Euch stellen.
    Ich bin ein blutiger Anfänger mit VB - wir haben zwar ein paar kleine Scripte bei der Arbeit, das ist aber alles sehr einfach und ich musste mich nie wirklich damit beschäftigen.
    Ich bin bisher in der Kornshell, UNIX, VI, vim, dos-batch-scripting, powershell und wmic als Admin zu Hause.

    Das hat sich nun geändert und ich bin mit Visual Basic konfrontiert. Das lerne ich soeben und seit Tagen lese ich mein Buch "Einstieg in Visual Basic" von Thomas Theis und durchforste das Internet auf VB-Foren und Codeschnippsel :)

    So, genug der langen Rede - Frage: Kann mir jemand (bitte Anfänger-geeignet ;) ) hier mal helfen?

    Ich versuche eine Textdatei zu lesen, daraus bestimmte Werte zu extrahieren und diesen wiederrum Variablen zuzuweisen.

    Dies ist meine Input.txt Datei (aus der NC Welt, es geht um x,y,z koordinaten)

    Quellcode

    1. VIELE ANDERE ZEILEN
    2. ********************
    3. NOCH MEHR INFOS : WERTE 00000040
    4. INFOS INFOS : WERTE WERTE 00000050
    5. ..usw usw
    6. OBJEKTKENNUNG : OBJEKTNAME_HIER_HIER 00000090
    7. BIEGERADIUS : 16.60 MM 00000120
    8. ********************
    9. TOLERANZ : 1.000 mm
    10. PNTW610 = POINT / .000 , .000 , .000 00000190
    11. PNT0002 = POINT / 57.262 , -.000 , -.000 00000200
    12. PNT0003 = POINT / 27.230 , 12.535 , 55.510 00000210
    13. PNTW609 = POINT / 27.230 , 32.752 , 73.092 00000220
    14. $ TN = 00000230
    15. $ DAT = 17.06.2013-10:00:48 00000240
    16. VDA2 = END 00000250

    Und was ich erreichen muss ist:
    Die Werte dieser Angaben herausbekommen:
    OBJEKTKENNUNG
    BIEGERADIUS
    Und die x,y und z-Koordinaten der "POINT"-Reihen.

    Am Ende muss ich das in eine CSV-Datei (die den Namen der OBJEKTKENNUNG trägt) schreiben in diesem Format:
    X,Y,Z,Biegeradius
    X,Y,Z,Biegeradius

    Quellcode

    1. .000,.000,.000,16.60
    2. 57.262,-.000,-.000,16.60
    3. 27.230,12.535,55.510,16.60
    4. 27.230,32.752,73.092,16.60


    Es können auch wesentlich mehr POINT-Zeilen darin vorkommen, nicht nur 3 - auch mal 90 oder mehr.

    Und meine Versuche scheitern kläglich, weil ich im Moment einfach nicht weiss wie ich die Daten vernünftig da extrahiere :S
    Ich versuchte mit streamreader, split, trim, filereader - alles was ich so fand, aber ich kriegs nicht hin.

    Hat da jemand für mich mal bitte die richtige Info?

    VB.NET-Quellcode

    1. ' Hier öffnen wir die Files
    2. Private Sub cmdFolder_Click(sender As Object, e As EventArgs) Handles cmdFolder.Click
    3. '
    4. ' Variablen Deklaration
    5. Dim ofd As New OpenFileDialog
    6. ofd.Multiselect = True
    7. ofd.InitialDirectory = "G:\dvlp\NCFILES"
    8. ofd.Filter = "NC_Dateien (*.txt)|*.txt|" &
    9. " Alle Dateien (*.*)|*.*"
    10. ofd.Title = "Dateien zum Öffnen auswählen"
    11. If ofd.ShowDialog() = Windows.Forms.DialogResult.OK Then
    12. For Each file As String In ofd.FileNames
    13. 'DEBUG
    14. 'MessageBox.Show("Öffnen: " & file)
    15. 'DEBUG
    16. '''''' Das hier funktioniert AB hier...
    17. Dim filereader As System.IO.StreamReader
    18. filereader = My.Computer.FileSystem.OpenTextFileReader(file)
    19. Dim stringreader As String
    20. stringreader = filereader.ReadToEnd()
    21. MsgBox("The first line of file is " & stringreader)
    22. '''''' Das hier funktioniert BIS hier...
    23. '
    24. ' Hier versuchen wir mit streamreader die zeilen einzulesen
    25. ' den Biegeradius und Objektkennung zu finden und die Werte zuzuweisen
    26. ' Weise Objektkennung einer Variablen zu
    27. Dim OBJEKTKENNUNG
    28. ' Weise Biegeradius einer Variablen zu
    29. ' Loop durch die POINTS und lege sie im Array ab
    30. ' schreib den schmonz in eine csv Datei mit namen der Objektkennung
    31. Next
    32. End If
    33. End Sub


    Danke für Eure Unterstützung :) VB macht Spass, aber die Syntax bringt mich im Moment noch an den Rand des Wahnsinns :cursing:

    Ich denke, das mit dem Schreiben in die CSV-Datei bekomme ich hin, sobald ich die Werte in Variablen, bzw. einem Array habe.
    ~~~~~~~~~~~~~
    Gruß, RiffRaff

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RiffRaff“ ()

    Bitte VB-Tag benutzen - aber richtig

    Dann versuchst du, mehrere Dateien auf einmal einzulesen - ist das beabsichtigt?
    Sollen dabei mehrere Ausgabedateien entstehen, oder muss das alles in dieselbe Ausgabe-Csv?
    Also wenn alles in dieselbe Datei soll, dann ist Csv als Datenformat überfordert.

    Ansonsten konzentriere dich drauf, erstmal eine Datei korrekt zu konvertieren.

    Schreib dir dafür eine Methode, und überleg dazu, was soll in die Function hineingehen, und was soll wieder rauskommen?

    Mein Vorschlag: Hineingehen soll der Dateiname, und rauskommen soll eine Liste von String-Arrays, also eine 2-dimensionale Auflistung.
    die erste Dimension repräsentiert die Zeilen, und die 2.Dimension repräsentiert die Daten der einzelnen Datensätze.

    VB.NET-Quellcode

    1. private Function GetData(filename as String)as List(Of String())
    2. dim returnValue = new List(of String())
    3. 'datei auslesen, liste befüllen
    4. return returnValue
    5. end function
    eine weitere Methode wäre zu schreiben, der man den AusgabePfad angibt, und die dann das Csv dafür raushaut. Das ist ganz einfach:

    VB.NET-Quellcode

    1. private Sub WriteCsv(fileName As STring, data as List(Of String()))
    2. IO.File.WriteAllLines(fileName, data.Select(Function(strings)String.Join("; ", strings)).ToArray)
    3. End Sub
    ok - es ist nur einfach, wenn man sich auskennt ;) Aber um dich auszukennen zu lernen bist du ja hier ;)
    (achtung: Code ungetestet)

    ErfinderDesRades schrieb:

    Bitte VB-Tag benutzen - aber richtig

    Dann versuchst du, mehrere Dateien auf einmal einzulesen - ist das beabsichtigt?
    Sollen dabei mehrere Ausgabedateien entstehen, oder muss das alles in dieselbe Ausgabe-Csv?

    Das ist richtig - mehrere Dateien, die alle nach dem selben Muster aufgebaut sind, sollen verarbeitet werden.
    Und für jede einzelne Datei soll es dann eine csv-Datei geben die den Namen der enthaltenen "OBJEKTKENNUNG" trägt.


    Ansonsten konzentriere dich drauf, erstmal eine Datei korrekt zu konvertieren.

    Schreib dir dafür eine Methode, und überleg dazu, was soll in die Function hineingehen, und was soll wieder rauskommen?
    Mein Vorschlag: Hineingehen soll der Dateiname, und rauskommen soll eine Liste von String-Arrays, also eine 2-dimensionale Auflistung.


    Mein Versuch ist es jede Datei einzeln zu verarbeiten - dieses Datei öffnen, alle auswählen und er zeigt mir nacheinander in der MsgBox die Files an sieht ja gut aus - ich dachte, dass ich da einfach ansetzen kann und dann die
    Formatierung/Aufarbeitung der jweiligen Datei gleich abhandeln kann.

    Mein Problem sind im Augenblick, so glaube ich, die RegExp um die Zeilen zu filtern und die richtigen Dinge zu finden.
    An meiner kornshell würde ich einfach ein "for file in *; do; export OBJEKTKENNUNG=$(grep -i "Objektkennung" $file; awk -F: '{print $2}');done
    machen und ich hätte alle Namen. Das gleiche mit dem Biegeradius und noch ein Array für die Koordinaten.
    Aber ich weiß einfach (noch) nicht wie ich die Sache in VB angehen muss. Mit DOS-Batch-Scripting würde ich es wohl auch hinbekomme, aber sobald es an Arrays dabei geht wird es unschön und schrecklich.


    Ich ackere mich gleich mal durch Dein Beispiel, mal sehen ob der Groschen nicht fällt.

    (Für mehr Input, Hilfe und Hiwneise bin ich total dankbar; bei der Sache fehlte mir leider die Zeit mich besser reinzuarbeiten und nächste Woche soll ich ergebnisse liefern, real-life halt :thumbdown: )

    Danke für Deine Antwort.

    Zum quoten, vb-quellcode-editor:
    Ist das nicht korrekt? Ich habe den vb-code doch richtig angelegt, oder?
    Meine Input-Datei habe ich extra als "code" hinzugefügt, da der normale "quote" die ganzen leerzeichen entfernt - falls das wichtig ist, wollte ich gern, dass man die sieht.
    Auch wenn ich auf dem Reiter "Quellcode" den "VB-Knopf" nutze kommen die gleichen Tags heraus. Oder mache ich da etwas falsch? Ich habe Deinen Link gelesen, sehe aber im Moment meinen Fehler nicht ;(
    ~~~~~~~~~~~~~
    Gruß, RiffRaff
    Ich hab mir das mal angeschaut, hab da ein Beispiel erstellt, das dann anschliessend in eine CSV zu bekommen denke ich das schaffst du schon ;)
    Ich denke so müsste das auch mit deinen anderen Dateien funktionieren.

    VB.NET-Quellcode

    1. Public Class Form1
    2. ''''Inhalt D:\test.txt
    3. 'NOCH MEHR INFOS : WERTE 00000040
    4. 'INFOS INFOS : WERTE WERTE 00000050
    5. '..usw usw
    6. 'OBJEKTKENNUNG : OBJEKTNAME_HIER_HIER 00000090
    7. 'BIEGERADIUS : 16.60 MM 00000120
    8. '********************
    9. 'TOLERANZ : 1.000 mm
    10. 'PNTW610 = POINT / .000 , .000 , .000 00000190
    11. 'PNT0002 = POINT / 57.262 , -.000 , -.000 00000200
    12. 'PNT0003 = POINT / 27.230 , 12.535 , 55.510 00000210
    13. 'PNTW609 = POINT / 27.230 , 32.752 , 73.092 00000220
    14. '$$ TN = * 00000230
    15. '$$ DAT = 17.06.2013-10:00:48 00000240
    16. 'VDA2 = END
    17. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    18. Dim contents As New List(Of String)
    19. Dim s As String = IO.File.ReadAllText("D:\test.txt")
    20. Dim r As New System.Text.RegularExpressions.Regex("(?<=OBJEKTKENNUNG.*?:.*?)([A-Z0-9].*|[a-z0-9].*)(?=[0-9]{8})")
    21. Dim m As System.Text.RegularExpressions.MatchCollection = r.Matches(s)
    22. contents.Add(m(0).ToString)
    23. r = New System.Text.RegularExpressions.Regex("(?<=BIEGERADIUS.*?:.*?)([0-9]+.*)(?=.*MM)")
    24. m = r.Matches(s)
    25. Dim biegeradius As String = m(0).ToString
    26. r = New System.Text.RegularExpressions.Regex("(?<=PNT.*?= POINT /.*?)([0-9]+.*)(?=[0-9]{8})")
    27. m = r.Matches(s)
    28. For i = 0 To m.Count - 1
    29. contents.Add(m(i).ToString.Replace(vbTab, "").Replace(" "c, "") & "," & biegeradius)
    30. Next
    31. For i = 0 To contents.Count - 1
    32. MessageBox.Show(contents(i))
    33. Next
    34. End Sub
    35. End Class

    RiffRaff schrieb:

    Zum quoten, vb-quellcode-editor:
    Ist das nicht korrekt? Ich habe den vb-code doch richtig angelegt, oder?
    guck ins VisualStudio: For-Schleifen sind immer eingerückt. In deim post aber nicht. Ist momentan nicht weiter schlimm, nur wenn das eine Gewohnheit wird, dann ists eine Unhöflichkeit, nämlich um Hilfe bei Codes zu bitten, aber den nichtmal vernünftig gelayoutet zu präsentieren.

    Was heißt "ackern durch mein Code"? Ich hab doch garkein Code gegeben, sondern nur die leere Hülle einer Function.
    Verstehst du den Sinn dieser leeren Hülle? Also was sie eingegeben bekommen muß, und was sie dafür zurückgibt?

    @Derfuhr:: ok, das ist jetzt Code, nur gewissermaßen ohne Hülle.
    Das konzentriert sich auch auf eine Datei, allerdings ist die festverdrahtet, und die Ausgabe ist auch noch ein annerer Datentyp, als was ich preferiere (du: String, ich: List(Of Strings)).

    Naja - zu viele Köche - muss der TE sehen, womit er weiter machen will...
    Ja da muss der TE guggen, ich wollte im jetzt nicht die ganze Arbeit abnehmen, sondern nur aufzeigen wie er an die gewünschten Daten kommt, ich bin mir fast sicher, das aus deiner geposteten Hülle und meinem Beispiel eine gutes Gericht werden kann.
    jo, wird wohl. Meine Hülle taugt auch nix, denn ich hab folgendes überlesen:

    RiffRaff schrieb:

    Am Ende muss ich das in eine CSV-Datei (die den Namen der OBJEKTKENNUNG trägt)
    Die Methode bekommt also bereits alle Informationen, einschließlich der Ausgabe-Datei (die sie ja selbst ausliest).
    Damit entfällt der Sinn eines Rückgabewertes, sondern das Teil kann die Ausgabemethode selbst aufrufen. Statt GetData() also nun ConvertFile():

    VB.NET-Quellcode

    1. private Sub ConvertFile(filename as String)
    2. dim outPutFile As String
    3. dim list = new List(of String())
    4. 'datei auslesen: outPutFile auslesen, liste befüllen
    5. WriteCsv(outPutFile , list )
    6. end Sub
    Oh man, Ihr seid echt klasse! Danke für die vielen Hinweise und den Code und alles!!

    Bin gerade wieder zu Hause und werde mich nachher noch intensiv ransetzen - ich bin zuversichtlich, dass ich das damit hinbekomme :thumbsup:

    Und werde dann auch den fertigen Code hier, hoffentlich korrekt formatiert, einfügen.

    Ich glaube im VB-Paradiese bin ich gut aufgehoben, bei so einer netten Begrüssung und der Notfall-Lösung - wobei ich das hoffentlich nicht nochmal so benötige.
    Tatsächlich bin ICH immer der, der die Manuals liest, sich die Sachen aneignet und lernt.
    Und bin selber oft genervt, wenn Leute in den Foren um eine Lösung bitten und sich dann später nicht nochmal blicken lassen - oder, noch schlimmer, einfach irgendwann schreiben: "Ok, habs jetzt hinbekommen" und nicht mal beschreiben, wie und was... :thumbdown:


    Danke nochmals! ^^
    ~~~~~~~~~~~~~
    Gruß, RiffRaff
    Hallo,
    ich nochmal.
    Nochmals allerherzlichsten Dank! Das klappt ganz wunderbar :thumbsup:
    Ich habe noch den neuen Namen der Datei (die Objektkennung) mit rtrim von Leerzeichen befreit und hoffe, dass auch das Schreiben in die Datei so gut aussieht.
    Zumindest tut es ganue das, was es soll. Ich kann eine oder mehrere Dateien auswählen und nach Klick auf "OK" werden die benötigten Daten extrahiert und in entsprechende einzelne csv.Dateien abgelegt.

    Ausserdem habe ich mir noch den Pfad extrahiert - etwas umständlich mit 2x reverse - so habe ich es im Internet gefunden, wenn man den OpenFileDialog nutzen möchte. Da ich jetzt nichts anderes da noch ausprobieren wollte, beliess ich es erstmal damit - zumindest funktioniert das auch. In Version 2 werde ich dann die Verbesserungen einbauen, die ich noch finde und nachlese - jetzt habe ich ja schon mal damit eine gute Ausgangsbasis.

    Ihr habt mit echt super geholfen und, kein Scherz, damit meinen morgigen Sonntag gerettet!!

    Und als nächstes werde ich mir die RegExp aneignen - was da steht, verstehe ich noch nicht wirklich...üben, üben..üben... :thumbup:

    So, nun bin ich auf dem Quellcode-Reiter und VB-Quotiere das hier nochmal rein - hoffentlich korrekt.

    VB.NET-Quellcode

    1. Private Sub cmdFolder_Click(sender As Object, e As EventArgs) Handles cmdFolder.Click
    2. Dim sPath As String
    3. Dim ofd As New OpenFileDialog
    4. ofd.Multiselect = True
    5. ofd.InitialDirectory = "G:\dvlp\NC_Daten"
    6. 'Der Anwender kann zwischen .txt Dateien oder Alle Dateien waehlen
    7. ofd.Filter = "NC_Dateien (*.txt)|*.txt|" &
    8. " Alle Dateien (*.*)|*.*"
    9. ofd.Title = "Dateien zum Öffnen auswählen"
    10. If ofd.ShowDialog() = Windows.Forms.DialogResult.OK Then
    11. ' Schreibe den Pfad der Files in sPath, damit wir dorthin nachher
    12. ' die csv zurückschreiben können
    13. sPath = ofd.FileName 'das ist der komplette Pfad
    14. 'MsgBox(sPath) '
    15. sPath = StrReverse(sPath) 'Den String reversieren
    16. sPath = Mid(sPath, InStr(sPath, ""), Len(sPath)) 'ab dem ersten Slash
    17. sPath = StrReverse(sPath) 'Erneut reversieren
    18. 'Jetzt steh in sPath der Folder-Path
    19. ' Fuer jede Datei, die wir waehlen....tue folgendes:
    20. For Each file As String In ofd.FileNames
    21. 'DEBUG
    22. 'MessageBox.Show("Öffnen: " & file)
    23. 'DEBUG
    24. Dim contents As New List(Of String)
    25. Dim s As String = IO.File.ReadAllText(file)
    26. Dim r As New System.Text.RegularExpressions.Regex("(?<=OBJEKTKENNUNG.*?:.*?)([A-Z0-9].*|[a-z0-9].*)(?=[0-9]{8})")
    27. Dim m As System.Text.RegularExpressions.MatchCollection = r.Matches(s)
    28. contents.Add(m(0).ToString)
    29. r = New System.Text.RegularExpressions.Regex("(?<=BIEGERADIUS.*?:.*?)([0-9]+.*)(?=.*MM)")
    30. m = r.Matches(s)
    31. Dim biegeradius As String = m(0).ToString
    32. r = New System.Text.RegularExpressions.Regex("(?<=PNT.*?= POINT /.*?)([0-9]+.*)(?=[0-9]{8})")
    33. m = r.Matches(s)
    34. For i = 0 To m.Count - 1
    35. contents.Add(m(i).ToString.Replace(vbTab, "").Replace(" "c, "") & "," & biegeradius)
    36. Next
    37. For i = 1 To contents.Count - 1
    38. 'MessageBox.Show(contents(i))
    39. 'Hier in die jeweilige Datei schreiben
    40. 'Die Datei soll in sPath und den Namen der objektkennung.csv bekommen
    41. 'Objektkennung hat leerzeichen rechts, darum rtrim
    42. My.Computer.FileSystem.WriteAllText(sPath & "" & RTrim(contents(0)) & ".csv", contents(i) & vbCrLf, True)
    43. Next
    44. Next
    45. End If
    46. End Sub


    /EDIT: In den Anführungsstrichen hinter ...(sPath & ""... steht eigentlich ein Backslash - der wird hier aber nicht angezeigt, bzw. entfernt.

    Und entschuldigt bitte mein Viel-Schreiberei, das ist so in mir drin :)
    ~~~~~~~~~~~~~
    Gruß, RiffRaff

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RiffRaff“ ()

    ich empfehle dir nochmal: schreib dir eine Methode, die sich explizit um die Verarbeitung einer Datei kümmert.
    Das ist einfach, und ist eine wesentliche Verbesserung deiner Architektur.

    Dann kann man anfangen, so Sachen wie den Pfad extrahieren verbessern, oder diese sehr unwirtschaftliche innere Schleife

    VB.NET-Quellcode

    1. For i = 1 To contents.Count - 1
    2. 'MessageBox.Show(contents(i))
    3. 'Hier in die jeweilige Datei schreiben
    4. 'Die Datei soll in sPath und den Namen der objektkennung.csv bekommen
    5. 'Objektkennung hat leerzeichen rechts, darum rtrim
    6. My.Computer.FileSystem.WriteAllText(sPath & "" & RTrim(contents(0)) & ".csv", contents(i) & vbCrLf, True)
    7. Next
    durch was effizientes ersetzen.

    Ich hätt noch 2, 3 weitere wesentliche Verbesserungsvorschläge, aber eins nachm anneren - zunächst mal Architektur.