В практике разработчика 1С часто возникает задача агрегации данных в объекте ТаблицаЗначений. Метод Свернуть() является стандартным инструментом для группировки строк и суммирования ресурсов. Однако, когда дело доходит до колонок с типом Булево, поведение платформы может показаться неочевидным. Разберем детально, что происходит при попытке «просуммировать» логические значения и какие альтернативные способы существуют для решения более сложных задач группировки.
Проанализируем базовый механизм работы метода Свернуть(). Если в параметре КолонкиСуммирования указана колонка с типом Булево, платформа не выдает ошибку, а применяет специфическую логику. На практике это работает как логическая операция ИЛИ по всем строкам, входящим в группу.
Рассмотрим пример. Допустим, у нас есть таблица с результатами проверок, где колонка СтатусПроверки имеет тип Булево. Если хотя бы в одной строке группы значение было Истина, то после выполнения метода Свернуть() итоговое значение в этой колонке для всей группы станет Истина. Результат Ложь получится только в том случае, если во всех сворачиваемых строках было значение Ложь.
Рассмотрим этот процесс на примере кода:
// Создаем таблицу значений
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Группа", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Флаг", Новый ОписаниеТипов("Булево"));
// Заполняем данными
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Группа = "Объект1";
НоваяСтрока.Флаг = Ложь;
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Группа = "Объект1";
НоваяСтрока.Флаг = Истина;
// Выполняем свертку
ТЗ.Свернуть("Группа", "Флаг");
// В результате для Группы "Объект1" Флаг будет равен Истина (Ложь ИЛИ Истина)
Выясним причину, по которой метод может повести себя непредсказуемо. Критически важным условием для корректной работы логического суммирования является строгая типизация колонки. Если колонка таблицы значений имеет составной тип (например, Булево и Число или Неопределено), то при попытке свертки платформа может столкнуться с конфликтом типов.
Посмотрим на важные нюансы:
NULL или Неопределено, поведение метода зависит от версии платформы, но чаще всего это приводит к ошибке преобразования типов при суммировании.ТаблицыЗначений через объект ОписаниеТипов.Часто разработчику требуется не логическое «ИЛИ», а именно количество строк, где установлено значение Истина. Метод Свернуть() не умеет выполнять операцию КОЛИЧЕСТВО для булевых данных напрямую. В этом случае мы должны применить обходной путь — приведение к числовому типу.
Разберем алгоритм действий по шагам:
1, если флаг равен Истина, и 0 в противном случае.Пример реализации такого подхода:
// Добавляем колонку для счета
ТЗ.Колонки.Добавить("Счетчик", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0)));
Для Каждого Стр Из ТЗ Цикл
Стр.Счетчик = ?(Стр.Флаг = Истина, 1, 0);
КонецЦикла;
// Сворачиваем по колонке Счетчик
ТЗ.Свернуть("Группа", "Счетчик");
// Теперь в колонке Счетчик содержится количество попаданий Истина
Если задача агрегации данных выходит за рамки простого суммирования (например, нужно одновременно получить МИНИМУМ, МАКСИМУМ и КОЛИЧЕСТВО), использование метода Свернуть() становится неэффективным. Наиболее профессиональным подходом в 1С v8 является использование Запроса к временной таблице.
Проанализируем преимущества этого метода:
СУММА, МИНИМУМ, МАКСИМУМ, КОЛИЧЕСТВО).Пример использования запроса для обработки ТаблицыЗначений:
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
// Передаем таблицу в запрос
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ";
Запрос.УстановитьПараметр("ТЗ", ТЗ);
Запрос.Выполнить();
// Выполняем группировку с нужными функциями
Запрос.Текст =
"ВЫБРАТЬ
| ВТ_Данные.Группа КАК Группа,
| МАКСИМУМ(ВТ_Данные.Флаг) КАК ФлагИЛИ,
| МИНИМУМ(ВТ_Данные.Флаг) КАК ФлагИ,
| СУММА(ВЫБОР КОГДА ВТ_Данные.Флаг ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) КАК КоличествоИстин
|ИЗ
| ВТ_Данные КАК ВТ_Данные
|ГРУППИРОВАТЬ ПО
| ВТ_Данные.Группа";
РезультатТЗ = Запрос.Выполнить().Выгрузить();
В некоторых случаях, когда таблица совсем небольшая или требуется прервать обработку при первом же нахождении Истина, оправдано использование обычного цикла. Это позволяет избежать накладных расходов на вызов тяжелых механизмов свертки или запросов.
Рассмотрим пример функции, которая проверяет наличие хотя бы одного истинного значения в группе вручную:
Функция ЕстьХотяБыОднаИстина(ТЗ, ИмяКолонки)
Для Каждого Стр Из ТЗ Цикл
Если Стр[ИмяКолонки] = Истина Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Подведем итоги нашего анализа. Метод Свернуть() — это мощный и быстрый инструмент, встроенный непосредственно в движок платформы 1С. Его поведение с типом Булево как логическое «ИЛИ» является штатным и может эффективно использоваться для схлопывания статусов или признаков в отчетности.
Основные выводы:
Свернуть() по булевой колонке.Запросам к временным таблицам.Таким образом, понимание внутренних механизмов платформы позволяет выбирать наиболее оптимальный способ обработки данных в зависимости от конкретной технической задачи.