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