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