簡體   English   中英

釋放Interop Excel對象

[英]Release Interop Excel object

我目前正在編寫一個在Excel文件中使用VBA宏的C#.NET應用程序。

當用戶單擊按鈕時,我從c#應用程序運行宏。 我必須等待所有數據下載完畢,這就是為什么這是執行“ Application.Quit”的VBA代碼的原因。

有我的代碼:

private void toolStripButton5_Click(object sender, EventArgs e)
    {
        int lastUsedRowFund, lastUsedRowEquity, lastUsedRowBond, lastUsedRowAccount = 0;

        Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
        Excel.Workbook oWB = null;
        Excel.Worksheet oSheetFund = null;
        Excel.Worksheet oSheetEquity = null;
        Excel.Worksheet oSheetBond = null;
        Excel.Worksheet oSheetAccount = null;

        oXL.Visible = false;

        oWB = oXL.Workbooks.Open("C:\\extract.xlsm");

        oSheetFund = oWB.Sheets["Fund"];
        oSheetEquity = oWB.Sheets["Equity"];
        oSheetBond = oWB.Sheets["Bond"];
        oSheetAccount = oWB.Sheets["Account"];

        string[] valuesHeaderFund = {"field1", "field2" };

        string[] valuesHeaderEquity = {"field1", "field2"};

        string[] valuesHeaderBond = {"field1", "field2"};

        string[] valuesHeaderAccount = {"field1", "field2"};

        Excel.Range headerFund = oSheetFund.get_Range("A1", "AA1");
        Excel.Range headerEquity = oSheetEquity.get_Range("A1", "AE1");
        Excel.Range headerBond = oSheetBond.get_Range("A1", "AE1");
        Excel.Range headerAccount = oSheetAccount.get_Range("A1", "AE1");

        headerFund.Value2 = valuesHeaderFund;
        headerEquity.Value2 = valuesHeaderEquity;
        headerBond.Value2 = valuesHeaderBond;
        headerAccount.Value2 = valuesHeaderAccount;

        Excel.Range lastRowFund = oSheetFund.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
        Excel.Range lastRowEquity = oSheetEquity.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
        Excel.Range lastRowBond = oSheetBond.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
        Excel.Range lastRowAccount = oSheetAccount.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);

        lastUsedRowFund = lastRowFund.Row;
        lastUsedRowEquity = lastRowEquity.Row;
        lastUsedRowBond = lastRowBond.Row;
        lastUsedRowAccount = lastRowAccount.Row;

        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
            string[] data = { row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString()};

            if (row.Cells[5].Value.ToString() == "FON")
            {

                lastUsedRowFund += 1;
                oSheetFund.get_Range("A" + lastUsedRowFund, "K" + lastUsedRowFund).Value2 = data;

            }
            else if (row.Cells[5].Value.ToString() == "ACT")
            {

                lastUsedRowEquity += 1;
                oSheetEquity.get_Range("A" + lastUsedRowEquity, "K" + lastUsedRowEquity).Value2 = data;

            }
            else if (row.Cells[5].Value.ToString() == "OBL")
            {

                lastUsedRowBond += 1;
                oSheetBond.get_Range("A" + lastUsedRowBond, "K" + lastUsedRowBond).Value2 = data;

            }
            else if (row.Cells[5].Value.ToString() == "ACCOUNT")
            {

                lastUsedRowAccount += 1;
                oSheetAccount.get_Range("A" + lastUsedRowAccount, "K" + lastUsedRowAccount).Value2 = data;

            }
        }

        RunMacro(oXL, new Object[] { "Main" });

        oXL.UserControl = false;

        //oWB.Close();
        //oXL.Quit();

        releaseObject(lastRowFund);
        releaseObject(lastRowEquity);
        releaseObject(lastRowBond);
        releaseObject(lastRowAccount);
        releaseObject(headerFund);
        releaseObject(headerEquity);
        releaseObject(headerBond);
        releaseObject(headerAccount);
        releaseObject(oSheetFund);
        releaseObject(oSheetEquity);
        releaseObject(oSheetBond);
        releaseObject(oSheetAccount);
        releaseObject(oWB);
        releaseObject(oXL);

    private void RunMacro(object oApp, object[] oRunArgs)
    {
        oApp.GetType().InvokeMember("Run",
            System.Reflection.BindingFlags.Default |
            System.Reflection.BindingFlags.InvokeMethod,
            null, oApp, oRunArgs);
    }

    private void releaseObject(object obj)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
            obj = null;
        }
        catch (Exception ex)
        {
            obj = null;
            MessageBox.Show("Unable to release the Object " + ex.ToString());
        }
        finally
        {
            GC.Collect();
        }
    }

當我單擊toolStripButton5時,一切正常。 但是最后,任務管理器中的“ EXCEL.EXE”進程仍然存在。 當我再次單擊該按鈕時,將創建一個新的“ EXCEL.EXE”,但是當任務完成時,進程將正確釋放。 當我退出應用程序時,第一個進程已發布。

您能否幫助我在第一次單擊時正確釋放對象。

問候,

丹妮

不幸的是,退出Excel應用程序並不是那么簡單,因為Interoop服務的COM對象仍然存在於內存中。 這就是Excel.exe進程仍在運行的原因。 每個對象都可以使用Marshal類釋放。 樣例代碼:

Marshal.ReleaseComObject(excelSheets);   //Worksheet
Marshal.ReleaseComObject(excelSheet);    //Sheet

...等等。 希望這可以幫助。

現在,它可以很好地工作了。 當我使用Excel執行第二次提取時,在創建新的過程時正確釋放了第一個過程。

我只是替換為“ releaseObject”中的System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); 通過Marshal.ReleaseComObject(obj);

也許是因為我使用“使用System.Runtime.InteropServices;” 在標題中。

非常感謝。

問候

暫無
暫無

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

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