В практике разработки на платформе 1С часто встречается ситуация, когда структура печатной формы или отчета требует наличия содержания или итоговых данных в самом начале документа (на первой странице). Однако технически данные для этого содержания (номера страниц, перечень разделов, итоговые суммы по категориям) становятся известны только в процессе обхода всей выборки данных и формирования основного "тела" отчета. Рассмотрим, как элегантно решить эту задачу, избежав типичных ошибок и проблем с производительностью.
Проанализируем наиболее надежный и производительный подход. Вместо того чтобы пытаться "раздвинуть" уже готовый документ и вставить данные вверх, мы будем использовать промежуточный (временный) табличный документ для хранения основной части отчета. Этот метод позволяет избежать проблем с пересчетом индексов строк при каждой вставке.
Разберем алгоритм по шагам:
Вывести(), чтобы добавить содержимое временного документа в итоговый вслед за содержанием.Посмотрим на пример реализации кода:
// Инициализируем итоговый документ и временный для тела отчета
ТабДокИтоговый = Новый ТабличныйДокумент;
ТабДокТело = Новый ТабличныйДокумент;
// 1. Формируем основное тело отчета во временный документ
Для Каждого СтрокаДанных Из РезультатЗапроса Цикл
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
// Заполняем параметры...
ТабДокТело.Вывести(ОбластьСтрока);
// Параллельно собираем данные для содержания
ДобавитьВСодержание(СтрокаДанных, СписокСодержания);
КонецЦикла;
// 2. Теперь выводим содержание в начало ИТОГОВОГО документа
ОбластьШапкаСодержания = Макет.ПолучитьОбласть("ШапкаСодержания");
ТабДокИтоговый.Вывести(ОбластьШапкаСодержания);
Для Каждого ЭлементСодержания Из СписокСодержания Цикл
ОбластьСтрокаСодержания = Макет.ПолучитьОбласть("СтрокаСодержания");
// Заполняем параметры...
ТабДокИтоговый.Вывести(ОбластьСтрокаСодержания);
КонецЦикла;
// 3. Присоединяем подготовленное тело отчета
ТабДокИтоговый.Вывести(ТабДокТело);
// Выводим результат пользователю
ТабДокИтоговый.Показать();
Если по каким-то причинам вам необходимо манипулировать уже существующим документом, можно использовать метод ВставитьОбласть. Этот метод позволяет "раздвинуть" строки документа и вставить новую область в указанное место. Однако здесь разработчики часто сталкиваются с ошибкой «Выделение не соответствует вставляемому блоку». Выясним причину этой ошибки и как ее избежать.
Эта ошибка возникает, когда размер (количество колонок или строк) вставляемой области из макета не совпадает с размером области, указанной в качестве целевой в табличном документе. Чтобы вставка прошла гладко, рекомендуется указывать целевую область не как диапазон ячеек (например, "R1C1:R1C5"), а как всю строку целиком.
Проанализируем правильный синтаксис вставки:
// Получаем область из макета
ОбластьДляВставки = Макет.ПолучитьОбласть("Содержание");
// Вставляем область в самую первую строку итогового документа
// Используем конструкцию "R1", чтобы указать на всю первую строку
ТабДок.ВставитьОбласть(ОбластьДляВставки, ТабДок.Область("R1"), ТипСмещенияТабличногоДокумента.ПоВертикали);
Использование ТабДок.Область("R1") гарантирует, что 1С выделит всю строку "до бесконечности" вправо, что позволяет избежать конфликтов с шириной колонок и объединенными ячейками.
При использовании любого из методов важно учитывать технические аспекты, которые могут повлиять на корректность отображения данных:
ТабличныйДокумент имеет единую сетку колонок. Если в содержании колонки должны иметь одну ширину, а в основной части — другую, то при объединении документов через Вывести() настройки колонок будут взяты из той части, которая выводится первой. Чтобы решить эту проблему, рекомендуется настраивать сетку в макете максимально детально или использовать объединение ячеек для создания нужного визуального эффекта.ВставитьОбласть работает медленнее, чем Вывести. При каждой вставке 1С вынуждена пересчитывать структуру всего документа ниже точки вставки. Если в вашем отчете тысячи строк, вставка в начало документа в цикле может существенно замедлить формирование отчета. В таких случаях метод со сборкой из двух документов (Метод 1) является единственно верным.РисунокТабличногоДокумента), убедитесь, что в их свойствах установлено корректное Расположение (привязка к ячейкам). В противном случае при программном смещении строк рисунки могут "уплыть" или остаться на месте.Рассмотрим более сложный пример, который можно оформить в виде универсальной процедуры для вставки текстовых блоков в начало уже сформированного документа. Это может быть полезно для постобработки отчетов СКД.
Процедура ТаблДок_ДобавитьИнфоВВерх(Инфо, ТаблДок, КоличествоСтрокДляВставки = 1) Экспорт
// Сохраняем текущую фиксацию, если она была
СтараяФиксация = ТаблДок.ФиксацияСверху;
// Вставляем пустые строки в начало
Для НомерСтроки = 1 По КоличествоСтрокДляВставки Цикл
// Берем пустую строку за пределами данных для копирования формата
СтрокаЗаПорогом = ТаблДок.ВысотаТаблицы + 1;
ОбластьПустая = ТаблДок.Область(СтрокаЗаПорогом, , СтрокаЗаПорогом);
// Вставляем ее в начало
ТаблДок.ВставитьОбласть(ОбластаяПустая, ТаблДок.Область("R1"), ТипСмещенияТабличногоДокумента.ПоВертикали);
КонецЦикла;
// Заполняем вставленные строки данными
ОбластьТекст = ТаблДок.Область(1, 1);
ОбластьТекст.Текст = Инфо;
ОбластьТекст.АвтоВысотаСтроки = Истина;
// Восстанавливаем или увеличиваем фиксацию строк
ТаблДок.ФиксацияСверху = СтараяФиксация + КоличествоСтрокДляВставки;
КонецПроцедуры
Подведем итог: если вы знаете структуру содержания заранее, но не знаете данных — используйте временный табличный документ для накопления тела отчета. Если же требуется разовая вставка небольшой области в начало готового документа — используйте ВставитьОбласть с указанием всей строки "R1", чтобы избежать ошибок позиционирования.