При работе с 1С в облачных сервисах (например, scloud.ru) или на серверах под управлением ОС Linux, разработчики часто сталкиваются с проблемой — для её решения есть универсальная загрузка и обновление данных XLSX для Linux-серверов. Привычный способ чтения Excel-файлов через COM-объект, который отлично работает на локальной машине с Windows, перестает функционировать и выдает ошибку: «COM-объекты поддерживается только в операционных системах Windows». Это происходит потому, что технология COM является эксклюзивной для Windows.
Рассмотрим, как правильно организовать чтение Excel-файла в такой среде, используя встроенные средства платформы 1С и соблюдая принципы клиент-серверной архитектуры.
Основная ошибка заключается в попытке использовать Новый COMОбъект("Excel.Application") на сервере, где не установлен MS Excel или операционная система не является Windows. Платформа 1С предоставляет кросс-платформенный инструмент для работы с табличными данными — объект ТабличныйДокумент, для работы с которым создана обработка импорта Excel в справочники через ТабличныйДокумент.
Этот объект способен напрямую читать файлы форматов .xls и .xlsx без привлечения внешних компонент или самого Excel — на этом принципе построена универсальная обработка загрузки и обновления из Excel для 1С. Метод Прочитать() загружает содержимое файла в табличный документ 1С, после чего данные можно обрабатывать.
Проанализируем базовый код для чтения файла на сервере:
&НаСервере
Функция ПрочитатьExcel_ПостроительЗапроса(ПутьКФайлуЗагрузкиExcel)
ТабДок = Новый ТабличныйДокумент;
ФайлExcel = Новый Файл(ПутьКФайлуЗагрузкиExcel);
Если ФайлExcel.Существует() Тогда
ТабДок.Прочитать(ПутьКФайлуЗагрузкиExcel);
// Преобразуем данные в ТаблицуЗначений с помощью ПостроителяЗапроса
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
Построитель.ЗаполнитьНастройки();
Построитель.Выполнить();
ТаблицаИзExcel = Построитель.Результат.Выгрузить();
Иначе
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не удалось прочитать файл по причине: файл не найден";
Сообщение.Сообщить();
Возврат Неопределено;
КонецЕсли;
Возврат ТаблицаИзExcel;
КонецФункции
Этот код отлично сработает, но только при одном условии: файл по пути ПутьКФайлуЗагрузкиExcel должен быть физически доступен серверу 1С. В облачной среде или при стандартной клиент-серверной работе файл, который пользователь выбирает на своем компьютере, находится на клиенте, и сервер не имеет к нему прямого доступа. Это приводит нас ко второй, не менее важной части задачи.
Чтобы сервер смог обработать файл, его нужно сначала передать с клиентской машины на сервер. Для этого в 1С существует стандартный механизм работы с временным хранилищем.
Посмотрим на пошаговый процесс:
Этот механизм реализован с помощью асинхронных вызовов, чтобы не блокировать интерфейс пользователя на время передачи файла. Разберем код, который реализует эту логику.
Шаг 1. Код на стороне клиента
Создадим команду, которая будет запускать процесс выбора и загрузки файла. Для этого используем метод НачатьПомещениеФайла и передадим в него ОписаниеОповещения — это указание, какую процедуру нужно вызвать после завершения операции.
&НаКлиенте
Процедура ПрочитатьExcelВТЗ(Команда)
// Описываем процедуру, которая будет вызвана после выбора и помещения файла
ОбработкаОкончанияПомещения = Новый ОписаниеОповещения(
"ОбработчикОкончанияПомещения", ЭтотОбъект);
// Запускаем стандартный диалог выбора файла и его передачу на сервер
НачатьПомещениеФайла(ОбработкаОкончанияПомещения, ,
ПутьЗагрузки, Ложь, ЭтотОбъект.УникальныйИдентификатор);
КонецПроцедуры
Шаг 2. Клиентский обработчик результата
Теперь создадим ту самую процедуру-обработчик, которую мы указали в ОписаниеОповещения. Она выполнится, когда файл будет помещен во временное хранилище. В нее платформа передаст результат (успех/неудача) и адрес данных в хранилище.
&НаКлиенте
Процедура ОбработчикОкончанияПомещения(Результат, Адрес,
ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Результат Тогда
// Если файл успешно помещен, вызываем серверную процедуру для его обработки
// и передаем ей адрес данных в хранилище
ПрочитатьExcelВТЗНаСервере(Адрес);
Иначе
Сообщить("Файл не был помещен.");
КонецЕсли
КонецПроцедуры
Мы подошли к финальному этапу: серверной обработке файла, который был передан с клиента. Серверная процедура получает адрес, извлекает по нему двоичные данные файла, сохраняет их во временный файл уже на сервере и затем читает с помощью ТабличныйДокумент.
Посмотрим на полный серверный код:
&НаСервере
Процедура ПрочитатьExcelВТЗНаСервере(АдресВХранилище)
// Вызываем нашу функцию чтения, передав ей адрес из временного хранилища
ВремТЗ = ПрочитатьExcel_ПостроительЗапроса(АдресВХранилище);
Если ТипЗнч(ВремТЗ) = Тип("ТаблицаЗначений") Тогда
// Далее выполняем полезную работу с полученной таблицей значений
// Например, загружаем в табличную часть документа
ЗагрузитьТЗВТЧ(ВремТЗ);
КонецЕсли
КонецПроцедуры
&НаСервере
Функция ПрочитатьExcel_ПостроительЗапроса(АдресФайлаВХранилище)
// 1. Получаем двоичные данные файла из временного хранилища
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресФайлаВХранилище);
// Проверяем, что данные получены
Если ДвоичныеДанныеФайла = Неопределено Тогда
// Обработка ошибки
Возврат Неопределено;
КонецЕсли;
// 2. Создаем временный файл на сервере
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанныеФайла.Записать(ИмяВременногоФайла);
// Можно сразу удалить данные из временного хранилища, чтобы освободить память
УдалитьИзВременногоХранилища(АдресФайлаВХранилище);
ТабДок = Новый ТабличныйДокумент;
// 3. Читаем данные из временного файла на сервере
Попытка
ТабДок.Прочитать(ИмяВременногоФайла);
Исключение
// Обработка ошибки чтения файла
Сообщить("Не удалось прочитать файл Excel. " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
// 4. Удаляем временный файл с диска сервера
УдалитьФайлы(ИмяВременногоФайла);
// 5. Преобразуем данные в ТаблицуЗначений
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
Построитель.ЗаполнитьНастройки();
Построитель.Выполнить();
ТаблицаИзExcel = Построитель.Результат.Выгрузить();
Возврат ТаблицаИзExcel;
КонецФункции
Таким образом, мы реализовали полный, корректный и надежный механизм загрузки Excel-файла в облачной среде 1С. Мы отказались от неподдерживаемой технологии COM и использовали стандартные платформенные объекты, учитывая особенности клиент-серверного взаимодействия. Для этой задачи есть обработка универсальной загрузки из Excel в любые документы и справочники.
Несмотря на свою универсальность, метод чтения через ТабличныйДокумент имеет некоторые особенности, о которых стоит помнить:
ТабличныйДокумент не сможет его прочитать. Необходимо предварительно снять защиту.