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