Не удается сохранить файл Excel после его обновления в консольном приложении С#

Информация:

Установленная версия MS Excel: Excel 2013 (при необходимости можно попробовать изменить)

Используемая справочная библиотека: библиотека объектов Microsoft Excel 15.0 (версия 1.8)

.Net Framework: 4.7.2 (изменить нельзя)

Тип приложения: консольное приложение (нельзя изменить)

Что мне нужно:

Итак, у меня есть рабочая книга Excel, в которой уже есть около 8000 строк на первых 2 листах и ​​несколько графиков на 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,
                    Missing.Value,
                    Missing.Value,
                    MSExcel.XlSearchOrder.xlByRows,
                    MSExcel.XlSearchDirection.xlPrevious,
                    false,
                    Missing.Value,
                    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();, в которой говорится, что не удается сохранить файл только для чтения.


person SunainaDG    schedule 06.10.2020    source источник
comment
Полностью опишите полученное вами исключение. Какой тип исключения, каково точное сообщение об исключении, есть ли какие-либо внутренние исключения?   -  person mason    schedule 06.10.2020
comment
Cannot Save Read-Only file сообщение довольно ясное. Вы получите ту же ошибку, если сами откроете Excel и попытаетесь отредактировать и сохранить этот файл — фактически, именно это вы и сделали. Возможно, вы используете загруженный файл в качестве шаблона?   -  person Panagiotis Kanavos    schedule 06.10.2020
comment
Было бы намного проще использовать библиотеку, такую ​​​​как EPPlus или NPOI, для создания файла xlsx без необходимости установки Excel. Заполнить лист данными с помощью EPPlus так же просто, как sheet.Cells.LoadFromCollection(events);. Если лист содержит именованные таблицы, вы можете получить к ним доступ и добавить строки   -  person Panagiotis Kanavos    schedule 06.10.2020
comment
откуда первоисточник? Это что-то, что вы загрузили из удаленного сетевого расположения? И вы, конечно, открыли это вручную и убедились, что на самом деле это не документ только для чтения? support.microsoft.com/en-us/office/   -  person MikeJ    schedule 06.10.2020
comment
Итак, я только что проверил все, что вы, ребята, предложили.   -  person SunainaDG    schedule 06.10.2020


Ответы (1)


Хорошо, поэтому я публикую это как ответ, а не комментарий, потому что я считаю, что многие из нас могут делать то же самое, даже не осознавая этого.

Особая благодарность @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();
           }
       }
    

Теперь я вызвал этот метод Close() из блока finally в моем классе Program.cs.

  1. Затем мне пришлось буквально перезагрузить машину, чтобы снять эту блокировку: D.

И теперь он работает нормально. :)

person SunainaDG    schedule 06.10.2020