分离后按行值对数据表条目进行分组

时间:2016-05-26 11:40:35

标签: vb.net list datagridview datatable

发生了什么: 我有一个由姓名,ID,评论组成的表格。除非用户提交多于1个条目,否则每个ID都是唯一的。此时,用户可能有3行,其中ID相同,以显示这些条目全部由1个用户输入,并且它们属于一起。

下面我将发布我最初做的事情,将它们分成单独的datagridview,每个按钮下面的按钮最终将用于处理它上面的datagrid条目。

因此,这导致我试图弄清楚的两件事情,并且通过反复试验和谷歌研究没有太多运气。

1.。)如何将数据表中具有相同ID的任何条目放入相同的数据网格视图中,而不是为每个条目创建单独的数据网格。

2.)假设上面可以做的话,如果可能的话,我怎样才能使每个下面生成的按钮只对应上面的数据网格?虽然以编程方式创建的每个数据网格和按钮都可以分配一个唯一的ID,允许每个ID对应另一个吗?

    Dim dst As New DataSet
    For i As Integer = 0 To DT.Rows.Count - 1
        Dim intLastRow As Integer = i
        If intLastRow > DT.Rows.Count - 1 Then intLastRow = DT.Rows.Count - 1
        Dim dtbNew As DataTable = DT.Clone
        dtbNew.TableName = DT.TableName
        For j As Integer = i To intLastRow
            dtbNew.ImportRow(DT.Rows(j))
        Next j
        dst.Tables.Add(dtbNew)
    Next i

    For Each table As DataTable In dst.Tables
        Dim DGV As New DataGridView
        Dim BTN As New Button
        BTN.Text = "Show Details"
        BTN.Width = 120
        DGV.DataSource = table
        DGV.Width = 800
        DGV.Height = 80
        FlowLayoutPanel1.Controls.Add(DGV)
        FlowLayoutPanel1.Controls.Add(BTN)
    Next
    FlowLayoutPanel1.AutoScrollPosition = New Point(FlowLayoutPanel1.Top)

错误

Dim DT As New DataTable
    DT.Load(SQLMP)

    Dim groups As IEnumerable(Of IGrouping(Of Integer, DataRow)) = DT.Select.GroupBy(Function(row) row.Field(Of Integer)("ORDER_ID"))

