DGV: Felder, die per RowPrepaint zur Laufzeit gefüllt werden, werden nicht exportiert

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

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    DGV: Felder, die per RowPrepaint zur Laufzeit gefüllt werden, werden nicht exportiert

    Hallo zusammen.

    Ich habe hier ein seltsames Phänomen. Zur Laufzeit lasse ich mir in einem DGV zusätzlich zu den gebundenen Daten noch ein paar Felder per
    RowPrepaint mit Zusatzinformationen aus einer anderen DataTable füllen. Das klappt im Programm selbst auch sehr gut. Allerdings wenn ich
    die ganze Geschichte dann nach Excel exportieren möchte sind die Felder, die per RowPrepaint gefüllt wurden nur soweit ausgefüllt, wie es der
    Bildschirm gerade anzeigt. Bei den anderen Zeilen steht dann nix drin. Kann ich das Problem irgendwie umgehen? Me.ValidateChildren
    hab ich schon ausgetestet und bringt nichts.

    VB.NET-Quellcode

    1. Private Sub dgv_RowPrePaint(sender As Object, e As DataGridViewRowPrePaintEventArgs) Handles aDgvFahrzeugTablet.RowPrePaint
    2. Dim rw = DirectCast(DirectCast(aDgvFahrzeugTablet.Rows(e.RowIndex).DataBoundItem, DataRowView).Row, FahrzeugTabletRow)
    3. If Not rw.Anmeldename = AppDefaults.DefaultDummy Then
    4. Dim fahrzeugRowsAktiv = Dts.Fahrzeug.Where(Function(x) x.FahrzeugTabletRow Is rw AndAlso x.Aktiv)
    5. If fahrzeugRowsAktiv.Count > 0 Then
    6. aDgvFahrzeugTablet.Item("standortFahrzeugstamm", e.RowIndex).Value = String.Join(" | ", fahrzeugRowsAktiv.Select(Function(x) x.StandortRow.Name))
    7. aDgvFahrzeugTablet.Item("kennzeichenFahrzeugstamm", e.RowIndex).Value = String.Join(" | ", fahrzeugRowsAktiv.Select(Function(x) x.Kennzeichen))
    8. aDgvFahrzeugTablet.Item("mitarbeiterFahrzeugstamm", e.RowIndex).Value = String.Join(" | ", fahrzeugRowsAktiv.Select(Function(y) y.MitarbeiterRow.expFullname))
    9. aDgvFahrzeugTablet.ConditionedDgvCellBackColor(e, rw.StandortRow.Name <> aDgvFahrzeugTablet.Item("standortFahrzeugstamm", e.RowIndex).Value?.ToString, "standortFahrzeugstamm")
    10. End If
    11. Dim fahrzeugRowsInaktiv = Dts.Fahrzeug.Where(Function(x) x.FahrzeugTabletRow Is rw AndAlso Not x.Aktiv)
    12. If fahrzeugRowsInaktiv.Count > 0 Then
    13. aDgvFahrzeugTablet.Item("altfahrzeuge", e.RowIndex).Value = String.Join(" | ", fahrzeugRowsInaktiv.Select(Function(x) x.Kennzeichen))
    14. End If
    15. End If
    16. aDgvFahrzeugTablet.ConditionedDgvRowForeColor(e, Not rw.Aktiv)
    17. End Sub
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Was erwartest Du? Wann wird denn RowPrepaint aufgerufen? Wie der Name sagt: Direkt, bevor die Zeile gemalt wird. Aber Zeilen, die nicht angezeigt werden müssen, weil außerhalb des gezeigten Scrollbereichs, werden nicht benötigt, daher kein RowPrepaint, daher kein Datennachladen, daher kein Export.
    Ändere Deine Exportfunktion so, dass eben die Zusatzspalten auf jeden Fall für jede Zeile ausgeführt werden. Mehr Tipps sind ohne Exportcode von meiner Seite nicht möglich.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed: Das hab ich mir schon gedacht, dass das so abläuft leider.. :(
    Also müsste ich entweder die Tabelle, die an's DGV gebunden ist erweitern oder das DGV komplett manuell befüllen... oder gibt es eine andere Möglichkeit?

    Den Export-Code kann ich gerne anhängen - am Ende landet aber alles in einer neuen DataTable und die wird über das NuGet-Paket EPPlus dann
    zu ner Excel-Datei verwurstet.

    VB.NET-Quellcode

    1. aDgvFahrzeugTablet.CopyOrExportSelection(True)


    Spoiler anzeigen

    VB.NET-Quellcode

    1. ''' <summary> Stellt einen Dialog zur Auswahl des Inhalts eins DGV zum Export oder Kopieren bereit. </summary>
    2. <Extension>
    3. Public Sub CopyOrExportSelection(dgv As DataGridView, excel As Boolean, Optional orderBy As String = Nothing, Optional pdf As Boolean = False, Optional pdfDescription As String = Nothing)
    4. Using dlg As New dlgDGVcopyExport
    5. Dim listbox = dlg.chkLbSpalten
    6. Dim lstDgvCols As New List(Of dgvCol)
    7. For Each col As DataGridViewColumn In dgv.Columns
    8. If col.Visible Then
    9. lstDgvCols.Add(New dgvCol With {.name = col.Name, .headertext = convertTrimString(col.HeaderText), .valueType = col.ValueType})
    10. End If
    11. Next
    12. dlg.Text = If(excel, "Export Excel", "in Zwischenablage kopieren")
    13. listbox.DataSource = lstDgvCols
    14. listbox.DisplayMember = "headertext"
    15. listbox.ValueMember = "name"
    16. For i = 0 To listbox.Items.Count - 1
    17. listbox.SetItemChecked(i, True) 'alle Items auf Checked setzen
    18. Next
    19. If dlg.ShowDialog <> DialogResult.OK Then Return
    20. Dim selectedDgvCols As New List(Of dgvCol)
    21. For Each chkItm In listbox.CheckedItems
    22. selectedDgvCols.Add(DirectCast(chkItm, dgvCol))
    23. Next
    24. Select Case True
    25. Case dlg._Selection = "all"
    26. If excel Then
    27. exportSelectionToExcel(dgv, "Export", selectedDgvCols, dlg._header)
    28. ElseIf pdf Then
    29. 'exportSelectionToPDF(dgv, pdfDescription, selectedDgvCols, dlg._header)
    30. Else
    31. copySelectionToClipboard(dgv, selectedDgvCols, dlg._header)
    32. End If
    33. Case dlg._Selection = "marked"
    34. Dim lstRow = (From rw In dgv.SelectedRows.Cast(Of DataGridViewRow)() Order By rw.Index).ToList
    35. If excel Then
    36. exportSelectionToExcel(dgv, "Export", selectedDgvCols, dlg._header, lstRow)
    37. ElseIf pdf Then
    38. 'exportSelectionToPDF(dgv, pdfDescription, selectedDgvCols, dlg._header, lstRow)
    39. Else
    40. copySelectionToClipboard(dgv, selectedDgvCols, dlg._header, lstRow)
    41. End If
    42. End Select
    43. End Using
    44. End Sub


    Spoiler anzeigen

    VB.NET-Quellcode

    1. ''' <summary>Exportiert den selektierten Inhalt eines DGVs inkl. Angabe von Sheetname in eine Excel-Datei via EPPlus</summary>
    2. Private Sub exportSelectionToExcel(dgv As DataGridView, wsn As String, selectedCols As List(Of dgvCol), Header As Boolean, Optional lstrow As List(Of DataGridViewRow) = Nothing)
    3. Dim excelFile = saveAs("Excel-Dateien (*.xlsx)|*.xlsx")
    4. If excelFile = "" Then Return
    5. If excelFile.IsInUse Then
    6. msgInformation($"Die Datei {excelFile} ist bereits geöffnet, bitte einen neuen Dateinamen angeben.")
    7. excelFile = saveAs("Excel-Dateien (*.xlsx)|*.xlsx")
    8. Else
    9. If File.Exists(excelFile) Then File.Delete(excelFile)
    10. End If
    11. Dim eFi = New FileInfo(excelFile)
    12. Using pck As New ExcelPackage(eFi)
    13. Dim wks = pck.Workbook.Worksheets.Add(wsn)
    14. Dim dtExport As New DataTable
    15. For Each col In selectedCols
    16. Dim dtCol As New DataColumn
    17. With dtCol
    18. .ColumnName = col.name
    19. .Caption = col.headertext
    20. 'If col.valueType IsNot Nothing Then .DataType = col.valueType
    21. End With
    22. dtExport.Columns.Add(dtCol)
    23. Next
    24. SetCellValueForExport(dtExport, dgv, lstrow)
    25. wks.Cells("A1").LoadFromDataTable(dtExport, If(Header, True, False))
    26. With wks.Cells(wks.Dimension.Address).Style.Border
    27. .Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin
    28. .Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin
    29. .Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin
    30. .Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin
    31. End With
    32. wks.Cells(wks.Dimension.Address).AutoFitColumns()
    33. pck.Save()
    34. End Using
    35. If msgQuestionInfo($"Der Export wurde unter {excelFile} gespeichert.{Environment.NewLine}Soll die Datei geöffnet werden?") = DialogResult.Yes Then
    36. Process.Start(excelFile)
    37. End If
    38. End Sub

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Manuell befüllen … weiß nicht, was Du meinst. Den Befüllcode hast Du ja im RowPrepaint-EventHandler. Ich würd den Code in eine neue Methode kopieren und dort so anpassen, dass er für alle existierenden Rows ausgeführt wird. Und diese neue Methode wird eben vor dem Export aufgerufen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed:

    Mit manuell befüllen meinte ich, dass ich keine DataTable bzw. BindingSource als Datenquelle dran hefte sondern die Spalten und Zeilen des DGV manuell
    erzeuge (das mache ich an manchen anderen Stellen im Programm, wo ich mir aus etlichen Tabellen Krempel zusammen suchen muss)...
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: