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