使用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();
将会对性能产生零的影响,如果不重新使用interior
variables,甚至可能会被“优化”回原始的单线程。
但是,改变
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()); } }
总结所有的信息在这里。
- 分配时不要使用两个点。
- 使用AutoReleaseComObject类。
- 使用Microsoft知识库中描述的ReleaseObject方法(使用while循环) :从.NET客户端自动化后,Office应用程序不会退出 。
- 使用GC.Collect和GC.WaitForPendingFinalizers。
- 如果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安装它,或者从站点下载组件。