Разработчики 1С часто сталкиваются с задачей импорта данных из электронных таблиц Excel. Традиционный и один из самых популярных способов решения этой задачи — использование COM-соединения. Однако при переносе работающего кода с клиентского компьютера на сервер 1С код часто перестает работать, возвращая ошибку «Недоступен интерфейс СОМ» или «Ошибка при вызове конструктора (COMОбъект)».
В этой статье мы подробно разберем, почему возникает данная проблема, детально проанализируем разницу между основными инструментами работы с COM, изучим пошаговые инструкции по настройке операционной системы для исправления серверных ошибок, а также рассмотрим современные альтернативные методы загрузки файлов без использования COM-технологий.
Начнем с разбора классического недоразумения, с которым столкнулся автор темы на форуме. Коллега демонстрирует работающий код с использованием конструкции COMObject, в то время как код автора с использованием COMОбъект выдает ошибку.
Выясним причину этого явления. На уровне платформы 1С:Предприятие имена COMObject и COMОбъект являются абсолютно идентичными синонимами. Первое написание представляет собой англоязычный вариант имени конструктора, а второе — русскоязычный. Платформа одинаково успешно распознает оба варианта. Если у одного разработчика работает один вариант, а у другого нет, дело всегда кроется в других сопутствующих факторах:
COMObject). В таком случае синтаксический анализатор 1С не сможет распознать имя метода.Этот важный вопрос часто остается без должного внимания. Рассмотрим подробнее, как работают эти механизмы и какой из них предпочтительнее использовать в различных сценариях.
Конструктор Новый COMОбъект("Excel.Application") выполняет явное создание нового экземпляра приложения. При каждом вызове этой строки операционная система запускает новый изолированный процесс excel.exe. Если в коде возникнет ошибка или разработчик забудет корректно вызвать метод закрытия приложения, этот процесс останется «висеть» в оперативной памяти сервера, потребляя ресурсы.
Функция ПолучитьCOMОбъект(ПутьКФайлу) работает иначе. Она пытается открыть указанный файл напрямую. Если операционная система обнаруживает, что приложение Excel уже запущено и нужный файл открыт, платформа не будет плодить новые процессы, а подключится к уже существующему активному экземпляру. Это существенно экономит ресурсы сервера и оперативную память.
Существует также синтаксис с пустым первым параметром: ПолучитьCOMОбъект(, "Excel.Application"). Этот вызов пытается перехватить ссылку на уже запущенный в системе сеанс Excel. Если в данный момент ни один процесс Excel не активен, система вернет ошибку. Этот метод удобен для интеграции с уже открытыми пользователем документами на клиенте, но практически неприменим для фоновых серверных задач.
Когда код инициализации выполняется на сервере 1С под учетной записью службы (например, USR1CV8), Excel отказывается запускаться. Проанализируем системные причины этой проблемы и разберем по шагам варианты их решения.
Если на сервере установлен 64-разрядный сервер 1С:Предприятие, а пакет Microsoft Office установлен в стандартной 32-разрядной версии, то прямая инициализация через Новый COMОбъект завершится ошибкой. 64-битный процесс сервера 1С физически не может загрузить в свое адресное пространство 32-битные библиотеки динамической компоновки (DLL) COM-объекта.
Решение через специальный запуск DCOM:
Для настройки совместной работы системным администраторам необходимо запустить консоль настройки DCOM в режиме совместимости с 32-разрядными приложениями. Обычный запуск через команду dcomcnfg не покажет 32-битный Excel в списке. Используйте следующую команду в строке «Выполнить» (Win + R):
mmc comexp.msc /32
В открывшейся оснастке найдите компонент Microsoft Excel Application, перейдите в его свойства, откройте вкладку «Удостоверение» и выберите пункт «Текущий пользователь» или укажите конкретные учетные данные администратора, под которыми будет запускаться процесс.
При запуске из-под системной учетной записи службы (которая не осуществляет интерактивный вход в Windows), Excel пытается инициализировать окружение пользователя и обращается к папке рабочего стола (Desktop) в профиле этой службы. Если этой папки в системе не существует, Excel аварийно завершает работу.
Решение:
Необходимо вручную создать пустые папки по указанным путям в зависимости от разрядности операционной системы и пакета офиса:
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopПосле создания папки обязательно предоставьте пользователю, под которым запускается служба сервера 1С (например, USR1CV8), полные права доступа (Чтение, Запись, Изменение) на созданную папку Desktop.
Использование COM-соединения на сервере считается устаревшим и небезопасным архитектурным подходом. Оно привязывает систему 1С к операционной системе Windows и требует обязательной установки лицензионного пакета MS Office на сервере. Рассмотрим современные альтернативы.
Платформа 1С:Предприятие обладает мощным встроенным механизмом чтения файлов в форматах .xls и .xlsx напрямую, без привлечения стороннего софта. Посмотрим на практический пример реализации такого чтения:
ВременныйФайл = ПолучитьИмяВременногоФайла(Объект.ТипФайла);
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Объект.АдресФайла);
ДвоичныеДанные.Записать(ВременныйФайл);
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ВременныйФайл, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Сообщить("Файл успешно прочитан платформой!");
Исключение
Сообщить("Не удалось прочитать файл: " + ОписаниеОшибки());
КонецПопытки;
Преимущества данного метода:
Если на сервере установлены необходимые драйверы данных, файл Excel можно прочитать как обычную реляционную базу данных с помощью SQL-запросов. Для этого используется провайдер Microsoft.ACE.OLEDB.12.0. Этот метод работает невероятно быстро на больших объемах данных, поскольку не открывает визуальный интерфейс таблиц, а считывает сырые строки напрямую из структуры файла.
Если отказаться от технологии COM в вашем проекте невозможно (например, требуется читать сложные формулы или макросы), необходимо написать максимально оптимизированный алгоритм. Классическое чтение ячеек в цикле вида Cells(Row, Col).Value работает медленно из-за постоянных обращений к COM-интерфейсу на каждой итерации.
Рассмотрим эффективный способ загрузки данных, при котором вся область таблицы считывается в массив 1С за один единственный COM-запрос:
Функция ПрочитатьЛистExcelВТаблицу(ПутьКФайлу, НомерЛиста = 1) Экспорт
Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь;
Книга = Excel.Workbooks.Open(ПутьКФайлу);
Лист = Книга.Sheets(НомерЛиста);
Исключение
Если Excel <> Неопределено Тогда
Excel.Quit();
КонецЕсли;
ВызватьИсключение "Ошибка инициализации Excel: " + ОписаниеОшибки();
КонецПопытки;
// Определяем заполненные границы листа с помощью SpecialCells(11)
Попытка
ВсегоСтрок = Лист.Cells.SpecialCells(11).Row;
ВсегоКолонок = Лист.Cells.SpecialCells(11).Column;
// Создаем таблицу значений для выгрузки данных
ТЗ = Новый ТаблицаЗначений;
Для Счетчик = 1 По ВсегоКолонок Цикл
ТЗ.Колонки.Добавить("Колонка" + Счетчик, Новый ОписаниеТипов("Строка"));
КонецЦикла;
// Считываем всю заполненную область в COM-массив за один запрос
Область = Лист.Range(Лист.Cells(1, 1), Лист.Cells(ВсегоСтрок, ВсегоКолонок));
Данные = Область.Value.Выгрузить(); // Выгружаем двумерный массив
// Переносим данные массива в ТаблицуЗначений 1С
Для ИндексСтроки = 0 По ВсегоСтрок - 1 Цикл
НоваяСтрока = ТЗ.Добавить();
Для ИндексКолонки = 0 По ВсегоКолонок - 1 Цикл
НоваяСтрока[ИндексКолонки] = Строка(Данные[ИндексКолонки][ИндексСтроки]);
EndЦикла;
КонецЦикла;
Исключение
Сообщить("Ошибка при чтении данных: " + ОписаниеОшибки());
КонецПопытки;
// Обязательно корректно закрываем приложение Excel
Книга.Close(Ложь);
Excel.Quit();
Excel = Неопределено;
Возврат ТЗ;
КонецФункции
Используя данный метод, вы минимизируете количество обращений к интерфейсу COM, что позволяет сократить время загрузки объемных файлов Excel в десятки раз. При этом не забывайте обрабатывать исключения, чтобы гарантировать закрытие процесса excel.exe в оперативной памяти сервера при возникновении непредвиденных ошибок в ходе выполнения транзакций.