如何根据数据库列值填充DataGridView并转置展示设备使用数据
实现DataGridView的交叉表(行转列)展示
要实现你需要的这种机器-周的交叉表展示,核心是将源数据的行(按周的记录)转置为列(周作为表头),然后绑定到DataGridView。下面以C# WinForms为例,一步步实现:
核心思路
- 从数据库获取原始数据
- 提取所有唯一的机器和需要展示的周(包括无数据的周,比如2018-14)
- 构建转置后的DataTable,把机器作为行,周作为列,单元格填充对应的
HOURSHPIECESP格式 - 将转置后的表绑定到DataGridView
代码实现
步骤1:获取原始数据
首先用ADO.NET从数据库读取USAGE表的数据(这里以SQL Server为例,其他数据库只需替换对应的连接和适配类):
DataTable sourceData = new DataTable(); // 替换成你的数据库连接字符串 string connString = "Server=你的服务器;Database=你的库名;Integrated Security=True;"; using (SqlConnection conn = new SqlConnection(connString)) { string query = "SELECT MACHINE, WEEK, HOURS, PIECES FROM USAGE"; SqlDataAdapter adapter = new SqlDataAdapter(query, conn); adapter.Fill(sourceData); }
步骤2:整理元数据(机器和周列表)
我们需要先拿到所有唯一的机器,以及从最小到最大周的连续周列表(确保2018-14这种无数据的周也显示为列):
// 获取排序后的唯一机器列表 List<string> machines = sourceData.AsEnumerable() .Select(r => r.Field<string>("MACHINE")) .Distinct() .OrderBy(m => m) .ToList(); // 处理周:将"yyyy-ww"转为可排序的数值(如2018-12→201812),生成连续周范围 var weekNums = sourceData.AsEnumerable() .Select(r => r.Field<string>("WEEK")) .Distinct() .Select(w => int.Parse(w.Replace("-", ""))) .ToList(); int minWeek = weekNums.Min(); int maxWeek = weekNums.Max(); // 生成所有连续周的字符串格式 List<string> allWeeks = new List<string>(); for (int w = minWeek; w <= maxWeek; w++) { string year = w.ToString().Substring(0, 4); string week = w.ToString().Substring(4).PadLeft(2, '0'); // 确保周数是两位 allWeeks.Add($"{year}-{week}"); }
步骤3:构建转置后的DataTable
创建交叉表结构,填充每个机器的周数据:
DataTable pivotTable = new DataTable(); // 添加第一列:机器名 pivotTable.Columns.Add("MACHINE", typeof(string)); // 添加所有周作为列 foreach (string week in allWeeks) { pivotTable.Columns.Add(week, typeof(string)); } // 预构建数据字典提升查找效率(大数据量时更明显) var dataLookup = sourceData.AsEnumerable() .ToDictionary( r => Tuple.Create(r.Field<string>("MACHINE"), r.Field<string>("WEEK")), r => Tuple.Create(r.Field<int>("HOURS"), r.Field<int>("PIECES")) ); // 填充每一行机器的数据 foreach (string machine in machines) { DataRow row = pivotTable.NewRow(); row["MACHINE"] = machine; foreach (string week in allWeeks) { var key = Tuple.Create(machine, week); if (dataLookup.ContainsKey(key)) { var hp = dataLookup[key]; row[week] = $"{hp.Item1}H {hp.Item2}P"; } else { row[week] = string.Empty; // 无数据则留空 } } pivotTable.Rows.Add(row); }
步骤4:绑定到DataGridView
最后把转置好的表绑定到控件,调整显示样式:
dataGridView1.DataSource = pivotTable; // 自动调整列宽,优化显示 dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; dataGridView1.RowHeadersVisible = false; // 隐藏行头,更简洁
注意事项
- 如果不需要显示无数据的周(比如2018-14),可以跳过生成连续周的步骤,直接使用
weekNums转成字符串的列表即可 - 如果使用其他数据库(如MySQL、Oracle),只需替换
SqlConnection、SqlDataAdapter为对应数据库的类(如MySqlConnection) - 若数据量极大,建议在数据库层面先做分组聚合,减少内存处理的压力(比如用SQL的PIVOT函数提前转置,但不同数据库的PIVOT语法有差异)
内容的提问来源于stack exchange,提问作者Miguel Terlaak
相关产品推荐
相关产品推荐

