При автоматизации работы с Microsoft Office из среды 1С:Предприятие разработчики часто сталкиваются с непредвиденными ошибками на этапе создания новых файлов. Одной из наиболее коварных является ошибка: «Произошла исключительная ситуация (Microsoft Excel): Невозможно получить свойство Add класса Workbooks». Эта проблема парализует выгрузку отчетов, отправку заказов поставщикам и другие критически важные бизнес-процессы.
В этой статье мы подробно разберем по шагам, почему возникает эта ошибка, проанализируем исходный код, выявим скрытые инфраструктурные причины и рассмотрим несколько способов решения — от правильной настройки операционной системы до полного отказа от ненадежной технологии COM в пользу нативных механизмов платформы 1С.
Рассмотрим типичный фрагмент кода, в котором происходит сбой. Разработчик пытается подключиться к Excel, открыть существующий файл во временном каталоге, а если его нет — создать новый пустой документ с помощью метода Add():
НаименованиеФайла = "Заказ " + СокрЛП(ПоставщикДляОтбора.Наименование);
ИмяФайла = КаталогВременныхФайлов() + НаименованиеФайла + ".xls";
ФайлДанных = ИмяФайла;
// Подключаемся к MS Excel
Попытка
Excel = Новый COMОбъект("Excel.Application");
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Попытка
Книга = Excel.Workbooks.Open(ФайлДанных);
Исключение
// Если файл не найден, создаем новую книгу
Книга = Excel.Workbooks.Add();
Книга.SaveAs(ФайлДанных);
КонецПопытки;
В этой схеме заложена логическая ловушка. Если файла во временном каталоге еще нет (что абсолютно естественно при первом запуске), метод Open() гарантированно вызывает исключение. Управление передается в блок Исключение, где вызывается Excel.Workbooks.Add(). И именно здесь программа аварийно завершает работу.
При этом сам COM-объект Excel.Application успешно создается, проверка на заполненность (например, сравнение с Неопределено) возвращает Истина, но при попытке вызвать любое свойство или метод объекта Workbooks происходит сбой маршалинга интерфейсов COM.
Выясним главную причину этого поведения. В подавляющем большинстве случаев сервер 1С:Предприятия (или клиентское приложение) работает в 64-разрядном режиме, тогда как пакет Microsoft Office (включая Excel) установлен в 32-разрядной версии.
Когда 64-битный процесс 1С пытается инициализировать COM-объект 32-битного приложения, операционная система Windows запускает Excel в отдельном адресном пространстве через суррогатный процесс. На этапе создания самого объекта Excel.Application ошибки не возникает. Однако при попытке передать сложные типы данных или обратиться к дочерним коллекциям (таким как Workbooks) через границу разрядности (32 <-> 64 бит), механизмы COM/OLE Windows не справляются с трансляцией вызовов (маршалингом). Это приводит к потере связи с объектом и генерации ошибки.
Если у вас нет возможности переустановить Microsoft Office на 64-разрядную версию, необходимо вручную настроить службу DCOM в Windows, чтобы предоставить серверу 1С корректный доступ к компонентам Excel. Выполним следующие шаги:
regedit) и перейдите в ветку HKEY_CLASSES_ROOT\AppID. Проверьте, существует ли раздел EXCEL.EXE. Если он отсутствует, создайте его. Внутри раздела добавьте строковый параметр с именем AppID и значением {00020812-0000-0000-C000-000000000046} (это глобальный идентификатор приложения Microsoft Excel).Win + R, введите команду:
mmc comexp.msc /32
USR1CV8 или SYSTEM), предоставив ему полные права.Проанализируем еще одну скрытую проблему. Когда код выполняется в фоновом задании на стороне сервера 1С, служба сервера работает от имени системной учетной записи. Excel при создании новой книги (метод Add()) или при ее сохранении обращается к каталогу «Рабочий стол» (Desktop) текущего пользователя.
У системных учетных записей (таких как SYSTEM, NetworkService или локальных сервисных пользователей без загрузки профиля) папка «Рабочий стол» в структуре каталогов Windows по умолчанию отсутствует. Из-за этого Excel не может инициализировать буферные файлы и завершает вызов Add() ошибкой.
Рассмотрим процедуру создания необходимых директорий. Вам нужно зайти на сервер под учетной записью администратора и вручную создать пустые папки по следующим путям:
C:\Windows\System32\config\systemprofile\DesktopC:\Windows\SysWOW64\config\systemprofile\DesktopПосле создания папок обязательно нажмите на каждую из них правой кнопкой мыши, перейдите в «Свойства» -> «Безопасность» и предоставьте пользователю службы 1С (например, USR1CV8) полные права на чтение, запись и изменение этих папок.
Вернемся к исходному коду автора. Попытка открыть заведомо отсутствующий файл и последующий перехват ошибки через Попытка...Исключение — это крайне неэффективный подход, который перегружает систему лишними вызовами внешних COM-библиотек. Посмотрим, как можно улучшить этот алгоритм средствами встроенного языка 1С:
// Проверяем существование файла средствами самой платформы 1С
ФайлНаДиске = Новый Файл(ФайлДанных);
Попытка
Excel = Новый COMОбъект("Excel.Application");
Исключение
ЗаписьЖурналаРегистрации("Интеграция.Excel", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
ВызватьИсключение "Не удалось запустить Microsoft Excel на сервере!";
КонецПопытки;
Если ФайлНаДиске.Существует() Тогда
// Если файл есть, просто открываем его
Книга = Excel.Workbooks.Open(ФайлДанных);
Иначе
// Если файла нет, сначала создаем чистую книгу и сохраняем её
Книга = Excel.Workbooks.Add();
Книга.SaveAs(ФайлДанных);
КонецЕсли;
Такой подход избавляет от необходимости генерировать системные исключения Windows при стандартном сценарии работы системы и делает код более стабильным и читаемым.
Использование Microsoft Excel через COM-соединение на стороне сервера официально не рекомендуется самой корпорацией Microsoft. Десктопные офисные приложения не рассчитаны на работу в многопоточных фоновых процессах: они утекают по памяти, плодят зависшие процессы EXCEL.EXE в диспетчере задач и требуют интерактивного взаимодействия с пользователем при возникновении любых микроошибок.
Платформа 1С:Предприятие обладает мощным набором встроенных инструментов, которые позволяют формировать полноценные файлы Excel формата .xlsx или .xls без установленного MS Office на сервере и вне зависимости от разрядности операционной системы.
Рассмотрим пример создания файла для отправки контрагенту силами платформы 1С. Мы можем сформировать обычный табличный документ, заполнить его данными и сохранить в нужном формате одной строчкой кода:
// Создаем табличный документ в памяти 1С
ТабДок = Новый ТабличныйДокумент;
// Заполняем документ (выводим макеты, области, параметры)
// Например, выведем шапку заказа
Макет = ПолучитьМакет("МакетЗаказа");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.Поставщик = ПоставщикДляОтбора;
ТабДок.Вывести(ОбластьШапка);
// Сохраняем готовый документ в формате XLSX напрямую на диск
ИмяФайла = КаталогВременныхФайлов() + "Заказ_" + СокрЛП(ПоставщикДляОтбора.Код) + ".xlsx";
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
Преимущества этого метода неоспоримы:
EXCEL.EXE в диспетчере задач, которые забивают память сервера.Если вам обязательно нужно использовать COM-объект Excel (например, при заполнении сложного готового шаблона с макросами), настройте 32-битную консоль DCOM и создайте системные папки Desktop в каталоге профиля. Если же перед вами стоит стандартная задача выгрузки данных, воспользуйтесь нативным методом ТабличныйДокумент.Записать() — это сэкономит ваше время и обеспечит бесперебойную работу информационной базы.