Datagridview schneller in Excel exportieren

  • VB.NET

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Datagridview schneller in Excel exportieren

    Hallo
    Ich habe eine Datagridview die an eine BindingSource gebunden ist. Die BindingSource ist an eine Datatabel gebunden. Die BindingSource habe ich eingebaut um die Filterfunktion zu verwenden.
    Ich möchte jetzt nun die Daten aus der Datagridview in eine Excel Datei schreiben.
    Ich habe das mit folgendem Code realisiert mit
    Imports Microsoft.Office.Interop

    VB.NET-Quellcode

    1. Dim saveFileDialog1 As New SaveFileDialog()
    2. saveFileDialog1.Filter = "Excel|*.xlsx"
    3. saveFileDialog1.Title = "Exportieren"
    4. If saveFileDialog1.ShowDialog = DialogResult.OK Then
    5. Try
    6. Dim xlApp As Excel.Application
    7. Dim xlWorkBook As Excel.Workbook
    8. Dim xlWorkSheet As Excel.Worksheet
    9. Dim misValue As Object = System.Reflection.Missing.Value
    10. Dim i As Integer
    11. Dim j As Integer
    12. xlApp = New Excel.Application
    13. xlWorkBook = xlApp.Workbooks.Add(misValue)
    14. xlWorkSheet = CType(xlWorkBook.Sheets(1), Excel.Worksheet
    15. For i = 0 To DataGridView2.RowCount - 1
    16. For j = 0 To DataGridView2.ColumnCount - 1
    17. If DataGridView1(j, i).Value IsNot Nothing Then
    18. xlWorkSheet.Cells(i + 1, j + 1) = DataGridView2(j, i).Value.ToString()
    19. End If
    20. Next
    21. Next
    22. xlWorkSheet.SaveAs(saveFileDialog1.FileName)
    23. xlWorkBook.Close()
    24. xlApp.Quit()
    25. Catch ex As Exception
    26. 'Fehler
    27. MsgBox("Fehler beim Übertragen der Daten nach Excel!" & vbCrLf &
    28. ex.Message, MsgBoxStyle.Exclamation)
    29. End Try
    30. End If


    Das funktioniert auch. Allerdings dauert das verdammt lange. Bei 6000 Zeilen zirka 1 Minute. Wenn ich die Inhalte aus der Datagridview manuell kopiere, Excel öffne und einfüge geht das sofort.
    Weiss jemand wie ich das schneller machen kann?
    Wichtig: Ich möchte nur die Daten aus der Datagridview in der Excel Datei haben (also die gefilterten) nicht die aus der Datatabel.
    mfg
    @gitarre94 Mach es ohne Excel. Sieh Dir mal dieses Projekt an.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    gitarre94 schrieb:

    vb.net ... c#
    Sorry, das ist mir persönlich egal.
    Du kannst die Klassen einzeln übertragen, gugst Du hier,
    oder Du lässt Dir das vom IlSpy machen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    ok danke das umwandeln klappt schonmal :)
    Allerdings weiss ich nicht wie ich weiter vorgehen soll.
    Ich habe jetzt 2 Klassen erstellt.
    1. Klasse: ExcelWriter.vb
    2. Klasse: Program.vb
    Wie kann ich jetzt die Zeilen in eine Excel Datei schreiben?

    @Eierlein
    oh ok danke :)
    Ich hab jetzt die Klasse ExcelWriter erstellt.
    Jetzt weiss ich allerdingswas nicht wie ich weiter machen soll.
    Wie kann ich jetzt die Zeilen in eine Excel Datei schreiben?

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

    gitarre94 schrieb:

    in eine Excel Datei schreiben
    Das ist eine Console-Anwendung, und die läuft ab in der Klasse Program in der Prozedur Main:

    C#-Quellcode

    1. static void Main(string[] args)
    2. {
    3. FileStream stream = new FileStream("demo.xls", FileMode.OpenOrCreate);
    4. ExcelWriter writer = new ExcelWriter(stream);
    5. writer.BeginWrite();
    6. writer.WriteCell(0, 0, "ExcelWriter Demo");
    7. writer.WriteCell(1, 0, "int");
    8. writer.WriteCell(1, 1, 10);
    9. writer.WriteCell(2, 0, "double");
    10. writer.WriteCell(2, 1, 1.5);
    11. writer.WriteCell(3, 0, "empty");
    12. writer.WriteCell(3, 1);
    13. writer.EndWrite();
    14. stream.Close();
    15. }
    Da werden einzelne Zellen beschrieben.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    gitarre94 schrieb:

    jede Zelle einzeln
    Jou.
    Wenn Du dabei mal (zumindest partiell) das .ToString() weglässt, kommen sogar korrekte Datentypen dort an.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo gitarre94,
    mit folgendem Projekt kannst du ganz bequem DataTables oder gar komplette DataSets
    in ein Excel-Dokument (2007/2010) schreiben, ohne Excel installiert zu haben:
    Link: closedxml.codeplex.com/releases/view/197852
    Kleine Anleitung für den Einstieg: community.dev-reference.de/ind…-installiertes-MS-Office/
    @OnkelR
    geht das auch mit einer Datagridview?
    Oder macht es vielleicht Sinn die Datagridview in eine Datatabel zu schreiben und die Datatabel dann zu exportien? (Wenn das geht)

    @RodFromGermany
    einen Nachteil hat die Variante trotzdem. Man kann nur maximal 2^16 = 65536 Zeilen exportieren. Danach kommt die Fehlermeldung "arithmetischer Überlauf"
    Oder kann man das irgendwie beseitigen?
    Aber von Laufzeit schonmal ein großer Schritt nach vorne.
    Hab mal eine Messung gemacht mit 57000 Zeilen.
    1. Variante mit Imports.Microsoft.Interop = 70minuten (hochgerechnet)
    2. Variante in BIFF Format: 0:43 Minuten
    :D

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „gitarre94“ ()

    Du kannst den momentanen Inhalt des DGV per Hand in eine Excel-Tabelle schaufeln -> closedxml.codeplex.com/wikipag…erringTitle=Documentation
    Oder du kreierst eine Abfrage und schickst dann das Ergebnis in eine DataTable (Abfrage.CopyToDataTable), welche du dann in eine Excel-Tabelle schaufelst -> closedxml.codeplex.com/wikipag…erringTitle=Documentation
    oder...oder

    Hier sind paar Beispiele: closedxml.codeplex.com/documentation
    Wie sind die Laufzeiten?

    Schneller als man glaubt. Ich war zumindest positiv überrascht.

    Können auch mehr als 65000 Spalten gespeichert werden?

    Wer zur Hölle benötigt so viele Spalten?

    Ich habs zB. mit ca. 30.000 Datensätzen a 15 Spalten unterschiedlichster Datentypen getestet.

    gitarre94 schrieb:

    "arithmetischer Überlauf"
    mit welchem Code?
    Mit welchen Datentypen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    1.

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Produces Excel file without using Excel
    3. ''' </summary>
    4. Public Class ExcelWriter
    5. Private stream As Stream
    6. Private writer As BinaryWriter
    7. Private clBegin As UShort() = {&H809, 8, 0, &H10, 0, 0}
    8. Private clEnd As UShort() = {&Ha, 0}
    9. Private Sub WriteUshortArray(value As UShort())
    10. For i As Integer = 0 To value.Length - 1
    11. writer.Write(value(i))
    12. Next
    13. End Sub
    14. ''' <summary>
    15. ''' Initializes a new instance of the <see cref="ExcelWriter"/> class.
    16. ''' </summary>
    17. ''' <param name="stream">The stream.</param>
    18. Public Sub New(stream As Stream)
    19. Me.stream = stream
    20. writer = New BinaryWriter(stream)
    21. End Sub
    22. ''' <summary>
    23. ''' Writes the text cell value.
    24. ''' </summary>
    25. ''' <param name="row">The row.</param>
    26. ''' <param name="col">The col.</param>
    27. ''' <param name="value">The string value.</param>
    28. Public Sub WriteCell(row As Integer, col As Integer, value As String)
    29. Dim clData As UShort() = {&H204, 0, 0, 0, 0, 0}
    30. Dim iLen As Integer = value.Length
    31. Dim plainText As Byte() = Encoding.ASCII.GetBytes(value)
    32. clData(1) = CUShort(8 + iLen)
    33. clData(2) = CUShort(row)
    34. clData(3) = CUShort(col)
    35. clData(5) = CUShort(iLen)
    36. WriteUshortArray(clData)
    37. writer.Write(plainText)
    38. End Sub
    39. ''' <summary>
    40. ''' Writes the integer cell value.
    41. ''' </summary>
    42. ''' <param name="row">The row number.</param>
    43. ''' <param name="col">The column number.</param>
    44. ''' <param name="value">The value.</param>
    45. Public Sub WriteCell(row As Integer, col As Integer, value As Integer)
    46. Dim clData As UShort() = {&H27e, 10, 0, 0, 0}
    47. clData(2) = CUShort(row)
    48. clData(3) = CUShort(col)
    49. WriteUshortArray(clData)
    50. Dim iValue As Integer = (value << 2) Or 2
    51. writer.Write(iValue)
    52. End Sub
    53. ''' <summary>
    54. ''' Writes the double cell value.
    55. ''' </summary>
    56. ''' <param name="row">The row number.</param>
    57. ''' <param name="col">The column number.</param>
    58. ''' <param name="value">The value.</param>
    59. Public Sub WriteCell(row As Integer, col As Integer, value As Double)
    60. Dim clData As UShort() = {&H203, 14, 0, 0, 0}
    61. clData(2) = CUShort(row)
    62. clData(3) = CUShort(col)
    63. WriteUshortArray(clData)
    64. writer.Write(value)
    65. End Sub
    66. ''' <summary>
    67. ''' Writes the empty cell.
    68. ''' </summary>
    69. ''' <param name="row">The row number.</param>
    70. ''' <param name="col">The column number.</param>
    71. Public Sub WriteCell(row As Integer, col As Integer)
    72. Dim clData As UShort() = {&H201, 6, 0, 0, &H17}
    73. clData(2) = CUShort(row)
    74. clData(3) = CUShort(col)
    75. WriteUshortArray(clData)
    76. End Sub
    77. ''' <summary>
    78. ''' Must be called once for creating XLS file header
    79. ''' </summary>
    80. Public Sub BeginWrite()
    81. WriteUshortArray(clBegin)
    82. End Sub
    83. ''' <summary>
    84. ''' Ends the writing operation, but do not close the stream
    85. ''' </summary>
    86. Public Sub EndWrite()
    87. WriteUshortArray(clEnd)
    88. writer.Flush()
    89. End Sub
    90. End Class


    VB.NET-Quellcode

    1. Namespace XLSExportDemo
    2. Class Program
    3. Private Shared Sub Main(args As String())
    4. Dim stream As New FileStream("demo.xls", FileMode.OpenOrCreate)
    5. Dim writer As New ExcelWriter(stream)
    6. writer.BeginWrite()
    7. writer.WriteCell(0, 0, "ExcelWriter Demo")
    8. writer.WriteCell(1, 0, "int")
    9. writer.WriteCell(1, 1, 10)
    10. writer.WriteCell(2, 0, "double")
    11. writer.WriteCell(2, 1, 1.5)
    12. writer.WriteCell(3, 0, "empty")
    13. writer.WriteCell(3, 1)
    14. writer.EndWrite()
    15. stream.Close()
    16. End Sub
    17. End Class
    18. End Namespace


    2. Datentyp String

    Ich habe mich jetzt allerdings jetzt für die Variante von @OnkelR entschieden.
    @OnkelR ist es auch möglich Bilder/Logos in die Xml Datei einzufügen?

    gitarre94 schrieb:

    Bilder/Logos in die Xml Datei einzufügen?
    genau wie beim Studio-Designer, Du musst das Bild in einen Base64String und zurück konvertieren, gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!