构建以逗号分隔的相关值字符串以在 ListView 控件中显示

Posted

技术标签:

【中文标题】构建以逗号分隔的相关值字符串以在 ListView 控件中显示【英文标题】:Building a comma-separated string of related values to display in a ListView control 【发布时间】:2014-01-24 16:45:30 【问题描述】:

我是 vb 的新手,目前我手头有这个项目,需要我显示一些员工信息。我已经将我所有的数据存储在 ms 访问中,在一个名为“ScheduleInfo”的表中。共有三行:“WorkerID”、“TaskNo”和“TimeTaken”。每个工人都需要一定的时间来完成每项任务。

问题是我必须在 vb.net 中显示任务(组合在一起),能够完成任务的工人数量(根据任务计算工人),以及哪些是工人(工人 ID)。

我只设法在ListView 上显示前两列,它们将我的任务组合在一起并计算有多少工作人员可用于该任务。

工人ID |任务编号 |耗时

1 | 1 | 7.5 4 | 1 | 2.5 1 | 2 | 3.5 2 | 2 | 1.5 1 | 3 | 2.5 2 | 3 | 4.5 3 | 3 | 3.5 2 | 4 | 3.5-名单还在继续-

我无法附上我的数据库外观的图像,这里大概是一个想法。

我正在尝试在 vb 上显示它,例如:

任务编号 |工人人数 |可用工人

1 | 2 | 1、4 2 | 2 | 1 , 2 3 | 3 | 1、2、3

-根据我有多少任务,列表继续-

我的代码

 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        conn.ConnectionString = myConString
        conn.Open()

        Dim SQLString As String = ("SELECT [TaskNo], COUNT(*) FROM ScheduleInfo GROUP BY TaskNo")
        cmd = New OleDbCommand(SQLString, conn)


        da = New OleDbDataAdapter(cmd)
        ds = New DataSet
        da.FillSchema(ds, SchemaType.Source, "ScheduleInfo")
        da.Fill(ds, "ScheduleInfo")
        dt = ds.Tables("ScheduleInfo")


        LstViewScheduleInfo.Columns.Add("TaskNo", 150, HorizontalAlignment.Center)
        LstViewScheduleInfo.Columns.Add("No of Workers", 150, HorizontalAlignment.Center)
        LstViewScheduleInfo.Columns.Add("List Of Workers", 150, HorizontalAlignment.Center)

        For Each row As DataRow In dt.Rows()
            Dim lst As ListViewItem
            lst = LstViewScheduleInfo.Items.Add(row(0))

            For i As Integer = 1 To dt.Columns.Count - 1
                lst.SubItems.Add(row(i))
            Next

        Next

        conn.Close()

    End Sub

我不确定这是否是正确的做法,这就是我所拥有的。 现在我不知道如何循环访问数据库并拉出可以从事这项工作的工人。我是否使用另一个 sql 查询?任何帮助将不胜感激。

【问题讨论】:

显示的 LV 似乎只是显示摘要类型信息。您将需要一个不同的数据集来获取详细信息。 “工人名单”列似乎很奇怪。 您如何知道您的数据库中有哪些工作人员可以执行此任务?如果你能从你的数据库中展示一些有助于理解的数据。 您展示的所有内容都与 HOW MANY 类型的事物有关 - 有多少任务,有多少工人忙,有多少工人空闲。对于哪些工人是免费的,您需要一个不同的查询。根据@Ikiet 的评论,如果没有有关数据的更多信息,我们将无法提供帮助 那是表,不是数据库。大概有一个 Worker 表,大概ScheduleInfo 只有一个工人在忙时的条目;并在完成后被删除/清除或状态更改。因此,在Worker 上创建一个查询以选择所有在ScheduleInfo 中没有“打开”条目的人。 Access 有查询构建工具来帮助解决这个问题,然后您可以调用该查询或将 SQL 粘贴到您的应用中。 @Plutonix 可以说只有一名工人可以完成一项任务,所以我在任务的后期随机分配了一名工人。但现在我必须让我的“工人名单”显示出来。例如我的列表视图中的第 1 行,它将是 TaskNo 1,第二列将是 2,因为只有 2 个任务,第三列将像“1,4”,这意味着只有工人 1 和工人 4 可用。我知道我必须循环它,但我应该把循环放在哪里?我要像你说的那样再使用一个数据集吗? 【参考方案1】:

您问题的本质是“如何在我的 DataTable 的每一行中为 [TaskNo] 构建一串 [WorkerID] 值?

