Работа с файлами Microsoft Excel на стороне сервера в рамках регламентных или фоновых заданий — задача классическая, но часто сопровождающаяся труднодиагностируемыми ошибками. Типичная ситуация: обработка прекрасно работает «под пользователем» в интерактивном режиме, но при попытке запустить её по расписанию возникает исключительная ситуация: "Метод SaveAs из класса Workbook завершен неверно". В этой статье мы подробно разберем причины этой ошибки, проанализируем настройки операционной системы и рассмотрим современные способы формирования многолистовых документов Excel без использования COM-объектов.
Прежде всего, проанализируем ситуацию. Когда мы запускаем Excel интерактивно, приложение инициализируется в сессии текущего пользователя Windows. У него есть доступ к графическому интерфейсу, принтерам по умолчанию и временным папкам профиля. Регламентное задание выполняется в «Сессии 0» под учетной записью службы сервера 1С (обычно это USR1CV8). В этой среде Excel не находит привычного окружения, что приводит к краху внутренних методов COM-объекта, таких как SaveAs.
Одной из самых странных, но эффективных мер является создание определенных папок в системных профилях Windows. Microsoft Excel при выполнении операций сохранения требует наличия папки Desktop в профиле пользователя, от имени которого он запущен. Поскольку служба 1С работает под системным профилем, эти папки нужно создать вручную.
Рассмотрим по шагам, что нужно сделать:
C:\Windows\System32\config\systemprofile\Desktop.C:\Windows\System32\config\systemprofile\DesktopC:\Windows\SysWOW64\config\systemprofile\DesktopUSR1CV8 или .\Администратор).Как показывает практика и обсуждение на форумах, часто проблема кроется в банальном отсутствии прав на запись в папку, куда должен быть сохранен итоговый файл. Выясним причину: когда вы запускаете код вручную, файл записывается от вашего имени. В регламентном задании запись идет от имени USR1CV8.
Проанализируем алгоритм проверки прав:
Z:\Отчеты\), так как они подключаются только в сеансе пользователя. Используйте полные UNC-пути: \\ServerName\ShareFolder\file.xlsx.USR1CV8 (или того, под которым работает сервер 1С) и предоставьте ему права «Изменение» и «Запись».Использование COM-объекта Excel.Application на сервере считается «плохим тоном» и не рекомендуется самой компанией Microsoft. Это медленно, требует установки Office на сервер и нестабильно. Рассмотрим более надежный способ — использование объекта ПакетОтображаемыхДокументов, который позволяет программно формировать файлы Excel с несколькими листами напрямую средствами платформы 1С.
Разберем пример кода, который решает задачу автора темы (формирование файла с двумя листами):
// Создаем табличные документы для каждого листа
ТабДокЛист1 = Новый ТабличныйДокумент;
// ... тут заполняем первый лист данными (например, 50 000 строк) ...
ТабДокЛист1.ИмяСтраницы = "Данные_Часть1";
ТабДокЛист2 = Новый ТабличныйДокумент;
// ... заполняем второй лист ...
ТабДокЛист2.ИмяСтраницы = "Данные_Часть2";
// Используем ПакетОтображаемыхДокументов для объединения листов в одну книгу
Пакет = Новый ПакетОтображаемыхДокументов;
// Добавляем листы в пакет
ЭлементПакета1 = Пакет.Состав.Добавить();
ЭлементПакета1.Данные = ПоместитьВоВременноеХранилище(ТабДокЛист1);
ЭлементПакета2 = Пакет.Состав.Добавить();
ЭлементПакета2.Данные = ПоместитьВоВременноеХранилище(ТабДокЛист2);
// Записываем пакет в один файл XLSX
ПутьКФайлу = "\\Server\Reports\Report_50k.xlsx";
Пакет.Записать(ПутьКФайлу, ТипФайлаПакетаОтображаемыхДокументов.XLSX);
В этом примере мы используем метод Записать у объекта ПакетОтображаемыхДокументов. Это работает значительно быстрее, чем COM, и не требует наличия Excel на сервере. При записи большого объема данных (как у автора — по 60 000 строк на лист) этот метод потребляет меньше памяти и не вызывает ошибок «Session 0».
Если вам достаточно одного листа, можно использовать прямой метод ТабличныйДокумент.Записать(). Однако, как было отмечено в ходе обсуждения, даже этот метод может выдать «Ошибка доступа к файлу», если права настроены неверно. Посмотрим на правильный синтаксис:
ТабДок = Новый ТабличныйДокумент;
// Заполнение данными...
Попытка
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Исключение
ЗаписьЖурналаРегистрации("Ошибка сохранения Excel",
УровеньЖурналаРегистрации.Ошибка, , ,
ОписаниеОшибки());
ВызватьИсключение; // Пробрасываем ошибку дальше для мониторинга
КонецПопытки;
Выясним причину, почему отладка таких ошибок затруднена. Регламентное задание выполняется на сервере, и обычная точка останова может не сработать. Для эффективного поиска проблемы рекомендуем:
НайтиФайлы() непосредственно перед сохранением. Это поможет убедиться, что сервер «видит» каталог.-debug в строке запуска службы).ExcelПриложение.DisplayAlerts = Ложь;, если вы все же используете COM-объект. Это предотвратит зависание процесса при возникновении модальных окон в невидимой сессии.ExcelПриложение.Quit(); и обнулять переменные (ExcelПриложение = Неопределено;).Проанализировав все вышеперечисленные методы, можно сделать вывод: наиболее стабильным и современным решением для регламентных заданий является использование объекта ПакетОтображаемыхДокументов. Если же бизнес-логика требует именно COM (например, использование макросов), то ключом к успеху станет правильная настройка папок Desktop в системных профилях Windows и расширение прав для учетной записи USR1CV8.