При переносе клиентского кода формирования отчетов в Excel в регламентные или фоновые задания разработчики 1С часто сталкиваются с ситуацией: подключение через COM-объект Excel.Application проходит успешно, листы создаются и заполняются данными, однако на этапе вызова метода SaveAs процесс падает с ошибкой: «Произошла исключительная ситуация (Microsoft Office Excel): Метод SaveAs из класса Workbook завершен неверно».
Разберем причины такого поведения платформы и операционной системы, выясним, почему на сервере Excel ведет себя иначе, чем на рабочем компьютере пользователя, и рассмотрим пошаговые варианты решения проблемы.
Проанализируем контекст выполнения. На клиентской машине Excel запускается в активном пользовательском сеансе, где операционная система автоматически предоставляет все необходимые компоненты рабочего стола и пользовательского окружения. В фоновом же задании 1С код исполняется на сервере под учетной записью службы «Агент сервера 1С:Предприятия».
Приложение Microsoft Excel исторически проектировалось как настольная клиентская программа. При выполнении операции сохранения рабочей книги через COM-интерфейс Excel проверяет наличие специальной служебной папки Desktop (Рабочий стол) в профиле того пользователя, от имени которого запущен процесс. Если эта папка отсутствует, вызов Workbook.SaveAs аварийно прерывается системной ошибкой.
Выясним, под какой учетной записью работает служба сервера 1С. В зависимости от настроек вашей системы примените соответствующий вариант:
В этом случае необходимо вручную создать папки Desktop в системных профилях Windows на сервере 1С (в зависимости от разрядности установленной ОС и Microsoft Office):
Для 64-разрядной ОС: C:\Windows\SysWOW64\config\systemprofile\Desktop
Для 32-разрядной ОС или 64-битного Office: C:\Windows\System32\config\systemprofile\Desktop
Рекомендуется создать обе эти папки, чтобы исключить влияние разрядности процессов.
Если служба 1С настроена по стандартам безопасности, она выполняется под отдельной учетной записью. В этом случае папка должна физически существовать в каталоге профиля пользователя:
C:\Users\USR1CV8\Desktop
Убедитесь, что у учетной записи службы 1С есть полные права доступа (NTFS) на эту директорию, а также на временную папку ОС и целевой каталог сохранения.
Посмотрим на пример кода, позволяющего программно проверить и создать системные каталоги непосредственно перед началом работы с COM-объектом:
Попытка
СоздатьКаталог("C:\Windows\SysWOW64\config\systemprofile\Desktop");
Исключение
// Ошибку игнорируем, если каталог уже существует или нет прав
КонецПопытки;
Попытка
СоздатьКаталог("C:\Windows\System32\config\systemprofile\Desktop");
Исключение
// Ошибку игнорируем
КонецПопытки;
Создание каталога Desktop устраняет падение метода SaveAs, однако для стабильной работы фонового задания необходимо учесть критические нюансы автоматизации Office:
DisplayAlerts = Ложь.51 (xlOpenXMLWorkbook).Исключение или Попытка ... ЗавершитьПопытку, чтобы избежать накопления зависших процессов EXCEL.EXE в диспетчере задач сервера.Рассмотрим правильный шаблон формирования и сохранения файла:
Попытка
Excel = Новый COMОбъект("Excel.Application");
Исключение
ЗаписьЖурналаРегистрации("ВыгрузкаExcel", УровеньЖурналаРегистрации.Ошибка,,,
"Не удалось инициализировать Excel.Application: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Excel.DisplayAlerts = Ложь;
Excel.Visible = Ложь;
Попытка
Книга = Excel.Workbooks.Add();
Лист = Книга.Worksheets(1);
// Заполнение ячеек данными
Лист.Cells(1, 1).Value = "Тестовые данные";
ИмяФайла = ПолучитьИмяВременногоФайла("xlsx");
// Код 51 соответствует формату xlOpenXMLWorkbook (.xlsx)
Книга.SaveAs(ИмяФайла, 51);
Книга.Close(Ложь);
Исключение
ЗаписьЖурналаРегистрации("ВыгрузкаExcel", УровеньЖурналаРегистрации.Ошибка,,,
"Ошибка при формировании файла: " + ОписаниеОшибки());
Если Книга <> Неопределено Тогда
Книга.Close(Ложь);
КонецЕсли;
КонецПопытки;
Excel.Quit();
Excel = Неопределено;
Разработчики Microsoft официально не рекомендуют использовать COM-автоматизацию пакета Microsoft Office на стороне сервера из-за проблем с масштабируемостью и утечками памяти. В платформе 1С:Предприятие существует полностью штатный и безопасный способ сохранения данных в XLSX без использования установленного на сервере MS Excel.
Разберем по шагам, как решить эту задачу стандартными средствами платформы:
ТабДок = Новый ТабличныйДокумент;
// Формируем и заполняем табличный документ стандартными методами платформы
// ...
ИмяФайла = ПолучитьИмяВременногоФайла("xlsx");
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
Преимущества данного подхода очевидны: код не зависит от разрядности операционной системы, не требует установки пакета Office на сервере, работает на серверах под управлением Linux и гарантированно изолирован от ошибок неинтерактивных сеансов Windows.