Как убрать пустые строки с пустым регистратором в отчете СКД "Остатки и обороты"?

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

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

Попытки установить банальный отбор вида "Регистратор Заполнено" приводят к другой проблеме: из отчета полностью пропадают строки с начальными и конечными остатками, что делает отчет некорректным. В этой статье мы подробно разберем, почему возникает этот эффект, и рассмотрим несколько эффективных способов его полного устранения.

Выясняем причину: механика работы виртуальной таблицы

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

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

Платформа 1С вынуждена генерировать эти строки-границы, чтобы компоновщик данных мог корректно рассчитать и вывести остатки на начало и на конец. Если за весь выбранный период движений не было вообще, мы получаем ровно две строки с пустыми регистраторами. Наша задача — скрыть эти сервисные строки от пользователя, не повредив при этом расчет итоговых показателей.

Рассмотрим подробнее по шагам все доступные способы решения этой проблемы.

Решение №1: Приведение НЕОПРЕДЕЛЕНО к NULL и включение флага "Игнорировать NULL"

По умолчанию в СКД для полей-периодов (к которым относится и Регистратор) предусмотрена опция "Игнорировать NULL". Однако этот механизм работает только тогда, когда значение поля действительно равно NULL. В виртуальной таблице остатков и оборотов в качестве пустого регистратора часто выступает значение НЕОПРЕДЕЛЕНО. Чтобы СКД смогла отсечь эти строки, нам нужно принудительно преобразовать это значение в запросе.

Разберем, как изменить запрос в конструкторе схемы компоновки данных. Вместо простого выбора поля Регистратор мы применим конструкцию ВЫБОР:


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

После изменения текста запроса необходимо выполнить следующие действия в СКД:

  1. Перейдите на вкладку "Наборы данных".
  2. Найдите в списке полей наше поле Регистратор.
  3. В колонке "Роль" нажмите на кнопку редактирования параметров роли.
  4. Убедитесь, что для роли установлен признак "Игнорировать NULL".

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

Решение №2: Правильная настройка ролей полей (Регистратор + ПериодСекунда)

Очень часто простое включение флага "Игнорировать NULL" у регистратора не дает желаемого результата. Происходит это потому, что СКД не понимает связь временных периодов в запросе. Чтобы механизм отработал штатно, в схеме компоновки данных необходимо жестко задать роли для всех временных полей.

Выясним, какие поля обязательно должны присутствовать в запросе. Нам понадобятся поля Регистратор и ПериодСекунда. Выберем их в запросе и настроим их роли следующим образом:

  1. Для поля Регистратор:
    • Тип роли: Период.
    • Порядковый номер периода: 1.
    • Флаг "Игнорировать NULL": Должен быть установлен.
  2. Для поля ПериодСекунда (его обязательно нужно выбрать в запросе и вытащить на вкладку "Наборы данных"):
    • Тип роли: Период.
    • Порядковый номер периода: 2.
    • Флаг "Обязательное": Обязательно установите этот флаг.

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

Решение №3: Изменение структуры группировок (Отказ от детальных записей)

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

Посмотрим на пример правильной настройки структуры отчета на вкладке "Настройки" в СКД:

  1. Удалите стандартную группировку "Детальные записи" из корня структуры отчета.
  2. Вместо нее создайте иерархическую структуру группировок. Например, сначала сгруппируйте данные по аналитике: Номенклатура, затем внутри нее добавьте группировку по полю Регистратор.
  3. Выделите созданную группировку по полю Регистратор и перейдите на ее локальную вкладку "Отбор" (настройки отбора именно для этой группировки, а не для всего отчета в целом!).
  4. Добавьте условие отбора: Регистратор Заполнено (или Регистратор ЕСТЬ НЕ NULL).

Проанализируем, как теперь будет работать отчет. На уровне родительской группировки (например, Номенклатура) СКД рассчитает и выведет абсолютно корректные остатки на начало и на конец периода, так как глобальный отбор на отчет не накладывался. При этом внутри группировки по номенклатуре подчиненная группировка по регистраторам просто скроет пустые строки-границы, так как сработает локальный отбор группировки. В итоге пользователь увидит только красивые строки с реальными документами движения.

Решение №4: Разделение запроса на Обороты и Остатки (Универсальный ручной метод)

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

В этом случае мы рекомендуем отказаться от использования виртуальной таблицы ОстаткиИОбороты и собрать данные вручную с помощью объединения нескольких таблиц.

Рассмотрим структуру такого запроса:


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

ОБЪЕДИНИТЬ ВСЕ

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

ОБЪЕДИНИТЬ ВСЕ

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

После объединения таблиц в СКД необходимо зайти на вкладку "Роли" для полей ресурсов (остатков) и настроить их связь. Мы указываем СКД, какие поля отвечают за начальный остаток, а какие — за конечный. Так как мы полностью контролируем получение данных и самостоятельно разделили обороты и остатки, СКД не будет генерировать лишние системные строки-границы. Нам останется лишь включить флаг "Игнорировать NULL" для поля Регистратор, и отчет примет идеальный вид.

← На главную