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