Aus VB Excel Zelle formatieren ohne Late binding

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Mabbi.

    Aus VB Excel Zelle formatieren ohne Late binding

    Hallo,

    ich baue gerade einen DatenExport, Ziel ist es ein Excel File zu generieren.

    Die Daten werden in eine DataGridView geladen (zur Kontrolle) und dann in eien Excel Datei exportiert.
    Die Ausgabe zeigt aktuell Kundendaten, weist der AdrNummer aus einer anderen DB die korrekte Postleitzahl und Ort zu und generiert dann Umsatzsummen pro Jahr und alternativ für ein (abweichendes) Geschäftsjahr
    Das klappt soweit auch ganz gut mit folgendem Code:

    VB.NET-Quellcode

    1. Dim App As New Excel.Application
    2. Dim Book As Excel.Workbook = App.Workbooks.Add
    3. 'Neues Datenblatt anlegen
    4. Dim Sheet As Excel.Worksheet = CType(Book.Sheets.Add, Excel.Worksheet)
    5. Sheet.Name = "Kundenstatistik"
    6. Dim Zeile As Integer = 1
    7. Sheet.Cells.Item(Zeile, 1) = "AdrNr"
    8. Sheet.Cells.Item(Zeile, 2) = "Name"
    9. Sheet.Cells.Item(Zeile, 3) = "Plz_Ort"
    10. Sheet.Cells.Item(Zeile, 3) = "Summe Gesamt"
    11. 'Jahresliste generieren
    12. Dim Spalte As Integer = 5
    13. For i As Integer = 2010 To DateTime.Now.Year
    14. .Cells.Item(Zeile, Spalte) = i.ToString
    15. Spalte += 1
    16. Next
    17. 'GJ Liste erstellen
    18. For i As Integer = 2010 To DateTime.Now.Year
    19. .Cells.Item(Zeile, Spalte) = "GJ " & (i - 1).ToString & "/" & CStr(i).ToString
    20. Spalte += 1
    21. Next
    22. 'Vorrücken
    23. Zeile += 1
    24. Spalte = 1
    25. 'Daten holen
    26. For i As Integer = 0 To DataGridView1.Rows.Count - 1
    27. For j As Integer = 0 To DataGridView1.Columns.Count - 1
    28. 'Daten
    29. .Cells.Item(Zeile, Spalte) = DataGridView1.Item(j, i).Value
    30. Spalte += 1
    31. 'PLZ Zuordnen
    32. If j = 1 Then
    33. Dim strPLZ As String = PLZ_zuordnen(CInt(DataGridView1.Item(0, i).Value))
    34. .Cells.Item(Zeile, Spalte) = strPLZ
    35. Spalte += 1
    36. End If
    37. Next j
    38. 'neue Zeile
    39. Zeile += 1
    40. Spalte = 1
    41. Next i
    42. End With
    43. 'Speichern
    44. Book.SaveAs("C:\Users\xxx\Desktop\Kundenstat.xlsx")
    45. App.Quit()
    46. App = Nothing


    Nun möchte ich die Zellen in Excel noch formatieren(Zahlen als EuroSummen darstellen) und gezielt den Hintergrund einfärben bevor ich Sie speichere.
    Hierzu habe ich dies gefunden: Excel Zellen formatieren aus VB

    Hieraus bekomme ich einfach keinen sinnvollen Ansatz hin, der mit Option Strict On funktioniert, es kommt der Late Binding Fehler.

    Wahrscheinlich seh ich mal wieder den Wald vor Bäumen nicht, könntet Ihr mir da bitte weiterhelfen, wie man das realisieren kann ?

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

    Ich möchte nicht auf den Code eingehen, dafür habe ich erstens einmal eine Frage:
    Wie kommen die Daten ins DGV? Ich hoffe auf eine Antwort wie "mittels Datenbindung an [Dataset | List Of <T>]", sowas halt.
    Wenn du typisierst arbeitest würde ich dir empfehlen, nimm EPPlus und schreibe die Daten darüber in eine Excel-Tabelle.
    Excel wird dazu nicht einmal benötigt, auch das Formatieren von Werten ist alles damit kein Hexenwerk.
    Allerdings empfehle ich aus lizenzrechtlichen Gründen die Version EPPlus.4.5.3.3 zu installieren (es gibt dazu NuGet-Pakete, die Version kann dort auch gewählt werden).
    @Dksksm:
    Ich habe Rohdaten in einer Art csv Datei, automatisch generierter Export aus unserer Warenwirtschaft.

    VB.NET-Quellcode

    1. Dim AlleZeilen As New List(Of String())
    2. Call Rohdaten_DB_laden(AlleZeilen, DP_Adressen_Rohdaten)
    3. Call LadeAdressDaten(AlleZeilen)
    4. AlleZeilen.Clear()
    5. AlleZeilen = Nothing


    Die bereite ich auf und lade sie in eine _Adressdaten Klasse.

    VB.NET-Quellcode

    1. Public Class Adresse
    2. Public Property Kundennummer As Double
    3. Public Property Telefonnummer As String
    4. Public Property Str_HausNr As String
    5. Public Property Fkzeichen As String
    6. Public Property Plz_Ort As String
    7. Public Property Konditionen As String
    8. Public Property VK As String
    9. Public Property Email As String
    10. Public Property Sperre As String
    11. Public Property Name1 As String
    12. Public Property Name2 As String
    13. Public Property ZAZ As String
    14. Public Property MWST As String
    15. End Class


    Das gleiche mache ich mit dem Rechnungsarchiv der Warenwirtschaft und schiebe die in eine weiter Klasse _Rechnungsdaten.

    Aus den beiden Klassen befülle ich ein DataTable, den binde ich dann zur Visualisierung an die DGV.

    Nun will mein Chef nicht nur gucken können in der App, sondern eine Excel Datei als Export um halt mit den Zahlen und Sortierungen rumspielen zu können.
    Als .csv bekomm ich das problemlos hin, dann müsste ich die aber immer manuell nachbearbeiten und als .xlsx speichern.

    Nachtrag: Ich generiere die Excel Datei aus der DGV weil man dort schon filtern/sortieren/kondensieren kann.
    Der Datatable enthält alle Daten, die DGV nur die aktuell erwünschten. Und die sollen exportiert werden.

    Deswegen habe ich mir gestern das Erstellen von Excel files angeschaut, geht auch soweit: Erstellen und mit den Daten befüllen (s. Code 1. Post oben)
    Nur beim Formatieren scheitere ich an OPTION STRICT ON.

    z.B.:

    VB.NET-Quellcode

    1. Sheet.Cells.EntireColumn.AutoFit()


    führt zum Late Binding Error.

    Da ich konsequent alles mit Strict On programmiere, um es einfach so sauber wie möglich machen zu müssen, suche ich nun eine Lösung um gezielt Zellen in einem Excel-Worksbook/Sheet zu formatieren.

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „Mabbi“ ()

    Mabbi schrieb:

    Das klappt soweit auch ganz gut mit folgendem Code:
    Ich glaube nicht, dass dein Code so kompiliert. Ich sehe zwar ein End With aber kein korrespo0ndierendes With.

    Mabbi schrieb:

    Hieraus bekomme ich einfach keinen sinnvollen Ansatz hin, der mit Option Strict On funktioniert
    Du setzt doch schon für jede Zelle den Wert. Genauso gut kannst du auch das Format setzen
    Zeig mal deine Fehlversuche, die mit Option Strict On nicht funktionieren.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    @petaod: Sorry, mein Fehler. Ich hatte für die Frage unwichtiges aus dem Code gelöscht und ausversehen auch das "with" rauseditiert.

    Hier das komplette Modul:

    VB.NET-Quellcode

    1. Imports Microsoft.Office.Interop


    VB.NET-Quellcode

    1. Private Sub BUT_Export_Click(sender As System.Object, e As System.EventArgs) Handles BUT_Export.Click
    2. 'WW-Rohadaten laden und in die _Adressdaten schaufeln
    3. Dim AlleZeilen As New List(Of String())
    4. Call Rohdaten_DB_laden(AlleZeilen, DP_Adressen_Rohdaten)
    5. Call LadeAdressDaten(AlleZeilen)
    6. AlleZeilen.Clear()
    7. AlleZeilen = Nothing
    8. Dim App As New Excel.Application
    9. Dim Book As Excel.Workbook = App.Workbooks.Add
    10. 'Neues Datenblatt anlegen
    11. Dim Sheet As Excel.Worksheet = CType(Book.Sheets.Add, Excel.Worksheet)
    12. Sheet.Name = "Kundenstatistik"
    13. 'Leere Datenblaetter loeschen
    14. For i As Integer = 1 To 3
    15. Sheet = CType(Book.Sheets(2), Excel.Worksheet)
    16. Sheet.Delete()
    17. Next
    18. Dim Zeile As Integer = 1
    19. Sheet = CType(Book.Sheets(1), Excel.Worksheet)
    20. With Sheet
    21. Sheet.Cells.Item(Zeile, 1) = "AdrNr"
    22. Sheet.Cells.Item(Zeile, 2) = "Name"
    23. Sheet.Cells.Item(Zeile, 3) = "Plz_Ort"
    24. Sheet.Cells.Item(Zeile, 4) = "Summe Gesamt"
    25. 'Jahresliste generieren
    26. Dim Spalte As Integer = 5
    27. For i As Integer = 2010 To DateTime.Now.Year
    28. .Cells.Item(Zeile, Spalte) = i.ToString
    29. Spalte += 1
    30. Next
    31. 'GJ Liste erstellen
    32. For i As Integer = 2010 To DateTime.Now.Year
    33. .Cells.Item(Zeile, Spalte) = "GJ " & (i - 1).ToString & "/" & CStr(i).ToString
    34. Spalte += 1
    35. Next
    36. 'Vorrücken
    37. Zeile += 1
    38. Spalte = 1
    39. 'Daten holen
    40. For i As Integer = 0 To DataGridView1.Rows.Count - 1
    41. For j As Integer = 0 To DataGridView1.Columns.Count - 1
    42. 'Daten
    43. .Cells.Item(Zeile, Spalte) = DataGridView1.Item(j, i).Value
    44. Spalte += 1
    45. 'PLZ Zuordnen
    46. If j = 1 Then
    47. Dim strPLZ As String = PLZ_zuordnen(CInt(DataGridView1.Item(0, i).Value))
    48. .Cells.Item(Zeile, Spalte) = strPLZ
    49. Spalte += 1
    50. End If
    51. Next j
    52. 'neue Zeile
    53. Zeile += 1
    54. Spalte = 1
    55. Next i
    56. End With
    57. Sheet.Cells.EntireColumn.AutoFit()
    58. 'Speichern
    59. Book.SaveAs("C:\Users\xxx\Desktop\Kundenstat.xlsx")
    60. App.Quit()
    61. App = Nothing
    62. 'Aufräumen
    63. _Adressdaten.Clear()
    64. End Sub


    Wennich nun oberhalb der PLZ-Zuordnung im xlsx Part(oben) folgendes einfüge

    VB.NET-Quellcode

    1. 'Name fettschreiben
    2. If j = 0 Then
    3. .Cells(Zeile, Spalte).font.bold = True
    4. End If


    Bekomme ich folgenden Fehler :
    Fehler 3 "Option Strict On" lässt spätes Binden nicht zu. C:\Users\xxx\documents\visual studio 2010\Projects\xxx\xxx\Gr_Stat.vb 422 xxx

    Das gleiche passiert auch wenn ich folgendes versuche:

    VB.NET-Quellcode

    1. .Cells.Item(Zeile, Spalte).font.bold = True



    Wobei ich glaube, der Ansatz ist einfach falsch.
    Das Autofit funktioniert nun, BOLD bekomme ich aber mit den Versuchen nur ohne STRICT ON in der xlsx-Tabelle. (mit dieser Variante: .Cells(Zeile, Spalte).font.bold = True)

    Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von „Mabbi“ ()

    Leider Nein, aber ein anderer Fehler-Code:




    Und endlich ein Fehler mit Korrekturoptionen....so gehts mit Option Strict ON:

    VB.NET-Quellcode

    1. 'Name fettschreiben
    2. If j = 0 Then
    3. '.Cells(j, i).font.bold = True
    4. Dim rng As Excel.Range = CType(.Cells.Item(Zeile, Spalte), Excel.Range)
    5. rng.Font.Bold = True
    6. End If


    Danke für die Hilfe, nun kmme ich alleine weiter. :thumbsup:

    P.S.: Sieht ganz logisch und offensichtlich aus...das mit den Wald und den Bäumen...Ihr wisst schon...

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

    da muss dann auch der CType auf der rechten sein davor.
    Nimm gleich @petaod's Variante, weil das ist direkt gecasted.

    Intellisence zeigt dir aber nicht nur den Fehler, sondern macht dir doch auch einen Korrekturvorschlag, hab es grade mal getestet.
    Intellisence korrigiert es sogar selbst für dich, musst halt nur machen lassen.
    Mein Fehler war, ich hatte auch Option Strict nicht On, liegt daran, dass ich eigentlich nie in VB.Net, sondern in C# progge.
    Hi,

    eine kleine Frage zum Abschluß hätte ich noch...(auch wenn es etwas am thread-Topic vorbei geht)

    VB.NET-Quellcode

    1. Dim App As New Excel.Application
    2. Dim Book As Excel.Workbook = App.Workbooks.Add
    3. ....
    4. 'Speichern
    5. Book.SaveAs(DP_KunStat)
    6. 'Aufräumen
    7. App.Quit()
    8. App = Nothing


    Ich mache die Excel Application auf, arbeite daran bis alles fertig ist und schliesse Sie am Ende wieder (korrekt?)
    Im Windows Taskmanager verschwindet aber der Excel-Prozess erst, wenn ich komplett aus der App rausgehe.

    Die Haupt-App die das Kundenstatitik-Module aufruft ist ein ziemlich grosses Programm geschrieben um permanent zu laufen.
    Eigentlich möchte ich nicht, das da unnötige/ungenutzte Prozesse im Hintergrund sich nicht schliessen, wenn diese nicht mehr gebraucht werden.

    Was mache ich beim Schliessen der externen Excel-APP hier falsch ? (oder liegt das am Debuggen ?)
    (Eigentlich bräuchte ich doch nicht mal das App = Nothing, sollte doch der garbage collector automatisch entfernen. Ich schreibe es aus alter gewohnheit immer noch rein)