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