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

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

При разработке интерфейсов и обработок в 1С часто возникает задача подсчета итогов не по всей таблице целиком (как это делает стандартный метод Итог()), а в разрезе конкретных позиций — например, по наименованиям номенклатуры, группам или видам изделий. Разберем по шагам основные способы решения этой задачи: от простого метода встроенного языка до выполнения запроса к данным в оперативной памяти.

Способ 1. Использование встроенного метода Свернуть()

Если данные уже находятся в объекте ТаблицаЗначений, самый быстрый способ получить сгруппированные итоги — воспользоваться методом Свернуть(). Этот метод объединяет одинаковые строки по указанным колонкам группировки и суммирует значения в числовых колонках.

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

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


// Создаем копию исходной таблицы, чтобы не потерять данные на форме
ТаблицаИтогов = ИсходнаяТаблица.Скопировать();

// Первым параметром передаем колонки группировки через запятую,
// вторым параметром — колонки, по которым нужно сложить числовые показатели
ТаблицаИтогов.Свернуть("Номенклатура", "Количество, Сумма");

// Теперь в ТаблицаИтогов содержатся только уникальные позиции с их суммарными итогами
Для Каждого Стр Из ТаблицаИтогов Цикл
    Сообщить("Позиция: " + Строка(Стр.Номенклатура) + " | Итого: " + Строка(Стр.Количество));
КонецЦикла;

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

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

Рассмотрим пример запроса к таблице в памяти:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Т.Номенклатура КАК Номенклатура,
    |    СУММА(Т.Количество) КАК Количество,
    |    СУММА(Т.Сумма) КАК Сумма
    |ИЗ
    |    &ТаблицаДанных КАК Т
    |СГРУППИРОВАТЬ ПО
    |    Т.Номенклатура
    |УПОРЯДОЧИТЬ ПО
    |    Номенклатура";

Запрос.УстановитьПараметр("ТаблицаДанных", ИсходнаяТаблица);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

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


Таблица = Новый ТаблицаЗначений;

// Задаем тип для ссылки на справочник
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Номенклатура"));
ОписаниеТипаНоменклатура = Новый ОписаниеТипов(МассивТипов);
Таблица.Колонки.Добавить("Номенклатура", ОписаниеТипаНоменклатура);

// Задаем числовой тип для количества и суммы
КвалификаторыЧисла = Новый КвалификаторыЧисла(15, 3, ДопустимыйЗнак.Неотрицательный);
ОписаниеТипаЧисло = Новый ОписаниеТипов("Число", , , КвалификаторыЧисла);
Таблица.Колонки.Добавить("Количество", ОписаниеТипаЧисло);
Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));

Способ 3. Получение данных из элементов управляемой формы

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

Для расчета итогов необходимо передать данные на сервер и выполнить преобразование:

  1. Если обрабатывается табличная часть основного объекта формы (например, документа или обработки):
    
    &НаСервере
    Функция ПолучитьИтогиПоОбъекту()
        ОбъектОбработки = РеквизитФормыВЗначение("Объект");
        ТЗ = ОбъектОбработки.Товары.Выгрузить();
        ТЗ.Свернуть("Номенклатура", "Количество, Сумма");
        Возврат ТЗ;
    КонецФункции
    
  2. Если на форме создан произвольный реквизит с типом таблицы:
    
    &НаСервере
    Функция ПолучитьИтогиПоРеквизитуФормы()
        ТЗ = ДанныеФормыВЗначение(Элементы.ТаблицаНаФорме, Тип("ТаблицаЗначений"));
        ТЗ.Свернуть("Номенклатура", "Количество");
        Возврат ТЗ;
    КонецФункции
    

Способ 4. Группировка на клиенте через Соответствие

Если расчет требуется выполнить на стороне тонкого клиента без лишнего обращения к серверу, применим алгоритм с объектом Соответствие. Это позволяет накопить суммы за один проход по строкам таблицы:


ИтогиПоНоменклатуре = Новый Соответствие;

Для Каждого СтрокаТаблицы Из Элементы.ТаблицаТоваров.ТекущиеДанные Цикл
    ТекущийКлюч = СтрокаТаблицы.Номенклатура;
    НакопленноеКоличество = ИтогиПоНоменклатуре[ТекущийКлюч];
    
    Если НакопленноеКоличество = Неопределено Тогда
        ИтогиПоНоменклатуре.Вставить(ТекущийКлюч, СтрокаТаблицы.Количество);
    Иначе
        ИтогиПоНоменклатуре.Вставить(ТекущийКлюч, НакопленноеКоличество + СтрокаТаблицы.Количество);
    КонецЕсли;
КонецЦикла;

Таким образом, для быстрого подсчета внутри простых алгоритмов оптимально использовать метод Свернуть() на предварительно скопированной таблице, а при сложных условиях выборки и связывания — запрос к типизированной таблице значений на сервере.

← На главную