Datengebundenes DGV nach Integer sortieren

  • VB.NET

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

    Datengebundenes DGV nach Integer sortieren

    Hallo liebes Forum :D

    Leider bin ich auf ein Problem gestossen, an dem ich mir langsam aber sicher die Zähne ausbeisse.
    Ich habe ein Programm geschrieben, das den Verlauf von Google Chrome, Mozilla Firefox und Opera mittels SQLite ausliest und in jeweils einem DataGridView anzeigt.

    Nun möchte ich alle drei DGV bzw. dessen Daten in das erste dieser drei DGV kombinieren. Dazu habe ich folgenden Ansatz, der auch soweit super funktioniert:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Function CombineDataGridViews() As Boolean
    2. Dim dataset1 As DataSet = gridViewToData(DataGridView1)'Chrome
    3. Dim dataset2 As DataSet = gridViewToData(DataGridView2)'Firefox
    4. Dim dataset3 As DataSet = gridViewToData(DataGridView3)'Opera
    5. Dim finaldata As New DataSet
    6. Try
    7. dataset1.Merge(dataset2, True, MissingSchemaAction.Add) '2 in 1
    8. dataset1.AcceptChanges()
    9. dataset3.Merge(dataset1, True, MissingSchemaAction.Add) '1 in 3
    10. dataset3.AcceptChanges()
    11. DataGridView4.DataSource = dataset3.Tables(0) 'für Bearbeitung in 4tem DGV anzeigen
    12. Dim mtCell As Integer = 0
    13. Dim row As DataGridViewRow = New DataGridViewRow()
    14. For rowNo As Integer = DataGridView4.Rows.Count - 2 To 0 Step -1 'Leere Zeilen entfernen
    15. row = DataGridView4.Rows(rowNo)
    16. Try
    17. For j = 0 To row.Cells.Count - 2
    18. If row.Cells(j).Value Is Nothing OrElse row.Cells(j).Value Is DBNull.Value Then
    19. mtCell += 1
    20. End If
    21. Next
    22. If mtCell = row.Cells.Count - 1 Then
    23. DataGridView4.Rows.RemoveAt(rowNo)
    24. End If
    25. mtCell = 0
    26. Catch ex As Exception
    27. Exit For
    28. End Try
    29. Next rowNo
    30. finaldata = gridViewToData(DataGridView4)
    31. DataGridView1.DataSource = finaldata.Tables(0) 'Bearbeitete Daten wieder in DGV1 übertragen
    32. Return True
    33. Catch ex As Exception
    34. MsgBox("Fehler")
    35. Return False
    36. End Try
    37. Return True
    38. End Function
    39. Private Function gridViewToData(ByVal dgv As DataGridView) As DataSet
    40. Dim ds As New DataSet
    41. Try
    42. ' Add Table
    43. ds.Tables.Add("Invoices")
    44. ' Add Columns
    45. Dim col As DataColumn
    46. For Each dgvCol As DataGridViewColumn In dgv.Columns
    47. col = New DataColumn(dgvCol.Name)
    48. ds.Tables("Invoices").Columns.Add(col)
    49. Next
    50. 'Add Rows from the datagridview
    51. Dim row As DataRow
    52. Dim colcount As Integer = dgv.Columns.Count - 1
    53. For i As Integer = 0 To dgv.Rows.Count - 1
    54. row = ds.Tables("Invoices").Rows.Add
    55. For Each column As DataGridViewColumn In dgv.Columns
    56. row.Item(column.Index) = dgv.Rows.Item(i).Cells(column.Index).Value
    57. Next
    58. Next
    59. Return ds
    60. Catch ex As Exception
    61. MsgBox("Error")
    62. Return Nothing
    63. End Try
    64. End Function


    Das eigentliche Problem liegt aber beim Sortieren des DGV im Code nach einem Integer, in meinem Fall nach der Anzahl Aufrufe einer Webseite.
    Diese werden z.B. anstatt 1,4,11,23,115 folgendermaßen sortiert: 1,11,115,23,4

    Hierzu wollte ich eine neue Spalte vom Typ Integer hinzufügen und die Werte übernehmen um anschließend nach dieser Spalte zu sortieren.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. ' Neue Spalte an letzter Position
    2. Me.DataGridView1.Columns.Add("sort_col", "sort_col")
    3. Me.DataGridView1.Columns("sort_col").ValueType = GetType(Integer)
    4. Me.DataGridView1.Columns("sort_col").DisplayIndex = Me.DataGridView1.ColumnCount - 1
    5. Me.DataGridView1.Columns("sort_col").Visible = True
    6. ' Werte übernehmen
    7. For Each line As DataGridViewRow In DataGridView1.Rows
    8. line.Cells(Me.DataGridView1.ColumnCount - 1).Value = line.Cells(3).Value
    9. Next
    10. 'sortieren
    11. DataGridView1.Sort(DataGridView1.Columns("sort_col"), ComponentModel.ListSortDirection.Descending)


    Dabei tritt aber folgende Fehlermeldung auf: Das datengebundene DataGridView-Steuerelement kann nur nach datengebundenen Spalten sortiert werden.

    Das Thema wurde schon in diesem Thread behandelt, jedoch führte bei mir weder die darin beschriebene Lösung noch mehrfaches googeln zum Erfolg.
    Ich bin noch ziemlich neu in VB also bitte entschuldigt wenn mein Code weder elegant noch performant ist :whistling:

    Für jede Hilfe wäre ich sehr dankbar

    LG Patrick
    Umfangreicher Converter im Browser: CloudConvert
    Temporäre e-Mail: temp-mail
    Text-Übersetzter: DeepL
    Kostenloser Webspace: bplaced
    Hallihallo @Manü,

    Danke für die schnelle Antwort. :D
    Ich bin nicht ganz sicher ob ich dich richtig verstehe. Das Sortieren sollte erst nach dem Kombinieren der Daten erfolgen damit die Daten aller Browser berücksichtigt werden.
    Bitte sag bescheid wenn ich da was missverstehe.

    LG Patrick
    Umfangreicher Converter im Browser: CloudConvert
    Temporäre e-Mail: temp-mail
    Text-Übersetzter: DeepL
    Kostenloser Webspace: bplaced

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

    Versuche einmal folgendes:
    Setze dazu einfach die Sort-Eigenschaft der BindingSource auf den Namen der Spalte,
    die Du sortieren willst. Sind es mehrere Spalten, so schaue unten...
    Mit ASC (default) und DESC gibt man eine aufsteigende bzw absteigende Sortierung an.

    VB.NET-Quellcode

    1. myBindingSource.Sort = "Spalte1" '1 Spalte
    2. myBindingSource.Sort = "Spalte1, Spalte2" '2 Spalten
    3. myBindingSource.Sort = "Spalte1, Spalte2 DESC" ' 2 Spalten, letzte absteigend
    Zahlen (wie Integer usw.) werden dann entsprechend ihrer Werte sortiert...
    Danke @VB1963 für den Tipp. Leider habe ich keine Ahnung von Datenbank-Programmierung.
    Habe das mal so probiert aber ich denke dass das anders gemeint war: :rolleyes:

    VB.NET-Quellcode

    1. Private Sub sortDGV()
    2. Dim bs As BindingSource = DataGridView1.DataSource
    3. bs.Sort = "visit_count"
    4. End Sub


    Die Verlaufs-Daten selbst lese ich so aus:

    VB.NET-Quellcode

    1. Public Function GetFirefoxData()
    2. Dim Success As Boolean = False
    3. Dim Attempts As Integer = 0
    4. Dim filename As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Mozilla\Firefox\Profiles\" & GetFirefoxUserDir() & "\places.sqlite"
    5. Dim sql As String = "select * from moz_places;"
    6. Dim conn = New SQLiteConnection((Convert.ToString("Data Source=") & filename) + ";Version=3;")
    7. Try
    8. conn.Open()
    9. Dim ds As New DataSet()
    10. Dim da = New SQLiteDataAdapter(sql, conn)
    11. da.Fill(ds)
    12. DataGridView2.DataSource = ds.Tables(0).DefaultView
    13. Catch generatedExceptionName As Exception
    14. Throw
    15. End Try
    16. Return Success
    17. End Function



    LG Patrick
    Umfangreicher Converter im Browser: CloudConvert
    Temporäre e-Mail: temp-mail
    Text-Übersetzter: DeepL
    Kostenloser Webspace: bplaced
    @VB1963 Nochmals Danke für die Starthilfe :thumbsup:
    Ich habe meinen Code (vgl. Original-Post) nun wie folgt angepasst (Zeile 8, 42, 43):

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Function CombineDataGridViews() As Boolean
    2. Dim dataset1 As DataSet = gridViewToData(DataGridView1)
    3. Dim dataset2 As DataSet = gridViewToData(DataGridView2)
    4. Dim dataset3 As DataSet = gridViewToData(DataGridView3)
    5. Dim finaldata As New DataSet
    6. Dim bs As New BindingSource
    7. Try
    8. dataset1.Merge(dataset2, True, MissingSchemaAction.Add) '2 in 1
    9. dataset1.AcceptChanges()
    10. dataset3.Merge(dataset1, True, MissingSchemaAction.Add) '1 in 3
    11. dataset3.AcceptChanges()
    12. DataGridView4.DataSource = dataset3.Tables(0) 'für Bearbeitung in 4tem DGV anzeigen
    13. Dim mtCell As Integer = 0
    14. Dim row As DataGridViewRow = New DataGridViewRow()
    15. For rowNo As Integer = DataGridView4.Rows.Count - 2 To 0 Step -1 'Leere Zeilen entfernen
    16. row = DataGridView4.Rows(rowNo)
    17. Try
    18. For j = 0 To row.Cells.Count - 2
    19. If row.Cells(j).Value Is Nothing OrElse row.Cells(j).Value Is DBNull.Value Then
    20. mtCell += 1
    21. End If
    22. Next
    23. If mtCell = row.Cells.Count - 1 Then
    24. DataGridView4.Rows.RemoveAt(rowNo)
    25. End If
    26. mtCell = 0
    27. Catch ex As Exception
    28. Exit For
    29. End Try
    30. Next rowNo
    31. finaldata = gridViewToData(DataGridView4)
    32. bs.DataSource = finaldata.Tables(0)
    33. bs.Sort = "visit_count"
    34. DataGridView1.DataSource = bs 'Bearbeitete Daten wieder in DGV1 übertragen
    35. Return True
    36. Catch ex As Exception
    37. MsgBox("Error")
    38. Return False
    39. End Try
    40. Return True


    Es gibt keine Fehlermeldung jedoch sieht alles noch genau so aus wie zum Beginn. Mache ich da was falsch?
    //EDIT: Es wird zwar sortiert, jedoch nach wie vor textbasiert

    LG Patrick
    Umfangreicher Converter im Browser: CloudConvert
    Temporäre e-Mail: temp-mail
    Text-Übersetzter: DeepL
    Kostenloser Webspace: bplaced

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

    Du verwendest das DGV untypisch als Datenhalter und manipulierst dort die Daten per Code? Mache so etwas gleich in einer Tabelle...
    Was die Methode gridViewToData genau macht, kann man nicht ausmachen...
    Wie sieht finalData im Detail aus?
    Die sortierte Spalte wird vom Typ String sein?
    Was du auch probieren kannst, ist die Datenbank (deine SQLite File) per typisierten DataSet einzulesen.
    Dann kannst du das ganze "in-RAM" verarbeiten und mergen. Spart m.M. nach viel Arbeitsspeicher, da nicht für jede Zeile in deinem Fall ein neues DataRow-Objekt mit allem Drum und Dran erzeugt werden muss, sondern du nur 3 Listen hast, die kannst du dann "joinen".
    Diese gejointe Liste, bzw ge-merge-te liste kannst du dann über DataBinding an deine Controls binden (in deinem Fall dein Gesamt-DGV)

    Edit:
    Hierzu unter system.data.sqlite.org/downloa…le-x86-2015-1.0.102.0.exe den Installer herunterladen und installieren. Anschließend rebooten. Nach dem Reboot dein VS öffnen (ich verwende VS2015 CE). Hier unter Projekt -> Klasse hinzufügen -> DataSet -> Rechtsklick -> hinzufügen -> TableAdapter -> Neue Verbindung -> Ändern -> System.Data.SQLite Database File -> Ok -> URI zu Database einfügen -> OK. Danach kannst du mit

    VB.NET-Quellcode

    1. Dim ta = new DeinTableAdapter()
    2. Dim ds1 = new DeinDataSet()
    3. ta.Fill(ds1.deine_tabelle)
    arbeiten.


    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell

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