当行数超过3000时,C#Excel互操作占用的进程太长

当行数超过3000时,C#Excel互操作占用的进程太长,c#,excel,C#,Excel,当行数超过3000行时,C#Excel互操作的处理时间太长,当我将Excel分解为1500行并处理Excel时,其处理时间不超过2分钟 注意:我想知道为什么两个1500行的excel处理速度更快,而一个3000行以上的excel处理时间太长 有时会引发以下异常 Return argument has an invalid type. at System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type

当行数超过3000行时,C#Excel互操作的处理时间太长,当我将Excel分解为1500行并处理Excel时,其处理时间不超过2分钟

注意:我想知道为什么两个1500行的excel处理速度更快,而一个3000行以上的excel处理时间太长

有时会引发以下异常

Return argument has an invalid type.
   at System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type paramType)
   at System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg, Object[] outArgs, Object returnValue)
   at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
   at Microsoft.Office.Interop.Excel.Range.get_Columns()
   at PayableManagementHandler.Common.Utilities.ReadFileDetails(Request requestObj) 
方法调用性能问题

public static DataTable ReadFileDetails(Request requestObj)
{
    DataTable fileDetailsTable = null; 
    try
    {
        Excel.Application xlApp;
        Excel.Workbook xlWorkBook;
        Excel.Worksheet xlWorkSheet;
        Excel.Range range;
        DataRow row = null;
       
       
        xlApp = new Microsoft.Office.Interop.Excel.Application();
        xlWorkBook = xlApp.Workbooks.Open(requestObj.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing);
        xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
        range = xlWorkSheet.UsedRange;
        if ((null != range) && (null != range.Cells) &&
            (requestObj.Source != PayableHndlrResource.STR_SOURCE ?  range.Columns.Count.ToString() == PayableHndlrResource.ColumnsCount :
            (requestObj.FileName.Contains(ConfigurationManager.AppSettings["FileName"]) || requestObj.FileName.Contains(ConfigurationManager.AppSettings["FileName"]) ? range.Columns.Count.ToString() == PayableHndlrResource.ColumnsCount : range.Columns.Count.ToString() == PayableHndlrResource.ColumnsCount)))
        {
            fileDetailsTable = new DataTable("ExcelData");
            for (int rowCount = 1; rowCount <= range.Rows.Count; rowCount++)
            {
                if (range.Cells[rowCount, 1].Value2 != null)
                {
                    if (rowCount > 1)
                        row = fileDetailsTable.Rows.Add();
                    for (int col = 1; col <= range.Columns.Count; col++)
                    {
                        if (rowCount == 1)

                        {
                            fileDetailsTable.Columns.Add((string)(range.Cells[rowCount, col] as Excel.Range).Value2).ToString().Trim();
                        }
                        else
                        {
                            if (requestObj.Source == PayableHndlrResource.STR_SOURCE)
                            {
                                row[col - 1] = ((range.Cells[rowCount, col] as Excel.Range).Value);
                            }
                            else
                            {
                                string data = Convert.ToString((range.Cells[rowCount, col] as Excel.Range).Value);
                                if (data != null)
                                {
                                    switch (fileDetailsTable.Columns[col - 1].Caption.ToString().ToUpper())
                                    {
                                        case "SECONDARY ID":
                                            row[col - 1] = data.Trim().ToString().Truncate(15);
                                            break;
                                        case "ACCOUNT NAME":
                                            row[col - 1] = data.Trim().ToString().Truncate(255);
                                            break;
                                        case "BUSINESS UNIT1":
                                            row[col - 1] = data.Trim().ToString().Truncate(100);
                                            break;
                                        case "BUSINESS UNIT2":
                                            row[col - 1] = data.Trim().ToString().Truncate(100);
                                            break;
                                        case "DESCRIPTION":
                                            row[col - 1] = data.Trim().ToString().Truncate(100);
                                            break;
                                        case "VENDOR":
                                            row[col - 1] = data.Trim().ToString().Truncate(51);
                                            break;
                                        case "CITY":
                                            row[col - 1] = data.Trim().ToString().Truncate(35);
                                            break;
                                        default:
                                            row[col - 1] = data.Trim().ToString();
                                            break;
                                    }
                                }
                                else
                                {
                                    if (fileDetailsTable.Columns[col - 1].Caption.ToString().ToUpper() == "REPORT TOTAL"
                                        || fileDetailsTable.Columns[col - 1].Caption.ToString().ToUpper() == "TRANSACTION AMOUNT"
                                            || fileDetailsTable.Columns[col - 1].Caption.ToString().ToUpper() == "ACCOUNT NO"
                                                )
                                    {
                                        row[col - 1] = 0;
                                    }
                                    else if (fileDetailsTable.Columns[col - 1].Caption.ToString().ToUpper() == "TOTAL"
                                                || fileDetailsTable.Columns[col - 1].Caption.ToString().ToUpper() == " AMOUNT")
                                    {
                                        row[col - 1] = DateTime.MinValue;
                                    }
                                    else
                                    {
                                        row[col - 1] = string.Empty;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            xlWorkBook.Close(true, requestObj.FileName, Type.Missing);
            xlApp.Quit();

            ReleaseObject(xlWorkSheet);
            ReleaseObject(xlWorkBook);
            ReleaseObject(xlApp);

            if (requestObj.Source == PayableHndlrResource.STR_SOURCE)
            {
                SetDefaultValueForCTSI(fileDetailsTable,requestObj.CompanyId);
            }
        }
    }
    catch (Exception)
    {
        throw;
    }
    return fileDetailsTable;
}
公共静态数据表ReadFileDetails(请求对象)
{
DataTableFileDetailStable=null;
尝试
{
Excel.applicationxlapp;
Excel.工作簿;
Excel工作表;
范围;
DataRow行=null;
xlApp=新的Microsoft.Office.Interop.Excel.Application();
xlWorkBook=xlApp.Workbooks.Open(requestObj.FileName,Type.Missing,Type.Missing,Type.Missing,Type.Missing,
类型。缺失,类型。缺失,类型。缺失,类型。缺失,类型。缺失,
类型。缺失,类型。缺失,类型。缺失,类型。缺失,类型。缺失,
类型。缺失,类型。缺失);
xlWorkSheet=(Excel.Worksheet)xlWorkBook.Worksheets.get_项(1);
range=xlWorkSheet.UsedRange;
if((null!=范围)&&(null!=范围.单元格)&&
(requestObj.Source!=PayableHndlrResource.STR_Source?range.Columns.Count.ToString()==PayableHndlrResource.columnsunt:
(requestObj.FileName.Contains(ConfigurationManager.AppSettings[“FileName”])| | requestObj.FileName.Contains(ConfigurationManager.AppSettings[“FileName”])?range.Columns.Count.ToString()==PayableHndlResource.ColumnsCount:range.Columns.Count.ToString()==PayableHndlResource.ColumnsCount)))
{
fileDetailsTable=新数据表(“ExcelData”);
对于(int rowCount=1;rowCount 1)
row=fileDetailsTable.Rows.Add();

对于(int col=1;col您的代码显然正在崩溃,您不知道发生在何处或原因。我过去做过的一些事情是在try/catch外部的顶部创建一个变量。运行该过程,然后在异常中放置一个断点以查看问题所在。我打赌这可能是某个数据类型异常。您希望阻塞一种类型的对象和您获得的值不是该类型,因此阻塞。虽然这是一个存根,但它可能有助于您缩小失败的范围。它失败的另一个原因可能是第一个1500ish记录都正常,然后您有一些奇怪的数据,这就是导致失败的原因

这是你发布的内容的精简版本

public static DataTable ReadFileDetails(Request requestObj)
{
    DataTable fileDetailsTable = null; 
    var failStep = 1;
    try
    {
        Excel.Application xlApp;
        Excel.Workbook xlWorkBook;
        Excel.Worksheet xlWorkSheet;
        Excel.Range range;
        DataRow row = null;
       
       
        xlApp = new Microsoft.Office.Interop.Excel.Application();
        xlWorkBook = xlApp.Workbooks.Open(requestObj.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing);
        xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
        range = xlWorkSheet.UsedRange;
        if ((null != range) && (null != range.Cells) &&
            (requestObj.Source != PayableHndlrResource.STR_SOURCE ?  range.Columns.Count.ToString() == PayableHndlrResource.ColumnsCount :
            (requestObj.FileName.Contains(ConfigurationManager.AppSettings["FileName"]) || requestObj.FileName.Contains(ConfigurationManager.AppSettings["FileName"]) ? range.Columns.Count.ToString() == PayableHndlrResource.ColumnsCount : range.Columns.Count.ToString() == PayableHndlrResource.ColumnsCount)))
        {
            fileDetailsTable = new DataTable("ExcelData");


            for (int rowCount = 1; rowCount <= range.Rows.Count; rowCount++)
            {
                failStep = 1;
                if (range.Cells[rowCount, 1].Value2 != null)
                {
                    if (rowCount > 1)
                        row = fileDetailsTable.Rows.Add();

                    for (int col = 1; col <= range.Columns.Count; col++)
                    {
                        if (rowCount == 1)

                        {
                           failStep = 2;
                            fileDetailsTable.Columns.Add((string)(range.Cells[rowCount, col] as Excel.Range).Value2).ToString().Trim();
                        }
                        else
                        {
                           // checking before he IF to make sure
                           // no problem of the source type...
                           failStep = 3;
                            if (requestObj.Source == PayableHndlrResource.STR_SOURCE)
                            {
                                failStep = 4;
                                row[col - 1] = ((range.Cells[rowCount, col] as Excel.Range).Value);
                            }
                            else
                            {
                                failStep = 5;

                                string data = Convert.ToString((range.Cells[rowCount, col] as Excel.Range).Value);

etc... with rest of code
                }
            }
            failStep = 99;

            xlWorkBook.Close(true, requestObj.FileName, Type.Missing);
            xlApp.Quit();

            ReleaseObject(xlWorkSheet);
            ReleaseObject(xlWorkBook);
            ReleaseObject(xlApp);

            if (requestObj.Source == PayableHndlrResource.STR_SOURCE)
            {
                SetDefaultValueForCTSI(fileDetailsTable,requestObj.CompanyId);
            }
        }
    }
    catch (Exception e)
    {
        // at this point, you can look at the explicit exception
        // and also look at the "failStep" variable to see where
        // it failed.  Then put a break point at that location
        // to add additional logging information.
        throw;
    }
    return fileDetailsTable;
}
公共静态数据表ReadFileDetails(请求对象)
{
DataTableFileDetailStable=null;
var-failStep=1;
尝试
{
Excel.applicationxlapp;
Excel.工作簿;
Excel工作表;
范围;
DataRow行=null;
xlApp=新的Microsoft.Office.Interop.Excel.Application();
xlWorkBook=xlApp.Workbooks.Open(requestObj.FileName,Type.Missing,Type.Missing,Type.Missing,Type.Missing,
类型。缺失,类型。缺失,类型。缺失,类型。缺失,类型。缺失,
类型。缺失,类型。缺失,类型。缺失,类型。缺失,类型。缺失,
类型。缺失,类型。缺失);
xlWorkSheet=(Excel.Worksheet)xlWorkBook.Worksheets.get_项(1);
range=xlWorkSheet.UsedRange;
if((null!=范围)&&(null!=范围.单元格)&&
(requestObj.Source!=PayableHndlrResource.STR_Source?range.Columns.Count.ToString()==PayableHndlrResource.columnsunt:
(requestObj.FileName.Contains(ConfigurationManager.AppSettings[“FileName”])| | requestObj.FileName.Contains(ConfigurationManager.AppSettings[“FileName”])?range.Columns.Count.ToString()==PayableHndlResource.ColumnsCount:range.Columns.Count.ToString()==PayableHndlResource.ColumnsCount)))
{
fileDetailsTable=新数据表(“ExcelData”);
对于(int rowCount=1;rowCount 1)
row=fileDetailsTable.Rows.Add();

对于(int col=1;col如果perf是紧密循环中的一个主要问题,我最喜欢的是用VBA编写它并从C调用宏#您是否期望我们阅读这堵代码墙并解决问题?您需要学习一步一步地调试,习惯于遵循代码并理解它的功能。我调试过,但自己无法理解只需要一些建议来找出我真正缺少的@CamiloTerevintocould是内存吗?VSTO本质上是一个带有非托管代码的库,使用COM。在访问完元素后,必须释放COM引用。否则,内存将无法正确释放。还请注意,COM调用没有那么快。如果您愿意的话要处理多行,最好的解决方案是将整个范围复制到一个C#数组中,在C#中处理数组,然后写回数组。这将大大加快速度。