Как в СКД сделать отбор по типу документа регистратора?

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

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

В этой статье мы подробно разберем несколько практических способов реализации такого отбора — от простых условий в запросе до продвинутых и максимально оптимизированных методов с использованием встроенных механизмов СКД.

Решение 1. Жесткое ограничение типов документов в тексте запроса

Рассмотрим ситуацию, когда требования к отчету однозначно определяют: данные должны выбираться только для конкретных видов документов, и пользователю не нужно давать возможность этот список расширять. В этом случае проще всего наложить ограничение непосредственно в тексте запроса с помощью оператора ССЫЛКА.

Давайте проанализируем исходный запрос, который выбирает данные из регистра накопления:


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

Чтобы ограничить выборку документов только типами ОприходованиеТоваров и СписаниеТоваров, мы добавим в секцию ГДЕ проверку типа ссылки регистратора:


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

Преимущества метода:

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

Недостатки метода:

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

Решение 2. Использование функции ТИПЗНАЧЕНИЯ в запросе

Если мы хотим дать пользователю возможность самостоятельно выбирать типы документов в настройках отчета, то одним из очевидных решений является вычисление типа регистратора прямо в запросе. Для этого используется встроенная функция ТИПЗНАЧЕНИЯ.

Модифицируем наш запрос следующим образом:


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

После добавления поля ТипДокумента выполним следующие шаги в конструкторе СКД:

  1. Перейдем на вкладку «Настройки».
  2. Выберем вкладку «Отбор» в нижней части окна настроек.
  3. Добавим наше новое доступное поле ТипДокумента в список отборов.
  4. Установим вид сравнения, например, Равно или В списке, и выведем этот отбор на форму (сделаем его быстрым доступом для пользователя).

Важное предупреждение о производительности! Этот метод таит в себе серьезную опасность для больших баз данных. Дело в том, что поле Регистратор имеет составной тип данных, который может состоять из десятков различных документов. При выполнении функции ТИПЗНАЧЕНИЯ(Регистратор) на уровне СУБД (например, MS SQL Server или PostgreSQL) генерируется огромная конструкция CASE WHEN ... THEN ... для сопоставления внутренних табличных идентификаторов типов. Если в регистре накопления содержатся миллионы записей, СУБД будет вынуждена произвести полное сканирование таблицы (Table Scan), что приведет к колоссальной нагрузке на процессор сервера и долгому формированию отчета.

Решение 3. Оптимальный встроенный способ СКД (без изменения запроса)

Платформа 1С:Предприятие обладает мощными встроенными механизмами оптимизации, о которых начинающие разработчики часто не знают. СКД умеет самостоятельно накладывать эффективные SQL-фильтры по типам составных полей. Мы можем организовать отбор без искусственного добавления поля ТИПЗНАЧЕНИЯ в запрос.

Давайте разберем по шагам, как это настроить:

  1. Оставим исходный запрос без изменений (не добавляя в него поле ТипДокумента).
  2. В конструкторе СКД перейдем на вкладку «Настройки», а затем на вкладку «Отбор».
  3. Добавим в отбор стандартное поле Регистратор.
  4. В колонке «Вид сравнения» выберем один из специальных типов сравнения:
    • Тип — если пользователю нужно выбрать строго один вид документа (например, только ДокументСсылка.СписаниеТоваров).
    • В списке типов (или Тип в списке) — если нужно предоставить пользователю возможность выбрать несколько видов документов одновременно.
  5. В колонке «Значение» выберем интересующие нас типы документов из дерева метаданных конфигурации.

Почему это оптимально: При использовании этого механизма платформа 1С на уровне генерации итогового SQL-запроса подставит точные условия проверки типов без тяжелых вычислений «на лету». СУБД отработает этот запрос максимально быстро, используя индексы таблицы регистрации.

Решение 4. Использование фигурных скобок {ГДЕ ...} в запросе СКД

Если нам необходимо совместить гибкость пользовательского интерфейса и жесткое ограничение разработчика, лучшим решением станет использование расширения языка запросов СКД — фигурных скобок {ГДЕ ...}.

Посмотрим, как выглядит такой запрос:


ВЫБРАТЬ
    ПартииТоваровНаСкладах.Период,
    ПартииТоваровНаСкладах.Регистратор,
    ПартииТоваровНаСкладах.Номенклатура,
    ПартииТоваровНаСкладах.ХарактеристикаНоменклатуры,
    ПартииТоваровНаСкладах.Количество,
    ПартииТоваровНаСкладах.Стоимость,
    ПартииТоваровНаСкладах.Регистратор.Подразделение КАК Подразделение,
    ПартииТоваровНаСкладах.Основание
ИЗ
    РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
{ГДЕ
    (ПартииТоваровНаСкладах.Регистратор ССЫЛКА Документ.ОприходованиеТоваров
    ИЛИ ПартииТоваровНаСкладах.Регистратор ССЫЛКА Документ.СписаниеТоваров)}

Как это работает:

  1. Если пользователь в настройках отчета не устанавливает данный отбор, то условие внутри фигурных скобок полностью игнорируется платформой, и в СУБД уходит легкий запрос без лишних проверок.
  2. Как только пользователь активирует этот отбор на форме, СКД динамически подставляет условия ССЫЛКА в результирующий SQL-запрос, обеспечивая высокое быстродействие системы.

Решение 5. Программный метод через параметр типа «ОписаниеТипов»

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

Рассмотрим, как это реализовать:

  1. В СКД на вкладке «Параметры» создадим новый параметр с именем ТипДокументаРегистратора.
  2. Зададим ему тип данных ОписаниеТипов. В ограничении типов выберем только те документы, которые разрешено выбирать пользователю (например, ДокументСсылка.ОприходованиеТоваров и ДокументСсылка.СписаниеТоваров).
  3. Выведем этот параметр на форму отчета. Теперь пользователю будет доступен лаконичный выбор только из этих двух типов документов.
  4. В модуле объекта отчета напишем обработчик события ПриКомпоновкеРезультата, который будет считывать значение этого параметра и динамически добавлять элемент отбора в компоновщик настроек:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Получаем текущие настройки отчета
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Находим наш параметр
    ПараметрТип = Настройки.ПараметрыДанных.Элементы.Найти("ТипДокументаРегистратора");
    
    Если ПараметрТип <> Неопределено И ПараметрТип.Использование И ЗначениеЗаполнено(ПараметрТип.Значение) Тогда
        
        // Создаем новый элемент отбора по полю Регистратор
        НовыйОтбор = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Регистратор");
        НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Тип;
        НовыйОтбор.ПравоеЗначение = ПараметрТип.Значение;
        НовыйОтбор.Использование = Истина;
        
    КонецЕсли;
    
    // Выполняем компоновку с новыми настройками
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Этот метод сочетает в себе максимальное удобство для конечного пользователя (которому не нужно блуждать по огромному списку метаданных) и высокую производительность запросов к базе данных.

Резюме и рекомендации

Мы подробно разобрали пять различных подходов к решению задачи. Подведем итоги:

← На главную