Как прочитать файл Excel в веб-клиенте 1С и почему не работает COM-объект?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с файлами Microsoft Excel в среде веб-клиента 1С часто преподносит неприятные сюрпризы разработчикам. Код, который годами безупречно функционировал в файловом режиме или тонком клиенте, при попытке запуска через браузер может просто «зависнуть» или прекратить выполнение без каких-либо диагностических сообщений. В этой статье мы проанализируем, почему так происходит, и рассмотрим наиболее надежные способы чтения данных Excel, которые будут работать в любых условиях.

Почему классический COM-метод дает сбой в Веб-клиенте?

Традиционный подход к чтению Excel через COMОбъект("Excel.Application") имеет ряд критических ограничений при работе через веб-сервер. Давайте разберем основные причины возникновения проблем:

  1. Окружение серверного процесса: Когда код выполняется на стороне сервера (а в веб-клиенте это происходит всегда при передаче файла), Excel запускается от имени пользователя, под которым работает служба веб-сервера (например, IIS или Apache). У этого пользователя часто нет прав на запуск графических приложений или отсутствуют необходимые системные папки (например, папка Desktop в профиле системной учетной записи).
  2. Интерактивные окна: Если Excel при открытии файла захочет задать вопрос о битых ссылках, обновлении связей или несовпадении форматов, он выведет диалоговое окно в «невидимой» сессии на сервере. Процесс будет бесконечно ждать ответа пользователя, который никто никогда не увидит.
  3. Особенности передачи файлов: В веб-клиенте нельзя просто указать путь к локальному диску C:\MyFiles\data.xls. Файл необходимо сначала интерактивно выбрать, поместить во временное хранилище и только потом передать на сервер.

Рассмотрим, как правильно организовать работу, если вы все же решили использовать COM, и какие есть более современные альтернативы.

Метод 1. Настройка передачи файла на сервер

Первым делом проанализируем ситуацию с передачей файла. В веб-клиенте метод ПоместитьФайл в неинтерактивном режиме работать не будет. Нам необходимо использовать современные асинхронные методы платформы. Рассмотрим правильную последовательность действий на стороне клиента и сервера.

На стороне клиента мы должны получить двоичные данные файла и отправить их во временное хранилище:


&НаКлиенте
Процедура ЗагрузитьФайлExcel(Команда)
    
    // В веб-клиенте мы не можем напрямую обратиться к пути на диске пользователя
    // Поэтому используем диалог выбора файла
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтаФорма);
    ПараметрыЗагрузки = Новый ПараметрыДиалогаПомещенияФайлов;
    НачатьПомещениеФайлаНаСервер(Оповещение, , , , , ПараметрыЗагрузки, УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораФайла(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Адрес во временном хранилище получен, теперь вызываем серверную процедуру
    ЧтениеЕксельНаСервере(Результат.Адрес);
    
КонецПроцедуры

Метод 2. Чтение через Табличный документ (Нативный способ)

Проанализируем самый надежный способ, который рекомендует сообщество и сама фирма 1С. Это использование объекта ТабличныйДокумент. Этот метод не требует установленного Microsoft Office на сервере, работает значительно быстрее и стабильнее в веб-клиенте.

Разберем по шагам, как прочитать данные из временного хранилища и преобразовать их в таблицу значений:


&НаСервере
Процедура ЧтениеЕксельНаСервере(АдресФайла)
    
    // Создаем временное имя файла на сервере с правильным расширением
    ВременныйФайл = ПолучитьИмяВременногоФайла("xlsx");
    
    // Извлекаем данные из хранилища
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайла);
    ДвоичныеДанные.Записать(ВременныйФайл);
    
    // Читаем файл в табличный документ 1С
    ТабДок = Новый ТабличныйДокумент;
    Попытка
        ТабДок.Прочитать(ВременныйФайл, СпособЧтенияЗначенийТабличногоДокумента.Значение);
    Исключение
        Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    // Определяем границы данных
    ВсегоСтрок = ТабДок.ВысотаТаблицы;
    ВсегоКолонок = ТабДок.ШиринаТаблицы;
    
    Если ВсегоСтрок = 0 Тогда
        Сообщить("Файл пуст!");
        Возврат;
    КонецЕсли;
    
    // Рассмотрим быстрый способ переноса данных в Таблицу Значений через Построитель
    Построитель = Новый ПостроительЗапроса;
    // Указываем область данных (вся таблица)
    ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область(1, 1, ВсегоСтрок, ВсегоКолонок));
    Построитель.ИсточникДанных = ИсточникДанных;
    Построитель.Выполнить();
    
    ТаблицаРезультат = Построитель.Результат.Выгрузить();
    
    // Теперь у нас есть ТаблицаЗначений, с которой удобно работать
    Для Каждого СтрокаДанных Из ТаблицаРезультат Цикл
        // Обработка данных
        // Например: НоваяСтрока = Объект.ДанныеЗагрузки.Добавить();
        // ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных);
    КонецЦикла;
    
    // Не забываем удалять временный файл
    УдалитьФайлы(ВременныйФайл);
    
КонецПроцедуры

Преимущества этого метода: мы полностью избавляемся от зависимости от COM-технологии. Код будет одинаково успешно работать и на Windows-сервере, и на Linux-сервере, а также не потребует лицензий на MS Office для сервера.

Метод 3. Нюансы работы с COM в Веб-среде (если нельзя иначе)

Если специфика задачи требует именно использования COMОбъект (например, нужно читать сложные формулы или макросы), выясним причину, по которой код автора из примера Excel.WorkBooks.Open(ВыбФайл) может не работать.

Обратите внимание на тип переменной ВыбФайл. В коде автора это объект типа Файл. Метод Open приложения Excel ожидает на вход строку (полный путь к файлу), а не объект 1С. В обычном клиенте 1С может произвести неявное преобразование типов, но на сервере в веб-клиенте это часто приводит к ошибке. Правильно передавать строковую переменную:


// Ошибка автора: Excel.WorkBooks.Open(ВыбФайл); 
// Где ВыбФайл = Новый Файл(...);

// Правильный вариант:
ИмяФайлаНаСервере = ПолучитьИмяВременногоФайла("xls");
ФайлНаСервере = ПолучитьИзВременногоХранилища(АдресФайла);
ФайлНаСервере.Записать(ИмяФайлаНаСервере);

Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь; // Отключаем все диалоги
Попытка
    Excel.Workbooks.Open(ИмяФайлаНаСервере); // Передаем СТРОКУ пути
    // Дальнейшая логика...
Исключение
    // Обязательно закрываем Excel при ошибке
    Excel.Quit();
    ВызватьИсключение;
КонецПопытки;

Важные рекомендации по настройке сервера

Если вы продолжаете использовать COM-объекты на стороне сервера, проанализируйте следующие настройки вашей ОС:

Подводя итог, можно сказать, что для веб-клиента наиболее оптимальным и современным решением является использование объекта ТабличныйДокумент в сочетании с ПостроителемЗапроса. Это гарантирует стабильную работу системы и избавляет от сложностей администрирования серверного окружения.

← На главную