30 июл. 2013 г.

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


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

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

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


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

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

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

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

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

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


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

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


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


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

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


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

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

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


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

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

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

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


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

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

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

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

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

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

    ОтветитьУдалить
  6. Автор, дай Бог тебе здоровья!!! Пол инета перерыл, уже думал, что такое невозможно со стандартными диалогами...

    ОтветитьУдалить
  7. Спасибо, как раз искала, как такое сделать!

    ОтветитьУдалить
  8. Спасибо огромное за труды.

    ОтветитьУдалить
  9. Храни тебя Господь! Выручил!

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