Вот чувствую, что опять кто-нибудь напишет, как было со «Сканирочкой», что решение до безобразия простое… Что делать… 🙁 Когда клиент ставит самую что есть конкретную задачу, которую, казалось бы, сделал – и забыл, коварно подкрадывается мысль: «А нет ли у задачи более общего решения, чтобы потом …»
… Потом – не делать заново, когда похожая задача появится. Потом – продавать, если решение получится интересным. В крайнем случае, потом – попиариться на инфостарте, ведь это весело. 😀
Вот и сейчас… Клиент просит настроить список колонок для формы списка конкретного документа, чтобы пользователи с разными ролями видели свои колонки. И ведь приложил список, для какой роли – какие колонки надо отображать! Большой список… Вобщем, представил я, как в ПриОткрытии буду тупо прописывать эти проверки и проставлять видимость колонок, и как-то тоскливо стало. Их же … много! Выход: предоставить пользователю инструмент, чтобы сам он мог забавляться со своими колонками, сколько ему влезет. И кстати, если уж для конкретного объекта я это делаю, то почему не позволить делать такую настройку для любого объекта? Болезнь у меня такая…
Все…
Описанный метод может быть использован при разработке конфигураций с нуля, для «ленивой» настройки видимости элементов форм объектов.
В архиве — пример конфигурации, где приведена настройка для разных пользователей по разным ролям видимости элементов форм справочников, документов…
ПС…
При решении этой задачи хотел, как красивее, чтобы элементы формы можно было в виде дерева выводить. Столкнулся с непониманием со стороны 1С. Оказывается, нет у элемента формы поля «Владелец», как есть в любой порядочной платформы для разработчика. Но ведь хочется, балин! Помогла миста… Там этот вопрос обсуждался (один небезызвестный гений), и было предложено решение. Правда… Реализовали они его там через … спину. Что ж, не всем дано познать глубины рекурсии 😉
Привожу свое решение мистовского метода поиска принадлежности элементов формы к панелям. Я правда еще в своей настройке видимости разношу и по страницам эл-ты формы, но здесь — код только для разнесения по панелям. Думаю, пригодится коллегам.
// Основная функция. На выходе получаем дерево эл-тов формы, распределенных по панелям
// На вход подаем тип объекта («Справочники», «Документы») и его имя из метаданных.
Функция СтроитьДеревоЭлементовФормы(ТипОбъекта,ИмяОбъекта,ИмяФормы)
ТабЭлтов=АнализаАднака(ТипОбъекта,ИмяОбъекта,ИмяФормы);
ТабЭлтов.Сортировать(«Уровень Возр, ЭтоПанель Возр, Панель Возр»);
Береза=Новый ДеревоЗначений;
Береза.Колонки.Добавить(«ЭлементФормы»);
Форма=ВернутьФорму(ТипОбъекта,ИмяОбъекта,ИмяФормы);
ВзраститьБерезу(Береза.Строки,Форма,ТабЭлтов,0);
Возврат Береза;
КонецФункции
// Потребуется много раз получать форму, чтобы мучить ее элементы
Функция ВернутьФорму(ТипОбъекта,ИмяОбъекта,ИмяФормы)
Если ТипОбъекта=»Справочники» Тогда
Объект=Справочники[ИмяОбъекта];
ИначеЕсли ТипОбъекта=»Документы» Тогда
Объект=Документы[ИмяОбъекта];
КонецЕсли;
Форма=Объект.ПолучитьФорму(ИмяФормы);
Возврат Форма;
КонецФункции
// Тут строим таблицу всех элементов и раскидываем их по панелям
Функция АнализаАднака(ТипОбъекта,ИмяОбъекта,ИмяФормы)
Форма=ВернутьФорму(ТипОбъекта,ИмяОбъекта,ИмяФормы);
Панели=Новый Массив;
ЭлТы=Новый ТаблицаЗначений;
ЭлТы.Колонки.Добавить(«Элт»);
ЭлТы.Колонки.Добавить(«Панель»);
ЭлТы.Колонки.Добавить(«Уровень»);
ЭлТы.Колонки.Добавить(«ЭтоПанель»);
Для Каждого Эл Из Форма.ЭлементыФормы Цикл
Нов=Элты.Добавить();
Нов.Элт=Эл.Имя;
Нов.Уровень=0;
Нов.ЭтоПанель=Ложь;
Если ТипЗнч(Эл)=Тип(«Панель») Тогда
Панели.Добавить(Эл.Имя);
Нов.ЭтоПанель=Истина;
КонецЕсли;
КонецЦикла;
Для К=0 По Панели.ВГраница() Цикл
ОбрабатываемПанель(ТипОбъекта,ИмяОбъекта,ИмяФормы,Панели[К],ЭлТы);
КонецЦикла;
Возврат ЭлТы;
КонецФункции
// А тут удаляем очередную панель и смотрим, что осталось
Процедура ОбрабатываемПанель(ТипОбъекта,ИмяОбъекта,ИмяФормы,ИмяПанели,ЭлТы)
Форма=ВернутьФорму(ТипОбъекта,ИмяОбъекта,ИмяФормы);
ТекПанель=Форма.ЭлементыФормы[ИмяПанели];
Форма.ЭлементыФормы.Удалить(ТекПанель);
Для Каждого Стр Из ЭлТы Цикл
Если Стр.Элт<>ИмяПанели Тогда
Если Форма.ЭлементыФормы.Найти(Стр.Элт)=Неопределено Тогда
Стр.Панель=ИмяПанели;
Стр.Уровень=Стр.Уровень+1;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Ну это типа преобразование таблицы значений в дерево.
// Рекурсия!!! И этим все сказано…
Процедура ВзраститьБерезу(ВеткиБерезы,Форма,ТабЭлтов,Уровень)
Для Каждого Стр Из ТабЭлтов Цикл
Если Стр.Уровень<>Уровень Тогда
Продолжить;
КонецЕсли;
НоваяВетка=ВеткиБерезы.Добавить();
НоваяВетка.ЭлементФормы=Форма.ЭлементыФормы[Стр.Элт];
Если Стр.ЭтоПанель Тогда
ВзраститьБерезу(НоваяВетка.Строки,Форма,ТабЭлтов,Уровень+1);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
ППС…
Еще немалое удивление вызвал тот факт, что нельзя из формы нормальным способом узнать, к чему она относится. Впрочем, решение — есть. Почти… В некоторых (нормальных) конфигурациях имеется некий глобальный метод, который вызывается при открытии любой формы. Некий глПриОткрытии(ЭтаФОрма). Вот в этот метод можно кое-что прописать, чтобы не лезть в каждую форму списка, выбора или объекта.
Привожу пример решения для справочников. Т.е., по переданному ЭтаФорма ищем справочник, которому эта форма принадлежит и вызываем нашу обработку:
Найд=Ложь;
Попытка
МД=ЭтаФорма.ЭтотОбъект.Метаданные();
Найд=Истина;
Исключение
КонецПопытки;
Если Найд Тогда
Для Каждого Эл Из ЭтаФорма.ЭлементыФормы Цикл
Если ТипЗнч(Эл)=Тип(«ТабличноеПоле») Тогда
Попытка
МД=Метаданные.НайтиПоТипу(ТипЗнч(Эл.Значение));
Исключение
Продолжить;
КонецПопытки;
Если Метаданные.Справочники.Содержит(МД) Тогда
Найд=Истина;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Найд Тогда
Спр=Справочники[МД.Имя];
Для Каждого Ф ИЗ МД.Формы Цикл
Если Спр.ПолучитьФорму(Ф.Имя)=ЭтаФорма Тогда
ОбработкаНастройки=Обработки.НастройкаВидимости.Создать();
ОбработкаНастройки.УстановитьВидимость(«Спраочники.»+МД.Имя,ЭтаФорма,Ф.Имя);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Конечно, самый железный метод — сравнивать полученную форму с любой формой в конфигурации. Но это как-то жестоко…