2012-05-23 103 views
1

所有的,我有一個實用工具將DataTables導出到Excel(到均爲 .xls和.xlsx文件類型)。當我達到DataTable(從SQL Server中提取)的列或行限制時,我想將DataTable劃分爲子對象,每個對象都受限制(對於.xls 256列和65,536行以及.xlsx 16,384列和1,048,576行) 。將數據表分成多個數據表

到目前爲止,我已經寫了下面的方法做我想做的

public static List<DataTable> SplitDataTable(DataTable mother, int nColLimit) 
{ 
    List<int[]> rangeList = new List<int[]>(); 
    int primaryCols = mother.Columns.Count; 
    int nSplitCount = Convert.ToInt32(primaryCols/nColLimit); 
    int max = -1; 

    // Get the child ranges. 
    int tmpSup = 0; 
    for (int splits = 0; splits < nSplitCount; splits++) 
    { 
     if (rangeList.Count == 0) 
      tmpSup = (splits + 1) * (nColLimit - 1); 
     else 
      tmpSup = rangeList[splits - 1][1] + nColLimit; 
     rangeList.Add(new int[2] { splits * nColLimit, tmpSup }); 
     if (max < tmpSup) 
      max = tmpSup; 
    } 
    rangeList.Add(new int[2] { ++max, primaryCols }); 

    // Build child DataTables. 
    List<DataTable> childList = new List<DataTable>(); 
    int childIndex = 0; 
    foreach (int[] range in rangeList) 
    { 
     childList.Add(new DataTable()); 
     for (int i = range[0]; i < range[1]; i++) 
      for (int j = 0; j < mother.Rows.Count; j++) 
       childList[childIndex].Rows[j][i] = mother.Rows[j][i]; 
     childIndex++; 
    } 
    return childList; 
} 

然而,這將引發與消息的indexOutOfRangeException「有位置0無行」。我很欣賞錯誤來自哪裏,但將mother的完整列複製到孩子的最佳方法是什麼?

我也曾嘗試

List<DataTable> childList = new List<DataTable>(); 
int childIndex = 0; 
foreach (int[] range in rangeList) 
{ 
    childList.Add(new DataTable()); 
    foreach(DataRow row in mother.Rows) 
    { 
     DataRow tmpRow = childList[childIndex].NewRow(); 
     for (int i = range[0]; i < range[1]; i++) 
      tmpRow[i + 1] = row[i + 1]; 
    } 
    childIndex++; 
} 

給出同樣範圍的異常。

謝謝你的時間。

編輯:我是如何做到這短期

foreach (int[] range in rangeList) 
{ 
    childList.Add(new DataTable()); 
    string strSqlTmp = 
    String.Format("declare @columns varchar(max) " + 
     "select @columns = case when @columns is null " + 
     "then '' " + 
     "else @columns + ', ' " + 
     "end + name " + 
      "from sys.columns " + 
      "where object_id = object_id('{0}') and name in " + 
       "(SELECT COLUMN_NAME " + 
        "FROM [{1}].INFORMATION_SCHEMA.COLUMNS " + 
        "WHERE TABLE_NAME = N'{0}' " + 
        "AND ORDINAL_POSITION > {2} AND ORDINAL_POSITION < {3}) " + 
     "declare @query varchar(max) " + 
     "set @query = 'select ' + @columns + ' from {0}' " + 
     "exec (@query); 
    // Then get each DataTable from SQL Server and fill the child list... 

回答

1

你得到IndexOutOfRange例外是因爲你試圖在新DataTable不存在引用Column真正的原因。這條線:

childList.Add(new DataTable()); 

確實添加新DataTablechildList,但DataTable沒有列和行。

通常情況下,我可能會使用DataTable.Clone()方法創建一個新的DataTable,其結構與DataTable的結構相同,但顯然這不適用於您。在你的情況下,你必須使用DataTable.Columns.Add方法明確添加DataColumn

喜歡的東西:

for (int i = 0; i < numberOfColumns; i++) { 
    dataTable.Columns.Add(string.Format("Column {0}", i)); 
} 

以上片段是非常簡單的。由於您將自己創建DataColumn,因此您需要自行命名並輸入每個DataColumn

+0

非常感謝您的時間。與此同時,我撇清了並要求SQL Server去做。我編輯了我的問題,以顯示如果您感興趣的話,這是如何完成的... – MoonKnight

+0

很高興您能夠正常工作,並感謝您發佈您的解決方案。 –

1

我剛剛創建了一個拆分數據表的方法。 「.Batch」方法是從MoreLinq引用的。

private static List<DataTable> SplitTable(DataTable originalTable, int batchSize) 
     { 
      List<DataTable> tables = new List<DataTable>(); 

      foreach (var rowBatch in originalTable.Rows.Cast<DataRow>().Batch(batchSize)) 
      { 
       var batchTable = new DataTable(originalTable.TableName); 

       foreach (DataColumn column in originalTable.Columns) 
        batchTable.Columns.Add(column.ColumnName, column.DataType); 

       foreach (DataRow row in rowBatch) 
        batchTable.Rows.Add(row.ItemArray); 

       tables.Add(batchTable); 
      } 
      return tables; 
     } 

以防萬一,這將是有幫助的人:)