При интеграции систем автоматизации с внешними источниками данных разработчики часто сталкиваются с необходимостью загрузки информации из файлов Microsoft Excel. Одним из классических методов решения этой задачи является использование механизма Automation (COM-объектов). Однако при попытке инициализации объекта Excel.Application код нередко аварийно завершается.
В этой статье мы подробно разберем, почему возникает ошибка "Invalid class string (0x800401F3)", научимся правильно настраивать операционную систему для работы COM-объектов на стороне сервера, а также рассмотрим современные, более быстрые и кроссплатформенные альтернативы загрузки файлов Excel, которые вообще не требуют наличия установленного Microsoft Office на компьютере.
Данный сбой происходит на этапе инициализации объекта операционной системы Windows. Когда мы пишем в коде 1С конструкцию:
Эксель = New COMObject("Excel.Application");
Платформа обращается к системному реестру Windows, чтобы найти зарегистрированный класс с идентификатором (ProgID) Excel.Application и запустить соответствующее приложение. Если операционная система возвращает ошибку с кодом 0x800401F3 (Недопустимая строка класса), это означает, что запись о таком классе в реестре отсутствует или недоступна для текущего процесса.
Проанализируем основные причины, из-за которых это происходит:
USR1CV8) или системной учетной записи Network Service. У этих учетных записей по умолчанию нет прав на запуск и активацию локальных COM-серверов.Рассмотрим по шагам решения для каждого сценария.
Если на сервере установлен Microsoft Office, но код на сервере все равно падает с ошибкой, выполним тонкую настройку службы DCOM. Это позволит 64-битному серверу 1С корректно работать с 32-битным Excel.
Шаг 1. Регистрация связи в системном реестре. Нам необходимо явно связать класс Excel с его идентификатором приложения. Для этого запустим редактор реестра regedit и перейдем в ветку:
HKEY_CLASSES_ROOT\AppID\
Создадим новый раздел с именем EXCEL.EXE. Внутри этого раздела создадим строковый параметр (String Value) с именем AppID и значением ID класса Excel: {00020812-0000-0000-C000-000000000046}.
Шаг 2. Запуск консоли настройки служб компонентов. На 64-битных операционных системах стандартная оснастка DCOM может не отображать 32-битные приложения. Чтобы увидеть их, запустим консоль специальной командой через меню "Выполнить" (Win + R):
mmc comexp.msc /32
Шаг 3. Настройка прав доступа. В открывшемся окне перейдем по пути: "Службы компонентов" — "Компьютеры" — "Мой компьютер" — "Настройка DCOM". Найдем в списке элемент Microsoft Excel Application (или "Документ Microsoft Excel"), откроем его свойства правой кнопкой мыши:
USR1CV8) и предоставим ему полные права: локальный запуск, удаленный запуск, локальная активация, удаленная активация.Шаг 4. Создание системных папок Desktop. Это важнейший "фокус", без которого Excel откажется открывать файлы в фоновом режиме сервера. Нам необходимо вручную создать пустые папки Desktop, чтобы у системного профиля была имитация рабочего стола:
C:\Windows\SysWOW64\config\systemprofile\DesktopC:\Windows\System32\config\systemprofile\DesktopОбязательно предоставим пользователю службы 1С (USR1CV8) полные права (Read/Write) на эти папки.
После проведения этих настроек и перезапуска службы сервера 1С, вызов New COMObject("Excel.Application") начнет работать стабильно.
Использование COM-объектов имеет огромные недостатки: низкая скорость работы, жесткая привязка к операционной системе Windows, необходимость покупки лицензий MS Office для сервера, утечки памяти при незакрытых процессах excel.exe.
Начиная с платформы 1С:Предприятие 8.3, разработчикам доступен нативный механизм чтения файлов Excel без использования каких-либо сторонних библиотек. Объект ТабличныйДокумент умеет самостоятельно открывать и парсить файлы форматов .xls и .xlsx прямо на сервере (в том числе под управлением Linux!).
Рассмотрим, как переписать исходный код автора темы на использование табличного документа:
// Создаем новый табличный документ на сервере
ТабДок = Новый ТабличныйДокумент;
Попытка
// Читаем файл Excel напрямую в табличный документ
ТабДок.Прочитать("C:\Программист\1.xlsx");
Исключение
ВызватьИсключение "Не удалось прочитать файл! Ошибка: " + ОписаниеОшибки();
КонецПопытки;
// Получаем границы заполненной области
КоличествоСтрок = ТабДок.ВысотаТаблицы;
КоличествоКолонок = ТабДок.ШиринаТаблицы;
// Обходим строки и выводим данные из второй колонки
Для НомерСтроки = 1 По КоличествоСтрок Цикл
// Метод Область() возвращает ячейку, свойство Текст - ее строковое представление
ЗначениеЯчейки = ТабДок.Область(НомерСтроки, 2).Текст;
Сообщить(ЗначениеЯчейки);
КонецЦикла;
Преимущества этого подхода очевидны: этот код будет работать быстрее, запустится на сервере без установленного Excel, не требует настройки реестра DCOM и отлично отработает как на Windows, так и на Linux.
Если файл Excel содержит десятки тысяч строк, обход ячеек табличного документа в цикле Для НомерСтроки = 1 По КоличествоСтрок может занять значительное время. Выясним, как оптимизировать этот процесс.
Существует продвинутый и очень элегантный способ прочитать весь Excel-файл и преобразовать его в стандартную ТаблицуЗначений в памяти буквально за доли секунды без единого цикла! Для этого мы применим класс ПостроительЗапроса.
Разберем этот алгоритм по шагам:
// 1. Инициализируем и читаем документ
ТабДок = Новый ТабличныйДокумент;
// Важно использовать СпособЧтенияЗначенийТабличногоДокумента.Значение, чтобы сохранить типы данных (числа, даты)
ТабДок.Прочитать("C:\Программист\1.xlsx", СпособЧтенияЗначенийТабличногоДокумента.Значение);
// 2. Создаем построитель запроса
Построитель = Новый ПостроительЗапроса;
// 3. Передаем область заполненных ячеек табличного документа в качестве источника данных
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
// 4. Выполняем построение и выгружаем результат в Таблицу Значений
Построитель.Выполнить();
ТаблицаДанных = Построитель.Результат.Выгрузить();
// Теперь переменная ТаблицаДанных содержит готовую таблицу значений с колонками из Excel!
// Мы можем быстро обработать ее стандартными методами или запросом
Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
// Обработка данных
КонецЦикла;
Этот метод работает на аппаратном уровне платформы 1С и позволяет считывать файлы размером в 50 000 строк практически мгновенно. Это идеальное решение для загрузки больших прайс-листов или складских остатков.
Еще один профессиональный метод интеграции с файлами Excel — использование механизма Внешних источников данных в платформе 1С. Этот способ позволяет отправлять SQL-запросы к листам Excel-файла прямо из кода 1С, используя стандартный драйвер ODBC (Microsoft Access Database Engine).
Как это настроить:
ЗагрузкаИзExcel.[Лист1$].
// Строка подключения через ODBC драйвер
СтрокаПодключения = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=C:\Программист\1.xlsx;";
// Устанавливаем соединение
ВнешниеИсточникиДанных.ЗагрузкаИзExcel.УстановитьОбщиеПараметрыСоединения(СтрокаПодключения);
ВнешниеИсточникиДанных.ЗагрузкаИзExcel.УстановитьСоединение();
// Выполняем привычный запрос к таблице внешнего источника
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ExcelТаблица.Артикул КАК Артикул,
| ExcelТаблица.Цена КАК Цена
|ИЗ
| ВнешнийИсточникДанных.ЗагрузкаИзExcel.Таблица.Лист1 КАК ExcelТаблица";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Обрабатываем полученные строки
КонецЦикла;
Данный подход незаменим, когда в файле Excel хранятся огромные массивы структурированных табличных данных и нам нужно на лету делать соединения (LEFT JOIN) с существующими справочниками базы данных 1С.
Подведем итоги нашего анализа:
Desktop для системного профиля.Excel.Application) везде, где это возможно. Это устаревший, медленный и платформозависимый подход.ТабличныйДокумент.Прочитать() для простых задач загрузки данных. Это безопасно, надежно и работает на серверах Linux.ТабличныйДокумент с ПостроителемЗапроса — это ускорит импорт данных в сотни раз.