Как в отчете на СКД отобрать номенклатуру, которая находится более чем в одной ячейке?

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

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

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

Проанализируем внутренний механизм работы платформы 1С:Предприятие при формировании отчетов на СКД. Системные поля НомерПоПорядку и НомерПоПорядкуВГруппировке рассчитываются процессором вывода непосредственно в момент построения итогового табличного документа. К этому моменту все этапы компоновки данных, включая применение условий отбора, уже завершены.

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

Способ 1. Настройка отчета в пользовательском режиме через «Изменить вариант»

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

  1. Откроем форму отчета, перейдем в меню Еще и выберем пункт Прочее > Изменить вариант....
  2. Перейдем на вкладку Пользовательские поля, нажмем кнопку Добавить и выберем тип Новое поле-выражение.
  3. В поле Заголовок укажем понятное наименование, например, Количество ячеек.
  4. В строке Выражение итоговых записей напишем агрегатную формулу: Количество(Различные Ячейка). Строку детальных записей оставляем пустой.
  5. В структуре отчета в верхнем окне выделим группировку Номенклатура (обратим внимание: отбор должен накладываться именно на группировку номенклатуры, а не на корень отчета или детальные записи ячеек).
  6. В нижней части окна перейдем на вкладку Отбор и добавим новое условие: выберем наше пользовательское поле Количество ячеек, укажем вид сравнения Больше и значение 1.
  7. Нажмем Завершить редактирование и сформируем отчет.

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

Способ 2. Добавление ресурса в схеме компоновки данных (в Конфигураторе)

Если мы разрабатываем собственный отчет или дорабатываем существующую схему в конфигураторе, правильнее зафиксировать логику расчета на уровне ресурсов схемы:

  1. Откроем схему компоновки данных и перейдем на вкладку Ресурсы.
  2. Добавим поле Ячейка (или соответствующее поле места хранения).
  3. В колонке Выражение зададим: Количество(Различные Ячейка).
  4. В колонке Рассчитывать по... обязательно укажем группировку Номенклатура, чтобы ресурс не вычислялся для детальных записей ячеек.
  5. На вкладке Настройки на уровне группировки Номенклатура перейдем на закладку Отбор и установим условие: Ячейка (Количество различных) Больше 1.

Способ 3. Фильтрация на уровне запроса для больших объемов данных

Когда складской регистр содержит сотни тысяч записей, фильтрация средствами постобработки СКД может работать медленнее, так как платформа сначала выбирает все остатки в память, а затем отсекает лишнее. Оптимизируем выборку на уровне СУБД с помощью конструкции ИМЕЮЩИЕ (HAVING).

Посмотрим на пример текста запроса набора данных:


ВЫБРАТЬ
    Остатки.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВТ_НоменклатураСДублямиЯчеек
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК Остатки
СГРУППИРОВАТЬ ПО
    Остатки.Номенклатура
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Остатки.Ячейка) > 1
;

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

В этом запросе мы предварительно собираем только те товары, которые числятся более чем в одной ячейке, во временную таблицу ВТ_НоменклатураСДублямиЯчеек, а затем внутренним соединением получаем полные остатки только по отобранным позициям. Это существенно снижает нагрузку на сервер 1С и ускоряет вывод отчета.

Частые ошибки при настройке отбора

Выделим ключевые моменты, на которые стоит обратить внимание при настройке отчета:

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