Как программно сохранить отчет СКД в PDF-файл в 1С:Предприятие 8.3?

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

В процессе разработки в среде 1С:Предприятие 8.3 на управляемых формах часто возникает задача автоматического или полуавтоматического сохранения отчетов в файл формата PDF. Это может быть связано с необходимостью отправки прайс-листов клиентам, выгрузки актов сверки или архивации управленческой отчетности. Однако разработчики нередко сталкиваются со странной проблемой: код выполняется без ошибок, диалоговое окно сохранения отрабатывает штатно, но сформированный файл PDF оказывается абсолютно пустым.

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

Разбор типичной ошибки: почему файл сохраняется пустым?

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


&НаКлиенте
Процедура СохранитьВФайл(Команда)
    Режим = РежимДиалогаВыбораФайла.Сохранение; 
    ДиалогСохраненияФайла = Новый ДиалогВыбораФайла(Режим); 
    ДиалогСохраненияФайла.ПолноеИмяФайла = "Прайс"; 
    Фильтр = "Документ PDF (*.pdf)|*.pdf";                 
    ДиалогСохраненияФайла.Фильтр = Фильтр; 
    ДиалогСохраненияФайла.МножественныйВыбор = Ложь; 
    ДиалогСохраненияФайла.Заголовок = "Выберите файл"; 
    Если ДиалогСохраненияФайла.Выбрать() Тогда 
        ТабДокумент = Новый ТабличныйДокумент();
        ПутьКФайлу = ДиалогСохраненияФайла.ПолноеИмяФайла; 
        ТабДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.PDF);
    КонецЕсли;   
КонецПроцедуры

Выясним причину, по которой этот код генерирует пустой файл. Обратите внимание на следующую строку:

ТабДокумент = Новый ТабличныйДокумент();

Этой инструкцией мы создаем в оперативной памяти абсолютно новый, чистый и незаполненный объект типа ТабличныйДокумент. Наша программа никак не связывает этот новый объект с тем отчетом СКД, который пользователь уже сформировал на экране. Далее метод Записать() честно переносит этот пустой документ в указанный файл PDF. Логично, что на выходе получается документ нулевого размера.

Попытка привязаться к элементам формы: «Данные» против «Элементов»

Пытаясь исправить ошибку, разработчики часто пробуют обратиться к элементам формы напрямую через коллекцию элементов:

ТабДокумент = Элементы.Результат;

После написания такой строки платформа выдает ошибку о том, что метод Записать() недоступен. Почему так происходит? Разберем разницу между реквизитами формы (данными) и элементами формы (визуальным представлением):

  1. Элементы формы (доступные через коллекцию Элементы) — это элементы управления пользовательского интерфейса. Например, поле табличного документа на форме. У этого объекта нет метода для записи в файл, так как его задача — просто отображать данные на экране и реагировать на действия пользователя.
  2. Реквизиты формы (данные) — это сущности, которые хранят реальную информацию. На управляемой форме отчета по умолчанию создается реквизит с именем Результат, который имеет тип ТабличныйДокумент. Именно в него СКД выводит результат компоновки данных.

Поэтому обращаться нужно непосредственно к реквизиту формы Результат, минуя коллекцию Элементы.

Правильное решение для управляемой формы (на клиенте)

Для того чтобы успешно сохранить уже сформированный на экране отчет, нам достаточно вызвать метод Записать() у реквизита Результат. Ниже приведен рабочий, протестированный код клиентской процедуры:


&НаКлиенте
Процедура СохранитьВФайл(Команда)
    
    Режим = РежимДиалогаВыбораФайла.Сохранение; 
    ДиалогСохраненияФайла = Новый ДиалогВыбораФайла(Regim); 
    ДиалогСохраненияФайла.ПолноеИмяФайла = "Прайс-лист"; 
    Фильтр = "Документ PDF (*.pdf)|*.pdf";                 
    ДиалогСохраненияФайла.Фильтр = Фильтр; 
    ДиалогСохраненияФайла.МножественныйВыбор = Ложь; 
    ДиалогСохраненияФайла.Заголовок = "Выберите путь для сохранения отчета"; 
    
    Если ДиалогСохраненияФайла.Выбрать() Тогда 
        ПутьКФайлу = ДиалогСохраненияФайла.ПолноеИмяФайла; 
        
        // Обращаемся напрямую к реквизиту формы "Результат"
        Результат.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.PDF);
        
        ПоказатьПредупреждение(, "Отчет успешно сохранен в формат PDF!");
    КонецЕсли;   
    
