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