繁体   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