Как вывести содержание в начало табличного документа, если данные для него появляются только в конце формирования отчета

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

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

Метод 1. Сборка документа из нескольких частей (Рекомендуемый)

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

Разберем алгоритм по шагам:

  1. Создадим основной табличный документ (куда в итоге все будет выведено) и временный табличный документ для основного содержимого.
  2. В процессе формирования отчета (в цикле) выводим все данные "прайса" или основной части во временный документ. Параллельно заполняем таблицу значений или массив данными для будущего содержания.
  3. Когда основной цикл завершен, у нас есть готовое тело отчета во временном документе и накопленные данные для содержания.
  4. Выводим область содержания в основной (итоговый) табличный документ.
  5. Используем метод Вывести(), чтобы добавить содержимое временного документа в итоговый вслед за содержанием.

Посмотрим на пример реализации кода:


// Инициализируем итоговый документ и временный для тела отчета
ТабДокИтоговый = Новый ТабличныйДокумент;
ТабДокТело = Новый ТабличныйДокумент;

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

// 2. Теперь выводим содержание в начало ИТОГОВОГО документа
ОбластьШапкаСодержания = Макет.ПолучитьОбласть("ШапкаСодержания");
ТабДокИтоговый.Вывести(ОбластьШапкаСодержания);

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

// 3. Присоединяем подготовленное тело отчета
ТабДокИтоговый.Вывести(ТабДокТело);

// Выводим результат пользователю
ТабДокИтоговый.Показать();

Метод 2. Использование метода ВставитьОбласть()

Если по каким-то причинам вам необходимо манипулировать уже существующим документом, можно использовать метод ВставитьОбласть. Этот метод позволяет "раздвинуть" строки документа и вставить новую область в указанное место. Однако здесь разработчики часто сталкиваются с ошибкой «Выделение не соответствует вставляемому блоку». Выясним причину этой ошибки и как ее избежать.

Эта ошибка возникает, когда размер (количество колонок или строк) вставляемой области из макета не совпадает с размером области, указанной в качестве целевой в табличном документе. Чтобы вставка прошла гладко, рекомендуется указывать целевую область не как диапазон ячеек (например, "R1C1:R1C5"), а как всю строку целиком.

Проанализируем правильный синтаксис вставки:


// Получаем область из макета
ОбластьДляВставки = Макет.ПолучитьОбласть("Содержание");

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

Использование ТабДок.Область("R1") гарантирует, что 1С выделит всю строку "до бесконечности" вправо, что позволяет избежать конфликтов с шириной колонок и объединенными ячейками.

Важные нюансы при работе с Табличным документом

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

  1. Ширина колонок: ТабличныйДокумент имеет единую сетку колонок. Если в содержании колонки должны иметь одну ширину, а в основной части — другую, то при объединении документов через Вывести() настройки колонок будут взяты из той части, которая выводится первой. Чтобы решить эту проблему, рекомендуется настраивать сетку в макете максимально детально или использовать объединение ячеек для создания нужного визуального эффекта.
  2. Производительность: Метод ВставитьОбласть работает медленнее, чем Вывести. При каждой вставке 1С вынуждена пересчитывать структуру всего документа ниже точки вставки. Если в вашем отчете тысячи строк, вставка в начало документа в цикле может существенно замедлить формирование отчета. В таких случаях метод со сборкой из двух документов (Метод 1) является единственно верным.
  3. Объединенные ячейки: Если во вставляемой области из макета есть объединенные ячейки, то и целевая область в документе должна позволять такое объединение. Чаще всего ошибка соответствия блоков возникает именно из-за того, что вставляемая область "натыкается" на уже существующие объединения в документе.
  4. Объекты и рисунки: Если в вашей шапке или содержании присутствуют логотипы (объекты типа РисунокТабличногоДокумента), убедитесь, что в их свойствах установлено корректное Расположение (привязка к ячейкам). В противном случае при программном смещении строк рисунки могут "уплыть" или остаться на месте.

Пример функции для добавления информации в верхнюю часть документа

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


Процедура ТаблДок_ДобавитьИнфоВВерх(Инфо, ТаблДок, КоличествоСтрокДляВставки = 1) Экспорт
    
    // Сохраняем текущую фиксацию, если она была
    СтараяФиксация = ТаблДок.ФиксацияСверху;
    
    // Вставляем пустые строки в начало
    Для НомерСтроки = 1 По КоличествоСтрокДляВставки Цикл
        // Берем пустую строку за пределами данных для копирования формата
        СтрокаЗаПорогом = ТаблДок.ВысотаТаблицы + 1;
        ОбластьПустая = ТаблДок.Область(СтрокаЗаПорогом, , СтрокаЗаПорогом);
        
        // Вставляем ее в начало
        ТаблДок.ВставитьОбласть(ОбластаяПустая, ТаблДок.Область("R1"), ТипСмещенияТабличногоДокумента.ПоВертикали);
    КонецЦикла;
    
    // Заполняем вставленные строки данными
    ОбластьТекст = ТаблДок.Область(1, 1);
    ОбластьТекст.Текст = Инфо;
    ОбластьТекст.АвтоВысотаСтроки = Истина;
    
    // Восстанавливаем или увеличиваем фиксацию строк
    ТаблДок.ФиксацияСверху = СтараяФиксация + КоличествоСтрокДляВставки;
    
КонецПроцедуры

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

← На главную