Как вывести данные из Таблицы Значений или запроса в макет печатной формы в 1С?

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

В процессе разработки в среде «1С:Предприятие» программисты часто сталкиваются с задачей вывода подготовленных данных в печатную форму. Традиционный сценарий выглядит так: разработчик получает данные с помощью запроса, при необходимости обрабатывает их во временной таблице или выгружает в объект ТаблицаЗначений, после чего результат нужно представить пользователю в виде красивого и структурированного табличного документа.

В данной статье мы подробно разберем несколько практических способов вывода данных из запроса или Таблицы Значений (ТЗ) в макет печатной формы. Мы пройдем путь от простого классического перебора строк до продвинутых методов динамической генерации таблиц и использования Системы Компоновки Данных (СКД), а также затронем важные вопросы оптимизации программного кода.

Способ 1. Классический построчный вывод с использованием областей макета

Этот метод является наиболее распространенным и применяется тогда, когда структура печатной формы известна заранее и создана в конфигураторе в виде макета. Мы получаем макет, разбиваем его на строки-области (Шапка, Строка, Подвал) и последовательно выводим их в результирующий табличный документ.

Разберем по шагам классический алгоритм вывода:

  1. Выгрузим результат запроса в таблицу значений или будем использовать выборку напрямую.
  2. Получим макет печатной формы по его имени.
  3. Инициализируем новый объект ТабличныйДокумент, который и будет показан пользователю.
  4. Последовательно получим области макета (Заголовок, Шапка таблицы, Детальные записи, Подвал) и выведем их методом Вывести().

Рассмотрим пример кода, реализующий данный алгоритм:


// 1. Получаем данные (в нашем примере выгружаем запрос в Таблицу Значений)
ТаблицаДанных = Запрос.Выполнить().Выгрузить();

// 2. Инициализируем табличный документ и получаем макет
ТабДок = Новый ТабличныйДокумент;
ТабДок.Очистить(); // Очищаем документ перед заполнением
Макет = ПолучитьМакет("ПечатнаяФормаРеестр");

// 3. Получаем области макета
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ШапкаТаблицы");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");

// 4. Выводим статичную шапку документа
ОбластьЗаголовок.Параметры.ДатаОтчета = Формат(ТекущаяДата(), "ДЛФ=Д");
ТабДок.Вывести(ОбластьЗаголовок);
ТабДок.Вывести(ОбластьШапкаТаблицы);

// 5. Запускаем цикл по строкам таблицы значений для вывода детальных записей
Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
    // Заполняем параметры области детальных записей
    ОбластьСтрока.Параметры.Номенклатура = СтрокаДанных.Номенклатура;
    ОбластьСтрока.Параметры.Количество   = СтрокаДанных.Количество;
    ОбластьСтрока.Параметры.Разница      = СтрокаДанных.Разница;
    
    // Выводим заполненную область в итоговый документ
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

// 6. Выводим подвал с итогами
ТабДок.Вывести(ОбластьПодвал);

// 7. Показываем готовый документ пользователю
ТабДок.Показать("Реестр документов");

Важная оптимизация: Если в вашей таблице содержится 10, 20 или более колонок, ручное присвоение каждого параметра в цикле (как в шаге 5) превращается в рутину и загромождает код. Платформа 1С предлагает встроенный метод автоматического сопоставления имен параметров области и колонок таблицы. Мы можем использовать метод Заполнить() у параметров области:


Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
    // Автоматическое заполнение всех параметров области одноименными колонками строки ТЗ
    ОбластьСтрока.Параметры.Заполнить(СтрокаДанных);
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

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

Способ 2. Динамический вывод произвольной таблицы (без создания макета)

Иногда возникает задача вывести таблицу данных, структура которой заранее неизвестна, либо колонок слишком много и создавать под них фиксированный макет в конфигураторе нецелесообразно. В таких случаях мы можем сформировать макет "на лету" программно, напрямую обращаясь к ячейкам объекта ТабличныйДокумент.

Выясним, как реализовать этот алгоритм динамически:


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

// Шаг 1. Формируем шапку таблицы на основе колонок ТЗ
НомерКолонки = 1;
Для Каждого Колонка Из ТаблицаДанных.Колонки Цикл
    ЯчейкаШапки = ТабДок.Область(1, НомерКолонки);
    // Используем заголовок колонки, если он задан, иначе ее имя
    ЯчейкаШапки.Текст = ?(ЗначениеЗаполнено(Колонка.Заголовок), Колонка.Заголовок, Колонка.Имя);
    
    // Оформляем шапку: делаем шрифт жирным и устанавливаем границы
    ЯчейкаШапки.Шрифт = Новый Шрифт(ЯчейкаШапки.Шрифт, , , Истина);
    ЯчейкаШапки.ГраницаСнизу = Новый Линия(ТипЛинииСтенкиТабличногоДокумента.Сплошная, 2);
    
    НомерКолонки = НомерКолонки + 1;
