2012-05-23 104 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; 
     } 

以防万一,这将是有帮助的人:)