gifts2017

СКД - отбор значений. Форма подбора подчиненных значений при выборе нескольких Владельцев

Опубликовал Николай Захаренков (ikar-nikolay) в раздел Программирование - Практика программирования

Как недавно выяснилось - в СКД не реализован механизм подбора подчиненных значений при выборе нескольких Владельцев. Типовые средства выдают для выбора весь справочник с подчинениями при типе значения ВСписке у Владельца. Частичное решение данной проблемы описано в данной статье.

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

Форма выбора открывается, когда и у Подчиненного и у Владельца указан тип значения (ВСписке)!!!

Для реализации нам требуется:

1) создать произвольную форму в СКД с названием "ФормаВыбораПодчинения"
и следующими реквизитами (соответственно реквизиты ВладелецВыбор и ПодчиненныйВыбор должны иметь правильную ссылку)

В коде формы необходимо подставить название справочника подчиненных элементов в переменную строкаСпрПодчинененныхЭлементов (например "Договоры")

Все остальное без изменений. В коде дал подробные разъяснения что и зачем.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

//СоздаемНаименование колонок аналогично значениям отбора
Элементы.СписокПодчиненныхЭлементов.ПодчиненныеЭлементы.СписокПодчиненныхЭлементовВладелецВыбор.Заголовок = Параметры.СтруктураВладельца.ЛевоеЗначение;
Элементы.СписокПодчиненныхЭлементов.ПодчиненныеЭлементы.СписокПодчиненныхЭлементовВладелецВыбор.ТолькоПросмотр = Истина;
Элементы.СписокПодчиненныхЭлементов.ПодчиненныеЭлементы.СписокПодчиненныхЭлементовПодчиненныйВыбор.Заголовок = Параметры.СтруктураПодчиненного.ЛевоеЗначение;

// Создаем переданную структуру
списокзначенийВведенных = Параметры.СтруктураПодчиненного.ПравоеЗначение;
СписокПодчиненныхЭлементов.Очистить();
Если ТипЗнч(Параметры.СтруктураПодчиненного.ПравоеЗначение) = Тип("СписокЗначений") Тогда
Для каждого значение из списокзначенийВведенных Цикл

НовоеЗначение = СписокПодчиненныхЭлементов.Добавить();
НовоеЗначение.ПодчиненныйВыбор = значение.Значение;
НовоеЗначение.ВладелецВыбор = значение.Значение.Владелец;

КонецЦикла;
КонецЕсли;

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

строкаСпрПодчинененныхЭлементов = "автОсиОбъектаСтроительства";

ПараметрыПодбора = Новый Структура("ЗакрыватьПриВыборе, МножественныйВыбор", Истина, Ложь);
ФормаВыбора = ПолучитьФорму("Справочник."+строкаСпрПодчинененныхЭлементов+".ФормаВыбора",ПараметрыПодбора,Элемент);

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

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

&НаКлиенте
Процедура ВыполнитьОк(Команда)

// Получаем в списки значений значения Владельцев и Подчиненных элементов 
// для возврата их при закрытии формы

списокзначенийВладельцы = Новый СписокЗначений;
списокзначенийПодчиненные = Новый СписокЗначений;
Для каждого ВыбранныеЗначения Из СписокПодчиненныхЭлементов Цикл

Если списокзначенийПодчиненные.НайтиПоЗначению(ВыбранныеЗначения.ПодчиненныйВыбор) = Неопределено Тогда
списокзначенийПодчиненные.Добавить (ВыбранныеЗначения.ПодчиненныйВыбор);
КонецЕсли;

Если списокзначенийВладельцы.НайтиПоЗначению(ВыбранныеЗначения.ВладелецВыбор) = Неопределено Тогда
списокзначенийВладельцы.Добавить (ВыбранныеЗначения.ВладелецВыбор);
КонецЕсли;

КонецЦикла;

СтруктураДляВозврата = Новый Структура;
СтруктураДляВозврата.Вставить("списокзначенийВладельцы", списокзначенийВладельцы);
СтруктураДляВозврата.Вставить("списокзначенийПодчиненные", списокзначенийПодчиненные);
ЭтаФорма.Закрыть(СтруктураДляВозврата);

КонецПроцедуры


2) В КомпоновщикНастроекПользовательскиеНастройки (см. пост выше) на ПередНачаломИзменения вешаем приведенный ниже обработчик (смотрите в списке событий, на картинке он не выделен).


