尝试将大 Excel 文件读入 DataTable 时出现 OutOfMemoryException
OutOfMemoryException while trying to read big Excel file into DataTable
我正在使用 SSIS 包清理 .Xlsx 文件中的数据并将其加载到 SQL 服务器 table。
我还必须突出显示 .Xlsx 文件中包含错误数据的单元格,为此我必须根据列名和行 ID( 我的数据电子表格中有)取回列和行索引。为此,我将第一个电子表格 (Error_Sheet
) 中的每一列名称与我在第二个电子表格中添加的列的行进行比较,并对行执行相同的操作,如果我有相同的单元格值,我会返回我的数据电子表格的列和行索引,并突出显示基于该列和行索引的单元格。该脚本运行良好,但在尝试从服务器 运行 它后,我遇到了内存异常,并且在我的工作站上也运行正常。
我试图减少我正在获取数据的范围:AC1:AC10000
到 AC1:AC100
,它只在第一次编译后工作,但它再次抛出异常。
string strSQLErrorColumns = "Select * From [" + Error_Sheet + "AC1:AC100]";
OleDbConnection cn = new OleDbConnection(strCn);
OleDbDataAdapter objAdapterErrorColumns = new OleDbDataAdapter(strSQLErrorColumns, cn);
System.Data.DataSet dsErrorColumns = new DataSet();
objAdapterErrorColumns.Fill(dsErrorColumns, Error_Sheet);
System.Data.DataTable dtErrorColumns = dsErrorColumns.Tables[Error_Sheet];
dsErrorColumns.Dispose();
objAdapterErrorColumns.Dispose();
foreach (DataColumn ColumnData in dtDataColumns.Columns){
ColumnDataCellsValue = dtDataColumns.Columns[iCntD].ColumnName.ToString();
iCntE = 0;
foreach (DataRow ColumnError in dtErrorColumns.Rows){
ColumnErrorCellsValue = dtErrorColumns.Rows[iCntE].ItemArray[0].ToString();
if (ColumnDataCellsValue.Equals(ColumnErrorCellsValue)){
ColumnIndex = ColumnData.Table.Columns[ColumnDataCellsValue].Ordinal;
iCntE = iCntE + 1;
break;
}
}
iCntD = iCntD + 1;
}
ColumnIndexHCell = ColumnIndex + 1;
RowIndexHCell = RowIndex + 2;
Range rng = xlSheets.Cells[RowIndexHCell, ColumnIndexHCell] as Excel.Range;
rng.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow);
有任何其他方法可以在不使用大量内存的情况下将数据加载到 DataTable 中以获取列和行索引,或者使用 Excel.Range.Cell
而不是数据集和 DataTable 从中获取单元格值、列和行索引请提供 xlsx 文件?
我没有展示完整的代码,因为它很长。如果需要更多信息,请随时通知我。
当尝试从具有大量行的 Excel 读取数据时,最好按块 读取数据(在 OleDbDataAdapter 中,您可以使用分页选项来实现).
int result = 1;
int intPagingIndex = 0;
int intPagingInterval = 1000;
while (result > 0){
result = daGetDataFromSheet.Fill(dsErrorColumns,intPagingIndex, intPagingInterval , Error_Sheet);
System.Data.DataTable dtErrorColumns = dsErrorColumns.Tables[Error_Sheet];
//Implement your logic here
intPagingIndex += intPagingInterval ;
}
这将防止 OutOfMemory 异常。不再需要指定 AC1:AC10000
之类的范围
参考资料
我正在使用 SSIS 包清理 .Xlsx 文件中的数据并将其加载到 SQL 服务器 table。
我还必须突出显示 .Xlsx 文件中包含错误数据的单元格,为此我必须根据列名和行 ID( 我的数据电子表格中有)取回列和行索引。为此,我将第一个电子表格 (Error_Sheet
) 中的每一列名称与我在第二个电子表格中添加的列的行进行比较,并对行执行相同的操作,如果我有相同的单元格值,我会返回我的数据电子表格的列和行索引,并突出显示基于该列和行索引的单元格。该脚本运行良好,但在尝试从服务器 运行 它后,我遇到了内存异常,并且在我的工作站上也运行正常。
我试图减少我正在获取数据的范围:AC1:AC10000
到 AC1:AC100
,它只在第一次编译后工作,但它再次抛出异常。
string strSQLErrorColumns = "Select * From [" + Error_Sheet + "AC1:AC100]";
OleDbConnection cn = new OleDbConnection(strCn);
OleDbDataAdapter objAdapterErrorColumns = new OleDbDataAdapter(strSQLErrorColumns, cn);
System.Data.DataSet dsErrorColumns = new DataSet();
objAdapterErrorColumns.Fill(dsErrorColumns, Error_Sheet);
System.Data.DataTable dtErrorColumns = dsErrorColumns.Tables[Error_Sheet];
dsErrorColumns.Dispose();
objAdapterErrorColumns.Dispose();
foreach (DataColumn ColumnData in dtDataColumns.Columns){
ColumnDataCellsValue = dtDataColumns.Columns[iCntD].ColumnName.ToString();
iCntE = 0;
foreach (DataRow ColumnError in dtErrorColumns.Rows){
ColumnErrorCellsValue = dtErrorColumns.Rows[iCntE].ItemArray[0].ToString();
if (ColumnDataCellsValue.Equals(ColumnErrorCellsValue)){
ColumnIndex = ColumnData.Table.Columns[ColumnDataCellsValue].Ordinal;
iCntE = iCntE + 1;
break;
}
}
iCntD = iCntD + 1;
}
ColumnIndexHCell = ColumnIndex + 1;
RowIndexHCell = RowIndex + 2;
Range rng = xlSheets.Cells[RowIndexHCell, ColumnIndexHCell] as Excel.Range;
rng.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Yellow);
有任何其他方法可以在不使用大量内存的情况下将数据加载到 DataTable 中以获取列和行索引,或者使用 Excel.Range.Cell
而不是数据集和 DataTable 从中获取单元格值、列和行索引请提供 xlsx 文件?
我没有展示完整的代码,因为它很长。如果需要更多信息,请随时通知我。
当尝试从具有大量行的 Excel 读取数据时,最好按块 读取数据(在 OleDbDataAdapter 中,您可以使用分页选项来实现).
int result = 1;
int intPagingIndex = 0;
int intPagingInterval = 1000;
while (result > 0){
result = daGetDataFromSheet.Fill(dsErrorColumns,intPagingIndex, intPagingInterval , Error_Sheet);
System.Data.DataTable dtErrorColumns = dsErrorColumns.Tables[Error_Sheet];
//Implement your logic here
intPagingIndex += intPagingInterval ;
}
这将防止 OutOfMemory 异常。不再需要指定 AC1:AC10000
参考资料