System.Data.DataSetExtensions.dll`中出现未处理的“System.InvalidCastException”类型异常

其他信息:指定的演员表无效

1 个答案:

答案 0 :(得分:0)

您可以使用LinQ和lambda函数执行所需操作 让我们假设您有一个DataTable,其中包含所有这些条目。

执行此操作,您将获得按ID分组的行:

Dim groups = DT.Select.GroupBy(Function(row) row("ID"))

从现在开始,您可以从中提取部分数据表

Dim partialTables = groups.Select(
    Function(group)
        Dim partialTable = group.CopyToDataTable
        partialTable.TableName = group.Key
        Return partialTable
    End Function).ToList

然后,您可以查询表格列表中的特定ID,检索它并将其用作数据源:

YourDataGridView.DataSource = partialtables.FirstOrDefault(
    Function(table) table.TableName = "123")

我希望它有所帮助!

修改 您可以在下面看到我的建议的完整实现。我测试了它似乎工作正常

Private DT As DataTable, partialTables As List(Of DataTable)
Private WithEvents CB As ComboBox, DGV As DataGridView
Private Sub q37459856()
    DT = New DataTable
    DT.Columns.Add("Name", GetType(String))
    DT.Columns.Add("ID", GetType(Integer))
    DT.Columns.Add("Commens", GetType(String))
    DT.Rows.Add("aaaaaa", 1, "aaaaaa")
    DT.Rows.Add("bbbbbb", 2, "bbbbbb")
    DT.Rows.Add("cccccc", 1, "cccccc")
    DT.Rows.Add("dddddd", 2, "dddddd")
    DT.Rows.Add("eeeeee", 3, "eeeeee")
    DT.Rows.Add("ffffff", 1, "ffffff")
    DT.Rows.Add("gggggg", 2, "gggggg")
    DT.Rows.Add("hhhhhh", 3, "hhhhhh")
    DT.Rows.Add("iiiiii", 4, "iiiiii")

    Dim groups As IEnumerable(Of IGrouping(Of Integer, DataRow)) = DT.Select.GroupBy(Function(row) row.Field(Of Integer)("ID"))

    partialTables = groups.Select(
        Function(group)
            Dim partialTable = group.CopyToDataTable
            'IGrouping(Of Integer, DataRow) implements IEnumerable(of DataRow)
            'therefore, it implements Function .CopyToDataTable() 
            partialTable.TableName = group.Key.ToString("000")
            Return partialTable
        End Function).ToList

    Dim IDs = New List(Of String)({"all"}.Concat(partialTables.Select(Function(t) t.TableName)))

    Dim F As New Form
    CB = New ComboBox With {.Dock = DockStyle.Top, .DataSource = IDs}
    F.Controls.Add(CB)
    DGV = New DataGridView With {
        .Left = CB.Left,
        .Top = CB.Top + CB.Height + 3,
        .Width = CB.Width,
        .Height = F.ClientSize.Height - CB.Top - CB.Height - 6,
        .Anchor = AnchorStyles.Left + AnchorStyles.Top + AnchorStyles.Right + AnchorStyles.Bottom,
        .AllowUserToAddRows = False}
    F.Controls.Add(DGV)
    F.Show()
End Sub
Sub CB_SelectedValueChanged(sender As Object, e As EventArgs) Handles CB.SelectedValueChanged
    If CB.SelectedValue = "all" Then
        DGV.DataSource = DT
    Else
        DGV.DataSource = partialTables.FirstOrDefault(Function(t) t.TableName = CB.SelectedValue)
    End If
End Sub

编辑#2 为了提供问题的工作解决方案,下面是一个具有类似逻辑的版本,但依赖于 For ... Next 迭代而不是< EM> LINQ的:

Private DT As DataTable, partialTables As List(Of DataTable)
Private WithEvents CB As ComboBox, DGV As DataGridView
Private Sub q37459856_withoutLinq()
    DT = New DataTable
    DT.Columns.Add("Name", GetType(String))
    DT.Columns.Add("ORDER_ID", GetType(Integer))
    DT.Columns.Add("Comments", GetType(String))
    DT.Rows.Add("aaaaaa", 1, "aaaaaa")
    DT.Rows.Add("bbbbbb", 2, "bbbbbb")
    DT.Rows.Add("cccccc", 1, "cccccc")
    DT.Rows.Add("dddddd", 2, "dddddd")
    DT.Rows.Add("eeeeee", 3, "eeeeee")
    DT.Rows.Add("ffffff", 1, "ffffff")
    DT.Rows.Add("gggggg", 2, "gggggg")
    DT.Rows.Add("hhhhhh", 3, "hhhhhh")
    DT.Rows.Add("iiiiii", 4, "iiiiii")

    Dim allORDER_ID As New List(Of Integer)

    For Each dr In DT.Select
        If Not allORDER_ID.Contains(dr("ORDER_ID")) Then
            allORDER_ID.Add(dr("ORDER_ID"))
        End If
    Next

    Dim partialTable As DataTable
    partialTables = New List(Of DataTable)
    For Each ORDER_ID In allORDER_ID
        partialTable = DT.Clone
        partialTable.TableName = ORDER_ID.ToString("000")
        For Each dr In DT.Select("ORDER_ID=" & ORDER_ID)
            partialTable.ImportRow(dr)
        Next
        partialTables.Add(partialTable)
    Next

    Dim IDs = New List(Of String)({"all"})

    For Each partialTable In partialTables
        IDs.Add(partialTable.TableName)
    Next

    Dim F As New Form
    CB = New ComboBox With {.Dock = DockStyle.Top, .DataSource = IDs}
    F.Controls.Add(CB)
    DGV = New DataGridView With {
        .Left = CB.Left,
        .Top = CB.Top + CB.Height + 3,
        .Width = CB.Width,
        .Height = F.ClientSize.Height - CB.Top - CB.Height - 6,
        .Anchor = AnchorStyles.Left + AnchorStyles.Top + AnchorStyles.Right + AnchorStyles.Bottom,
        .AllowUserToAddRows = False}
    F.Controls.Add(DGV)
    F.Show()
End Sub
Sub CB_SelectedValueChanged(sender As Object, e As EventArgs) Handles CB.SelectedValueChanged
    If CB.SelectedValue = "all" Then
        DGV.DataSource = DT
    Else
        DGV.DataSource = partialTables.FirstOrDefault(Function(t) t.TableName = CB.SelectedValue)
    End If
End Sub