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

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

Применение метода рассматривается на примере отборов динамических списков, но этот же принцип можно использовать для работы с настройками СКД.
Заключение
Тестировалось на платформе 8.3.8+, режим совместимости 8.2.13+. Но описанные приемы должны работать и на более ранних версиях 1С 8.


