При переносе кода, работающего с файлами Microsoft Excel, из клиентской части (внешние обработки) в серверные модули (регламентные задания, привилегированные модули), разработчики часто сталкиваются с критической ошибкой: «Ошибка при вызове конструктора (COMОбъект) ... по причине: -2147024891(0x80070005): Отказано в доступе». Ситуация осложняется тем, что под административной учетной записью на клиенте всё работает корректно, но серверная служба 1С отказывается инициализировать объект. Проанализируем причины этой проблемы и разберем пошагово методы её решения.
Основная причина кроется в модели безопасности Windows. Когда мы запускаем 1С на клиенте, приложение работает под учетной записью текущего пользователя, который обычно имеет права на запуск интерактивных приложений. Сервер 1С:Предприятие чаще всего запускается как служба от имени специального пользователя (например, USR1CV8). У этого пользователя по умолчанию нет прав на запуск DCOM-компонентов Microsoft Office, а также отсутствует инициализированное окружение (профиль рабочего стола), необходимое для работы Excel.
Рассмотрим основной метод решения через настройку прав доступа. Нам потребуется настроить компонент Microsoft Excel Application. Выполним следующие шаги:
Win + R и введем команду dcomcnfg.exe.mmc comexp.msc /32.USR1CV8), предоставив ему все права (локальный/удаленный запуск и активация).Проанализируем технический нюанс, о котором часто забывают. Excel при запусте через COM-интерфейс требует наличия папки Desktop в профиле пользователя системы. Если её нет, конструктор выдаст ошибку доступа. Нам необходимо создать эти папки вручную:
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopПосле создания папок обязательно убедимся, что у пользователя USR1CV8 (или того, под кем запущен сервер) есть права «Полный доступ» на эти каталоги. Это одно из самых эффективных решений, не требующее предоставления прав администратора пользователю службы.
Разберем ситуацию, когда использование COM-объекта нежелательно (например, из-за низкой производительности или отсутствия Excel на сервере). Платформа 1С:Предприятие начиная с версии 8.3.6 позволяет читать файлы Excel напрямую. Рассмотрим пример использования объекта ТабличныйДокумент:
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
// Обработка данных табличного документа
Исключение
ЗаписатьЛогСобытий("Ошибка чтения файла: " + ОписаниеОшибки());
КонецПопытки;
Этот метод работает значительно быстрее, не требует наличия установленного Microsoft Office на сервере и исключает проблемы с правами доступа DCOM. Однако помните, что при чтении все листы книги могут быть объединены, а форматирование иногда искажается.
Если отказаться от COM невозможно, проанализируем, как ускорить работу. Чтение каждой ячейки по отдельности — крайне медленный процесс из-за постоянных обращений между процессами 1С и Excel. Посмотрим на пример кода, который считывает сразу весь лист в массив 1С:
Эксель = Новый COMОбъект("Excel.Application");
Эксель.DisplayAlerts = Ложь;
Эксель.Visible = Ложь;
Книга = Эксель.WorkBooks.Open(ИмяФайла);
Лист = Книга.Sheets(1);
// Получаем данные сразу всей области в массив (SafeArray)
ДанныеSafeArray = Лист.UsedRange.Value;
// Преобразуем в обычный массив 1С для удобства обработки
МассивДанных = ДанныеSafeArray.Выгрузить();
Книга.Close(Ложь);
Эксель.Quit();
Эксель = Неопределено;
Этот подход позволяет сократить время обработки файла с нескольких минут до нескольких секунд, так как минимизирует количество вызовов через COM-границу.
Работа с COM-объектами на сервере требует осторожности. Выясним основные правила:
Попытка...Исключение. В блоке исключения и в конце работы обязательно вызывайте Эксель.Quit(), иначе на сервере будут скапливаться «зомби-процессы» excel.exe, которые со временем потребят всю оперативную память.DisplayAlerts = 0 (или False). Если Excel на сервере решит задать вопрос (например, о сохранении изменений), процесс зависнет, так как нажать кнопку в невидимом окне некому.USR1CV8 права администратора сервера для решения этой проблемы. Это создает огромную дыру в безопасности. Лучше ограничиться точечными настройками DCOM и созданием папок Desktop.Подводя итог, можно сказать, что наиболее стабильным и современным решением является переход на встроенные средства платформы (ТабличныйДокумент.Прочитать()) или использование внешних библиотек, работающих с форматом XLSX напрямую как с XML-архивом. Если же COM необходим, начните с проверки наличия системных папок Desktop и настройки удостоверения в dcomcnfg.