使用Excel Interop Com对象时消除“2点”的使用 – C#

我无法发布Excel Interop Com对象,当我尝试保存并closures通过Excel Interop创build的Excel工作簿时,导致我的C#应用​​程序崩溃。 我觉得问题是,在某些情况下,我正在使用“2点”与excel互操作COM对象,从我读过的是不允许的。 我已经从大多数代码行中消除了2个点,但是我正在设法重新创build以下代码行,以便它们只使用一个点。 如果有人有任何build议,我将不胜感激。

workbook = (Excel.Workbook)app.Workbooks.Open(startForm.excelFileLocation,); workbook = (Excel.Workbook)app.Workbooks.Add(1); workSheet_range.Font.Color = System.Drawing.Color.FloralWhite.ToArgb(); workSheet_range.Font.Bold = font; workSheet_range.Interior.Color = System.Drawing.Color.Red.ToArgb(); 

使用两个点不是“不允许的”,但是它肯定会对性能产生影响,尤其是在紧密环路中运行时。

每个“点”是对Excel库的COM调用,它可能比正常的CLR对象访问慢得多。 一般来说,您希望尽可能减lessCOM调用的次数。

除非您重复使用相同的variables, 否则将两个点分割成两行不会产生任何影响。 例如,改变

 workSheet_range.Interior.Color = System.Drawing.Color.Red.ToArgb(); 

 var interior = workSheet_range.Interior; interior.Color = System.Drawing.Color.Red.ToArgb(); 

将会对性能产生零的影响,如果不重新使用interiorvariables,甚至可能会被“优化”回原始的单线程。

但是,改变

 var font = workSheet_range.Font; font.Color = System.Drawing.Color.FloralWhite.ToArgb(); font.Bold = font; 

将有一个更less的调用workSheet_range.Font所以你会看到增加的好处。

底线

我不会太在意改变每一个双点呼叫,而是使用一个好的分析工具来确定你的代码花费最多的时间,然后首先解决这个问题。

validation每条指令的返回types并分别分解。

你的第一行以“app.Workbooks”开始,它返回一个Workbookstypes的对象。 然后打开指令返回一个工作簿:

 workbooks = app.Workbooks; workbook = workbooks.Open(startForm.excelFileLocation); 

然后你可以像这样拆分第二个:

 workbook = workbooks.add(1); 

如果您不是“实际”InterOp对象的“点”,则可以使用多个点。

这是一个完整的示例:

 Using Excel = Microsoft.Office.Interop.Excel; public void Read() { Excel.Application xlApp = new Excel.Application(); Excel.Workbooks xlWorkBooks = xlApp.Workbooks; Excel.Workbook xlWorkBook = xlWorkBooks.Open(sourceFile); Excel.Worksheet xlWorkSheet = xlWorkBook.Worksheets[ 1 ]; Excel.Range range = xlWorkSheet.UsedRange; range = range.Cells; Array myValues = ( Array )range.Value; //now holds all the data in the sheet //The following is to ensure the EXCEL.EXE instance is released... //If you edit this code, know that using 2 dots (ex: range.Cells.Value) can create weird stuff! xlWorkBook.Close(false); xlWorkBooks.Close(); xlApp.Quit(); releaseObject(xlWorkSheet); releaseObject(xlWorkBook); releaseObject(xlWorkBooks); releaseObject(xlApp); xlWorkSheet = null; xlWorkBooks = null; xlWorkBook = null; xlApp = null; } private static void releaseObject( object obj ) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null; } catch (Exception ex) { obj = null; Console.WriteLine("Unable to release the Object " + ex.ToString()); } } 

总结所有的信息在这里。

  1. 分配时不要使用两个点。
  2. 使用AutoReleaseComObject类。
  3. 使用Microsoft知识库中描述的ReleaseObject方法(使用while循环) :从.NET客户端自动化后,Office应用程序不会退出 。
  4. 使用GC.Collect和GC.WaitForPendingFinalizers。
  5. 如果Excel进程在debugging时保持活动状态,请不要感到惊讶,只要运行应用程序,总是testing进程是否保持活动状态。

例如:

 using Microsoft.Office.Interop.Excel; ... var missing = Type.Missing; using (AutoReleaseComObject<Microsoft.Office.Interop.Excel.Application> excelApplicationWrapper = new AutoReleaseComObject<Microsoft.Office.Interop.Excel.Application>(new Microsoft.Office.Interop.Excel.Application())) { var excelApplicationWrapperComObject = excelApplicationWrapper.ComObject; excelApplicationWrapperComObject.Visible = true; var excelApplicationWrapperComObjectWkBooks = excelApplicationWrapperComObject.Workbooks; try { using (AutoReleaseComObject<Workbook> workbookWrapper = new AutoReleaseComObject<Workbook>(excelApplicationWrapperComObjectWkBooks.Open(@"C:\Temp\ExcelMoveChart.xlsx", false, false, missing, missing, missing, true, missing, missing, true, missing, missing, missing, missing, missing))) { var workbookComObject = workbookWrapper.ComObject; Worksheet sheetSource = workbookComObject.Sheets["Sheet1"]; ChartObject chartObj = (ChartObject)sheetSource.ChartObjects("Chart 3"); Chart chart = chartObj.Chart; chart.Location(XlChartLocation.xlLocationAsObject, "Sheet2"); ReleaseObject(chart); ReleaseObject(chartObj); ReleaseObject(sheetSource); workbookComObject.Close(false); } } finally { excelApplicationWrapperComObjectWkBooks.Close(); ReleaseObject(excelApplicationWrapperComObjectWkBooks); excelApplicationWrapper.ComObject.Application.Quit(); excelApplicationWrapper.ComObject.Quit(); ReleaseObject(excelApplicationWrapper.ComObject.Application); ReleaseObject(excelApplicationWrapper.ComObject); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } } private static void ReleaseObject(object obj) { try { while (System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0); obj = null; } catch (Exception ex) { obj = null; Console.WriteLine("Unable to release the Object " + ex.ToString()); } } 

我知道释放所有的对象,使用GC.Collect,而不是使用两个点,当分配似乎在顶部, 至less当我退出Excel的实例过程被释放,我不必以编程方式杀死Excel进程!

我会build议使用像NetOffice这样的库,它会照顾你释放所有的资源(所以你不必担心所有这些COM Interop调用),作为奖励,会给你intellisense。

您可以通过NuGet安装它,或者从站点下载组件。