Почему в отчете СКД выводятся неверные итоги при добавлении новых полей?

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

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

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

Разберем типичную ситуацию на примере запроса к виртуальной таблице ОстаткиИОбороты. Зачастую разработчики пытаются «облагородить» данные прямо в тексте запроса, используя функции ЕСТЬNULL или ВЫРАЗИТЬ. Посмотрим на пример кода, который приводит к проблемам:


ВЫБРАТЬ
    ЕСТЬNULL(ВЫРАЗИТЬ(ВзаиморасчетыСТаможнейОстаткиИОбороты.СуммаНачальныйОстаток КАК ЧИСЛО(15, 2)), 0) КАК СуммаНачальныйОстаток,
    ЕСТЬNULL(ВЫРАЗИТЬ(ВзаиморасчетыСТаможнейОстаткиИОбороты.СуммаПриход КАК ЧИСЛО(15, 2)), 0) КАК СуммаПриход,
    ВзаиморасчетыСТаможнейОстаткиИОбороты.Регистратор,
    ЕСТЬNULL(ВзаиморасчетыСТаможнейОстаткиИОбороты.Регистратор.НомерГТД, "") КАК НомерГТД,
    ВзаиморасчетыСТаможнейОстаткиИОбороты.Валюта
ИЗ
    РегистрНакопления.ВзаиморасчетыСТаможней.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, Движения, ) КАК ВзаиморасчетыСТаможнейОстаткиИОбороты

В данном примере мы видим сразу несколько потенциальных причин некорректного расчета итогов. Проанализируем их по порядку. Во-первых, использование конструкций ВЫРАЗИТЬ и ЕСТЬNULL для полей ресурсов (остатков). СКД рассчитывает остатки по особым алгоритмам, опираясь на метаданные. Когда мы оборачиваем поле в функцию, система может потерять связь этого поля с конкретным измерением или периодом. Во-вторых, обращение к реквизитам через точку от поля Регистратор (например, Регистратор.НомерГТД) внутри виртуальной таблицы остатков и оборотов часто приводит к неявным соединениям, которые дублируют строки, если у одного регистратора оказывается несколько связанных записей.

Механизм расчета остатков в СКД и роль полей

Выясним причину, по которой СКД «ошибается». В отличие от простых оборотных полей, которые суммируются линейно, остатки — это значения на конкретную временную точку. СКД вычисляет их, исходя из настроек на закладке «Роли» в наборе данных.

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

  1. Поле остатка: Убедитесь, что для начального остатка указан тип «Начальный остаток», а для конечного — «Конечный остаток».
  2. Имя: Оба поля (начальный и конечный остаток) должны иметь одинаковое имя в колонке «Имя» роли (например, Сумма), чтобы СКД понимала, что это разные состояния одного и того же ресурса.
  3. Связь по периоду: В роли поля остатка обязательно должно быть указано соответствующее поле периода (например, ПериодСекунда).

Проблема использования обращений «через точку»

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

Правильный подход заключается в следующем: если вам нужно вывести реквизит регистратора, вы должны добавить в группировку само поле Регистратор, а нужный реквизит (например, Организация) выводить как дополнительное поле этой группировки. Если же необходимо именно группировать данные по организации, которая не является измерением, но есть в регистраторе, следует использовать механизм родительских полей в ролях СКД.

Настройка родительских полей в СКД

Проанализируем настройку ролей для дочерних реквизитов. Если мы вытащили поле РегистраторОрганизация (через точку или ЕСТЬNULL), нам нужно зайти в настройки ролей этого поля в наборе данных СКД:

  1. Найдите строку с вашим полем (например, СтатусДокумента или НомерГТД).
  2. В колонке «Роль» откройте окно редактирования.
  3. Установите в качестве родительского поля — Регистратор.

Это «подскажет» системе компоновки, что данное поле является лишь свойством регистратора. В этом случае СКД поймет, что остаток не нужно множить на количество таких свойств, а нужно брать его один раз для каждой уникальной комбинации измерений и регистратора.

Влияние периодичности «Авто»

Посмотрим на параметр периодичности в виртуальной таблице: ОстаткиИОбороты(..., Авто, ...). Режим Авто удобен, но коварен. При его использовании СКД самостоятельно анализирует настройки отчета и выбирает минимально необходимый период. Однако, если в запросе намешаны и регистратор, и периоды, и сложные выражения с ЕСТЬNULL, система может построить запрос с избыточным вложением. Это часто приводит к тому, что записи движений начинают дублироваться, что моментально сказывается на итогах.

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

Работа с ресурсами и формулами

Разберем еще один важный аспект — закладку «Ресурсы». Для полей остатков формула расчета обычно выглядит как Сумма(НачальныйОстаток). Но крайне важно обратить внимание на колонку «Рассчитывать по...».

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

Рекомендации по исправлению

Подведем итог и составим пошаговый план действий для исправления некорректных итогов:

  1. Очистите запрос от лишних преобразований: Уберите ЕСТЬNULL и ВЫРАЗИТЬ для полей остатков и оборотов в самом тексте запроса. Эти операции лучше выполнять в настройках полей на уровне СКД (вкладка «Оформление» или «Вычисляемые поля»), чтобы не ломать метаданные виртуальной таблицы.
  2. Минимизируйте точки в запросе: Старайтесь не вытягивать реквизиты через точку внутри виртуальной таблицы. Лучше выбрать само поле-ссылку (например, ПлатежноеПоручение), а его реквизиты СКД подтянет автоматически, если они понадобятся пользователю в отчете.
  3. Настройте роли: Для всех «нештатных» полей, которые вы добавили в отчет и по которым считаются итоги, проверьте связь с периодом и родителем (Регистратором).
  4. Флаг «Игнорировать значения NULL»: В настройках роли поля остатка установите этот флаг. Это помогает корректно обрабатывать ситуации, когда по каким-то измерениям в определенные периоды не было движений.
  5. Проверьте уникальность: Убедитесь, что добавленное поле не создает ситуацию «один ко многим» для одной записи регистра. Если одному регистратору соответствует несколько значений вашего поля, итоги неизбежно «поплывут», так как остаток будет привязан к каждой строке.

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

← На главную