КонецЦикла;

// Шаг 2. Выводим строки с данными
ТекущаяСтрока = 2;
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
    НомерКолонки = 1;
    Для Каждого Колонка Из ТаблицаДанных.Колонки Цикл
        ЯчейкаДанных = ТабДок.Область(ТекущаяСтрока, НомерКолонки);
        ЯчейкаДанных.Текст = Строка(СтрокаТЗ[Колонка.Имя]);
        
        // Легкая рамка для ячеек данных
        ЯчейкаДанных.ГраницаСлева   = Новый Линия(ТипЛинииСтенкиТабличногоДокумента.Тонкая);
        ЯчейкаДанных.ГраницаСправа  = Новый Линия(ТипЛинииСтенкиТабличногоДокумента.Тонкая);
        ЯчейкаДанных.ГраницаСнизу   = Новый Линия(ТипЛинииСтенкиТабличногоДокумента.Тонкая);
        
        НомерКолонки = НомерКолонки + 1;
    КонецЦикла;
    ТекущаяСтрока = ТекущаяСтрока + 1;
КонецЦикла;

// Шаг 3. Настройка отображения сетки и автоширины колонок
ТабДок.ОтображатьСетку = Ложь;
ТабДок.Показать("Произвольный отчет");

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

Способ 3. Использование Системы Компоновки Данных (СКД) с внешним набором

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

Проанализируем программную реализацию вывода ТЗ через СКД:

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

Программный код для вывода выглядит следующим образом:


// 1. Помещаем нашу ТЗ в структуру внешних наборов данных
ВнешниеДанные = Новый Структура;
ВнешниеДанные.Вставить("ВнешнийИсточникДанных", ТаблицаДанных);

// 2. Получаем схему и настройки по умолчанию
СхемаСКД = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
НастройкиОтчета = СхемаСКД.НастройкиПоУмолчанию;

// 3. Выполняем компоновку макета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаСКД, НастройкиОтчета);

// 4. Инициализируем процессор компоновки и передаем туда внешние данные
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеДанные);

// 5. Выводим результат в табличный документ
ТабДок = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

ТабДок.Показать("Отчет на СКД");

Способ 4. Вывод через Построитель Отчета (для обычных форм)

Если разработка ведется на старых версиях платформы или в конфигурации на обычных формах (например, УТ 10.3, УПП 1.3), можно воспользоваться объектом ПостроительОтчета. Это быстрый и простой способ визуализации ТЗ, требующий минимум кода.


ТабДок = Новый ТабличныйДокумент;
Построитель = Новый ПостроительОтчета;

// Назначаем источником данных нашу таблицу
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаДанных);
Построитель.ВыводитьЗаголовокОтчета = Ложь;

// Построитель автоматически генерирует макет и заполняет его
Построитель.Вывести(ТабДок);
ТабДок.Показать("Отчет Построителя");

Обратите внимание: объект ПостроительОтчета считается устаревшим и не рекомендуется к использованию в новых разработках под управляемое приложение. В современных конфигурациях его полностью заменяет СКД.

Оптимизация параметров запроса и условий

Рассматривая исходный пример кода, часто можно заметить избыточные громоздкие конструкции при установке параметров запроса. Посмотрим на классический пример "как делать не надо":


Если Не ЗначениеЗаполнено(Контрагент) Тогда
    Запрос.УстановитьПараметр("НеПроверятьКонтрагент", Истина);
Иначе
    Запрос.УстановитьПараметр("НеПроверятьКонтрагент", Ложь);
КонецЕсли;

Этот код легко оптимизировать до одной строки, напрямую передавая результат логического выражения в параметр запроса. Это делает код чистым, лаконичным и более простым для чтения:


Запрос.УстановитьПараметр("НеПроверятьКонтрагент", Не ЗначениеЗаполнено(Контрагент));
Запрос.УстановитьПараметр("НеПроверятьДата", Не (ЗначениеЗаполнено(ДатаНач) И ЗначениеЗаполнено(ДатаКон)));

Также обратите внимание на условия связи в запросах. Использование конструкции вида ПриходнаяНакладнаяСостав.Ссылка <> НЕОПРЕДЕЛЕНО в запросах 1С является избыточным для реквизитов ссылочного типа и может негативно влиять на производительность СУБД, отключая использование индексов. Подобные проверки лучше исключать из условий связи.

← На главную