DataTable某列的值转换成行,返回交叉二维表

本文介绍了一个使用 C# 实现的将 DataTable 中指定列的值转换为行的方法,该方法适用于需要生成交叉表的数据展示场景。通过具体代码示例展示了如何创建初始 DataTable 并实现行到列的转换,最后将转换后的表格展示在 DataGridView 控件中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


private void BtnGetReport_Click(System.Object sender, System.EventArgs e)
{
	DataTable Dt = GetCrossTable(CreateDT(), "ID", "Type", "Score");
	Dgv.DataSource = Dt;
}


/// <summary>
/// 创建DataTable
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
protected DataTable CreateDT()
{
	DataTable tblDatas = new DataTable("Datas");
	//数据列
	tblDatas.Columns.Add("ID", Type.GetType("System.String"));
	tblDatas.Columns.Add("Name", Type.GetType("System.String"));
	tblDatas.Columns.Add("Type", Type.GetType("System.String"));
	tblDatas.Columns.Add("Score", Type.GetType("System.Int32"));

	//数据行
	tblDatas.Rows.Add(new object[] {"00001","张三","语文",89});
	tblDatas.Rows.Add(new object[] {"00001","张三","数学",90});
	tblDatas.Rows.Add(new object[] {"00001","张三","英语",79});
	tblDatas.Rows.Add(new object[] {"00001","张三","地理",70});
	tblDatas.Rows.Add(new object[] {"00001","张三","生物",95});

	tblDatas.Rows.Add(new object[] {"00002","李四","语文",87});
	tblDatas.Rows.Add(new object[] {"00002","李四","英语",86});
	tblDatas.Rows.Add(new object[] {"00002","李四","地理",82});

	tblDatas.Rows.Add(new object[] {"00003","王五","语文",81});
	tblDatas.Rows.Add(new object[] {"00003","王五","数学",70});
	tblDatas.Rows.Add(new object[] {"00003","王五","英语",88});
	tblDatas.Rows.Add(new object[] {"00003","王五","生物",96});
	return tblDatas;
}

/// <summary>
/// 将DataTable某列的值转换成行,返回交叉二维表
/// 注意:源表数据必须已按唯一值的列排序
/// </summary>
/// <param name="Dt">源表</param>
/// <param name="OnlyColumn">源表多行判断唯一值的列名</param>
/// <param name="CvrtColumn">源表需行转列的列名</param>
/// <param name="ValueColumn">源表的数据值列名,此列必须为数值</param>
/// <returns></returns>
/// <remarks></remarks>
public static DataTable GetCrossTable(DataTable Dt, string OnlyColumn, string CvrtColumn, string ValueColumn)
{
	if (Dt == null || Dt.Columns.Count < 3 || Dt.Rows.Count == 0) {
		return Dt;

	} else {
		//1.定义List,并赋值非转换列和值列的名称
		ArrayList ColumnList = new ArrayList();
		for (int i = 0; i <= Dt.Columns.Count - 1; i++) {
			if (Dt.Columns[i].ColumnName.ToString() != CvrtColumn & Dt.Columns[i].ColumnName.ToString() != ValueColumn) {
				ColumnList.Add(Dt.Columns[i].ColumnName.ToString());
			}
		}

		//2.定义返回表,将非转换的列和具体值列,添加至表
		DataTable ReDt = new DataTable();
		for (int i = 0; i <= ColumnList.Count - 1; i++) {
			ReDt.Columns.Add(ColumnList[i].ToString());
		}

		//2.将转换列的行不重复记录生成新表
		DataTable dtColumns = Dt.DefaultView.ToTable("dtColumns", true, CvrtColumn);

		//3.将转换列的行的值,生成返回表的列
		for (int i = 0; i <= dtColumns.Rows.Count - 1; i++) {
			string colName = null;
			if (dtColumns.Rows[i][0] is DateTime) {
				colName = Convert.ToDateTime(dtColumns.Rows[i][0]).ToString().Trim();
			} else {
				colName = dtColumns.Rows[i][0].ToString().Trim();
			}
			ReDt.Columns.Add(colName);
			ReDt.Columns[ReDt.Columns.Count - 1].DefaultValue = "0";
		}


		//4.定义DataRow为返回表的NewRow
		DataRow drNew = ReDt.NewRow();
		//5.将除转换行的列和值列之外的列,赋值上源表第一行的值
		for (int i = 0; i <= ColumnList.Count - 1; i++) {
			drNew[ColumnList[i].ToString()] = Dt.Rows[0][ColumnList[i].ToString()];
		}

		//数据唯一值,赋值为源表第一行唯一值
		string OnlyRow = drNew[OnlyColumn].ToString();
		//循环源表,判断赋值
		foreach (DataRow dr in Dt.Rows) {
			//转换的行的值(新表列名)
			string colName = dr[CvrtColumn].ToString().Trim();
			//数值行的值
			double dValue = Convert.ToDouble(dr[ValueColumn]);
			//新表新行的唯一值和源表对比
			if (dr[OnlyColumn].ToString().Equals(OnlyRow, StringComparison.CurrentCultureIgnoreCase)) {
				//相同,则新表新行的列(转换行)赋值
				drNew[colName] = dValue.ToString();
			} else {
				//不相同,则新表新增一行
				ReDt.Rows.Add(drNew);
				drNew = ReDt.NewRow();
				//并赋值源表当前行的非转行行和值行的数据
				for (int i = 0; i <= ColumnList.Count - 1; i++) {
					drNew[ColumnList[i].ToString()] = dr[ColumnList[i].ToString()];
				}
				//数据唯一值, 赋值为源表当前行的唯一值
				OnlyRow = drNew[OnlyColumn].ToString();
				drNew[colName] = dValue.ToString();
			}
		}
		ReDt.Rows.Add(drNew);
		return ReDt;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值