30 июл. 2013 г.

Эксперименты с отбором в подборе в список значений


Попробуем реализовать программную установку значений отбора в форме выбора, получаемой через "Подбор" формы редактирования списка значений. Напрямую повлиять на форму редактирования нельзя, она создается средствами платформы. Сразу же напрашивается вариант создания своей формы редактирования списка, с расширенным функционалом и красивыми кнопками. Но мы пойдем другим путем и попробуем передать параметры отбора в форму выбора необходимого справочника. Так же рассмотрим варианты реализации в обычном и управляемом приложениях.

Реализуем простую конфигурацию с двумя простыми справочниками:
-"Подразделения";
- "Склады", с реквизитом "Подразделение", тип "Справочник.Подразделения".

Начнем эксперименты с обычного приложения. Добавляем обычную форму выбора для справочника "Склады". Так же добавляем обработку, на форму выносим реквизиты:
- Подразделение, тип "СписокЗначений", тип значений списка "СправочникСсылка.Подразделения";
- Склад, тип "СписокЗначений", тип значений списка "СправочникСсылка.Склады".


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

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

 Запрос.УстановитьПараметр("Подразделение", Подразделение);

 Список = Новый СписокЗначений;
 Список.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
 
 Возврат Список;
 
КонецФункции 

Теперь, при изменении значения реквизита "Подразделение" будем выполнять следующую процедуру:

Процедура ПодразделениеПриИзменении(Элемент)
 
 Склад.ДоступныеЗначения = ?(Подразделение.Количество() = 0, Неопределено, Справочники.Склады.СписокПоПодразделению(Подразделение));
 
КонецПроцедуры
 
В результате, получаем следующую картину. Список выбора значений ограничивается по выбранному подразделению, но подбор все равно показывает весь справочник, а выбор значения, не принадлежащего доступным значениям, преобразуется в пустое значение.


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

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


Теперь реализуем тоже самое на управляемых формах. Создаем форму с такими же реквизитами.


&НаКлиенте
Процедура ПодразделениеПриИзменении(Элемент)
 
 ПодразделениеПриИзмененииНаСервере();
 
КонецПроцедуры

&НаСервере
Процедура ПодразделениеПриИзмененииНаСервере()
 
 Склад.ДоступныеЗначения = ?(Подразделение.Количество() = 0, Неопределено, Справочники.Склады.СписокПоПодразделению(Подразделение));
 
КонецПроцедуры
 
Видим, что варианты для выбора в списке мы ограничили, но кнопка подбора не активна. Поэтому реализация задачи через ДоступныеЗначения в нашем случае не подходит.


Переделаем процедуру ПодразделениеПриИзмененииНаСервере, будем использовать свойство ПараметрыВыбора элемента формы:

&НаСервере
Процедура ПодразделениеПриИзмененииНаСервере()
 
 НовыйМассив = Новый Массив();
 НовыйМассив.Добавить(
 Новый ПараметрВыбора("Отбор.Ссылка", ?(Подразделение.Количество() = 0, Неопределено, Справочники.Склады.СписокПоПодразделению(Подразделение)))
 );
 НовыеПараметры = Новый ФиксированныйМассив(НовыйМассив);
  
 Элементы.Склад.ПараметрыВыбора = НовыеПараметры;
 
КонецПроцедуры
 
Подбор стал активен, при добавлении элемента списка на форму выбора накладывается отбор, но форма выбора, вызываемая через подбор все равно показывает все значения справочника.


Отойдем ненадолго от наложения отбора и выполним небольшую оптимизацию. Сейчас мы передаем в параметр выбора список значений, формируемый на сервере. Размер этого списка, в свою очередь может быть довольно таки массивным, например для номенклатуры. Соответственно, мы можем получить значимую задержку при его формировании и передаче клиенту. Управляемые формы позволяют уйти от предварительного формирования набора значений для фильтрации.
Реализуем отбор по подразделению склада на стороне клиента:

&НаКлиенте
Процедура ПодразделениеПриИзменении(Элемент)
 
 НовыйМассив = Новый Массив();
 НовыйМассив.Добавить(Новый ПараметрВыбора("Отбор.Подразделение", Подразделение));
 НовыеПараметры = Новый ФиксированныйМассив(НовыйМассив);
 Элементы.Склад.ПараметрыВыбора = НовыеПараметры;
 
КонецПроцедуры 

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

&НаКлиенте
Процедура ПриОткрытии(Отказ)
 
 Если ТипЗнч(ВладелецФормы) = Тип("ТаблицаФормы") Тогда
  Для Каждого м Из ВладелецФормы.ТекущийЭлемент.ПараметрыВыбора Цикл
   эк = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
   эк.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(СтрЗаменить(м.Имя, "Отбор.", ""));
   эк.ПравоеЗначение = м.Значение;
   эк.ВидСравнения = ?(ТипЗнч(м.Значение) = Тип("СписокЗначений"), ВидСравненияКомпоновкиДанных.ВСписке, ВидСравненияКомпоновкиДанных.Равно);
  КонецЦикла;
 КонецЕсли;
 
КонецПроцедуры
 
Готово, после таких нехитрых манипуляций у нас и добавление элементов, и подбор значений ограничены выбранными элементами.


6 комментариев:

  1. Спасибо! Очень пригодилась статья, успехов!

    ОтветитьУдалить
  2. да, статья классная!

    ОтветитьУдалить
  3. Спасибо! Очень помогла статья. Считал что платформа так не позволяет делать и уже начал было делать свою форму подбора.

    ОтветитьУдалить
  4. Спа-си-бо! Огромное человеческое! Статья спасла мне минимум день, а то и два самостоятельных разгребательств. Немного напильником допилил - стало вообще хорошо. :)

    ОтветитьУдалить
  5. Спасибо большое. Очень помогло.

    ОтветитьУдалить