在C#控制台应用程序中更新Excel文件后无法保存

问题描述

信息:

已安装MS Excel版本:Excel 2013(可以根据需要尝试更改)

使用的参考库:Microsoft Excel 15.0对象库(1.8版)

.Net Framework:4.7.2(无法更改)

应用程序类型:控制台应用程序(无法更改)

我需要什么:

所以我有一个excel工作簿,它在前2个工作表中已经各有8000行,在其他4个工作表中有一些图形。 我需要将此数据添加到前两张纸之一中的现有数据的底部,进行刷新,保存并关闭

我正在做什么:

    using MSExcel = Microsoft.Office.Interop.Excel;

在类构造函数中-

    public UsageReportFileManager(string reportFolderPath)
    {
        excel = new MSExcel.Application();

        if (excel == null)
        {
            log.Error("-E-Unable to create report!!");
            throw new Exception("Microsoft excel is not installed on the client machine");
        }
        InitializeWorkbook();
    }

初始化工作簿功能-

    private void InitializeWorkbook()
    {
        if (excel != null)
        {
            var filePath = GetResultPath(); //This returns a path which ends with .xlsx and it is a path to the existing file.

            if (!File.Exists(filePath)) //This is just handling a situation in case the actual file is missing.
            {
                //Create copy from template
                var templatePath = GetTemplateFilePath(); // this is not a excel template btw,its a empty workbook with formulas.
                File.copy(templatePath,filePath);
                // Till here its working and new file is created if original file is missing
            }

            var missing = Missing.Value;
            _workbook = excel.Workbooks.Open(Filename: filePath,UpdateLinks: missing,ReadOnly: false,Format: missing,Password: missing,WriteResPassword: missing,IgnoreReadOnlyRecommended: true,Origin: missing,Delimiter: missing,Editable: true,Notify: missing,Converter: missing,AddTomru: true,Local: true
                );
        }
    }

在此类的单独函数中,在初始化该类后从Program.cs调用-

    public void UpdateLoginRawDataToWorkbook(List<HubAuditEvent> lstLoginData)
    {
            var dtLoginData = ConvertDataListToDatatable(lstLoginData); -- I will be getting more than 1500 rows here.

            if (dtLoginData.Rows.Count > 0)
            {
                MSExcel.Worksheet sheet = _workbook.Sheets["SheetAlreadyHasData"] as MSExcel.Worksheet;

                MSExcel.Range lastCell = sheet.Cells.Find(
                    "*",Missing.Value,MSExcel.XlSearchOrder.xlByRows,MSExcel.XlSearchDirection.xlPrevIoUs,false,Missing.Value);

                int lastRow = lastCell.Row;

                for (int i = 0; i < dtLoginData.Rows.Count; i++)
                {
                    int row = lastRow + i + 1;
                    for (int j = 0; j < dtLoginData.Columns.Count; j++)
                    {
                        var col = j + 1;
                        sheet.Cells[row,col] = dtLoginData.Rows[i][j].ToString();
                    }
                }

                _workbook.RefreshAll();
                excel.Calculate();
                _workbook.Save(); <-- I get an exception here saying Cannot Save Read-Only file ..
                _workbook.Close(true);
                excel.Quit();
      }

我在_workbook.Save();行遇到一个异常,说无法保存只读文件..

解决方法

好的,所以我将其发布为答案,而不是发表评论,因为我相信我们许多人可能在做同样的事情时甚至没有意识到。

特别感谢@PanagiotisKanavos和@MikeJ:您刚刚保存了我的一天。您的评论让我觉得我真的打开了文件“再次获得”

我再次说“是”,因为这就是发生的事情...

  1. 因此,我打开文件,检查其是否为只读文件并运行控制台应用程序。 (请参阅此处,我忘了关闭桌面应用程序上的工作簿)

  2. 然后在调试过程中,我得到了打开它的异常,因此,我在看到异常时就停止了调试。 (这是第一件事,因为我只是在测试,所以我忘记将excel.Quit()放在finally块中-我现在意识到这非常非常重要。即使我在finally块中包含了它,第二个错误我正在做的是在收到异常后立即停止应用程序。)

  3. 现在我有几个未关闭的打开excel对象的实例,因为到现在为止我已经调试了几次。 从那时起,无论我将excel.Quit()放在哪里,该实例由于某种原因都会在某个地方打开。

  4. 然后我检查了您的评论,并尝试再次再次手动打开它,并得到与只读相同的错误消息。那时一切都非常清晰。

  5. 现在,我在此FileManager类中创建了一个名为Close()的公共方法,该方法类似于:

       public void Close()
       {
           if(excel != null && _workbook != null)
           {
               _workbook.Close(true);
               excel.Quit();
           }
       }
    

现在,我从Program.cs类中的finally块中调用了此Close()方法。

  1. 然后我必须重新启动计算机才能释放该锁:D。

现在可以正常工作了。 :)