簡體   English   中英

盡管釋放了對象,Excel 仍未關閉

[英]Excel doesn't close despite objects being released

所以,我寫了一個 class 來處理打開 excel 文件,但是即使我調用關閉 function,excel 也沒有關閉。這在我開始使用多個工作簿之前就起作用了,所以我認為它與此有關,但我有不知道如何解決這個問題。 任何幫助表示贊賞!

這是代碼:

public class ExcelReaderClass
    {
        public Excel.Application? excelApp = null; // create a null excell object that will later be used to store the reference to the open excel app
        public Excel.Workbooks? excelBooks = null; // create a null object collection that will contain all workbooks
        public Excel.Workbook? excelBook = null; // create a null object that will contain a workbook (excel file)
        public Excel.Worksheet? curWorksheet = null; // create a null worksheet object that will contain the reference to the current worksheet that is open
        public Excel.Range? curWorksheetRange = null; // create a range object that will contain the data from the currently open worksheet

        // function that opens excel file and opens excel if it isnt already open
        public void openExcelFile(string filePath) // filePath = filepath for the worksheet that is to be opened
        {
            if(excelApp == null) // if excel isnt open
            {
                excelApp = new Excel.Application(); // create a new instance of excel

                excelApp.DisplayAlerts = false; // prevents "do you want to save" popups, which we want because we are only looking at files not changing them

                excelBooks = excelApp.Workbooks; // create a new instance of workbook object collection
            }

            excelBook = excelBooks.Add(filePath); // add the workbook to the collection
        }

        // function that closes all instances of excel opened by this program
        public void closeExcelFile(bool save, bool closeAll) // bool that controls whether only the worksheet is closed or the whole instance of excel
        {
            //excelBook.Save(); // save function not needed in this instance but might be useful later

            GC.Collect();
            GC.WaitForPendingFinalizers();

            foreach (Excel.Workbook workbook in excelBooks)
            {
                workbook.Close(save, System.Reflection.Missing.Value, System.Reflection.Missing.Value); // close the workbook 
                NAR(workbook);
            }

            NAR(excelBooks); ; // release the workbook collection from Com
            NAR(excelBook);
            NAR(curWorksheet);
            NAR(curWorksheetRange);

            if (closeAll) // if close all is true, we want to close the excel instance too
            {
                excelApp.Quit(); // quit out of excel

                NAR(excelApp); // release excel from Com
            }
        }

        public List<object[,]> readExcelFile(string[] filePaths) // 
        {
            List<object[,]> rangeList = new List<object[,]>(); // list of objects that will contain the data from the excel sheets

            foreach (var filePath in filePaths) // for each file
            {
                openExcelFile(filePath); // open the file in excel
            }

            foreach (var workbook in excelBooks) // iterate through workbooks 
            {
                var book = workbook as Excel.Workbook; // set book as a reference to the workbook

                curWorksheet = book.Worksheets[1]; // set this variable to the first sheet in the workbook
                curWorksheetRange = curWorksheet.UsedRange; // set this variable to the workbook range

                object[,]? range = (object[,])curWorksheetRange.Value2;

                rangeList.Add(range);
            }

            closeExcelFile(false,true);

            return (rangeList);
        }

        //function to kill object and release it from COM
        private void NAR(object o)
        {
            try
            {
                Marshal.FinalReleaseComObject(o);
            }
            catch { }
            finally
            {
                o = null;
            }
        }
    }

我試過使用GC.Collect()GC.WaitForPendingFinalizers()但這似乎也不起作用。

更新,這就是我修復代碼所做的。 隨意使用它。 (雖然在調試模式下不起作用)

public class ExcelReaderClass
    {
        public Excel.Application? excelApp = null; // create a null excell object that will later be used to store the reference to the open excel app
        public Excel.Workbooks? excelBooks = null; // create a null object collection that will contain all workbooks
        public Excel.Workbook? excelBook = null; // create a null object that will contain a workbook (excel file)
        public Excel.Worksheet? curWorksheet = null; // create a null worksheet object that will contain the reference to the current worksheet that is open
        public Excel.Range? curWorksheetRange = null; // create a range object that will contain the data from the currently open worksheet

        // function that opens excel file and opens excel if it isnt already open
        public void openExcelFile(string filePath) // filePath = filepath for the worksheet that is to be opened
        {
            if(excelApp == null) // if excel isnt open
            {
                excelApp = new Excel.Application(); // create a new instance of excel

                excelApp.DisplayAlerts = false; // prevents "do you want to save" popups, which we want because we are only looking at files not changing them

                excelBooks = excelApp.Workbooks; // create a new instance of workbook object collection
            }

            excelBook = excelBooks.Add(filePath); // add the workbook to the collection
        }

        // function that closes all instances of excel opened by this program
        public void closeExcelFile(bool save, bool closeAll) // bool that controls whether only the worksheet is closed or the whole instance of excel
        {
            foreach (Excel.Workbook workbook in excelBooks)
            {
                workbook.Close(save, System.Reflection.Missing.Value, System.Reflection.Missing.Value); // close the workbook 
            }

            excelBooks = null; // clear the reference to the workbook collection
            excelBook = null; // clear the reference to the active workbook
            curWorksheet = null; // clear the reference to the current worksheet
            curWorksheetRange = null; // clear the reference to the range of the current worksheet

            if (closeAll) // if close all is true, we want to close the excel instance too
            {
                excelApp.Quit(); // quit out of excel
                excelApp = null;
            }
        }

        public List<object[,]> readExcelFile(string[] filePaths)
        {
            List<object[,]> rangeList = new List<object[,]>();

            foreach (var filePath in filePaths)
            {
                openExcelFile(filePath);
            }

            Console.WriteLine();

            foreach (var workbook in excelBooks) // done to select the first workbook because other methods have failed but this works
            {
                var book = workbook as Excel.Workbook; // set book as a reference to the workbook

                curWorksheet = book.Worksheets[1]; // set this variable to the first sheet in the workbook
                curWorksheetRange = curWorksheet.UsedRange; // set this variable to the workbook range

                object[,]? range = (object[,])curWorksheetRange.Value2;

                rangeList.Add(range);
            }

            closeExcelFile(false,true);

            GC.Collect();
            GC.WaitForPendingFinalizers();

            return (rangeList);
        }
    }

簡要說明:我刪除了 NAR function 和它被調用的任何地方,在我的所有 excel 代碼執行后添加了GC.Collect()GC.WaitForPendingFinalisers ,並確保在調用 GC.* 函數之前將所有變量設置為 null。

暫無
暫無

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

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