尝试将大Excel文件读入DataTable时发生OutOfMemoryException

时间:2019-02-15 16:45:22

标签: c# excel ssis etl script-task

我正在使用SSIS包来清理数据并将.Xlsx文件中的数据加载到SQL Server表中。 我还必须突出显示.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);

还有其他方法可以在不使用大量内存的情况下或通过使用Excel.Range.Cell而不是数据集和DataTable来从xlsx文件获取单元格值,列和行索引的情况下,在DataTable中加载数据以获取列索引和行索引请吗?

我没有显示完整的代码,因为它很长。如果需要更多信息,请通知我。

1 个答案:

答案 0 :(得分:2)

当尝试从具有大量行的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

之类的范围

参考