Inhalt eines Excel-Sheets verarbeiten

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von vacuphase.

    Inhalt eines Excel-Sheets verarbeiten

    Hallo liebes Forum,
    letztes Mal wurde mir super geholfen und nun habe ich wieder etwas, wobei ich nicht weiterkomme.
    Die Aufgabe ist, ein Excel-Sheet, das Namen (auch doppelt vorkommende) mit Kontobewegungen (die sind alle verschieden) beinhaltet,
    mit VB abzufragen und jeden Namen (also Kunden) mit Kontobewegung in einer einzelnen .txt-Datei separat abzuspeichern.

    Ich bin nun soweit gekommen, dass mein Code alle Zeilen abgrast und jede Zeile in eine .txt speichert.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports excel = Microsoft.Office.Interop.Excel
    3. Public Class Form1
    4. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    5. Dim app As excel.Application = New excel.Application
    6. Dim fileReader As StreamReader = New StreamReader("bankkunden.xlsx")
    7. Dim output As String
    8. app.Workbooks.Open(CurDir() & "\bankkunden.xlsx")
    9. For i = 2 To 54
    10. 'output = datum & kontoveränderung & kontostand
    11. output = app.Range("A" & i).Value & " / " & app.Range("D" & i).Value
    12. Dim fileWriter As StreamWriter = New StreamWriter(i & ".txt", False)
    13. fileWriter.WriteLine(CStr(output))
    14. fileWriter.Close()
    15. Next
    16. End Sub
    17. End Class



    Leider bin ich nicht in der Lage herauszufinden, wie man das Excel-Sheet auf doppelte Namen überprüft und eben dann nicht jede Zeile einzeln speichert, sondern dann auch mal überspringt.
    Ebenso verhält es sich mit dem Verarbeiten der Buchungen. Ich weiß nicht, wie ich die so rausziehen kann, dass die zu den einzelnen Personen gehörigen Buchungen in die zur Person gehörige .txt reingeschrieben werden.

    Das Excel-Blatt sieht so aus:

    Spoiler anzeigen


    Datum Nachname Vorname Buchung
    02.02.2010 Simpson Homer 5,50
    02.02.2010 Simpson Homer -10,00
    20.02.2010 Burns Montgomery 50000000,00

    .
    .
    .



    Vielen Dank schonmal für Eure Hilfe :)
    fürs sortieren:

    VB.NET-Quellcode

    1. Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
    2. Dim test() =
    3. {Tuple.Create(1, "Hans", 50),
    4. tuple.Create(2, "Horst", 70),
    5. Tuple.Create(3, "Hans", 80),
    6. Tuple.Create(4, "Heidi", 70),
    7. Tuple.Create(5, "Hubert", 50),
    8. Tuple.Create(6, "Hansi", 70),
    9. Tuple.Create(7, "Hans", 50),
    10. Tuple.Create(8, "Horst", 70)} 'Erstellen der TestExcel ;)
    11. Dim AllePersonen() As String = (From k In test
    12. Select k.Item2
    13. Distinct).ToArray 'Aussortieren der Duplikate
    14. For Each EinzelPerson In AllePersonen 'Durchlaufen der Einzelpersonen
    15. Dim AktPerson = EinzelPerson
    16. Dim KontoSumme = (From p In test
    17. Where p.Item2 = AktPerson
    18. Select p.Item3).ToArray.Sum 'Summieren aller Einzelbewegungen
    19. TextBox3.AppendText(AktPerson &
    20. " hat zur Zeit: " &
    21. KontoSumme.ToString &
    22. "€ auf dem Konto." &
    23. vbNewLine)
    24. Next
    25. End Sub


    Die Range zum einlesen musste halt noch anpassen auf dein Excel Sheet... Wichtig fürs Sortieren ist einmal die neue Liste, die mit dem DISTINCT von Duplikaten befreit wird. Anhand dieser Liste gehste dann dein ganzes Blatt durch, sucht das jeweils komplett nach dem Namen ab und dann summiert der entsprechend die Kontobewegungen.
    Entsprechend bei Exce kannst du dann ja statt dem Tupel mit dem Range arbeiten und dann ensprechend den offset(zeile,spalte) absuchen oder auslesen
    Vielen Dank FloFuchs,
    Du hast mich schon viel weitergebracht :)
    Derzeit habe ich noch einen Fehler:
    Bei "[ ... ] ToArray.Sum sagt er mir
    "Fehler bei der Überladungsauflösung, da keine zugreifbare "Sum" diese Anzahl von Argumenten akzeptiert."

    Auch bin ich mir nicht sicher, ob das mit der Range so hinhaut ...
    Das Datum habe ich noch eingefügt und den FileWriter reingesetzt.

    Ich würde mich freuen, falls Du nochmal rüberschaust :)

    Spoiler anzeigen


    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. Dim app As excel.Application = New excel.Application
    3. Dim fileReader As StreamReader = New StreamReader("bankkunden.xlsx")
    4. Dim output As String
    5. app.Workbooks.Open(CurDir() & "\bankkunden.xlsx")
    6. Dim test() = {app.Range("A2:D54")}
    7. Dim AllePersonen() As String = (From k In test
    8. Select k.Item2
    9. Distinct).ToArray 'Aussortieren der Duplikate
    10. For Each EinzelPerson In AllePersonen 'Durchlaufen der Einzelpersonen
    11. Dim AktPerson = EinzelPerson
    12. Dim Datum = (From p In test
    13. Where p.Item2 = AktPerson
    14. Select p.Item1).ToArray.ToString
    15. Dim KontoSumme = (From p In test
    16. Where p.Item2 = AktPerson
    17. Select p.Item3).ToArray.Sum 'Summieren aller Einzelbewegungen
    18. Dim fileWriter As StreamWriter = New StreamWriter(EinzelPerson & ".txt", False)
    19. fileWriter.WriteLine(CStr(Datum & " / " & AktPerson & " / " & KontoSumme.ToString))
    20. fileWriter.Close()
    21. Next
    22. End Sub

    Und dann kannst du nicht einfach do das Tuple durch deinen Range ersetzen. Das musste schon etwas anders lösen. Schließlich kannste ja auch nicht einfach einen Range dann mit Item1, 2 3 ansprechen.
    du musst dann in deinem Range suchen und die Vergleiche dann auch entsprechend nicht über item sondern range.offset durchführen.
    Edit:
    kleines Beispiel um deine Excel-Datei in ein Tupel zu schaufeln:

    VB.NET-Quellcode

    1. xlApp.Visible = True
    2. Dim xlMappe = xlApp.Workbooks.Open(IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Test.xlsx"))
    3. Dim xlTabelle = CType(xlMappe.Worksheets("Tabelle1"), Excel.Worksheet)
    4. Dim KtoBewegungen As New List(Of Tuple(Of Date, String, Double))
    5. For i = 1 To xlTabelle.UsedRange.Rows.Count
    6. Dim xlDatum As Date = Date.Parse(CType(xlTabelle.Cells(i, 1), Excel.Range).Value.ToString)
    7. Dim xlName = CType(xlTabelle.Cells(i, 2), Excel.Range).Value.ToString & " " & CType(xlTabelle.Cells(i, 3), Excel.Range).Value.ToString
    8. Dim xlSaldo As Double = Double.Parse(CType(xlTabelle.Cells(i, 4), Excel.Range).Value.ToString)
    9. KtoBewegungen.Add(Tuple.Create(xlDatum, xlName, xlSaldo))
    10. Next
    11. xlMappe.Close()
    12. xlApp.Quit()

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

    Vielen Dank für Deine super Hilfe,
    ich glaube, wir sind nah an der Lösung.
    Deine Beispiele habe ich nun überführt und versucht anzupassen.
    Beim Ausführen des Programms sagt er mir in der Zeile

    VB.NET-Quellcode

    1. Dim xlDatum As Date = Date.Parse(CType(xlTabelle.Cells(i, 1), excel.Range).Value.ToString)
    ,
    dass der Objektverweis nicht auf eine Objektinstanz festgelegt sei.

    Woran liegt das denn? Ich kann mir keinen logischen Reim darauf machen.

    Ich hoffe Du hilfst mir noch weiter :)

    Hier der Kot:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. Dim app As excel.Application = New excel.Application
    3. app.Visible = False
    4. Dim xlMappe = app.Workbooks.Open(IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), CurDir() & "\bankkunden.xlsx"))
    5. Dim xlTabelle = CType(xlMappe.Worksheets("Buchungen"), excel.Worksheet)
    6. Dim KtoBewegungen As New List(Of Tuple(Of Date, String, Double))
    7. For i = 2 To xlTabelle.UsedRange.Rows.Count
    8. Dim xlDatum As Date = Date.Parse(CType(xlTabelle.Cells(i, 1), excel.Range).Value.ToString)
    9. Dim xlName = CType(xlTabelle.Cells(i, 2), excel.Range).Value.ToString & " " & CType(xlTabelle.Cells(i, 3), excel.Range).Value.ToString
    10. Dim xlSaldo As Double = Double.Parse(CType(xlTabelle.Cells(i, 4), excel.Range).Value.ToString)
    11. KtoBewegungen.Add(Tuple.Create(xlDatum, xlName, xlSaldo))
    12. Next
    13. xlMappe.Close()
    14. app.Quit()
    15. Dim AllePersonen() As String = (From k In KtoBewegungen
    16. Select k.Item2
    17. Distinct).ToArray 'Aussortieren der Duplikate
    18. For Each EinzelPerson In AllePersonen 'Durchlaufen der Einzelpersonen
    19. Dim AktPerson = EinzelPerson
    20. Dim Datum = (From p In KtoBewegungen
    21. Where p.Item2 = AktPerson
    22. Select p.Item1).ToArray.ToString
    23. Dim KontoSumme = (From p In KtoBewegungen
    24. Where p.Item2 = AktPerson
    25. Select p.Item3).ToArray.Sum 'Summieren aller Einzelbewegungen
    26. Dim fileWriter As StreamWriter = New StreamWriter(EinzelPerson & ".txt", False)
    27. fileWriter.WriteLine(CStr(Datum & " / " & AktPerson & " / " & KontoSumme.ToString))
    28. fileWriter.Close()
    29. Next
    30. End Sub
    1. War nicht an, nachdem ichs reingebaut habe, ging es auch nicht
    2. In der Datei steht was drin, hatte erst app.visible = true, da sah man, dass die richtige Datei aufgeht
    3. Weiß nicht genau, wie man das macht, er zeigt nur gelbe Zeilen und macht die Schleife anstandslos durch (müssen da Fehler angezeigt werden, wenn was faul ist)?

    Danke schonmal :)
    Also, hab da noch bissle was umgestellt...
    Wichtige Fragen... is die Excel richtig aufgebaut? wenn da zum Beispiel in Spalte A kein auf Datum formatierter Wert drin steht kann dein VB damit nix anfangen.
    Folgendes habe ich bei mir grade getestet, das läuft.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
    2. Dim app As New Excel.Application
    3. app.Visible = True
    4. Dim xlMappe = app.Workbooks.Open(
    5. IO.Path.Combine(Environment.GetFolderPath(
    6. Environment.SpecialFolder.MyDocuments),
    7. "Bankkunden.xlsx"))
    8. Dim xlTabelle = CType(xlMappe.Worksheets("Buchungen"), Excel.Worksheet)
    9. Dim KtoBewegungen As New List(Of Tuple(Of Date, String, Double))
    10. For i = 1 To xlTabelle.UsedRange.Rows.Count
    11. Dim xlDatum As Date = Date.Parse(CType(xlTabelle.Cells(i, 1), Excel.Range).Value.ToString)
    12. Dim xlName = CType(xlTabelle.Cells(i, 2), Excel.Range).Value.ToString & " " & CType(xlTabelle.Cells(i, 3), Excel.Range).Value.ToString
    13. Dim xlSaldo As Double = Double.Parse(CType(xlTabelle.Cells(i, 4), Excel.Range).Value.ToString)
    14. KtoBewegungen.Add(Tuple.Create(xlDatum, xlName, xlSaldo))
    15. Next
    16. xlMappe.Close()
    17. app.Quit()
    18. Dim AllePersonen() As String = (From k In KtoBewegungen
    19. Select k.Item2
    20. Distinct).ToArray 'Aussortieren der Duplikate
    21. For Each EinzelPerson In AllePersonen 'Durchlaufen der Einzelpersonen
    22. Dim AktPerson = EinzelPerson
    23. Dim Datum = (From p In KtoBewegungen
    24. Where p.Item2 = AktPerson
    25. Select p.Item1).ToArray.Max 'nicht .tostring sondern .max damit wir auch das passende Datum zum Endkontostand haben
    26. Dim KontoSumme = (From p In KtoBewegungen
    27. Where p.Item2 = AktPerson
    28. Select p.Item3).ToArray.Sum 'Summieren aller Einzelbewegungen
    29. Using sw As StreamWriter = New StreamWriter(
    30. Path.Combine(Environment.GetFolderPath(
    31. Environment.SpecialFolder.MyDocuments),
    32. EinzelPerson & ".txt"))
    33. sw.WriteLine(Datum.ToLongDateString & "|" & EinzelPerson & "|" & KontoSumme.ToString)
    34. End Using
    35. Next
    36. End Sub

    Wichtig:
    Schau dass Du richtig mit Path.Combine umgehst. Les es dir am nbesten noch mal auf MSDN durch. Dein Streamrider bitte mit Using benutzen! Und die aktuellen Parser benutzen (.Tostring)
    Schau es dir nochmal in Ruhe an, un vollzieh es nach. Falls Du Fragen zu ner Zeile hast... melde Dich
    Vielen Dank Flo,
    es geht leider noch nicht, gehabtes Problem.
    Die Excel ist auf jeden Fall richtig aufgebaut, er schriebt schön alles in die Variablen.
    Dazu habe ich mal rausgezogen, was in den Variablen steht.
    Die Iterationen scheint er durchzugehen aber aus unerfindlichem Grund bleibt er in der letzten Zeile stehen.

    Anbei mal ein Screenshot




    Und die Excel-Tabelle. Zeile 54 zeigt das, was als letztes in den Variablen steht.



    Hoffentlich findet sich der Fehler :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „vacuphase“ ()

    Edit:
    Ah ich denke: Schau dir mal bitte den Wert von

    VB.NET-Quellcode

    1. xlTabelle.UsedRange.Rows.Count
    speziell vom .Count
    Wahrscheinlich hast du unter deinen Daten noch ne Formatierung, dann zählt das auch als UsedRange. In der Zeile 55 versucht er dann Nothing in ein Date zu konvertieren, was dann natürlich einen Fehler gibt.
    Falls ja... packen wir das ganze einfach in eine große If - Abfrage

    VB.NET-Quellcode

    1. if CType(xlTabelle.Cells(i, 2), Excel.Range).Value.ToString ="" then
    2. exit for
    3. else
    4. 'Dein ganzer anderer Code
    5. end if


    Btw.. da das

    VB.NET-Quellcode

    1. CType(xlTabelle.Cells(i, 2), Excel.Range).Value.ToString

    so oft gebraucht wird, könntest du da noch ne Verbesserung einbringen. zB. das ganze mit Trycast machen statt mit Ctype und dann den Satz in ne Function auslagern.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „FloFuchs“ ()

    DAS PROGRAMM FUNZT :D :D

    Das Problem war genau die Tabelle, er hat den UsedRange-Count auf 78 gesetzt und dann versucht einen leeren String in die Variablen zu schaufeln.
    Ich habe einfach manuell mal die Schleife auf "for i=2 to 54" gesetzt und schon hat er alles so erstellt, wie gedacht.
    Ich habe dann noch eine Kundennummer eingefügt, dass dann die .txt "kundennummer.txt" heißt :)

    Ich probiere nochmal mit der zusätzlichen if-Struktur, die Du vorgeschlagen hast.

    Bis hierhin erstmal viiiiielen Dank, da wäre ich nie drauf gekommen :)

    Der Kot:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. Dim app As New excel.Application
    3. app.Visible = False
    4. Dim xlMappe = app.Workbooks.Open(
    5. IO.Path.Combine(Environment.GetFolderPath(
    6. Environment.SpecialFolder.MyDocuments),
    7. CurDir() & "\Bankkunden.xlsx"))
    8. Dim xlTabelle = CType(xlMappe.Worksheets("Buchungen"), excel.Worksheet)
    9. Dim KtoBewegungen As New List(Of Tuple(Of Date, String, Double))
    10. For i = 2 To 54 'xlTabelle.UsedRange.Rows.Count
    11. Dim xlDatum As Date = Date.Parse(CType(xlTabelle.Cells(i, 1), excel.Range).Value.ToString)
    12. Dim xlName = CType(xlTabelle.Cells(i, 2), excel.Range).Value.ToString & " " & CType(xlTabelle.Cells(i, 3), excel.Range).Value.ToString
    13. Dim xlSaldo As Double = Double.Parse(CType(xlTabelle.Cells(i, 4), excel.Range).Value.ToString)
    14. KtoBewegungen.Add(Tuple.Create(xlDatum, xlName, xlSaldo))
    15. Next i
    16. xlMappe.Close()
    17. app.Quit()
    18. Dim AllePersonen() As String = (From k In KtoBewegungen
    19. Select k.Item2
    20. Distinct).ToArray 'Aussortieren der Duplikate
    21. Dim kdnr As Integer = 0
    22. For Each EinzelPerson In AllePersonen 'Durchlaufen der Einzelpersonen
    23. Dim AktPerson = EinzelPerson
    24. kdnr += 1
    25. Dim Datum = (From p In KtoBewegungen
    26. Where p.Item2 = AktPerson
    27. Select p.Item1).ToArray.Max 'nicht .tostring sondern .max damit wir auch das passende Datum zum Endkontostand haben
    28. Dim KontoSumme = (From p In KtoBewegungen
    29. Where p.Item2 = AktPerson
    30. Select p.Item3).ToArray.Sum 'Summieren aller Einzelbewegungen
    31. Using sw As StreamWriter = New StreamWriter(
    32. Path.Combine(Environment.GetFolderPath(
    33. Environment.SpecialFolder.MyDocuments),
    34. CurDir() & "\" & kdnr & ".txt"))
    35. sw.WriteLine(Datum.ToLongDateString & " | " & EinzelPerson & " | " & KontoSumme.ToString)
    36. End Using
    37. Next
    38. End Sub
    Schön wenns funktioniert:
    Noch nen kleinen Tip zu Path.Combine, das is dazu geacht, dass du die & und die \ weglassen kannst. Also

    VB.NET-Quellcode

    1. Path.Combine(Environment.GetFolderPath(
    2. Environment.SpecialFolder.MyDocuments),
    3. CurDir(), kdnr & ".txt"))
    Also das mit dem Prüfen des leeren Strings in Zeile 55 geht nicht ...
    Er schmeißt mir wieder an den Kopf, dass Objektverweis nicht auf Objektinstanz festgelegt sei ...
    Das i im If-Statement ist 55, also völlig korrekt.

    VB.NET-Quellcode

    1. For i = 2 To xlTabelle.UsedRange.Rows.Count
    2. If CType(xlTabelle.Cells(i, 2), excel.Range).Value.ToString = "" Then
    3. Exit For
    4. Else
    5. Dim xlDatum As Date = Date.Parse(CType(xlTabelle.Cells(i, 1), excel.Range).Value.ToString)
    6. Dim xlName = CType(xlTabelle.Cells(i, 2), excel.Range).Value.ToString & " " & CType(xlTabelle.Cells(i, 3), excel.Range).Value.ToString
    7. Dim xlSaldo As Double = Double.Parse(CType(xlTabelle.Cells(i, 4), excel.Range).Value.ToString)
    8. KtoBewegungen.Add(Tuple.Create(xlDatum, xlName, xlSaldo))
    9. End If
    10. Next i


    Was kann das sein? :)
    Hab es ganz anders gemacht jetzt :)
    Das funzt tadellos :)
    Danke Dir, ich melde mich bestimmt nochmal, muss nämlich jetzt die Kundendaten in eine Excel-Mappe schreiben ...

    VB.NET-Quellcode

    1. Dim zeile As Integer = 2
    2. Do While Not CStr(xlTabelle.Cells(zeile, 1).value) = ""
    3. Dim xlDatum As Date = Date.Parse(CType(xlTabelle.Cells(zeile, 1), excel.Range).Value.ToString)
    4. Dim xlName = CType(xlTabelle.Cells(zeile, 2), excel.Range).Value.ToString & " " & CType(xlTabelle.Cells(zeile, 3), excel.Range).Value.ToString
    5. Dim xlSaldo As Double = Double.Parse(CType(xlTabelle.Cells(zeile, 4), excel.Range).Value.ToString)
    6. KtoBewegungen.Add(Tuple.Create(xlDatum, xlName, xlSaldo))
    7. zeile += 1
    8. Loop