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

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

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

Метод 1: Простой обход таблицы в цикле

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

Разберем пример кода, где нам нужно просуммировать колонку Сумма только для тех строк, где колонка Статус имеет значение "Оплачено":


ИтоговаяСумма = 0;
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
    Если СтрокаТЗ.Статус = "Оплачено" Тогда
        ИтоговаяСумма = ИтоговаяСумма + СтрокаТЗ.Сумма;
    КонецЕсли;
КонецЦикла;

Этот способ прост в написании и отладке, однако на таблицах с десятками тысяч строк он может работать медленнее, чем специализированные методы платформы.

Метод 2: Использование метода НайтиСтроки()

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

Проанализируем пример использования структуры отбора:


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

ИтоговаяСумма = 0;
Для Каждого Строка Из НайденныеСтроки Цикл
    ИтоговаяСумма = ИтоговаяСумма + Строка.Сумма;
КонецЦикла;

Важный момент: если по колонке, по которой идет поиск, предварительно создать индекс с помощью ТаблицаДанных.Индексы.Добавить("Статус"), скорость работы метода НайтиСтроки() значительно возрастет на больших объемах данных.

Метод 3: Использование запроса к таблице значений

Для сложных условий или если требуется сгруппировать данные по нескольким признакам, лучше всего использовать механизм запросов. Мы можем передать ТаблицуЗначений в запрос как параметр. Выясним причину, почему это считается одним из самых гибких решений.

Посмотрим на пример реализации запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СУММА(ТЗ.Сумма) КАК Итого
    |ИЗ
    |	&ВТ КАК ТЗ
    |ГДЕ
    |	ТЗ.Статус = &НужныйСтатус";

Запрос.УстановитьПараметр("ВТ", ТаблицаДанных);
Запрос.УстановитьПараметр("НужныйСтатус", "Оплачено");

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Если Выборка.Следующий() Тогда
    ИтоговаяСумма = Выборка.Итого;
КонецЕсли;

Внимание: при передаче таблицы значений в запрос необходимо, чтобы у всех колонок были явно заданы типы. Если колонка имеет тип "Произвольный", запрос не сможет быть выполнен и выдаст ошибку. Для назначения типов используйте ОписаниеТипов при создании таблицы.

Метод 4: Копирование таблицы с фильтром

Еще один профессиональный прием заключается в создании копии части таблицы с помощью метода Скопировать(). Этот метод принимает структуру отбора. После копирования мы получаем новую ТаблицуЗначений, в которой содержатся только нужные нам строки, и к этой новой таблице применяем штатный метод Итог().

Разберем этот подход по шагам:

  1. Создаем структуру отбора с нужными значениями.
  2. Вызываем метод Скопировать(СтруктураОтбора).
  3. Вызываем Итог("ИмяКолонки") у полученной копии.

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

Этот способ очень лаконичен, так как избавляет разработчика от написания ручных циклов. Платформа 1С оптимизирует копирование на внутреннем уровне, что часто делает этот метод быстрее обычного цикла Для Каждого.

Метод 5: Использование вспомогательной колонки

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

Проанализируем ситуацию: у нас есть колонка Сумма, и мы добавляем колонку СуммаОплачено. Тогда общий итог по условию будет равен простому итогу по новой колонке: ТаблицаДанных.Итог("СуммаОплачено").

Этот метод удобен тем, что итог пересчитывается мгновенно, если вы работаете с данными в форме и обновляете вспомогательную колонку при изменении статуса.

Метод 6: Метод Свернуть()

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


// Создаем копию, чтобы не испортить основную таблицу
ТЗ_ДляИтогов = ТаблицаДанных.Скопировать();
// Оставляем только нужные колонки
ТЗ_ДляИтогов.Свернуть("Статус", "Сумма");

// Теперь можно найти сумму конкретного статуса
СтрокаИтога = ТЗ_ДляИтогов.Найти("Оплачено", "Статус");
Если СтрокаИтога <> Неопределено Тогда
    ИтоговаяСумма = СтрокаИтога.Сумма;
КонецЕсли;

Рекомендации по выбору решения

Выясним, когда и какой метод применять:

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

← На главную