Как записать значение в уже выведенную область табличного документа в 1С?

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

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

Разберем природу этого поведения платформы 1С и проанализируем надежные практические способы решения данной задачи.

Ограничение платформы: почему нельзя изменить параметр после вывода

Прежде чем перейти к алгоритмам, выясним причину, по которой классическое обращение к параметрам не работает. Коллекция Параметры доступна только у объектов макета до момента их передачи в результирующий документ. Когда выполняется команда ТабДок.Вывести(Область), платформа преобразует шаблон ячеек в статические строки, заменяя имена параметров на их текущие значения. В сформированном объекте ТабличныйДокумент параметров больше нет — ячейки хранят только готовые свойства: Текст, Значение, Расшифровка и параметры оформления.

Кроме того, попытка сохранить область в массив (например, МассивОбластей.Добавить(Группировка)) сохраняет только ссылку на один и тот же объект макета. При изменении параметров на следующей итерации цикла значения перезапишутся во всех элементах массива.

Способ 1. Адресация ячейки по координатам через свойство ВысотаТаблицы

Рассмотрим самый быстрый и производительный метод. Если нельзя поменять параметр, мы можем напрямую изменить свойство Текст или Значение конкретной ячейки сформированного документа, запомнив номер строки в момент вывода заголовка группы.

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

  1. Выводим область шапки группы в результирующий табличный документ.
  2. Фиксируем текущий номер строки через свойство ТабДок.ВысотаТаблицы.
  3. Во вложенном цикле обходим подчиненные строки, попутно вычисляя итоговое значение, и выводим их в документ.
  4. По завершении расчета обращаемся к конкретной ячейке шапки с помощью метода ТабДок.Область(НомерСтроки, НомерКолонки) и устанавливаем итоговый текст.

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


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

Способ 2. Буферизация строк во временный ТабличныйДокумент

Проанализируем второй подход. Если требуется заполнить именно параметр в макете до его окончательного отображения в отчете, подчиненные строки можно временно накапливать в промежуточном объекте ТабличныйДокумент.

Разберем этот вариант по шагам:

  1. Создаем объект ВременныйТабДок = Новый ТабличныйДокумент.
  2. Обходим строки нижнего уровня, рассчитываем итог и выводим строки во ВременныйТабДок.
  3. Заполняем параметр в области шапки группы и выводим шапку в основной ТабДок.
  4. Выводим весь накопленный ВременныйТабДок в основной документ одним вызовом метода Вывести().

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


Для Каждого Строка1 Из Таб1 Цикл
    ТабДок.Вывести(Группировка1, 1);
    
    Для Каждого Строка2 Из Таб2 Цикл
        ВременныйТабДок = Новый ТабличныйДокумент;
        Параметр1 = 0;
        
        Для Каждого Строка3 Из Таб3 Цикл
            Параметр1 = Параметр1 + Строка3.Сумма;
            
            Группировка3.Параметры.Заполнить(Строка3);
            ВременныйТабДок.Вывести(Группировка3, 3);
        КонецЦикла;
        
        // Заполняем параметр перед выводом шапки
        Группировка2.Параметры.МойПараметр = Параметр1;
        ТабДок.Вывести(Группировка2, 2);
        
        // Выводим накопленные подчиненные строки
        ТабДок.Вывести(ВременныйТабДок);
    КонецЦикла;
КонецЦикла;

Способ 3. Поиск служебной метки через НайтиТекст()

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

При выводе шапки в ячейку параметра помещается уникальный текстовый маркер (например, "###ИТОГ_ГРУППЫ###"). После завершения вычислений в подчиненном цикле вызывается метод ТабДок.НайтиТекст(), который находит ячейку-заполнитель и заменяет маркер на реальное значение.

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


Для Каждого Строка2 Из Таб2 Цикл
    МеткаИтога = "###ИТОГ_" + Строка(Новый УникальныйИдентификатор) + "###";
    Группировка2.Параметры.МойПараметр = МеткаИтога;
    ТабДок.Вывести(Группировка2, 2);
    
    Параметр1 = 0;
    Для Каждого Строка3 Из Таб3 Цикл
        Параметр1 = Параметр1 + Строка3.Сумма;
        ТабДок.Вывести(Группировка3, 3);
    КонецЦикла;
    
    // Находим область с маркером и перезаписываем текст
    НайденнаяОбласть = ТабДок.НайтиТекст(МеткаИтога);
    Если НайденнаяОбласть <> Неопределено Тогда
        НайденнаяОбласть.Текст = Формат(Параметр1, "ЧДЦ=2");
    КонецЕсли;
КонецЦикла;

Способ 4. Предварительная подготовка данных в структуре или таблице

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

← На главную