Как передать отбор по контрагенту в список значений договоров в 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок часто возникает задача организовать выбор нескольких договоров, относящихся к определенному контрагенту. Типичная ситуация: на форме размещены поле ввода с типом СправочникСсылка.Контрагенты и поле ввода с типом СписокЗначений, содержащее элементы СправочникСсылка.ДоговорыКонтрагентов. Однако при интерактивном добавлении нового договора в открывающемся модальном окне редактирования списка платформа 1С сначала открывает справочник Контрагенты, требуя указать владельца. Рассмотрим, почему это происходит и какими способами можно реализовать удобный отбор договоров по выбранному контрагенту.

Причина поведения платформы и ограничения обычных форм

Справочник ДоговорыКонтрагентов является подчиненным справочнику Контрагенты. При интерактивном добавлении строки в стандартное системное окно «Редактирование списка значений» платформа 1С не знает контекста владельца, поэтому принудительно открывает выбор родительского объекта.

Стандартное окно редактирования списка значений является встроенным платформенным диалогом, и разработчик не имеет прямого доступа к его внутренним событиям и элементам управления. Разберем основные способы обхода этого ограничения для обычных форм и управляемого интерфейса.

Способ 1. Использование табличного поля и свойства «ВыборПоВладельцу»

Разберем вариант, когда список значений размещается на обычной форме не как простое поле ввода, а как элемент управления Табличное поле. В этом случае у колонки значения появляется собственное поле ввода, которому можно напрямую передать владельца.

Для реализации этого подхода выполним следующие шаги:

  1. Разместим на форме табличное поле, связав его с реквизитом СписокДоговоров (тип СписокЗначений).
  2. В обработчике события ПриИзменении поля выбора контрагента настроим ограничение по владельцу для колонки значения:

Процедура КонтрагентПриИзменении(Элемент)
    // Очищаем ранее выбранные договоры при смене контрагента
    СписокДоговоров.Очистить();
    
    // Устанавливаем владельца для поля ввода в колонке таблицы
    ЭлементыФормы.СписокДоговоров.Колонки.Значение.ЭлементУправления.ВыборПоВладельцу = Контрагент;
КонецПроцедуры

При таком подходе при добавлении строк непосредственно в табличное поле на форме список договоров сразу открывается с отбором по указанному контрагенту без промежуточного окна выбора владельца.

Способ 2. Открытие формы выбора с множественным выделением

Проанализируем второй вариант: отказ от системного диалога списка значений в пользу штатной формы выбора справочника ДоговорыКонтрагентов с включенным режимом множественного выбора.

Посмотрим на пример реализации в процедуре изменения контрагента или по кнопке подбора:


Процедура ВыбратьДоговорыКонтрагента()
    Если Не ЗначениеЗаполнено(Контрагент) Тогда
        Предупреждение("Сначала выберите контрагента!");
        Возврат;
    КонецЕсли;

    Форма = Справочники.ДоговорыКонтрагентов.ПолучитьФормуВыбора(, ЭтаФорма);
    Форма.МножественныйВыбор = Истина;
    
    // Устанавливаем отбор по владельцу
    Отбор = Форма.Отбор.Владелец;
    Отбор.ВидСравнения = ВидСравнения.Равно;
    Отбор.Значение = Контрагент;
    Отбор.Использование = Истина;
    
    СписокВыбранных = Форма.ОткрытьМодально();
    
    Если СписокВыбранных <> Неопределено Тогда
        СписокДоговоров.ЗагрузитьЗначения(СписокВыбранных);
    КонецЕсли;
КонецПроцедуры

Пользователь может выделить несколько нужных договоров с помощью клавиш Ctrl или Shift и нажать кнопку «Выбрать». Все отмеченные элементы будут загружены в реквизит СписокЗначений.

Способ 3. Заполнение списка через запрос и метод «ОтметитьЭлементы()»

Рассмотрим удобный сценарий, когда требуется быстро отметить нужные договоры флажками из полного перечня договоров контрагента. Для этого сформируем список доступных договоров запросом и вызовем встроенный диалог отметки элементов.

Разберем по шагам программный код:


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

Способ 4. Реализация подбора через немодальную форму и событие «ОбработкаПодбора»

Если контрагент имеет большой список договоров и пользователю требуется непрерывный подбор без закрытия формы выбора, применим стандартный механизм обработки подбора.

Откроем форму выбора справочника с флагом ЗакрыватьПриВыборе = Ложь:


Процедура КнопкаПодборНажатие(Элемент)
    ФормаВыбора = Справочники.ДоговорыКонтрагентов.ПолучитьФормуВыбора("ФормаВыбора", ЭтаФорма);
    ФормаВыбора.Отбор.Владелец.Установить(Контрагент);
    ФормаВыбора.РежимВыбора = Истина;
    ФормаВыбора.ЗакрыватьПриВыборе = Ложь;
    ФормаВыбора.Открыть();
КонецПроцедуры

В модуле основной формы обработки определим стандартную процедуру ОбработкаПодбора, которая принимает выбранные значения:


Процедура ОбработкаПодбора(ЗначениеПодбора, Источник)
    Если ТипЗнч(ЗначениеПодбора) = Тип("СправочникСсылка.ДоговорыКонтрагентов") Тогда
        Если СписокДоговоров.НайтиПоЗначению(ЗначениеПодбора) = Неопределено Тогда
            СписокДоговоров.Добавить(ЗначениеПодбора);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Настройка для управляемых форм (1С 8.3)

Выясним, как решается данная задача на управляемых формах. В управляемом интерфейсе функционал реализуется штатными механизмами платформы:

  1. В свойствах элемента формы, связанного со списком договоров, настраивается свойство СвязиПараметровВыбора, где указывается связь Отбор.Владелец(Контрагент).
  2. Либо в обработчике события НачалоВыбора динамически заполняется свойство ДоступныеЗначения списка значений на сервере:

&НаКлиенте
Процедура ДоговорыНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    ДоговорыНачалоВыбораНаСервере();
КонецПроцедуры

&НаСервере
Процедура ДоговорыНачалоВыбораНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Договоры.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.ДоговорыКонтрагентов КАК Договоры
        |ГДЕ
        |	Договоры.Владелец = &Владелец";
    Запрос.УстановитьПараметр("Владелец", Объект.Контрагент);
    
    Список = Новый СписокЗначений;
    Список.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
    
    Элементы.Договоры.ДоступныеЗначения = Список;
КонецПроцедуры

Выбор конкретного варианта зависит от используемого режима интерфейса (обычные или управляемые формы) и требований пользователей к удобству добавления и визуализации выбранных элементов.

← На главную