簡體   English   中英

使用Excel Interop Com對象時無法使用“2點” - C#

[英]Eliminating use of '2 dots' when using Excel Interop Com Objects - C#

我在發布Excel Interop Com Objects時遇到問題,當我嘗試保存然后關閉通過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();

驗證每條指令的返回類型並單獨分解。

您的第一行以“app.Workbooks”開頭,它返回Workbooks類型的對象。 然后Open指令返回一個工作簿:

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 KB中描述的ReleaseObject方法(使用while循環) :從.NET客戶端自動化后,Office應用程序不會退出
  4. 使用GC.Collect和GC.WaitForPendingFinalizers。
  5. 如果Excel進程在調試時保持活動狀態,請不要感到驚訝,只需運行應用程序即可測試進程是否保持活動狀態。

例如:

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進程!

我建議使用像NetOffice這樣的庫,它將負責為你釋放所有資源(所以你不必擔心所有這些COM Interop調用),作為獎勵,會給你智能感知。

您可以通過NuGet安裝它或從站點下載程序集。

使用兩個點並不是“不允許”,但它肯定會對性能產生影響,尤其是在緊密循環中運行時。

每個“點”是對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變量,則會對性能產生影響,甚至可以“優化”回原始單線程。

但是,改變

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

將減少對workSheet_range.Font的調用,以便您看到增量收益。

底線

我不會太擔心改變每個雙點調用,而是使用一個好的分析工具來確定代碼花費最多的時間,然后首先處理該區域。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM