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;
}
}