При разработке обработок для импорта или экспорта данных часто используется интеграция с Microsoft Excel через COM-соединение. Код инициализации выглядит предельно просто:
Excel = Новый COMОбъект("Excel.Application");
Однако в процессе выполнения этой строки разработчики нередко сталкиваются с неприятной ошибкой: «Ошибка при вызове конструктора (COMОбъект): -2147221005(0x800401F3): Недопустимая строка с указанием класса». Примечательно, что на одном компьютере (например, в файловой базе или в режиме обычного приложения) этот код может работать безупречно, а на другом (на сервере или в управляемом приложении) — завершаться аварийно.
В этой статье мы подробно разберем природу возникновения данной ошибки, проанализируем различные сценарии ее появления и рассмотрим пошаговые инструкции по ее устранению. Кроме того, мы изучим современные альтернативные методы работы с файлами Excel, которые позволят полностью отказаться от нестабильной технологии COM.
Код ошибки -2147221005 (0x800401F3) в операционной системе Windows дословно означает «Invalid class string». Это указывает на то, что подсистема COM (Component Object Model) не смогла найти в системном реестре Windows класс с программным идентификатором (ProgID) Excel.Application.
Основные причины, почему операционная система не может обнаружить этот класс, делятся на четыре категории:
Рассмотрим подробнее каждый сценарий и разберем практические шаги по решению проблемы.
В обычном приложении практически весь программный код по умолчанию выполняется на стороне клиента. Если на вашем локальном рабочем компьютере установлен Microsoft Office, то создание объекта Excel.Application проходит успешно.
В управляемом приложении выполнение кода переносится на сервер. Например, если вызов происходит в контексте &НаСервере, в фоновом задании или при выполнении регламентного задания, то Windows пытается инициализировать COM-объект непосредственно на физическом сервере приложений 1С.
Если на самом сервере приложений 1С пакет Microsoft Excel физически не установлен, система выдаст ошибку отсутствия класса.
Как решить эту проблему:
&НаКлиенте.Это наиболее распространенная причина сбоя в клиент-серверных базах данных. Современные серверы 1С практически всегда устанавливаются в 64-разрядной версии (x64). Процесс сервера rphost.exe работает как 64-битное приложение.
В то же время, на сервере может быть установлен 32-разрядный пакет Microsoft Office (x86). По умолчанию 64-битные приложения не могут напрямую вызывать 32-битные COM-серверы из-за разделения системного реестра на ветки 64-bit и WOW64 (32-bit). В результате сервер 1С просто «не видит» установленный Excel.
Пошаговая настройка DCOM (Службы компонентов) для решения конфликта разрядности:
Чтобы подружить 64-битный сервер 1С с 32-битным Excel, нам необходимо настроить запуск Excel как отдельного сервиса через Службы компонентов Windows. Выполним следующие шаги:
Win + R, введите команду comexp.msc /32 (для настройки 32-битных компонентов в 64-битной ОС) и нажмите Enter. Откроется окно «Службы компонентов».USR1CV8 или USR1CV83), и предоставьте ему полные права («Локальный запуск», «Локальная активация»).Даже после успешной настройки прав и разрядности Excel может наотрез отказываться запускаться под учетной записью службы Windows (например, System или USR1CV83). Дело в том, что Microsoft Excel изначально проектировался как интерактивное приложение. При запуске он обязательно ищет на диске папку «Рабочий стол» (Desktop) в профиле пользователя, который его запускает.
У системных учетных записей этой папки по умолчанию нет, из-за чего инициализация COM-объекта завершается внутренней ошибкой Windows.
Как решить эту проблему:
Необходимо вручную создать пустые папки Desktop в системных профилях Windows. Выполните создание папок по следующим путям (в зависимости от разрядности операционной системы):
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopПосле создания папок обязательно нажмите на них правой кнопкой мыши, перейдите в свойства безопасности и убедитесь, что пользователь службы 1С (USR1CV83) имеет права на чтение и запись в эти директории.
Если на вашем сервере или локальном компьютере вместо оригинального Microsoft Office установлен бесплатный аналог, например LibreOffice или OpenOffice, то попытка создать объект Excel.Application гарантированно вызовет ошибку 0x800401F3. Альтернативные пакеты регистрируют в системе совершенно другие COM-классы.
Решение для LibreOffice / OpenOffice:
Для работы с бесплатными офисными пакетами через COM-интерфейс вам необходимо использовать другие программные идентификаторы. Проанализируем пример кода для работы с LibreOffice Calc:
// Создаем менеджер сервисов LibreOffice
ServiceManager = Новый COMОбъект("com.sun.star.ServiceManager");
// Создаем структуру для работы с файлами
Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop");
// Массив параметров для открытия файла (в данном случае пустой)
Параметры = Новый COMSafeArray("VT_DISPATCH", 0);
// Открываем пустой документ или существующий файл
Документ = Desktop.loadComponentFromURL("private:factory/scalc", "_blank", 0, Параметры);
Важно помнить, что корпорация Microsoft официально не рекомендует использовать приложения пакета Microsoft Office на стороне сервера в неинтерактивных сессиях. Это связано с тем, что офисные программы не оптимизированы под многопоточную серверную нагрузку, склонны к утечкам оперативной памяти и могут зависать в памяти сервера бесконечными процессами excel.exe, требуя регулярной ручной очистки диспетчера задач.
Платформа 1С:Предприятие предлагает мощные встроенные механизмы, которые позволяют полностью отказаться от COM-объектов. Рассмотрим эти варианты подробнее.
Начиная с версии платформы 1С 8.3, разработчикам доступна возможность прямого чтения и записи файлов форматов XLSX, XLS без необходимости установки Microsoft Excel на компьютер или сервер. Этот метод работает невероятно быстро, стабильно и полностью кроссплатформенно (поддерживается на серверах под управлением Windows и Linux).
Проанализируем пример кода для чтения данных из файла Excel штатными средствами платформы:
// Создаем объект ТабличныйДокумент
ТабДок = Новый ТабличныйДокумент;
Попытка
// Читаем файл напрямую в табличный документ
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияТабличногоДокумента.XLSX);
// Получаем размеры прочитанной таблицы
ВысотаТаблицы = ТабДок.ВысотаТаблицы;
ШиринаТаблицы = ТабДок.ШиринаТаблицы;
// Обходим ячейки в цикле
Для Строка = 1 По ВысотаТаблицы Цикл
Для Колонка = 1 По ШиринаТаблицы Цикл
ЗначениеЯчейки = ТабДок.Область(Строка, Колонка).Текст;
// Выполняем обработку полученного значения...
КонецЦикла;
КонецЦикла;
Исключение
ЗаписьЖурналаРегистрации("ИмпортДанных", УровеньЖурналаРегистрации.Ошибка,,,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Не удалось прочитать файл Excel: " + ОписаниеОшибки();
КонецПопытки;
Этот подход решает проблему раз и навсегда, избавляя системных администраторов от необходимости настройки DCOM и покупки дополнительных лицензий Microsoft Office для сервера.
Если вам требуется высокая скорость чтения больших объемов данных из файлов Excel на Windows-сервере, хорошей альтернативой станет использование ADO. Данная технология позволяет обращаться к листам Excel как к таблицам реляционной базы данных с помощью привычных SQL-запросов.
Для работы этого метода на сервере не нужен сам Excel, достаточно установить бесплатный легковесный драйвер Microsoft Access Database Engine.
Посмотрим на пример реализации чтения данных через ADO:
// Инициализируем соединение ADO
Connection = Новый COMОбъект("ADODB.Connection");
Recordset = Новый COMОбъект("ADODB.Recordset");
// Строка подключения для работы с файлами XLSX
СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ПутьКФайлу + ";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";";
Попытка
Connection.Open(СтрокаПодключения);
// Запрос к первому листу книги Excel (имя листа должно оканчиваться знаком $)
ТекстЗапроса = "SELECT * FROM [Лист1$]";
Recordset.Open(ТекстЗапроса, Connection);
Пока Recordset.EOF() = Ложь Цикл
// Обработка данных строки
ПерваяКолонка = Recordset.Fields.Item(0).Value;
ВтораяКолонка = Recordset.Fields.Item(1).Value;
Recordset.MoveNext();
КонецЦикла;
Recordset.Close();
Connection.Close();
Исключение
// Обязательно закрываем соединения в случае ошибок
Если Recordset.State = 1 Тогда
Recordset.Close();
КонецЕсли;
Если Connection.State = 1 Тогда
Connection.Close();
КонецЕсли;
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
Ошибка подключения к COM-объекту Excel в 1С чаще всего кроется в несоответствии окружения: разрядности серверного процесса 1С и офисного пакета, а также в ограничениях прав доступа учетной записи службы. Для решения проблемы в рамках COM-технологии требуется внимательная настройка DCOM-прав через утилиту comexp.msc и подготовка папок окружения.
Тем не менее, лучшим решением в современных реалиях является плавный переход на встроенные кроссплатформенные методы платформы 1С:Предприятие (использование ТабличныйДокумент.Прочитать), которые избавят вашу систему от архитектурных зависимостей, повысят отказоустойчивость серверов и ускорят обработку документов.