将一个数据表拆分为多个数据表
本文关键字:数据表 拆分 一个 | 更新日期: 2023-09-27 18:35:11
All,我有一个实用程序可以将数据表导出到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...
您获得IndexOutOfRange
异常的原因是,您尝试在新DataTable
中引用不存在的Column
。 这一行:
childList.Add(new DataTable());
确实向childList
添加了一个新的DataTable
,但该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
。
我刚刚创建了一个拆分数据表的方法。该".批处理"方法引用自 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;
}
以防万一这对任何人有帮助:)