DGV in Excel exportieren-> Performance verbessern

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von SKeks.

    DGV in Excel exportieren-> Performance verbessern

    Hallo Community,

    Ich hab in meiner Applikation die Möglichkeit, die Inhalt einer DatagridView nach Excel zu exportieren.
    Bei geringen Datenmengen funktioniert dies wunderbar, bei höheren Datenmengen (~500 Zeilen mit ca 16 Spalten) kann dies jedoch einige Sekunden dauern.
    Dabei kann ich auch in der GUI derweil nichts machen.

    Hier mein Code:

    Quellcode

    1. Public Shared Sub exportDGV(dgv As DataGridView)
    2. ' return
    3. If dgv Is Nothing Or dgv.RowCount = 0 Then
    4. Exit Sub
    5. End If
    6. ' init variables for export
    7. Dim x_app As Excel.Application
    8. Dim x_workbook As Excel.Workbook
    9. Dim x_worksheet As Excel.Worksheet
    10. Dim misValue As Object = System.Reflection.Missing.Value
    11. Dim i As Integer
    12. Dim j As Integer
    13. ' init save file dialog
    14. Dim sfd_export As New SaveFileDialog
    15. sfd_export.Filter = "Excel Worksheet|*.xlsx |All Files|*.*"
    16. sfd_export.Title = "Save an Excel File"
    17. sfd_export.FileName = "result.xlsx"
    18. If sfd_export.ShowDialog() = Windows.Forms.DialogResult.OK Then
    19. ' create new excel objects
    20. x_app = New Excel.Application
    21. x_workbook = x_app.Workbooks.Add(misValue)
    22. x_worksheet = x_workbook.ActiveSheet
    23. ' set header
    24. For col As Integer = 0 To dgv.Columns.Count - 1
    25. x_worksheet.Cells(1, col + 1).Value = dgv.Columns(col).HeaderText
    26. x_worksheet.Cells(1, col + 1).Font.Bold = True
    27. Next
    28. ' some of the dgv have a last empty row, those we want to exclude
    29. Dim last_row_dgv = 0
    30. If dgv(0, dgv.RowCount - 1).Value Is Nothing Then
    31. last_row_dgv = 1
    32. End If
    33. ' fill data
    34. For i = 0 To dgv.RowCount - 1 - last_row_dgv
    35. For j = 0 To dgv.ColumnCount - 1
    36. x_worksheet.Cells(i + 2, j + 1) = dgv(j, i).Value.ToString()
    37. Next
    38. Next
    39. ' save to file
    40. Try
    41. x_worksheet.SaveAs(sfd_export.FileName)
    42. Catch ex As Exception
    43. Finally
    44. x_workbook.Close()
    45. x_app.Quit()
    46. End Try
    47. ' release objects
    48. releaseObject(x_app)
    49. releaseObject(x_workbook)
    50. releaseObject(x_worksheet)
    51. MessageBox.Show("Export successfully performed!", "Info")
    52. End If
    53. End Sub


    Habt ihr Ideen was ich in Bezug auf Performance besser machen könnte?
    Würde ein zusätzlicher BackgroundWorker hier Sinn machen?

    Liebe Grüße
    da würdich erstmal rumprobieren, obs nicht zuverlässiger und schneller geht.
    Im INet fahren OpenSource-Excel-Libraries herum, die einen sehr guten Ruf haben.

    Und BackgroundWorker war schon Schrott, als er erfunden wurde.
    Heutzutage würde man Async/await nutzen.

    Aber eins nach dem anderen:
    1) deine bisherigen Backgroundworker runterschmeißen
    2) nach einer performanteren Excel-Beschickung suchen
    3) diese performantere Excel-Beschickung mit Async/Await nebenläufig machen, damit das Gui nicht mehr blockiert.
    Hallo,

    es geht sehr viel schneller mit dem Daten nach Excel übertragen, wenn du zunächst deine Daten aus dem Grid in ein Range-Objekt überträgst und danach nur das Range-Obj in die Tabelle überträgst.

    VB.NET-Quellcode

    1. Dim ref As Excel.Range = DirectCast(_xlWorksheet.Cells(1, 1), Excel.Range)
    2. ref.Offset(1, 0).Value = "Header"
    3. Dim DataArray(Output.Count - 1, 2) As Object
    4. For i = 0 To OutputCount - 1 'Output ist eine List(of Double);
    5. DataArray(i, 0) = val1
    6. DataArray(i, 1) = val2
    7. DataArray(i, 2) = val3
    8. Next
    9. Dim Cell1 As String = DirectCast(_xlWorksheet.Cells(3, 1), Excel.Range).Address
    10. Dim xlRange As Excel.Range = _xlWorksheet.Range(Cell1).Resize(Output.Count, 3)
    11. xlRange.Value = DataArray


    Ich habe das Snipet mit generischen Variablen angepasst, statt die Bezeichnung meiner Variablen. Du musst es noch an dein Code anpassen; ich hoffe es ist so verständlich. Der Geschwindigkeitszuwachs im gegensatz zum zeilenweisen übertragen ist immens.

    Viele Grüße

    Edit: ich schaffs gerade nicht mit den Tags; hmmm ist ja trotzdem lesbar