我在发布Excel Interop Com对象时遇到问题,当我尝试保存然后关闭通过Excel Interop创建的Excel工作簿时,导致我的c#应用程序崩溃。我觉得问题是在某些情况下我使用'2点'与excel互操作COM对象,这是我不读的。我已经从大多数代码行中删除了2个点,但我正在找到一种方法来重新创建以下代码行,以便它们只使用一个点。如果有人有任何建议我会非常感激。
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();
答案 0 :(得分:3)
验证每条指令的返回类型并单独分解。
您的第一行以" app.Workbooks"开头返回Workbooks类型的对象。然后Open指令返回一个工作簿:
workbooks = app.Workbooks;
workbook = workbooks.Open(startForm.excelFileLocation);
然后您可以像这样拆分第二个:
workbook = workbooks.add(1);
如果您不是" dotting"可以使用多个点。实际的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 :(得分:1)
总结这里的所有信息。
例如:
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并且在分配时不使用两个点似乎超过顶部但至少当我退出Excel实例时,进程被释放,我不知道必须以编程方式杀死Excel进程!!
答案 2 :(得分:1)
我建议使用像 NetOffice 这样的库,它会为您释放所有资源(因此您不必担心所有这些COM Interop调用)作为奖励,会给你智能感知。
You can install it via NuGet或从网站下载程序集。
答案 3 :(得分:-1)
使用两个点并非“不允许”,但它肯定会对性能产生影响,尤其是在紧密循环中运行时。
每个“点”是对Excel库的COM调用,它可能比正常的CLR对象访问慢得多。通常,您希望将COM调用的数量减少到尽可能少。
通过分成两行来从两个点减少到一个不会对产生任何影响,除非重用相同的变量。例如,更改
workSheet_range.Interior.Color = System.Drawing.Color.Red.ToArgb();
到
var interior = workSheet_range.Interior;
interior.Color = System.Drawing.Color.Red.ToArgb();
如果您不重复使用interior
变量,将对性能产生 ZERO 影响,甚至可能会“优化”回原始单线程。
然而,改变
var font = workSheet_range.Font;
font.Color = System.Drawing.Color.FloralWhite.ToArgb();
font.Bold = font;
将减少对workSheet_range.Font
的呼叫,因此您将看到增量收益。
BOTTOM LINE
我不会太担心更改每个两点调用,而是使用一个好的分析工具来确定代码花费最多时间的位置,然后首先处理该区域。