Как программно добавить итоги для динамических колонок в табличной части управляемой формы?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Постановка задачи и анализ ситуации

Представим ситуацию: у нас есть документ распределения, в котором количество колонок зависит от текущего списка активных складов. Мы используем метод ИзменитьРеквизиты для динамического добавления колонок в табличную часть. Наша цель — сделать так, чтобы внизу каждой такой колонки отображалась сумма всех значений этой колонки, и эта сумма обновлялась при изменении данных пользователем. Проанализируем основные этапы решения этой задачи.

Шаг 1: Подготовка структуры реквизитов

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

Выясним причину, по которой это делается именно так. Свойство элемента формы ПутьКДаннымПодвала ожидает ссылку на реквизит, который существует в контексте формы. Если мы создадим реквизит внутри структуры таблицы, система может некорректно обрабатывать его как итог. Поэтому для каждой динамической колонки мы создадим "пару":

  1. Реквизит внутри таблицы (для ввода данных в строках).
  2. Реквизит в корне формы (для хранения суммы в подвале).

Шаг 2: Программное создание реквизитов и элементов

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


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

Шаг 3: Реализация пересчета итогов

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

Рассмотрим подробнее код клиентского обработчика:


&НаКлиенте
Процедура ОбработчикПриИзмененииКолонкиКоличества(Элемент)
    
    ИмяКолонки = Элемент.Имя;
    ИмяИтога = "Итого_" + ИмяКолонки;
    
    // Используем метод Итог() табличной части объекта
    // Обратите внимание: расчет идет по всей колонке ТЧ
    СуммаПоКолонке = Объект.Товары.Итог(ИмяКолонки);
    
    // Записываем результат в реквизит формы, привязанный к подвалу
    ЭтаФорма[ИмяИтога] = СуммаПоКолонке;
    
    // Если нужно обновить и общие итоги документа, вызываем доп. процедуры
    ОбновитьОбщиеИтогиДокумента();
    
КонецПроцедуры

Типичные ошибки и их решение

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

Еще один важный момент — свойство Подвал у самой таблицы. Проверьте в конфигураторе или установите программно:

Элементы.Товары.Подвал = Истина;

Без этой настройки подвал просто не будет отображаться на экране, даже если все пути к данным настроены верно.

Оптимизация производительности

Работа с динамическими реквизитами — ресурсоемкая операция. Рассмотрим рекомендации для повышения скорости работы:

  1. Кэширование: Сохраняйте список добавленных колонок в переменной модуля формы или в скрытом реквизите. Это позволит быстро удалять их перед перестроением сетки, не перебирая все элементы формы.
  2. Типизация: При создании ОписаниеТипов для числовых колонок всегда указывайте квалификаторы числа (например, 15 знаков всего и 3 знака после запятой). Это предотвратит ошибки при расчете метода Итог().
  3. Серверные вызовы: Старайтесь минимизировать количество перестроений сетки. Если состав складов меняется редко, лучше один раз сформировать форму при открытии.

Дополнительные возможности оформления

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

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

← На главную