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