К статье
Практический материал

Разработка и Конфигурация · 11 мин

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

Как свернуть таблицу значений в 1С по условию: метод Свернуть(), отбор строк, запросы к ТЗ, примеры кода и типичные ошибки разработчиков.

Метод Свернуть() таблицы значений в 1С группирует строки по указанным колонкам и суммирует числовые поля, но у него нет встроенного параметра условия. Поэтому «свернуть по условию» означает: сначала отобрать нужные строки, а затем свернуть результат — либо выполнить группировку запросом с предложением ГДЕ и СГРУППИРОВАТЬ ПО.

Задача встречается постоянно: свернуть только проведённые строки, только строки с ненулевым количеством, только по определённому складу или контрагенту. Ниже разобраны все рабочие подходы — от простого отбора перед свёрткой до запроса к таблице значений с произвольными условиями и агрегатными функциями, отличными от суммы.

Важно понимать ограничение штатного метода: Свернуть() умеет только суммировать. Если нужно посчитать среднее, максимум, количество различных значений или применить фильтр — потребуется запрос либо ручной обход строк. Выбор подхода зависит от объёма данных и сложности условия.

Как работает метод Свернуть() и почему в нём нет условия

Метод Свернуть(КолонкиГруппировок, КолонкиСуммирования) объединяет строки с одинаковыми значениями в колонках группировок, складывая значения колонок суммирования. Все остальные колонки, не указанные ни в первом, ни во втором параметре, удаляются из таблицы безвозвратно.

ТЗ.Свернуть("Номенклатура, Склад", "Количество, Сумма");

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

Условия в сигнатуре метода нет принципиально: метод работает со всей таблицей целиком. Поэтому фильтрацию выполняют до вызова — отдельным шагом. Это не недостаток платформы, а разделение ответственности: отбор строк и агрегация решаются разными инструментами.

Свёртка с предварительным отбором строк

Самый прямой способ свернуть по условию — сформировать новую таблицу только из подходящих строк и свернуть её. Для отбора используется метод НайтиСтроки() со структурой отбора или метод Скопировать() с параметром отбора.

Отбор = Новый Структура("Склад", СкладОтгрузки);

ТЗУсловие = ТЗ.Скопировать(Отбор);

ТЗУсловие.Свернуть("Номенклатура", "Количество, Сумма");

Метод Скопировать(Отбор) удобнее связки «НайтиСтроки + цикл добавления»: он сразу возвращает новую таблицу с отобранными строками, сохраняя структуру колонок. Исходная таблица при этом не изменяется, что снимает риск потери данных.

Ограничение подхода: структура отбора поддерживает только равенство (и массив значений для условия «в списке»). Условия вида «Количество > 0», «Сумма <> 0» или «Дата в интервале» через структуру не выразить — понадобится цикл с проверкой или запрос.

Отбор по неравенству через цикл

Если условие сложнее равенства, отбирайте строки вручную в новую таблицу:

ТЗОтбор = ТЗ.СкопироватьКолонки();

Для Каждого СтрокаТЗ Из ТЗ Цикл

Если СтрокаТЗ.Количество > 0 И СтрокаТЗ.Проведен Тогда

ЗаполнитьЗначенияСвойств(ТЗОтбор.Добавить(), СтрокаТЗ);

КонецЕсли;

КонецЦикла;

ТЗОтбор.Свернуть("Номенклатура", "Количество, Сумма");

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

Порядок действий при свёртке с отбором
  1. 1
    Определите условие: равенство (структура отбора) или сложное (цикл/запрос)
  2. 2
    Создайте копию таблицы с отобранными строками через Скопировать(Отбор) или цикл
  3. 3
    Вызовите Свернуть() у новой таблицы, указав колонки группировок и суммирования
  4. 4
    Проверьте, что исходная таблица осталась нетронутой, если она ещё нужна
  5. 5
    Проверьте итоги: сумма по свёрнутой таблице должна совпадать с суммой отобранных строк

Свёртка по условию через запрос к таблице значений

Наиболее гибкий способ — поместить таблицу значений во временную таблицу запроса и выполнить группировку с произвольным условием. Запрос поддерживает любые сравнения, функции, агрегаты МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ, КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...), чего метод Свернуть() не умеет.

Запрос = Новый Запрос;

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

Запрос.Текст =

"ВЫБРАТЬ

| ТЗ.Номенклатура КАК Номенклатура,

| ТЗ.Количество КАК Количество,

| ТЗ.Сумма КАК Сумма

|ПОМЕСТИТЬ ВТ_Данные

|ИЗ &ТЗ КАК ТЗ

|;

|ВЫБРАТЬ

| Данные.Номенклатура КАК Номенклатура,

| СУММА(Данные.Количество) КАК Количество,

| СУММА(Данные.Сумма) КАК Сумма

|ИЗ ВТ_Данные КАК Данные

|ГДЕ Данные.Количество > 0

|СГРУППИРОВАТЬ ПО Данные.Номенклатура";

Запрос.УстановитьПараметр("ТЗ", ТЗ);

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

Обратите внимание: условие ГДЕ применяется до группировки — фильтруются отдельные строки. Если нужно отфильтровать уже сгруппированные итоги (например, оставить только номенклатуру с суммарным количеством больше 100), используйте ИМЕЮЩИЕ.

Передача таблицы значений параметром запроса требует, чтобы типы колонок были определены и совместимы с типами запроса. Колонки составного типа «число или строка» могут вызвать ошибку — приводите колонки к конкретным типам при формировании таблицы.

