Работа с файлами Microsoft Excel в среде веб-клиента 1С часто преподносит неприятные сюрпризы разработчикам. Код, который годами безупречно функционировал в файловом режиме или тонком клиенте, при попытке запуска через браузер может просто «зависнуть» или прекратить выполнение без каких-либо диагностических сообщений. В этой статье мы проанализируем, почему так происходит, и рассмотрим наиболее надежные способы чтения данных Excel, которые будут работать в любых условиях.
Традиционный подход к чтению Excel через COMОбъект("Excel.Application") имеет ряд критических ограничений при работе через веб-сервер. Давайте разберем основные причины возникновения проблем:
Desktop в профиле системной учетной записи).C:\MyFiles\data.xls. Файл необходимо сначала интерактивно выбрать, поместить во временное хранилище и только потом передать на сервер.Рассмотрим, как правильно организовать работу, если вы все же решили использовать COM, и какие есть более современные альтернативы.
Первым делом проанализируем ситуацию с передачей файла. В веб-клиенте метод ПоместитьФайл в неинтерактивном режиме работать не будет. Нам необходимо использовать современные асинхронные методы платформы. Рассмотрим правильную последовательность действий на стороне клиента и сервера.
На стороне клиента мы должны получить двоичные данные файла и отправить их во временное хранилище:
&НаКлиенте
Процедура ЗагрузитьФайлExcel(Команда)
// В веб-клиенте мы не можем напрямую обратиться к пути на диске пользователя
// Поэтому используем диалог выбора файла
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтаФорма);
ПараметрыЗагрузки = Новый ПараметрыДиалогаПомещенияФайлов;
НачатьПомещениеФайлаНаСервер(Оповещение, , , , , ПараметрыЗагрузки, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат;
КонецЕсли;
// Адрес во временном хранилище получен, теперь вызываем серверную процедуру
ЧтениеЕксельНаСервере(Результат.Адрес);
КонецПроцедуры
Проанализируем самый надежный способ, который рекомендует сообщество и сама фирма 1С. Это использование объекта ТабличныйДокумент. Этот метод не требует установленного Microsoft Office на сервере, работает значительно быстрее и стабильнее в веб-клиенте.
Разберем по шагам, как прочитать данные из временного хранилища и преобразовать их в таблицу значений:
&НаСервере
Процедура ЧтениеЕксельНаСервере(АдресФайла)
// Создаем временное имя файла на сервере с правильным расширением
ВременныйФайл = ПолучитьИмяВременногоФайла("xlsx");
// Извлекаем данные из хранилища
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайла);
ДвоичныеДанные.Записать(ВременныйФайл);
// Читаем файл в табличный документ 1С
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ВременныйФайл, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Определяем границы данных
ВсегоСтрок = ТабДок.ВысотаТаблицы;
ВсегоКолонок = ТабДок.ШиринаТаблицы;
Если ВсегоСтрок = 0 Тогда
Сообщить("Файл пуст!");
Возврат;
КонецЕсли;
// Рассмотрим быстрый способ переноса данных в Таблицу Значений через Построитель
Построитель = Новый ПостроительЗапроса;
// Указываем область данных (вся таблица)
ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область(1, 1, ВсегоСтрок, ВсегоКолонок));
Построитель.ИсточникДанных = ИсточникДанных;
Построитель.Выполнить();
ТаблицаРезультат = Построитель.Результат.Выгрузить();
// Теперь у нас есть ТаблицаЗначений, с которой удобно работать
Для Каждого СтрокаДанных Из ТаблицаРезультат Цикл
// Обработка данных
// Например: НоваяСтрока = Объект.ДанныеЗагрузки.Добавить();
// ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных);
КонецЦикла;
// Не забываем удалять временный файл
УдалитьФайлы(ВременныйФайл);
КонецПроцедуры
Преимущества этого метода: мы полностью избавляемся от зависимости от COM-технологии. Код будет одинаково успешно работать и на Windows-сервере, и на Linux-сервере, а также не потребует лицензий на MS Office для сервера.
Если специфика задачи требует именно использования 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-объекты на стороне сервера, проанализируйте следующие настройки вашей ОС:
USR1CV8), есть полные права на чтение и запись в каталоге временных файлов.dcomcnfg проверьте настройки для компонента Microsoft Excel Application. На вкладке «Удостоверение» лучше всего указать конкретного пользователя с правами администратора, а не «Запускающий пользователь».Excel.Quit(). В веб-клиенте процессы могут «зависать» в памяти сервера, что со временем приведет к нехватке ресурсов и падению всего сервера 1С.Подводя итог, можно сказать, что для веб-клиента наиболее оптимальным и современным решением является использование объекта ТабличныйДокумент в сочетании с ПостроителемЗапроса. Это гарантирует стабильную работу системы и избавляет от сложностей администрирования серверного окружения.