Разработка и Конфигурация · 11 мин
1С: сворачивание таблицы значений и ошибка обращения к процедуре как к функции
Как правильно использовать метод Свернуть таблицы значений в 1С и устранить ошибку «Обращение к процедуре объекта как к функции». Примеры кода и типичные ошибки.
Метод Свернуть() таблицы значений — один из самых востребованных инструментов при группировке данных в 1С: он объединяет строки с одинаковыми значениями в указанных колонках и суммирует числовые поля. Однако именно с ним разработчики часто сталкиваются с ошибкой «Обращение к процедуре объекта как к функции», которая останавливает выполнение модуля.
Причина кроется в синтаксисе встроенного языка: Свернуть() — это процедура, а не функция. Она не возвращает значение, а изменяет саму таблицу, к которой применена. Попытка присвоить результат вызова переменной или использовать его в выражении приводит к ошибке компиляции ещё до запуска кода.
Ниже разобраны правильные приёмы сворачивания таблиц значений, причины возникновения ошибки, способы её исправления и альтернативные варианты группировки данных через запросы и сводные структуры.
Как работает метод Свернуть у таблицы значений
Метод Свернуть(КолонкиГруппировок, КолонкиСуммирования) группирует строки таблицы значений по указанным колонкам. Все строки с совпадающими значениями в колонках группировки объединяются в одну, а значения колонок суммирования складываются. Колонки, не входящие ни в первый, ни во второй параметр, после сворачивания удаляются из таблицы.
Оба параметра передаются строкой с именами колонок через запятую. Второй параметр можно опустить — тогда строки просто сгруппируются без суммирования, что удобно для получения уникальных комбинаций значений. Важно помнить: суммировать можно только колонки с числовым типом, иначе при выполнении возникнет ошибка.
Ключевая особенность — метод работает «на месте». Исходная таблица после вызова изменяется, и вернуть её первоначальное состояние можно только из заранее сохранённой копии. Это принципиально отличает Свернуть() от функций вроде Найти() или Скопировать(), которые возвращают результат.
Почему возникает ошибка «Обращение к процедуре объекта как к функции»
Ошибка появляется на этапе компиляции модуля, когда код пытается использовать результат вызова процедуры. Типичный проблемный фрагмент выглядит так:
Результат = ТаблицаТоваров.Свернуть("Номенклатура", "Количество,Сумма");
Поскольку Свернуть() — процедура, у неё нет возвращаемого значения, и конструкция с присваиванием недопустима. Конфигуратор сообщит об ошибке ещё при проверке модуля, а в тонком клиенте выполнение прервётся с соответствующим сообщением.
Аналогичная ситуация возникает, когда вызов процедуры вставляют внутрь выражения: в условие Если, в параметр другого метода или в строковое выражение. Например, Если ТЗ.Свернуть("Поле") Тогда — тоже ошибка. Правило простое: вызов процедуры всегда оформляется отдельным оператором без использования результата.
Отдельный случай — путаница между методами платформы и собственными процедурами общих модулей. Если разработчик объявил процедуру, а вызывает её как функцию, возникает та же ошибка. Проверяется это просмотром объявления метода: ключевое слово Процедура или Функция в заголовке.
Правильный синтаксис сворачивания с примерами
Корректный вызов оформляется отдельным оператором, а результат читается из той же таблицы после выполнения:
ТаблицаТоваров.Свернуть("Номенклатура,Склад", "Количество,Сумма");
Для Каждого Строка Из ТаблицаТоваров Цикл
Сообщить(Строка(Строка.Номенклатура) + ": " + Строка.Количество);
КонецЦикла;
Если исходные данные нужны дальше, перед сворачиванием делают копию. Метод Скопировать() — это уже функция, она возвращает новую таблицу, которую можно безопасно сворачивать:
СводнаяТаблица = ТаблицаТоваров.Скопировать();
СводнаяТаблица.Свернуть("Номенклатура", "Количество,Сумма");
Для получения списка уникальных значений одной колонки второй параметр опускают. После такого вызова в таблице останется только колонка группировки с уникальными значениями — удобная замена ручному поиску дублей:
УникальныеСклады = ТаблицаТоваров.Скопировать();
УникальныеСклады.Свернуть("Склад");
Как сохранить исходные данные и организовать проверку результата
Главный риск при сворачивании — потеря детальных данных. Если таблица используется дальше в алгоритме, сворачивайте копию, а не оригинал. Когда таблица получена из внешнего источника (запроса, файла, формы), убедитесь, что после сворачивания она нигде больше не читается в развёрнутом виде.
Для контроля корректности сворачивания полезно сравнить итоги до и после. Сумма по сворачиваемой числовой колонке не должна измениться — меняется только количество строк:
ИтогДо = ТаблицаТоваров.Итог("Сумма");
СводнаяТаблица = ТаблицаТоваров.Скопировать();
СводнаяТаблица.Свернуть("Номенклатура", "Сумма");
Если СводнаяТаблица.Итог("Сумма") <> ИтогДо Тогда
ВызватьИсключение "Итоги не совпадают после сворачивания";
КонецЕсли;
Обратите внимание: метод Итог() — функция, она возвращает число, поэтому её результат присваивать можно и нужно. Путаница между Итог() и Свернуть() — частый источник ошибки: разработчик по аналогии с функцией Итог() ожидает, что и Свернуть() вернёт таблицу.
Как проверить результат сворачивания
Суммы совпадают
Итог изменился — возможно, свёрнута не та таблица или потеряны строки
Остались только колонки группировки и суммирования
Нужная колонка исчезла — она не была указана в параметрах
Строк стало меньше или столько же
Число строк не изменилось при наличии дублей — проверьте значения в колонках группировки
Альтернативы: запрос, сводная таблица и группировка в СКД
Если данные берутся из информационной базы, сворачивать таблицу значений вручную часто не нужно — эффективнее сгруппировать записи на уровне запроса с помощью конструкции СГРУППИРОВАТЬ ПО и агрегатных функций СУММА(). Сервер СУБД выполнит группировку быстрее, чем обход строк в коде, а в память попадёт уже готовый результат.
Когда исходные данные уже находятся в таблице значений (например, загружены из файла), ручное сворачивание оправдано. Для отчётов на СКД группировку лучше выполнять средствами схемы компоновки — тогда пользователь сможет менять состав группировок самостоятельно, без изменения кода.
Способы группировки данных
Подходит, когда данные уже в памяти: загрузка из файла, программно сформированная таблица. Ограничение — изменяет исходную таблицу и работает только с простым суммированием
Оптимально при выборке из базы: быстрее, меньше памяти, доступны разные агрегатные функции. Требует написания текста запроса
Лучший вариант для отчётов с настраиваемыми группировками. Избыточен для простых служебных расчётов
Смежные ошибки при работе с процедурами и функциями
Ошибка «Обращение к процедуре объекта как к функции» встречается не только со Свернуть(). Тот же механизм срабатывает при неправильном вызове процедур формы, методов документов и собственных процедур общих модулей. Например, Результат = Объект.Записать() — типичная ошибка: Записать() у объекта документа — процедура.
Обратная ситуация тоже возможна: вызов функции без использования результата проходит без ошибки компиляции, но результат теряется. Например, ТЗ.Найти(Значение, "Колонка") без присваивания выполнит поиск впустую. Такие ошибки компилятор не отловит — их выявляют только тестированием и код-ревью.
Полезная привычка — перед вызовом незнакомого метода открыть синтакс-помощник (Ctrl+F1 на имени метода) и посмотреть описание: там явно указано, возвращает ли метод значение и какого типа. Это занимает секунды и избавляет от отладки.
Порядок действий при возникновении ошибки
- 1Найдите строку, указанную в сообщении об ошибке, и определите, какой метод вызывается как функция
- 2Откройте описание метода в синтакс-помощнике и убедитесь, что это процедура
- 3Уберите присваивание: оформите вызов отдельным оператором
- 4Если результат нужен в другой переменной, сначала создайте копию таблицы методом Скопировать(), затем сверните копию
- 5Проверьте модуль через «Конфигурация — Проверка конфигурации» или синтаксический контроль модуля
- 6Прогоните сценарий на тестовых данных и сверьте итоги до и после сворачивания
После исправления обязательно проверьте весь модуль целиком: подобные ошибки часто идут группами, когда фрагмент кода копировался в несколько мест. Синтаксическая проверка модуля в конфигураторе покажет все проблемные строки сразу.
Если ошибка возникает в типовой конфигурации без ваших доработок, проверьте, не изменён ли модуль расширением или внешней обработкой. В чистой типовой поставке такая ошибка практически исключена — она характерна именно для доработанного кода.
Удобный шаблон: всегда называйте свёрнутую копию иначе, чем исходную таблицу (например, ТЗДетально и ТЗСводно). Это исключает случайное использование свёрнутых данных там, где ожидаются детальные строки.
Частые вопросы
Можно ли свернуть таблицу значений в новую переменную одной строкой?
Напрямую нет, потому что Свернуть() — процедура. Стандартный приём в две строки: сначала НоваяТЗ = ИсходнаяТЗ.Скопировать(), затем НоваяТЗ.Свернуть("Колонки", "Суммы"). Метод Скопировать() — функция и возвращает новую таблицу.
Что происходит с колонками, не указанными в параметрах Свернуть()?
Они удаляются из таблицы. После вызова остаются только колонки группировки и колонки суммирования. Если нужная колонка пропала — добавьте её в первый параметр, но учтите, что это изменит уровень группировки.
Почему при сворачивании возникает ошибка, хотя синтаксис правильный?
Чаще всего колонка суммирования содержит нечисловые значения или в имени колонки опечатка. Также проверьте, что колонка существует в таблице: если таблица загружена из внешнего источника, состав колонок мог измениться.
Как свернуть таблицу значений по дате без времени?
Прямой возможности нет — сворачивание идёт по точному совпадению значений. Добавьте в таблицу вычисляемую колонку, заполните её через НачалоДня(Дата) в цикле, и сворачивайте уже по ней. Альтернатива — поместить таблицу во временную таблицу запроса и сгруппировать там.
Отличается ли поведение Свернуть() на сервере и на клиенте?
Нет, метод работает одинаково в обоих контекстах. Но помните, что таблица значений недоступна в тонком и веб-клиенте — там используются данные формы. Сворачивание таких данных выполняют в серверной процедуре.
Что делать, если ошибка «Обращение к процедуре как к функции» указывает на мой собственный метод?
Откройте объявление метода и посмотрите ключевое слово: Процедура или Функция. Если метод должен возвращать значение — замените объявление на Функцию и добавьте Возврат. Если возврат не нужен — уберите присваивание в месте вызова.
Что важно запомнить
Свернуть() — процедура: она изменяет саму таблицу и ничего не возвращает, поэтому результат вызова нельзя присваивать переменной. Для получения свёрнутой копии используйте связку Скопировать() + Свернуть(), а корректность результата проверяйте сравнением итогов до и после группировки.