При разработке сложных конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача ограничить список выбора (например, справочника Номенклатура) в зависимости от того, в каком документе пользователь вводит данные. Стандартный механизм «ввода по строке» вызывает событие ОбработкаПолученияДанныхВыбора в модуле менеджера справочника. Однако здесь разработчик сталкивается с серьезным ограничением: этот метод выполняется на сервере в контексте менеджера объекта, и он «не знает», из какой именно формы (документа поступления, реализации или требования-накладной) был инициирован запрос.
В этой статье мы подробно разберем, как передать контекст формы в модуль менеджера, рассмотрим архитектурные подходы БСП (Библиотеки Стандартных Подсистем) и научимся внедрять универсальные решения, не требующие ручной правки каждой формы в конфигурации.
Когда пользователь начинает набирать первые буквы наименования в поле ввода, платформа автоматически инициирует поиск. В этот момент срабатывает обработчик:
Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
// Здесь мы должны сформировать список ДанныеВыбора
КонецПроцедуры
Параметр Параметры имеет тип Структура. По умолчанию он содержит такие ключи, как СтрокаПоиска, ВыборГруппИЭлементов, СпособПоиска и Отбор. Но в нем отсутствует информация о владельце формы или имени самой формы. Если нам нужно запретить выбор определенной группы номенклатуры только для «Документа А», но разрешить для «Документа Б», нам необходимо найти способ «пробросить» идентификатор документа в эту структуру.
Если конфигурация построена на базе ERP, КА 2 или УТ 11, мы можем воспользоваться механизмом переопределения событий форм. Это самый элегантный способ, позволяющий избежать модификации сотен объектов метаданных. Мы внедрим логику в общие модули, которые отвечают за создание форм.
Рассмотрим по шагам, как это реализовать:
МодификацияКонфигурацииПереопределяемый или специализированные модули БСП типа СобытияФорм).ПриСозданииНаСервере.ПараметрыВыбора нужный нам контекст.Проанализируем пример кода для расширения общего модуля:
&После("ПриСозданииНаСервере")
Процедура Инт_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Определим список типов документов, для которых нужна фильтрация
// Это можно вынести в настройки или регистр сведений
Для Каждого Элемент Из ЭтаФорма.Элементы Цикл
// Проверяем, является ли элемент полем ввода и связан ли он с номенклатурой
Если ТипЗнч(Элемент) = Тип("ПолеФормы")
И Элемент.Вид = ВидПоляФормы.ПолеВвода Тогда
// Нам нужно убедиться, что путь к данным ведет к справочнику Номенклатура
// Для упрощения можно проверять имя поля, если оно стандартизировано
Если Найти(Элемент.ПутьКДанным, "Номенклатура") > 0 Тогда
// Формируем структуру параметров выбора
НовыйПараметр = Новый ПараметрВыбора("ИмяФормыВладельца", ЭтаФорма.ИмяФормы);
// Добавляем параметр в массив параметров выбора элемента
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(НовыйПараметр);
Элемент.ПараметрыВыбора = Новый ФиксированныйМассив(МассивПараметров);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот подход позволяет централизованно пометить все поля номенклатуры во всех формах системы тегом с именем формы.
Теперь, когда мы научили форму передавать свое имя, нам нужно научить модуль менеджера справочника Номенклатура принимать и обрабатывать эти данные. Разберем, как изменить стандартную логику поиска.
В модуле менеджера справочника Номенклатура (лучше также через расширение) модифицируем процедуру ОбработкаПолученияДанныхВыбора:
&Вместо("ОбработкаПолученияДанныхВыбора")
Процедура Инт_ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
// Проверяем, пришел ли наш хитрый параметр
ИмяФормы = "";
Если Параметры.Свойство("ИмяФормыВладельца", ИмяФормы) Тогда
// Теперь мы точно знаем, откуда пришел запрос!
Если ИмяФормы = "Документ.ПоступлениеТоваровУслуг.Форма.ФормаДокумента" Тогда
// Устанавливаем СтандартнаяОбработка в Ложь, чтобы выполнить свой запрос
СтандартнаяОбработка = Ложь;
// Выполняем запрос с учетом ограничений
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 40
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО &СтрокаПоиска
| И НЕ Номенклатура.ЭтоГруппа
| И НЕ Номенклатура.Ссылка В ИЕРАРХИИ(&ЗапрещеннаяГруппа)";
Запрос.УстановитьПараметр("СтрокаПоиска", "%" + Параметры.СтрокаПоиска + "%");
Запрос.УстановитьПараметр("ЗапрещеннаяГруппа", ПолучитьЗапрещеннуюГруппуДляПоступления());
Выборка = Запрос.Выполнить().Выбрать();
СписокРезультатов = Новый СписокЗначений;
Пока Выборка.Следующий() Цикл
СписокРезультатов.Добавить(Выборка.Ссылка, Выборка.Наименование);
КонецЦикла;
ДанныеВыбора = СписокРезультатов;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Выясним, существует ли способ решить задачу без написания кода в каждой форме. В платформе 1С предусмотрен механизм СвязиПараметровВыбора. Рассмотрим его возможности.
Если в документе есть реквизит (например, Склад или Подразделение), от которого должен зависеть список номенклатуры, мы можем настроить связь в метаданных поля формы. В этом случае значение указанного реквизита будет автоматически попадать в структуру Параметры.Отбор в модуле менеджера.
Алгоритм настройки:
Номенклатура в табличной части.Отбор.Склад) и путь к данным (например, Объект.Склад).Хотя этот метод не передает само имя формы, он позволяет передать любой реквизит объекта, по которому в модуле менеджера можно косвенно понять контекст или просто применить фильтр по значению этого реквизита.
При реализации собственного поиска в ОбработкаПолученияДанныхВыбора крайне важно соблюдать следующие правила:
ПОДОБНО, он может работать медленнее на огромных базах.Мы проанализировали ситуацию, когда стандартных средств платформы недостаточно для идентификации контекста вызова в модуле менеджера. Самым эффективным и масштабируемым решением является комбинированный подход:
ПараметрыВыбора через общий модуль БСП (используя расширение).ОбработкаПолученияДанныхВыбора в модуле менеджера справочника.Такой метод позволяет сохранить чистоту основной конфигурации и реализовать бизнес-логику любой сложности в одном месте, обеспечивая удобство работы пользователей при выборе данных.