Как изменить или конвертировать файл из XLS в PDF при использовании метода НачатьПомещениеФайлаНаСервер?

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

При разработке интерфейсов на управляемых формах часто возникает задача не просто загрузить файл на сервер, но и предварительно его обработать. Например, пользователь выбирает счет в формате Excel (XLS или XLSX), а система должна автоматически преобразовать его в PDF для единообразного хранения или печати. В этой статье мы подробно разберем, почему нельзя изменить файл «на лету» в момент выбора, и как правильно реализовать цепочку событий для достижения нужного результата.

Анализ проблемы: почему нельзя использовать ПередНачаломОбратныйВызов

Рассмотрим стандартный механизм асинхронного помещения файла. Метод НачатьПомещениеФайлаНаСервер() принимает несколько описаний оповещений, включая событие ПередНачаломОбратныйВызов. На первый взгляд кажется, что именно здесь можно перехватить выбранный файл и подменить его. Однако проанализируем технические ограничения платформы:

  1. Объект СсылкаНаФайл, который передается в это событие, предназначен только для чтения метаданных (имя, расширение, размер).
  2. Платформа к этому моменту уже заблокировала файл для передачи.
  3. Метод спроектирован для валидации: если файл слишком большой или имеет запрещенное расширение, мы можем установить Отказ = Истина, но не подменить содержимое.

Следовательно, правильная стратегия заключается в том, чтобы позволить файлу переместиться во временное хранилище, а затем обработать его на стороне сервера в обработчике завершения.

Пошаговый алгоритм решения задачи

Разберем процесс трансформации файла по шагам. Нам необходимо выполнить следующие действия:

  1. Инициировать выбор и загрузку файла на клиенте.
  2. В процедуре завершения проверить расширение файла.
  3. Если файл требует конвертации, передать адрес временного хранилища на сервер.
  4. На сервере прочитать данные в ТабличныйДокумент и сохранить их в новом формате.
  5. Очистить временное хранилище от исходного «мусорного» файла.

Реализация клиентской части

Сначала подготовим процедуру запуска выбора файла. Мы будем использовать ПараметрыДиалогаПомещенияФайлов, чтобы ограничить выбор только нужными нам форматами.


Процедура ЗагрузитьСчетНаФорме()
    
    ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
    ПараметрыДиалога.МножественныйВыбор = Ложь;
    ПараметрыДиалога.Заголовок = "Выберите файл со сканом счета";
    ПараметрыДиалога.Фильтр = "Файлы Excel (*.xls;*.xlsx)|*.xls;*.xlsx|Файл PDF (*.pdf)|*.pdf";
    
    ЗавершениеОбратныйВызов = Новый ОписаниеОповещения("ПослеЗагрузкиФайла", ЭтотОбъект);
    
    НачатьПомещениеФайлаНаСервер(ЗавершениеОбратныйВызов, , , , ПараметрыДиалога, ЭтаФорма.УникальныйИдентификатор);
    
КонецПроцедуры

Обратите внимание, что мы передаем УникальныйИдентификатор формы. Это критически важно: данные во временном хранилище будут «жить» до тех пор, пока открыта форма, что позволит нам манипулировать ими без риска преждевременного удаления.

Обработка результата и серверная конвертация

Теперь проанализируем процедуру оповещения ПослеЗагрузкиФайла. Если пользователь выбрал XLS, мы должны запустить процесс конвертации.


