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