Выбор подхода под конкретную задачу

Три подхода — прямое сворачивание копии, ручной обход и запрос — покрывают все сценарии, но у каждого своя ниша. Выбор зависит от типа условия, объёма данных и требуемых агрегатов.

Сравнение способов свёртки по условию

Скопировать(Отбор) + Свернуть()

Подходит для условий на равенство или «в списке». Самый короткий код. Не работает с неравенствами и вычисляемыми условиями.

Цикл с проверкой + Свернуть()

Подходит для любых условий на встроенном языке. Простая отладка. Медленнее запроса на больших таблицах.

Запрос к таблице значений

Максимальная гибкость: любые условия, ИМЕЮЩИЕ, агрегаты кроме суммы, соединения с другими данными. Требует аккуратности с типами колонок.

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

Ещё один сценарий — свёртка с условием по нескольким полям одновременно. В запросе это обычное ГДЕ Поле1 = &П1 И Поле2 > &П2. В ручном варианте придётся выстраивать вложенные проверки, что быстро загромождает код.

Маршрут решения

Как выбрать действие

Условие — равенство одному значению или спискуИспользуйте ТЗ.Скопировать(СтруктураОтбора) и Свернуть() у результата
Условие содержит >, <, <> или логику на встроенном языкеОтберите строки циклом в новую таблицу и сверните её
Нужны МАКСИМУМ, СРЕДНЕЕ, КОЛИЧЕСТВО РАЗЛИЧНЫХ или фильтр по итогам группИспользуйте запрос к таблице значений с СГРУППИРОВАТЬ ПО и ИМЕЮЩИЕ
Таблица очень большая и строится из регистровВыполняйте группировку запросом сразу к регистрам, минуя промежуточную ТЗ

Проверка результата и типичные ошибки

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

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

Типичные ошибки
01
Свёртка исходной таблицы вместо копии — теряются детальные строки и колонки, не входящие в параметры, восстановить их нельзя
02
Имя колонки в параметрах указано с опечаткой — платформа выдаёт ошибку или колонка молча удаляется из результата
03
Числовые значения хранятся в строковой колонке — суммирование даёт 0 или ошибку приведения типов
04
Ожидание, что Свернуть() отфильтрует строки — метод не имеет условия, фильтровать нужно до вызова
05
Значения NULL в суммируемых колонках при запросе — итог становится NULL, используйте ЕСТЬNULL(Поле, 0)

Отдельная ловушка — неявное различие типов. Если в колонке «Номенклатура» часть значений получена из разных источников и имеет одинаковое представление, но разные ссылки (например, предопределённые и обычные элементы), свёртка посчитает их разными группами. Проверяйте сами значения, а не их строковое представление.

Контрольные точки

Как проверить результат

Итог по суммируемой колонке
Норма

Итог свёрнутой таблицы равен итогу отобранных строк до свёртки

Тревожный признак

Итоги расходятся — потеряны строки или ошибка в условии отбора

Уникальность групп
Норма

Нет двух строк с одинаковыми значениями колонок группировок

Тревожный признак

Дубли групп — свёртка не выполнена или указаны не те колонки

Состав колонок
Норма

В результате только колонки группировок и суммирования

Тревожный признак

Пропала колонка, которая нужна дальше — её не включили в параметры

Ограничения и крайние случаи

Метод Свернуть() недоступен на тонком и веб-клиенте для таблиц значений, полученных с сервера как результат запроса, — там работайте на серверной стороне. Если таблица является реквизитом формы типа «ТаблицаЗначений», сворачивайте её через РеквизитФормыВЗначение(), а затем возвращайте обратно через ЗначениеВРеквизитФормы().

При свёртке колонок с типом «Дата» помните, что группировка идёт по точному значению, включая время. Две строки с датами 10:00 и 15:00 одного дня не свернутся вместе. Если нужна группировка по дню — сначала приведите даты к началу дня функцией НачалоДня() или группируйте в запросе по периодичности.

Суммирование больших денежных величин в колонках ограниченной разрядности может привести к переполнению. Задавайте колонкам суммирования достаточную длину и точность через КвалификаторыЧисла ещё при создании таблицы.

Итог

Что важно запомнить

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

Частые вопросы

Можно ли свернуть таблицу значений без суммирования?

Да. Вызовите ТЗ.Свернуть("Колонка1, Колонка2") без второго параметра — получите таблицу уникальных комбинаций указанных колонок. Это удобный способ получить список различных значений без запроса.

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

Метод Свернуть() умеет только суммировать. Для МАКСИМУМ, МИНИМУМ или СРЕДНЕЕ используйте запрос к таблице значений с группировкой и нужной агрегатной функцией, либо обходите строки циклом и сравнивайте значения вручную в соответствии.

Почему после Свернуть() пропали колонки?

Это штатное поведение: метод удаляет все колонки, не указанные ни в колонках группировок, ни в колонках суммирования. Если колонка нужна в результате, но не должна суммироваться, включите её в список группировок — тогда она сохранится как часть ключа группы.

Как свернуть табличную часть документа по условию?

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

Что быстрее: запрос к ТЗ или цикл с отбором?

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

Как отфильтровать группы после свёртки, например оставить итоги больше заданной суммы?

В запросе для этого служит предложение ИМЕЮЩИЕ: ИМЕЮЩИЕ СУММА(Данные.Сумма) > &Порог. Без запроса придётся после Свернуть() обойти результат и удалить лишние строки либо скопировать подходящие в новую таблицу.