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