Как исправить неверные остатки в СКД при группировке по Регистратору

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

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

Почему возникают ошибки в остатках?

Основная причина кроется в механизме работы виртуальных таблиц «ОстаткиИОбороты». Когда мы включаем в запрос поле Регистратор, СКД должна четко понимать иерархию периодов. Если настройки ролей полей в схеме компоновки заданы неверно или не заданы вовсе, система не может правильно сопоставить записи оборотов с остатками на конкретный момент времени. Еще одна частая причина — использование в группировках реквизитов измерений (например, Номенклатура.ВидНоменклатуры), которые СКД ошибочно начинает считать самостоятельными измерениями, что приводит к некорректному распределению итогов.

Шаг 1: Правильное построение запроса

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


ВЫБРАТЬ
    СырьеОстаткиИОбороты.Регистратор КАК Регистратор,
    СырьеОстаткиИОбороты.ПериодСекунда КАК ПериодСекунда,
    СырьеОстаткиИОбороты.МПЗ КАК МПЗ,
    СырьеОстаткиИОбороты.МПЗ.ВидМатериала КАК ВидМатериала,
    СырьеОстаткиИОбороты.МестоХранения КАК МестоХранения,
    СырьеОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток,
    СырьеОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
    СырьеОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
    СырьеОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток
ИЗ
    РегистрНакопления.Сырье.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК СырьеОстаткиИОбороты

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

Шаг 2: Настройка ролей полей периода

Это самый важный этап. Выясним, как правильно расставить «веса» периодов, чтобы остатки считались последовательно. Перейдем на вкладку «Наборы данных» и найдем колонку «Роль» для наших полей:

  1. Для поля ПериодСекунда:
    • Установим флажок Период.
    • Тип периода — Дополнительный.
    • Порядковый номер — 1.
  2. Для поля Регистратор:
    • Установим флажок Период.
    • Тип периода — Основной.
    • Порядковый номер — 2.

Важно: нумерация периодов (1, 2, 3...) указывает системе строгую последовательность их следования. Если мы выводим отчет за день, месяц и секунду, каждый уровень должен иметь свой номер. Это гарантирует, что остаток на конец одного регистратора станет начальным остатком для следующего.

Шаг 3: Решение проблемы с реквизитами измерений

Часто пользователь хочет видеть группировку не только по МПЗ, но и по его свойству, например, ВидМатериала. Если просто добавить это поле в отчет, остатки могут «развалиться». Проанализируем решение этой ситуации:

Для поля ВидМатериала (которое является реквизитом МПЗ.ВидМатериала) в настройках роли необходимо:

  1. Указать, что это Измерение.
  2. В поле Родитель обязательно выбрать основное измерение — МПЗ.

Это действие «привязывает» реквизит к его владельцу. Теперь СКД понимает, что остатки нужно считать по МПЗ, а ВидМатериала — это просто дополнительный разрез того же самого измерения, а не новая независимая координата.

Шаг 4: Как убрать пустые строки с остатками

При использовании детализации до регистратора в отчете часто появляются две «лишние» строки: в самом начале (с начальным остатком на границу периода) и в самом конце (с конечным остатком). Регистратор в них пустой (равен NULL или Неопределено).

Рассмотрим несколько способов борьбы с этим визуальным дефектом:

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

Шаг 5: Альтернативный метод (Объединение таблиц)

Если стандартная таблица ОстаткиИОбороты продолжает вести себя некорректно (например, при сложных соединениях с другими таблицами), можно использовать метод объединения двух разных наборов данных. Рассмотрим эту схему:

  1. Создаем Набор данных 1: выбираем только остатки из таблицы Остатки на начало периода.
  2. Создаем Набор данных 2: выбираем только обороты из таблицы Обороты в разрезе регистраторов.
  3. В СКД объединяем их по измерениям (например, по Номенклатуре и Складу).
  4. Остатки на конец периода рассчитываем в ресурсах СКД по формуле: Сумма(НачальныйОстаток) + Сумма(Приход) - Сумма(Расход).

Этот метод считается более трудоемким, но он дает 100% контроль над тем, какие строки попадают в отчет, и полностью исключает появление «фантомных» записей с пустыми регистраторами.

Резюме по настройке ресурсов

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


// Для начального остатка
ВычислитьВыражение("Сумма(КоличествоНачальныйОстаток)", "ПериодСекунда", "Группировка", "Первая", "Первая")

// Для конечного остатка
ВычислитьВыражение("Сумма(КоличествоКонечныйОстаток)", "ПериодСекунда", "Группировка", "Последняя", "Последняя")

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

← На главную