Разработка отчетов в системе компоновки данных (СКД) часто преподносит сюрпризы, когда дело доходит до вывода остатков в разрезе документов. Классическая ситуация: отчет без детализации показывает идеальные цифры, но стоит добавить группировку по полю Регистратор, как начальные и конечные остатки начинают «плыть», дублироваться или принимать странные значения. Проанализируем, почему это происходит, и разберем по шагам, как настроить отчет правильно.
Основная причина кроется в механизме работы виртуальных таблиц «ОстаткиИОбороты». Когда мы включаем в запрос поле Регистратор, СКД должна четко понимать иерархию периодов. Если настройки ролей полей в схеме компоновки заданы неверно или не заданы вовсе, система не может правильно сопоставить записи оборотов с остатками на конкретный момент времени. Еще одна частая причина — использование в группировках реквизитов измерений (например, Номенклатура.ВидНоменклатуры), которые СКД ошибочно начинает считать самостоятельными измерениями, что приводит к некорректному распределению итогов.
Для корректной работы отчета с регистратором в запросе обязательно должны присутствовать поля периодов разной детализации. Рассмотрим пример запроса к регистру накопления:
ВЫБРАТЬ
СырьеОстаткиИОбороты.Регистратор КАК Регистратор,
СырьеОстаткиИОбороты.ПериодСекунда КАК ПериодСекунда,
СырьеОстаткиИОбороты.МПЗ КАК МПЗ,
СырьеОстаткиИОбороты.МПЗ.ВидМатериала КАК ВидМатериала,
СырьеОстаткиИОбороты.МестоХранения КАК МестоХранения,
СырьеОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток,
СырьеОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
СырьеОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
СырьеОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток
ИЗ
РегистрНакопления.Сырье.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК СырьеОстаткиИОбороты
Обратим внимание на использование периодичности Авто в параметрах виртуальной таблицы. Это позволяет СКД самостоятельно выбирать нужные периоды, но накладывает на нас обязанность правильно настроить роли этих полей на вкладке «Наборы данных».
Это самый важный этап. Выясним, как правильно расставить «веса» периодов, чтобы остатки считались последовательно. Перейдем на вкладку «Наборы данных» и найдем колонку «Роль» для наших полей:
ПериодСекунда:
Регистратор:
Важно: нумерация периодов (1, 2, 3...) указывает системе строгую последовательность их следования. Если мы выводим отчет за день, месяц и секунду, каждый уровень должен иметь свой номер. Это гарантирует, что остаток на конец одного регистратора станет начальным остатком для следующего.
Часто пользователь хочет видеть группировку не только по МПЗ, но и по его свойству, например, ВидМатериала. Если просто добавить это поле в отчет, остатки могут «развалиться». Проанализируем решение этой ситуации:
Для поля ВидМатериала (которое является реквизитом МПЗ.ВидМатериала) в настройках роли необходимо:
МПЗ.Это действие «привязывает» реквизит к его владельцу. Теперь СКД понимает, что остатки нужно считать по МПЗ, а ВидМатериала — это просто дополнительный разрез того же самого измерения, а не новая независимая координата.
При использовании детализации до регистратора в отчете часто появляются две «лишние» строки: в самом начале (с начальным остатком на границу периода) и в самом конце (с конечным остатком). Регистратор в них пустой (равен NULL или Неопределено).
Рассмотрим несколько способов борьбы с этим визуальным дефектом:
Регистратор в выражении запроса можно использовать функцию ЕСТЬNULL(Регистратор, NULL). В настройках роли поля Регистратор установим флажок Игнорировать NULL. Это часто помогает скрыть пустые строки.Регистратор Заполнено. Однако будьте осторожны: если убрать эти строки, общие итоги в шапке отчета могут измениться, так как СКД может исключить входящее сальдо из общего расчета.Если стандартная таблица ОстаткиИОбороты продолжает вести себя некорректно (например, при сложных соединениях с другими таблицами), можно использовать метод объединения двух разных наборов данных. Рассмотрим эту схему:
Остатки на начало периода.Обороты в разрезе регистраторов.Номенклатуре и Складу).Сумма(НачальныйОстаток) + Сумма(Приход) - Сумма(Расход).Этот метод считается более трудоемким, но он дает 100% контроль над тем, какие строки попадают в отчет, и полностью исключает появление «фантомных» записей с пустыми регистраторами.
Проанализируем настройки на вкладке «Ресурсы». Для полей остатков (Начальный и Конечный) важно правильно указать выражение. Вместо простой суммы Сумма(КоличествоНачальныйОстаток) лучше использовать специализированные функции СКД, если вы используете несколько уровней периодов:
// Для начального остатка
ВычислитьВыражение("Сумма(КоличествоНачальныйОстаток)", "ПериодСекунда", "Группировка", "Первая", "Первая")
// Для конечного остатка
ВычислитьВыражение("Сумма(КоличествоКонечныйОстаток)", "ПериодСекунда", "Группировка", "Последняя", "Последняя")
Хотя в большинстве простых случаев СКД корректно отрабатывает стандартную функцию Сумма(...), если правильно настроены Роли полей, как мы разобрали выше. Всегда начинайте исправление именно с проверки ролей периодов и указания родительских измерений для атрибутов.