这是一个很常见的问题,方法取决于我们使用的数据库。例如,mysql 提供了一个GROUP_CONCAT() 函数,使我们能够将其作为主查询的一部分。对于 Access 数据库应用程序,常见的解决方案是使用自定义 VBA 函数(如 this one)将相关值串在一起。

不幸的是,用户定义的 VBA 函数只能用于从 Microsoft Access 应用程序本身运行的查询中,因此我们不能在 .NET 应用程序中使用这种方法。因此,.NET 应用程序必须构建自己的值列表。

以下代码说明了执行此操作的一种方法。 (它是 C# 代码,但 VB.NET 代码会非常相似。)

using (var con = new OleDbConnection())

    con.ConnectionString = myConnectionString;
    con.Open();

    var dt = new System.Data.DataTable("ListInfo");
    using (var da = new OleDbDataAdapter())
    
        // fill the DataTable with three columns, the third column being
        //     a placeholder that we will fill in below
        string sql =
                "SELECT [TaskNo], COUNT(*) AS NumWorkers, '' AS WorkersAvailable " +
                "FROM ScheduleInfo GROUP BY [TaskNo]";
        da.SelectCommand = new OleDbCommand(sql, con);
        da.Fill(dt);

        using (var cmd2 = new OleDbCommand())
        
            // create a Prepared Statement that we will use for each iteration
            cmd2.Connection = con;
            cmd2.CommandText =
                    "SELECT [WorkerID] FROM ScheduleInfo " +
                    "WHERE [TaskNo] = ? " +
                    "ORDER BY [WorkerID]";
            cmd2.Parameters.Add("?", OleDbType.Integer);
            cmd2.Prepare();

            // foreach row of the DataTable, build the string of WorkerID values
            foreach (System.Data.DataRow dr in dt.Rows)
            
                cmd2.Parameters[0].Value = dr["TaskNo"];
                string workerList = "";
                using (OleDbDataReader rdr = cmd2.ExecuteReader())
                
                    while (rdr.Read())
                    
                        workerList += ", " + rdr["WorkerID"].ToString();
                    
                
                dr["WorkersAvailable"] = workerList.Substring(2);  // remove leading ", "
            
        

        // for demo purposes, just dump the DataTable to the console
        Console.WriteLine(string.Format("0,6  1,10  2,16", "TaskNo", "NumWorkers", "WorkersAvailable"));
        Console.WriteLine(string.Format("0,6  1,10  2,16", "------", "----------", "----------------"));
        foreach (System.Data.DataRow dr in dt.Rows)
        
            Console.WriteLine(string.Format("0,6  1,10  2,-16", dr["TaskNo"], dr["NumWorkers"], dr["WorkersAvailable"]));
        
    
    con.Close();

[ScheduleInfo]中的示例数据

WorkerID  TaskNo  TimeTaken
--------  ------  ---------
       1       1        7.5
       4       1        2.5
       1       2        3.5
       2       2        1.5
       1       3        2.5
       2       3        4.5
       3       3        3.5
       2       4        3.5

控制台输出是

TaskNo  NumWorkers  WorkersAvailable
------  ----------  ----------------
     1           2  1, 4
     2           2  1, 2
     3           3  1, 2, 3
     4           1  2

【讨论】:

非常感谢您的回复。我会尽力理解它。至少现在我知道我的代码会是什么样子。顺便说一句,我忘了补充一件事。在我显示记录之后。我必须从每个任务中随机分配一个工人并将时间加在一起。我是否需要另一个查询来提取我的时间并以数组形式存储? @Crayon 这听起来像new question。 整件事就是生成一个员工序列。如果我的两个命令文本都没有抽出时间,我不知道如何抽出时间 @Crayon 在循环遍历 DataTable 中的行时,您始终可以同时提取 [WorkerID] [TimeTaken],并为每个 [TaskNo] 添加一个值] 到您的总时间。 非常感谢你,我设法让它工作了。谢谢!

以上是关于构建以逗号分隔的相关值字符串以在 ListView 控件中显示的主要内容,如果未能解决你的问题,请参考以下文章

使用 oracle sql 以逗号分隔的字符串

使用 LINQ/lambdas 构建以逗号分隔的内部异常消息字符串 [重复]

如何对查询中的字段进行编程,以在该记录的子数据表中显示逗号分隔的唯一值列表?

MS-Access查询以在另一列中收集逗号分隔的结果

PHP implode 爆炸逗号分隔值用于 if else 语句

如何构建包含 ListView.Builder 的自定义行,以在颤动中构建 ElevatedButton?