构建以逗号分隔的相关值字符串以在 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 控件中显示的主要内容,如果未能解决你的问题,请参考以下文章
使用 LINQ/lambdas 构建以逗号分隔的内部异常消息字符串 [重复]
如何对查询中的字段进行编程,以在该记录的子数据表中显示逗号分隔的唯一值列表?