Работа с файлами Excel (загрузка прайсов, накладных, списков номенклатуры) — одна из самых частых задач в практике программиста 1С. Часто для этих целей используется готовый шаблон простой обработки загрузки из excel, который позволяет быстро набросать код. Однако при переходе кода с клиента на сервер или при обновлении платформы часто возникают специфические ошибки. В этой статье мы подробно разберем ситуацию, когда при попытке прочитать Excel на стороне сервера возникают ошибки "Недопустимая строка с указанием класса" и проблемы с поиском файла по адресу временного хранилища.
Мы проанализируем причины возникновения этих ошибок, рассмотрим механизмы взаимодействия 1С и внешних приложений через COM, а также изучим правильные алгоритмы передачи файлов с клиента на сервер для последующей обработки.
Первая проблема, с которой мы можем столкнуться при запуске серверного кода, — это ошибка при инициализации объекта приложения Excel. Код выглядит следующим образом:
Попытка
Эксель = Новый COMОбъект("Excel.Application");
Исключение
// Обработка ошибки
КонецПопытки;
Если в этот момент система выдает ошибку "Недопустимая строка с указанием класса 0x800401F3" (Invalid class string), это однозначно указывает на проблемы с доступностью OLE/COM сервера Excel в текущем контексте. В редких случаях разработчики даже используют альтернативные технологии, например, COM объект на Python для 1С, чтобы обойти ограничения стандартного офисного пакета. Но чаще всего стоит проверить базовые настройки.
dcomcnfg, обеспечив доступ пользователю, от имени которого запущена служба 1С.systemprofile для корректной работы Excel в фоновом режиме.Важно помнить: использование COM-объектов возможно только в среде Windows. Если ваш сервер 1С развернут на Linux, технология работать не будет.
После устранения проблем с запуском Excel часто возникает вторая ошибка. Сценарий: пользователь выбирает файл на клиенте, мы помещаем его в хранилище и передаем адрес на сервер. Чтобы не запутаться в этом процессе, полезно изучить общие принципы того, как реализовано копирование файлов и каталогов между Клиентом и Сервером.
Неправильный код на сервере часто выглядит так:
&НаСервере
Процедура ОбработатьФайл(АдресВоВременномХранилище)
Эксель = Новый COMОбъект("Excel.Application");
// ОШИБКА ЗДЕСЬ: Excel не понимает адреса 1С
Книга = Эксель.Workbooks.Open(АдресВоВременномХранилище);
КонецПроцедуры
При выполнении этого кода мы получим сообщение: "Произошла исключительная ситуация (Microsoft Excel): К сожалению, нам не удалось найти файл e1cib/tempstorage/...".
Адрес e1cib/tempstorage/... — это внутренняя ссылка 1С. Процесс excel.exe ничего не знает об этом и ожидает получить физический путь к файлу на диске.
Чтобы внешнее приложение могло открыть файл, мы должны материализовать данные из хранилища. Рассмотрим корректную процедуру:
&НаСервере
Процедура Префикс_ЗаполнитьСуммыИзЭксельВместоНаСервере(АдресФайлаВоВременномХранилище)
ПутьКФайлу = ПолучитьИмяВременногоФайла("xlsx");
ДанныеИзХранилища = ПолучитьИзВременногоХранилища(АдресФайлаВоВременномХранилище);
Если ДанныеИзХранилища <> Неопределено Тогда
ДанныеИзХранилища.Записать(ПутьКФайлу);
КонецЕсли;
Попытка
Эксель = Новый COMОбъект("Excel.Application");
Эксель.DisplayAlerts = 0;
Книга = Эксель.Workbooks.Open(ПутьКФайлу);
ТекЛист = Книга.WorkSheets(1);
Данные = ТекЛист.UsedRange.Value;
Книга.Close(Ложь);
Эксель.Quit();
Исключение
Если Эксель <> Неопределено Тогда Эксель.Quit(); КонецЕсли;
ЗаписьЖурналаРегистрации("ЗагрузкаExcel", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
УдалитьФайлы(ПутьКФайлу);
КонецПроцедуры
Использование COM сегодня часто считается избыточным. Платформа предоставляет мощный объект ТабличныйДокумент, который умеет читать файлы .xls, .xlsx и .ods напрямую. Это намного стабильнее и быстрее. Для комплексных задач можно использовать универсальный импорт данных из различных форматов или применить портативную обработку чтения файла в таблицу или дерево значений, что значительно упрощает отладку.
Посмотрим, как можно реализовать чтение без COM:
&НаСервере
Процедура ЗагрузитьЧерезТабличныйДокумент(АдресФайлаВоВременномХранилище)
ПутьКФайлу = ПолучитьИмяВременногоФайла("xlsx");
Данные = ПолучитьИзВременногоХранилища(АдресФайлаВоВременномХранилище);
Данные.Записать(ПутьКФайлу);
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
Сообщить("Не удалось прочитать файл: " + ОписаниеОшибки());
УдалитьФайлы(ПутьКФайлу);
Возврат;
КонецПопытки;
УдалитьФайлы(ПутьКФайлу);
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
ЗначениеЯчейки = ТабДок.Область(НомерСтроки, 1).Текст;
// Обработка данных...
КонецЦикла;
КонецПроцедуры
ТабличныйДокумент, так как он кроссплатформенный. Если вам нужна готовая реализация для импорта в любой справочник, обратите внимание на обработку для импорта данных, которая поддерживает множество форматов.