Почему не сворачивается табличная часть документа в 1С и как это исправить?

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

Работа с табличными частями документов — одна из самых частых задач разработчика в среде 1С:Предприятие. Метод Свернуть кажется простым инструментом, однако на практике программисты часто сталкиваются с неочевидными ошибками: от некорректного поведения в отладчике до отсутствия суммирования данных. Разберем подробно, почему возникают эти проблемы и как их правильно решать.

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

Рассмотрим ситуацию, когда разработчик пытается проверить работу кода непосредственно в процессе отладки. При попытке выполнить команду вида Показатели.Свернуть("Должность, Сотрудник", "КбаллФакт, КдисФакт") в окне Вычислить выражение (Shift+F9), система выдает ошибку: «Обращение к процедуре объекта как к функции». Это происходит потому, что метод Свернуть является процедурой — он выполняет действия над объектом, но не возвращает никакого значения.

Важный нюанс: Окно «Вычислить выражение» предназначено для получения результата (значения), поэтому любая попытка вызвать там процедуру интерпретируется платформой как вызов функции. Чтобы проверить выполнение процедуры в отладчике, необходимо использовать окно Выполнить код (доступно в табло или через контекстное меню в некоторых версиях конфигуратора). Там код выполнится без попытки вернуть результат, и вы сможете увидеть изменения в объекте.

Различия метода Свернуть для Табличной части и Таблицы значений

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

  1. Для Табличной части (ТЧ): Платформа 1С накладывает жесткое требование — списки колонок группировки и колонок суммирования в совокупности должны покрывать все колонки табличной части. Поскольку структура ТЧ задана в метаданных и является фиксированной, система не может просто «удалить» лишние колонки в памяти. Если вы укажете только часть колонок, метод выдаст ошибку выполнения.
  2. Для Таблицы значений (ТЗ): Здесь метод работает гибче. Колонки, которые не попали ни в список группировки, ни в список суммирования, автоматически удаляются из таблицы после выполнения свертки. Именно поэтому в большинстве случаев предпочтительнее сначала выгрузить ТЧ в ТЗ, свернуть ее там, а затем использовать результат.

Посмотрим на пример правильной реализации через выгрузку в таблицу значений:


// Выгружаем ТЧ в промежуточную таблицу значений
ТзПоказатели = Показатели.Выгрузить();

// Сворачиваем ТЗ: указываем только нужные колонки
// Лишние колонки будут удалены автоматически
ТзПоказатели.Свернуть("Должность, Сотрудник", "КбаллФакт, КдисФакт");

// Далее используем свернутые данные, например, для формирования движений
Для Каждого ТекСтрока Из ТзПоказатели Цикл
    Движение = Движения.РегистрПремий.Добавить();
    Движение.Сотрудник = ТекСтрока.Сотрудник;
    Движение.Баллы = ТекСтрока.КбаллФакт;
КонецЦикла;

Проблема разрядности чисел при суммировании

Бывают случаи, когда метод Свернуть отрабатывает без ошибок, но результат суммирования кажется неверным. Проанализируем пример: у нас есть две строки с числом 0,9, после свертки мы ожидаем получить 1,8, но в таблице остается 0,9 или другое некорректное значение. Причина кроется в типе данных колонки.

Разберем понятие разрядности. Если в метаданных колонки КдисФакт указан тип Число (1, 1), это означает:

В такую колонку физически невозможно записать число 1,0 или больше, так как общее количество знаков (включая целую часть) ограничено единицей. Максимальное значение здесь — 0,9.

Решение: При использовании промежуточных таблиц значений или создании ТЧ в метаданных всегда закладывайте запас по разрядности. Для суммируемых показателей рекомендуется использовать точность Число (15, 2) или (15, 3), чтобы избежать потери данных при накоплении итога.

Где выполнять свертку: в проведении или перед записью?

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

Правильный подход:

Альтернативный метод: Использование запроса

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Док.Должность КАК Должность,
    |   Док.Сотрудник КАК Сотрудник,
    |   СУММА(Док.КбаллФакт) КАК КбаллФакт,
    |   СУММА(Док.КдисФакт) КАК КдисФакт
    |ПОМЕСТИТЬ ВтДанные
    |ИЗ
    |   &ТчПоказатели КАК Док
    |ГРУППИРОВАТЬ ПО
    |   Должность,
    |   Сотрудник;
    |
    |ВЫБРАТЬ * ИЗ ВтДанные";

// Передаем табличную часть как параметр запроса
Запрос.УстановитьПараметр("ТчПоказатели", Показатели.Выгрузить());

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

Такой подход считается более профессиональным в среде разработки 1С, так как он более нагляден и позволяет избежать проблем с разрядностью колонок в промежуточной таблице, если вы используете функции ВЫРАЗИТЬ внутри текста запроса.

← На главную