需求:數據庫數據都是縱向的,呈現的時候要求是橫向(列轉行)同時看到行頭(行轉列)。
分析:很多報表呈現都要求要這樣顯示,用類是可以實現,但是代碼多,又需要建很多dto。發下Excel有轉置功能,但又不想牽扯Excel這一套組件。就使用DataTable來實現,代碼也不多。
先看看示例數據3列10行:

我們要把它轉成3行10列,列轉行,行轉列同時完成:

百度上有不少轉換方案,都不盡如意。基本都是一個方向的轉換。要么是行轉列,要么是列轉行。干脆就自己寫了一個。
因為行轉列,列轉行要同時進行,我們需要仔細觀察數據,打個下標來觀察。
先把數據歸類為二維數組,從轉換后的表倒推回去,發現:
結果表的是【1,1】是原始表的【1,1】.
結果表的【1,2】是原始表的【2,1】,類推結果表【1,3】是原始表【3,1】
規律:下標對調就可以得到轉換表

代碼實現:
1、把源數據(包含列頭)轉換成二維數組,然后下標對調。這種方法使用最方便。就是要仔細算下標位置,應為列頭加進去了
private DataTable PivotDatatable(DataTable dtSource, string columnFilter)
{
var columns = columnFilter.Split(',');
DataTable dtFilter = dtSource.DefaultView.ToTable(false, columns);
DataTable dtResult = new DataTable();
var rowCount = dtFilter.Rows.Count;
var columnCount = columns.Length;
// 源數組的行數比DataTable的行數+1,, 加一行表頭
object[,] arrSource = new object[rowCount + 1, columnCount];
// 目標數組的行數等於選擇的列數,列數等於 源數據的行數+1, 加一列 屬性名
object[,] arrResult = new object[columnCount, rowCount + 1];
// 原數組第一行寫表頭
for (int i = 0; i < columnCount; i++)
{
arrSource[0, i] = dtFilter.Columns[i].ColumnName;
}
// 源數據 每一行寫 數據
for (int i = 0; i < rowCount; i++)
{
for (int j = 0; j < columnCount; j++)
{
arrSource[i + 1, j] = dtFilter.Rows[i][j];
}
}
// 原數 轉置到 目標數組
for (int i = 0; i < rowCount + 1; i++)
{
for (int j = 0; j < columnCount; j++)
{
arrResult[j, i] = arrSource[i, j];
}
}
// 創建 Datatable 的結構
for (int i = 0; i < rowCount + 1; i++)
{
dtResult.Columns.Add(arrResult[0, i].ToString());
}
List<string> valueList = new List<string>();
for (int i = 1; i < columnCount; i++)
{
for (int j = 0; j < rowCount + 1; j++)
{
valueList.Add(arrResult[i, j].ToString());
}
dtResult.Rows.Add(valueList.ToArray());
valueList.Clear();
}
return dtResult;
}
2、思路是數據轉換成二維碼(不含列頭),轉換完成后,再把列頭加入到新的table里面,不需要過多算下標
private DataTable SwapTable(DataTable tableData)
{
int intRows = tableData.Rows.Count;
int intColumns = tableData.Columns.Count;
//轉二維數組
string[,] arrayData = new string[intRows, intColumns];
for (int i = 0; i < intRows; i++)
{
for (int j = 0; j < intColumns; j++)
{
arrayData[i, j] = tableData.Rows[i][j].ToString();
}
}
//下標對換
string[,] arrSwap = new string[intColumns, intRows];
for (int m = 0; m < intColumns; m++)
{
for (int n = 0; n < intRows; n++)
{
arrSwap[m, n] = arrayData[n, m];
}
}
DataTable dt = new DataTable();
//添加列
for (int k = 0; k < intRows; k++)
{
dt.Columns.Add(
new DataColumn(arrSwap[0, k])
);
}
//添加行
for (int r = 1; r < intColumns; r++)
{
DataRow dr = dt.NewRow();
for (int c = 0; c < intRows; c++)
{
dr[c] = arrSwap[r, c].ToString();
}
dt.Rows.Add(dr);
}
//添加行頭
DataColumn ColRowHead = new DataColumn(tableData.Columns[0].ColumnName);
dt.Columns.Add(ColRowHead);
dt.Columns[ColRowHead.ColumnName].SetOrdinal(0);
for (int i = 0; i < intColumns - 1; i++)
{
dt.Rows[i][ColRowHead.ColumnName] = tableData.Columns[i + 1].ColumnName;
}
return dt;
}