&НаКлиенте
Процедура ПослеЗагрузкиФайла(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    АдресВХ = Результат.Адрес;
    Расширение = Результат.СсылкаНаФайл.Расширение;
    
    Если НРег(Расширение) = ".xls" Или НРег(Расширение) = ".xlsx" Тогда
        // Запускаем серверную конвертацию
        НовыйАдресPDF = КонвертироватьXLSвPDFНаСервере(АдресВХ, Расширение);
        АдресВХ = НовыйАдресPDF;
    КонецЕсли;
    
    // Дальнейшая логика записи адреса в справочник или документ
    ЗаписатьФайлВБазу(АдресВХ);
    
КонецПроцедуры

Рассмотрим подробнее серверную функцию. Основным инструментом здесь выступает ТабличныйДокумент. Он обладает мощным методом Прочитать(), который понимает форматы Excel, и методом Записать(), умеющим сохранять результат в PDF.


&НаСервере
Функция КонвертироватьXLSвPDFНаСервере(Знач ИсходныйАдрес, Знач Расширение)
    
    // 1. Получаем двоичные данные из хранилища
    ДанныеExcel = ПолучитьИзВременногоХранилища(ИсходныйАдрес);
    
    // 2. Создаем временный файл на диске сервера для чтения
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла(Расширение);
    ДанныеExcel.Записать(ИмяВременногоФайла);
    
    // 3. Читаем файл в табличный документ
    ТабДок = Новый ТабличныйДокумент;
    Попытка
        ТабДок.Прочитать(ИмяВременногоФайла);
    Исключение
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка чтения файла Excel: " + ОписаниеОшибки());
        Возврат ИсходныйАдрес;
    КонецПопытки;
    
    // 4. Настраиваем параметры печати для корректного PDF
    ТабДок.АвтоМасштаб = Истина; 
    ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт; // Или Портрет
    
    // 5. Сохраняем в PDF во временный файл
    ИмяФайлаPDF = ПолучитьИмяВременногоФайла("pdf");
    ТабДок.Записать(ИмяФайлаPDF, ТипФайлаТабличногоДокумента.PDF);
    
    // 6. Помещаем PDF обратно в хранилище
    ДанныеPDF = Новый ДвоичныеДанные(ИмяФайлаPDF);
    НовыйАдрес = ПоместитьВоВременноеХранилище(ДанныеPDF, ЭтаФорма.УникальныйИдентификатор);
    
    // 7. Очистка: удаляем старый адрес и временные файлы
    УдалитьИзВременногоХранилища(ИсходныйАдрес);
    УдалитьФайлы(ИмяВременногоФайла);
    УдалитьФайлы(ИмяФайлаPDF);
    
    Возврат НовыйАдрес;
    
КонецФункции

Важные нюансы и оптимизация

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

Работа с памятью: В коде выше мы использовали УдалитьИзВременногоХранилища(ИсходныйАдрес). Проанализируем ситуацию: когда файл загружается на сервер, он занимает место в оперативной памяти (или в сеансовых данных на диске). Если пользователи загружают сотни тяжелых файлов Excel, сервер может начать испытывать дефицит ресурсов. Принудительное удаление старого адреса после конвертации — признак хорошего тона в разработке.

Шрифты на сервере Linux: Если ваш сервер 1С работает под управлением Linux, вы можете столкнуться с тем, что в PDF вместо текста отображаются «квадратики». Это происходит из-за отсутствия стандартных шрифтов Windows (Arial, Times New Roman). Выясним причину: ТабличныйДокумент при рендеринге PDF ищет шрифты, указанные в исходном файле. Чтобы решить эту проблему, необходимо установить пакет msttcorefonts на сервер.

Параметры отображения: При конвертации Excel часто бывает слишком широким. Если не установить свойство АвтоМасштаб = Истина, PDF получится «разрезанным» на несколько листов по вертикали, что крайне неудобно для чтения счета. Также полезно анализировать количество колонок и программно менять ОриентацияСтраницы.

Современный подход: Использование Асинхронности (Async/Await)

Начиная с версии платформы 8.3.15, мы можем сделать код более линейным и читаемым, используя конструкцию Ждать. Посмотрим на пример, как это упрощает логику:


&НаКлиенте
Асинхр Процедура ЗагрузитьИКонвертироватьАсинхронно()
    
    ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
    // ... настройка параметров ...
    
    Результат = Ждать ПоместитьФайлНаСерверАсинхрон( , , , ПараметрыДиалога, ЭтаФорма.УникальныйИдентификатор);
    
    Если Результат <> Неопределено Тогда
        Адрес = Результат.Адрес;
        Если СтрЗаканчивается(Результат.СсылкаНаФайл.Имя, ".xls") Тогда
             Адрес = КонвертироватьXLSвPDFНаСервере(Адрес, ".xls");
        КонецЕсли;
        // Продолжаем работу с переменной Адрес
    КонецЕсли;
    
КонецПроцедуры

Этот подход избавляет нас от необходимости создавать отдельные процедуры-оповещения и делает структуру программы прозрачной.

Заключение

Мы выяснили, что прямая подмена файла внутри метода НачатьПомещениеФайлаНаСервер невозможна. Оптимальный путь — это постобработка во временном хранилище. Использование объекта ТабличныйДокумент позволяет быстро и без сторонних библиотек конвертировать офисные документы в PDF. Помните о важности очистки временных данных и настройки параметров печати, чтобы ваши пользователи получали качественные и красивые документы.

← На главную