【问题标题】:Splitting a DataTable into Multiple DataTables将一个 DataTable 拆分为多个 DataTable
【发布时间】:2012-05-23 18:37:40
【问题描述】:

所有,我有一个实用程序可以将 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...

【问题讨论】:

    标签: c# winforms datatable


    【解决方案1】:

    您收到IndexOutOfRange 异常的原因是您试图在新的DataTable 中引用不存在的Columns。这一行:

    childList.Add(new DataTable()); 
    

    确实将新的DataTable 添加到childList,但DataTable 没有列和行。

    通常我可能会使用DataTable.Clone() 方法创建一个新的DataTable,其结构与调用该方法的DataTable 相同,但显然这对您不起作用。在您的情况下,您必须使用 DataTable.Columns.Add 方法显式添加 DataColumns。

    类似:

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

    上面的sn-p很简单。由于您将自己创建 DataColumns,因此您需要自己命名并键入每个 DataColumn

    【讨论】:

    • 非常感谢您的宝贵时间。与此同时,我匆匆忙忙地要求 SQL Server 去做。如果您有兴趣,我已经编辑了我的问题以显示这是如何完成的......
    • 很高兴您成功了,感谢您发布您的解决方案。
    • 你能看看我的question 之一吗?
    【解决方案2】:

    我刚刚创建了一个拆分数据表的方法。 “.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;
            }
    

    以防万一这对任何人都有帮助:)

    【讨论】:

      猜你喜欢
      • 2015-10-24
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 2016-10-02
      • 2016-04-27
      • 2012-08-30
      • 1970-01-01
      • 2012-07-24
      相关资源
      最近更新 更多