Все, что нам необходимо ввести в обработчике событий, это строковое название реквизита владельца и подчиненного в переменные

НазваниеРеквизитаВладельца,

НазваниеРеквизитаПодчиненного.

&НаКлиенте
Процедура КомпоновщикНастроекПользовательскиеНастройкиПередНачаломИзменения(Элемент, Отказ)

// Название реквизитов Владельца и Подчиненного
НазваниеРеквизитаВладельца = "ОбъектСтроительства";
НазваниеРеквизитаПодчиненного = "Ось";

// Структуры для хранения текущих отборов и передачи их в форму
СтруктураПодчиненного = Новый Структура;
СтруктураВладельца = Новый Структура;
СтруктураДляПередачиВФорму = Новый Структура;

//Поехали! Если пытаются изменить отбор подчиненного элемента, тогда...
Если Элемент.ТекущиеДанные.Настройка = НазваниеРеквизитаПодчиненного Тогда

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

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

КонецЕсли;
КонецЦикла;

// Если Владелец присутствует в списке и используется...
Если СтруктураВладельца.Количество() > 0 Тогда 
Если СтруктураВладельца.Использование 
И СтруктураВладельца.ВидСравнения = Строка(ВидСравненияКомпоновкиДанных.ВСписке) 
И СтруктураПодчиненного.Использование 
И СтруктураПодчиненного.ВидСравнения = Строка(ВидСравненияКомпоновкиДанных.ВСписке) 
Тогда
//... вот только в этом случае мы открываем нашу форму выбора
СтруктураДляПередачиВФорму.Очистить();
СтруктураДляПередачиВФорму.Вставить("СтруктураПодчиненного", СтруктураПодчиненного);
СтруктураДляПередачиВФорму.Вставить("СтруктураВладельца", СтруктураВладельца);

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

ИначеЕсли Строка(строкаНастройки.ЛевоеЗначение) = НазваниеРеквизитаВладельца Тогда

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

строкаНастройки.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
строкаНастройки.ПравоеЗначение.Очистить();
Для каждого строкаНовойНастройки Из ИтоговыйПодбор.списокзначенийВладельцы Цикл
строкаНастройки.ПравоеЗначение.Добавить(строкаНовойНастройки.Значение); 
КонецЦикла;

КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;

КонецЕсли;

КонецПроцедуры

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

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Ден Вар (vardo) 19.02.14 07:42
Как недавно выяснилось - в СКД не реализован механизм подбора подчиненных значений при выборе нескольких Владельцев

Где это выяснилось? А для чего тогда в "Группе из списка"?
Прикрепленные файлы:
2. Николай Захаренков (ikar-nikolay) 19.02.14 12:00
(1) vardo, да тут мы пообщались: http://forum.infostart.ru/forum26/topic104485/

Нет отбора по подчиненным элементам при выборе нескольких Владельцев.
В группе из списка тоже не спасает. Ты выбираешь несколько Владельцев, открываешь для подбора подчиненные и вываливается весь список без отбора по выбранным Владельцам.

Если не так, то скажи, что не так делаю? Мне этот механизм был нужен очень срочно, поэтому писал на коленке без большого анализа. Конечный код немного поменялся - в текущем не хватает нескольких условий, как доотчитаюсь до конца, перезалью.
3. Ден Вар (vardo) 19.02.14 13:42
Я может не понимаю цели, но если нужно в отчете отобрать контрагента и его договора, то это вообще делается запросом с левым соединением в наборе данных СКД. И отбирай нужных контрагентов всписке отбором
4. Александр Овсянников (_LEV_) 19.02.14 23:49
тоже столкнулся с данной проблемой - как в отборах выбрать значение свойства по владельцу, а владельцев несколько.. вываливается весь список..
5. Николай Захаренков (ikar-nikolay) 20.02.14 01:39
(3) vardo, цель простая - в СКД выбираешь для отбора 3 контрагентов, начинаешь выбирать договора - кликаешь в отборе Договора и у тебя появляется список договоров только выбранных тобою 3-х контрагентов.
Типовая реализация - вываливается список со всеми существующими в конфигурации договорами без какого-либо отбора.
6. Art Fa (artfa) 22.09.14 00:32
(5) ikar-nikolay, да это так, но в УТ 11 в общей форме отчетов работает, другие конфы не смотрел