При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью отфильтровать данные в открываемой форме (например, в форме подбора товаров) не по одному конкретному значению, а по списку. Типичный пример: нужно показать документы или товары, соответствующие сразу двум или трем видам налогообложения. В этой статье мы подробно разберем, как реализовать такую задачу, проанализируем ограничения стандартных механизмов и рассмотрим наиболее эффективные программные способы установки сложных отборов.
Рассмотрим ситуацию, когда при нажатии кнопки на форме документа должен открываться подбор. В коде это обычно выглядит как заполнение структуры ПараметрыПодбора и вызов метода ОткрытьФорму(). По умолчанию, если мы передаем в структуру параметр, соответствующий имени поля в форме подбора, платформа пытается применить отбор по принципу "Равно".
Проанализируем пример кода, с которого началось обсуждение:
&НаКлиенте
Процедура ПодборТоваровПоРеализациям()
// ... проверки заполнения полей ...
ПараметрыПодбора = Новый Структура;
ПараметрыПодбора.Вставить("НалогообложениеНДС", Объект.НалогообложениеНДС);
ОткрытьФорму(
"ОбщаяФорма.ПодборТоваровПоРеализациямИПередачам",
ПараметрыПодбора,
ЭтаФорма);
КонецПроцедуры
В данном случае, если в Объект.НалогообложениеНДС находится одно значение, подбор сработает корректно. Но что делать, если нам нужно передать массив? Если мы просто подставим Массив вместо одиночного значения, стандартная обработка параметров в типовых формах (особенно в таких сложных, как ПодборТоваровПоРеализациямИПередачам) может выдать ошибку или просто проигнорировать условие, так как ожидается конкретный тип ссылки, а не коллекция.
Если у нас есть возможность вносить изменения в форму, которую мы открываем, то самый простой логический путь — передать в структуру ПараметрыПодбора объект типа Массив. Однако, как правильно заметили участники обсуждения, в этом случае в динамическом списке формы подбора условие сравнения должно быть изменено с "=" на "В" (или "В списке").
Рассмотрим, как это работает. В процедуре ПриСозданииНаСервере открываемой формы обычно происходит получение параметров:
// В модуле открываемой формы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("НалогообложениеНДС") Тогда
// Если мы передали массив, а в запросе динамического списка стоит условие:
// ГДЕ НалогообложениеНДС = &НалогообложениеНДС
// то произойдет ошибка. Нужно менять условие на:
// ГДЕ НалогообложениеНДС В (&НалогообложениеНДС)
КонецЕсли;
КонецПроцедуры
Важный нюанс: передача отбора через параметры формы напрямую чаще всего работает только как жесткое равенство. Для реализации гибкого списка значений лучше использовать специализированные свойства платформы.
Выясним, как обойтись без изменения кода типовой формы. Мы можем получить форму программно, установить нужные настройки в её основной динамический список и только после этого вывести её на экран пользователю. Этот метод является наиболее универсальным для Управляемых форм.
Разберем по шагам реализацию этого подхода:
ПолучитьФорму().ВидСравненияКомпоновкиДанных.ВСписке.Посмотрим на пример кода:
&НаКлиенте
Процедура ОткрытьПодборСНесколькимиЗначениями()
// 1. Формируем массив значений
МассивНалогов = Новый Массив;
МассивНалогов.Добавить(ПредопределенноеЗначение("Перечисление.ТипыНалогообложенияНДС.ПродажаОблагаетсяНДС"));
МассивНалогов.Добавить(ПредопределенноеЗначение("Перечисление.ТипыНалогообложенияНДС.ПродажаНеОблагаетсяНДС"));
// 2. Получаем форму, но не открываем её сразу
ПараметрыФормы = Новый Структура; // Сюда можно передать остальные стандартные параметры
ФормаПодбора = ПолучитьФорму("ОбщаяФорма.ПодборТоваровПоРеализациямИПередачам", ПараметрыФормы, ЭтаФорма);
// 3. Устанавливаем отбор в динамическом списке формы
// Предположим, основной список в форме называется "Список"
ГруппаОтбора = ФормаПодбора.Список.Отбор.Элементы;
// Очистим старые отборы по этому полю, если они могли быть установлены автоматически
Для Каждого ЭлементОтбора Из ГруппаОтбора Цикл
Если Строка(ЭлементОтбора.ЛевоеЗначение) = "НалогообложениеНДС" Тогда
ГруппаОтбора.Удалить(ЭлементОтбора);
КонецЕсли;
КонецЦикла;
// 4. Добавляем наш новый отбор "В списке"
НовыйОтбор = ГруппаОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("НалогообложениеНДС");
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
НовыйОтбор.ПравоеЗначение = МассивНалогов;
НовыйОтбор.Использование = Истина;
НовыйОтбор.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
// 5. Теперь открываем настроенную форму
ФормаПодбора.Открыть();
КонецПроцедуры
Платформа 1С поддерживает специальный ключ Отбор в структуре параметров открытия формы. Если динамический список в открываемой форме является Основным реквизитом, система попытается автоматически применить эти значения.
Рассмотрим ситуацию: если мы передадим в Отбор структуру, где значением поля является массив, современные версии платформы 8.3 автоматически преобразуют это в условие "В списке". Посмотрим на реализацию:
&НаКлиенте
Процедура ОткрытьФормуЧерезПараметрОтбор()
МассивЗначений = Новый Массив;
МассивЗначений.Добавить(Значение1);
МассивЗначений.Добавить(Значение2);
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("НалогообложениеНДС", МассивЗначений);
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("Отбор", СтруктураОтбора);
ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", ПараметрыОткрытия);
КонецПроцедуры
Важное ограничение: этот способ отлично работает для простых форм выбора справочников или документов. Однако для сложных форм типа "Подбор товаров", где логика заполнения списка переопределена в коде (используются временные таблицы, сложные запросы в ПриСозданииНаСервере), этот стандартный механизм может быть перекрыт программным кодом типовой конфигурации. Именно поэтому Метод 2 (программная установка через объект формы) считается более надежным в ERP-системах.
Если мы хотим гарантировать, что пользователь не сможет случайно отключить наш отбор в настройках списка, проанализируем использование свойства ФиксированныеНастройки. Это объект типа НастройкиКомпоновкиДанных, который передается в параметры формы.
Разберем пример создания таких настроек:
&НаСервере
Функция ПолучитьФиксированныеНастройки()
Настройки = Новый НастройкиКомпоновкиДанных;
ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("НалогообложениеНДС");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
МассивТипов = Новый Массив;
МассивТипов.Добавить(Пречисления.ТипыНалогообложенияНДС.Облагается);
МассивТипов.Добавить(Пречисления.ТипыНалогообложенияНДС.НеОблагается);
ЭлементОтбора.ПравоеЗначение = МассивТипов;
ЭлементОтбора.Использование = Истина;
Возврат Настройки;
КонецФункции
&НаКлиенте
Процедура ОткрытьСФиксированнымиНастройками()
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ФиксированныеНастройки", ПолучитьФиксированныеНастройки());
ОткрытьФорму("ОбщаяФорма.ПодборТоваровПоРеализациямИПередачам", ПараметрыФормы);
КонецПроцедуры
Мы проанализировали несколько способов передачи множественных значений в отбор. Подведем итоги выбора решения:
Параметры.Отбор с передачей массива.ПолучитьФорму() и обращение к Элементы.Отбор динамического списка.ФиксированныеНастройки.Помните, что при работе с типовыми конфигурациями важно проверять, как именно называется основной реквизит списка в форме (это может быть не только Список, но и Товары, Документы и т.д.), чтобы правильно обратиться к его свойствам из вызывающего кода.