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