КонецПроцедуры

Продвинутый уровень: формирование и сохранение отчета на сервере без участия формы

На практике задача часто усложняется: нам требуется формировать отчет СКД и сохранять его в PDF автоматически, например, в фоновом задании по расписанию для последующей рассылки по электронной почте. В этом случае у нас нет открытой формы и реквизита Результат.

Рассмотрим подробнее, как программно сгенерировать отчет СКД "с нуля" на стороне сервера и сохранить его в файл:


&НаСервереБезКонтекста
Процедура СформироватьОтчетВPDFНаСервере(ИмяОтчета, ПутьКФайлу)
    
    // 1. Получаем объект отчета и его схему компоновки
    ОтчетОбъект = Отчеты[ИмяОтчета].Создать();
    СхемаКомпоновкиДанных = ОтчетОбъект.СхемаКомпоновкиДанных;
    
    // 2. Получаем настройки отчета по умолчанию
    Настройки = ОтчетОбъект.КомпоновщикНастроек.ПолучитьНастройки();
    
    // 3. Создаем макет компоновки с помощью компоновщика макета
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, , , ТипГенератораМакетаКомпоновкиДанных.ВыводВТабличныйДокумент);
    
    // 4. Инициализируем процессор компоновки данных для обработки бизнес-логики и запросов
    ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки);
    
    // 5. Создаем результирующий табличный документ в памяти сервера
    ТабДок = Новый ТабличныйДокумент;
    
    // 6. Выводим результат компоновки в созданный табличный документ
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ТабДок);
    ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
    
    // Настраиваем параметры вывода для эстетичного отображения в PDF
    ТабДок.АвтоМасштаб = Истина;
    ТабДок.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
    
    // 7. Записываем табличный документ в файл на диске сервера
    ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.PDF);
    
КонецПроцедуры

Как сделать PDF-документ презентабельным? Важные настройки верстки

Просто сохранить отчет в PDF недостаточно. Если табличный документ содержит много колонок, он может хаотично разбиться на десятки страниц по ширине, превратив итоговый PDF в нечитаемый набор листов. Перед вызовом метода Записать() настоятельно рекомендуется программно управлять свойствами страницы:

Пример подготовки параметров печати перед сохранением:


ТабДокумент.АвтоМасштаб = Истина;
ТабДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабДокумент.ПолеСлева = 10;   // отступ 10 мм слева
ТабДокумент.ПолеСправа = 10;  // отступ 10 мм справа
ТабДокумент.ПолеСверху = 15;  // отступ 15 мм сверху для заголовка
ТабДокумент.ПолеСнизу = 10;   // отступ 10 мм снизу

Возможные проблемы со шрифтами при работе на Linux-сервере

Если ваша база 1С развернута в клиент-серверном варианте, а сервер функционирует под управлением операционной системы семейства Linux, при выгрузке отчетов в PDF на стороне сервера вы можете столкнуться со следующими проблемами:

Причина проблемы: Платформа 1С при формировании PDF на стороне сервера пытается использовать системные шрифты (например, Arial, Times New Roman, Calibri), прописанные в макете СКД. Если этих шрифтов нет в каталогах операционной системы Linux (по умолчанию они отсутствуют, так как защищены лицензиями Microsoft), платформа заменяет их на альтернативные или не может корректно обработать кодировку.

Решение:

  1. Установите пакет шрифтов TrueType Core Fonts на сервере Linux (например, выполнив команду sudo apt-get install ttf-mscorefonts-installer для дистрибутивов Debian/Ubuntu).
  2. Если у вас есть легальные шрифты в формате TTF/OTF, скопируйте их вручную в каталог /usr/share/fonts/truetype/ на сервере 1С.
  3. Обновите кэш шрифтов операционной системы с помощью команды fc-cache -f -v.
  4. Обязательно перезапустите службу сервера 1С (usr1cv8), чтобы платформа зафиксировала появление новых системных шрифтов.

Использование современных стандартов PDF (PDF/A) в 1С

Начиная со средних релизов платформы 8.3, в 1С появилась поддержка расширенных форматов сохранения файлов PDF. Вместо стандартного типа ТипФайлаТабличногоДокумента.PDF вы можете использовать константы для архивного хранения:

Использование стандартов PDF/A является хорошим тоном при проектировании систем автоматического документооборота и гарантирует долговечность отображения ваших отчетов СКД в неизменном виде.

← На главную