Почему возникает ошибка при вызове метода Свернуть у таблицы значений в 1С и как её исправить?

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

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

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

Анализ исходной проблемы и поиск ошибки в коде

Рассмотрим исходный фрагмент кода, который вызвал затруднения у автора темы на форуме:


Таб = Новый ТаблицаЗначений;   
Таб.Колонки.Добавить("Товар");

Для Каждого СтрокаПартииРаспределения ИЗ СтрокаДереваПартий.Строки Цикл
    Стр = Таб.Добавить();
    Стр.Товар = СтрокаПартииРаспределения.Номенклатура;
КонецЦикла;

Стр.Свернуть("Товар",);

В данном примере мы видим несколько критических ошибок, которые приводят к неработоспособности алгоритма. Разберем их пошагово.

  1. Вызов метода у неверного объекта. Это главная логическая ошибка в коде. Переменная Стр инициализируется внутри цикла Для Каждого как результат метода Добавить(). Соответственно, тип этой переменной — СтрокаТаблицыЗначений. Метод Свернуть() предназначен для работы со всей коллекцией данных в целом, поэтому он принадлежит исключительно объекту ТаблицаЗначений. Попытка вызвать его у строки таблицы приводит к ошибке: "Метод объекта не обнаружен (Свернуть)".
  2. Лишняя запятая в параметрах. В строке Стр.Свернуть("Товар",); после первого параметра установлена запятая, при этом второй параметр (колонки суммирования) оставлен пустым. Хотя платформа 1С лояльно относится к опущенным необязательным параметрам в некоторых методах, оставлять висящую запятую в самом конце вызова без последующих аргументов — плохая практика, которая в ряде режимов совместимости может вызывать синтаксические предупреждения конфигуратора.
  3. Использование переменной вне области видимости (логическая неточность). Переменная Стр определяется внутри цикла. После завершения цикла в ней остается ссылка на самую последнюю добавленную строку таблицы. Сворачивать одну конкретную (последнюю) строку не имеет никакого физического смысла.

Правильное решение проблемы

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

Скорректированный рабочий вариант кода будет выглядеть следующим образом:


Таб = Новый ТаблицаЗначений;   
Таб.Колонки.Добавить("Товар");

Для Каждого СтрокаПартииРаспределения ИЗ СтрокаДереваПартий.Строки Цикл
    Стр = Таб.Добавить();
    Стр.Товар = СтрокаПартииРаспределения.Номенклатура;
КонецЦикла;

// Правильный вызов метода у объекта ТаблицаЗначений
Таб.Свернуть("Товар");

После выполнения этого кода в таблице значений Таб останутся только уникальные строки с товарами, а все дублирующиеся элементы будут удалены.

Глубокое погружение: важные нюансы работы метода Свернуть()

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

1. Безвозвратное удаление неперечисленных колонок

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

Рассмотрим эту ситуацию на примере:


Таб = Новый ТаблицаЗначений;   
Таб.Колонки.Добавить("Товар");
Таб.Колонки.Добавить("Склад");
Таб.Колонки.Добавить("Количество");

// Заполняем таблицу данными...
// ...

// Мы хотим сгруппировать таблицу по товарам
Таб.Свернуть("Товар");

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

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

2. Ограничения по типам данных при суммировании

Второй параметр метода принимает список колонок, значения которых необходимо сложить. Платформа накладывает жесткие требования на типы данных в этих колонках:

  1. Суммировать можно только числа. Если колонка имеет строгий тип Число, операция пройдет успешно.
  2. Если колонка имеет неопределенный тип или составной тип данных, система попытается сложить только те ячейки, в которых на момент свертки физически находятся числа. Остальные значения будут проигнорированы или заменены на дефолтный ноль.
  3. Попытка просуммировать колонку, содержащую ссылки на справочники, документы или текстовые строки, не приведет к математическому сложению строк. Эти данные будут очищены, а в ячейках запишется число 0.

3. Недопустимость пересечения колонок

Списки колонок группировки (первый параметр) и колонок суммирования (второй параметр) ни при каких обстоятельствах не должны пересекаться. Вы не можете одновременно группировать по одной и той же колонке и суммировать её.

Если написать код следующим образом:

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

Платформа 1С незамедлительно вызовет ошибку времени выполнения: "Списки колонок не должны пересекаться". Всегда тщательно разделяйте аналитические разрезы и суммируемые показатели.

4. Ограничения контекста выполнения (Клиент-Сервер)

Объект ТаблицаЗначений является исключительно серверным типом данных. Он не существует на тонком клиенте и в веб-клиенте. Соответственно, производить любые манипуляции с этим объектом, включая вызов метода Свернуть(), непосредственно в клиентском коде (в процедурах с директивой выполнения &НаКлиенте) невозможно. Это вызовет синтаксическую ошибку еще на этапе компиляции модуля.

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


&НаКлиенте
Процедура ОбработатьДанныеФормы()
    // Передаем управление на сервер для работы с таблицей значений
    СвернутьТаблицуНаСервере();
КонецПроцедуры

&НаСервере
Процедура СвернутьТаблицуНаСервере()
    // Конвертируем данные формы в таблицу значений
    Таб = РеквизитФормыВЗначение("Объект.Товары", Тип("ТаблицаЗначений"));
    
    // Сворачиваем таблицу на сервере
    Таб.Свернуть("Товар", "Количество");
    
    // Возвращаем измененную таблицу обратно в данные формы
    ЗначениеВРеквизитФормы(Таб, "Объект.Товары");
КонецПроцедуры

5. Отличие свертки Таблицы Значений от Табличной Части

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

Главные отличия заключаются в следующем:

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

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

← На главную