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

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

1С: сворачивание таблицы значений и ошибка обращения к процедуре как к функции

Как правильно использовать метод Свернуть таблицы значений в 1С и устранить ошибку «Обращение к процедуре объекта как к функции». Примеры кода и типичные ошибки.

Метод Свернуть() таблицы значений — один из самых востребованных инструментов при группировке данных в 1С: он объединяет строки с одинаковыми значениями в указанных колонках и суммирует числовые поля. Однако именно с ним разработчики часто сталкиваются с ошибкой «Обращение к процедуре объекта как к функции», которая останавливает выполнение модуля.

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

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

Как работает метод Свернуть у таблицы значений

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

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

Ключевая особенность — метод работает «на месте». Исходная таблица после вызова изменяется, и вернуть её первоначальное состояние можно только из заранее сохранённой копии. Это принципиально отличает Свернуть() от функций вроде Найти() или Скопировать(), которые возвращают результат.

Почему возникает ошибка «Обращение к процедуре объекта как к функции»

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

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

Поскольку Свернуть() — процедура, у неё нет возвращаемого значения, и конструкция с присваиванием недопустима. Конфигуратор сообщит об ошибке ещё при проверке модуля, а в тонком клиенте выполнение прервётся с соответствующим сообщением.

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

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

Типичные ошибки
01
Присваивание результата Свернуть() переменной — процедура ничего не возвращает, возникает ошибка компиляции
02
Сворачивание исходной таблицы без копии — первоначальные данные теряются безвозвратно
03
Указание в колонках суммирования нечислового поля — ошибка при выполнении метода
04
Опечатка в имени колонки — метод сообщит, что колонка не найдена
05
Попытка свернуть пустую таблицу без проверки — в ряде сценариев последующая логика ломается на пустом результате

Правильный синтаксис сворачивания с примерами

Корректный вызов оформляется отдельным оператором, а результат читается из той же таблицы после выполнения:

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

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

Сообщить(Строка(Строка.Номенклатура) + ": " + Строка.Количество);

КонецЦикла;

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

СводнаяТаблица = ТаблицаТоваров.Скопировать();

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

Для получения списка уникальных значений одной колонки второй параметр опускают. После такого вызова в таблице останется только колонка группировки с уникальными значениями — удобная замена ручному поиску дублей:

УникальныеСклады = ТаблицаТоваров.Скопировать();

УникальныеСклады.Свернуть("Склад");

Как сохранить исходные данные и организовать проверку результата

Главный риск при сворачивании — потеря детальных данных. Если таблица используется дальше в алгоритме, сворачивайте копию, а не оригинал. Когда таблица получена из внешнего источника (запроса, файла, формы), убедитесь, что после сворачивания она нигде больше не читается в развёрнутом виде.

Для контроля корректности сворачивания полезно сравнить итоги до и после. Сумма по сворачиваемой числовой колонке не должна измениться — меняется только количество строк:

ИтогДо = ТаблицаТоваров.Итог("Сумма");

СводнаяТаблица = ТаблицаТоваров.Скопировать();

СводнаяТаблица.Свернуть("Номенклатура", "Сумма");

Если СводнаяТаблица.Итог("Сумма") <> ИтогДо Тогда

ВызватьИсключение "Итоги не совпадают после сворачивания";

КонецЕсли;

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

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

Как проверить результат сворачивания

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

Суммы совпадают

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

Итог изменился — возможно, свёрнута не та таблица или потеряны строки

Состав колонок после вызова
Норма

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

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

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

Количество строк
Норма

Строк стало меньше или столько же

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

Число строк не изменилось при наличии дублей — проверьте значения в колонках группировки

Альтернативы: запрос, сводная таблица и группировка в СКД

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

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

Способы группировки данных

Свернуть() таблицы значений

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

Группировка в запросе

Оптимально при выборке из базы: быстрее, меньше памяти, доступны разные агрегатные функции. Требует написания текста запроса

СКД

Лучший вариант для отчётов с настраиваемыми группировками. Избыточен для простых служебных расчётов

Смежные ошибки при работе с процедурами и функциями

Ошибка «Обращение к процедуре объекта как к функции» встречается не только со Свернуть(). Тот же механизм срабатывает при неправильном вызове процедур формы, методов документов и собственных процедур общих модулей. Например, Результат = Объект.Записать() — типичная ошибка: Записать() у объекта документа — процедура.

Обратная ситуация тоже возможна: вызов функции без использования результата проходит без ошибки компиляции, но результат теряется. Например, ТЗ.Найти(Значение, "Колонка") без присваивания выполнит поиск впустую. Такие ошибки компилятор не отловит — их выявляют только тестированием и код-ревью.

Полезная привычка — перед вызовом незнакомого метода открыть синтакс-помощник (Ctrl+F1 на имени метода) и посмотреть описание: там явно указано, возвращает ли метод значение и какого типа. Это занимает секунды и избавляет от отладки.

Порядок действий при возникновении ошибки

Как устранить ошибку
  1. 1
    Найдите строку, указанную в сообщении об ошибке, и определите, какой метод вызывается как функция
  2. 2
    Откройте описание метода в синтакс-помощнике и убедитесь, что это процедура
  3. 3
    Уберите присваивание: оформите вызов отдельным оператором
  4. 4
    Если результат нужен в другой переменной, сначала создайте копию таблицы методом Скопировать(), затем сверните копию
  5. 5
    Проверьте модуль через «Конфигурация — Проверка конфигурации» или синтаксический контроль модуля
  6. 6
    Прогоните сценарий на тестовых данных и сверьте итоги до и после сворачивания

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

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

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

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

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

Напрямую нет, потому что Свернуть() — процедура. Стандартный приём в две строки: сначала НоваяТЗ = ИсходнаяТЗ.Скопировать(), затем НоваяТЗ.Свернуть("Колонки", "Суммы"). Метод Скопировать() — функция и возвращает новую таблицу.

Что происходит с колонками, не указанными в параметрах Свернуть()?

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

Почему при сворачивании возникает ошибка, хотя синтаксис правильный?

Чаще всего колонка суммирования содержит нечисловые значения или в имени колонки опечатка. Также проверьте, что колонка существует в таблице: если таблица загружена из внешнего источника, состав колонок мог измениться.

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

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

Отличается ли поведение Свернуть() на сервере и на клиенте?

Нет, метод работает одинаково в обоих контекстах. Но помните, что таблица значений недоступна в тонком и веб-клиенте — там используются данные формы. Сворачивание таких данных выполняют в серверной процедуре.

Что делать, если ошибка «Обращение к процедуре как к функции» указывает на мой собственный метод?

Откройте объявление метода и посмотрите ключевое слово: Процедура или Функция. Если метод должен возвращать значение — замените объявление на Функцию и добавьте Возврат. Если возврат не нужен — уберите присваивание в месте вызова.

Итог

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

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