Настройка видимости элементов форм объектов по ролям, на уровне пользователя


Если вам лень самим колдовать с настройкой видимости относительно ролей - дайте мышку в руки администратору!

+ бонус... Вы не пробовали построить дерево элементов формы в 1С?  :D

Вот чувствую, что опять кто-нибудь напишет, как было со «Сканирочкой», что решение до безобразия простое… Что делать...  :( Когда клиент ставит самую что есть конкретную задачу, которую, казалось бы, сделал – и забыл, коварно подкрадывается мысль: «А нет ли у задачи более общего решения, чтобы потом …»

... Потом – не делать заново, когда похожая задача появится. Потом – продавать, если решение получится интересным. В крайнем случае, потом – попиариться на инфостарте, ведь это весело. :D

Вот и сейчас… Клиент просит настроить список колонок для формы списка конкретного документа, чтобы пользователи с разными ролями видели свои колонки. И ведь приложил список, для какой роли – какие колонки надо отображать! Большой список… Вобщем, представил я, как в ПриОткрытии буду тупо прописывать эти проверки и проставлять видимость колонок, и как-то тоскливо стало.  Их же … много! Выход: предоставить пользователю инструмент, чтобы сам он мог забавляться со своими колонками, сколько ему влезет. И кстати, если уж для конкретного объекта я это делаю, то почему не позволить делать такую настройку для любого объекта? Болезнь у меня такая…

В общем, получилось. Выкладываю. Пользуйтесь! 

 

 

Для использования сего нужно:

  1. В информационную базу добавить регистр (прилагается)
  2. Добавить обработку НастройкаВидимости
  3. В метод ПриОткрытии для форм того объекта, видимость полей которого предполагается настраивать, прописать: 

 

ОбработкаНастройки=Обработки.НастройкаВидимости.Создать();

ОбработкаНастройки.УстановитьВидимость(ЭтотОбъект,ЭтаФорма,"ФормаДокумента");

или, как вариант:

ОбработкаНастройки.УстановитьВидимость(СтроковыйИдентификаторОбъекта,ЭтаФорма,"ФормаДокумента");

 

 

где СтроковыйИдентификаторОбъекта - "Документы.ПриходнаяНакладная", "Справочники.Контрагенты" и т.д.

 

Все…

 

 

Описанный метод может быть использован при разработке конфигураций с нуля, для «ленивой» настройки видимости элементов форм объектов.

 

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

 

 

ПС...

 

При решении этой задачи хотел, как красивее, чтобы элементы формы можно было в виде дерева выводить. Столкнулся с непониманием со стороны 1С. Оказывается, нет у элемента формы поля "Владелец", как есть в любой порядочной платформы для разработчика. Но ведь хочется, балин! Помогла миста... Там этот вопрос обсуждался (один небезызвестный гений), и было предложено решение. Правда... Реализовали они его там через ... спину. Что ж, не всем дано познать глубины рекурсии ;)

 

Привожу свое решение мистовского метода поиска принадлежности элементов формы к панелям. Я правда еще в своей настройке видимости разношу и по страницам эл-ты формы, но здесь - код только для разнесения по панелям. Думаю, пригодится коллегам.

 

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

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

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

// А тут удаляем очередную панель и смотрим, что осталось
Процедура ОбрабатываемПанель(ТипОбъекта,ИмяОбъекта,ИмяФормы,ИмяПанели,ЭлТы)
    Форма=ВернутьФорму(ТипОбъекта,ИмяОбъекта,ИмяФормы);
    ТекПанель=Форма.ЭлементыФормы[ИмяПанели];
    Форма.ЭлементыФормы.Удалить(ТекПанель);
    Для Каждого Стр Из ЭлТы Цикл
        Если Стр.Элт<>ИмяПанели Тогда
            Если Форма.ЭлементыФормы.Найти(Стр.Элт)=Неопределено Тогда
                Стр.Панель=ИмяПанели;
                Стр.Уровень=Стр.Уровень+1;
            КонецЕсли;    
        КонецЕсли;    
    КонецЦикла;    
КонецПроцедуры    

// Ну это типа преобразование таблицы значений в дерево. 
// Рекурсия!!! И этим все сказано...
Процедура ВзраститьБерезу(ВеткиБерезы,Форма,ТабЭлтов,Уровень)
    Для Каждого Стр Из ТабЭлтов Цикл
        Если Стр.Уровень<>Уровень Тогда
            Продолжить;
        КонецЕсли;    
        НоваяВетка=ВеткиБерезы.Добавить();
        НоваяВетка.ЭлементФормы=Форма.ЭлементыФормы[Стр.Элт];
        Если Стр.ЭтоПанель Тогда
            ВзраститьБерезу(НоваяВетка.Строки,Форма,ТабЭлтов,Уровень+1);
        КонецЕсли;    
    КонецЦикла;    
КонецПроцедуры    

 

ППС...

Еще немалое удивление вызвал тот факт, что нельзя из формы нормальным способом узнать, к чему она относится. Впрочем, решение - есть. Почти... В некоторых (нормальных) конфигурациях имеется некий глобальный метод, который вызывается при открытии любой формы. Некий глПриОткрытии(ЭтаФОрма). Вот в этот метод можно кое-что прописать, чтобы не лезть в каждую форму списка, выбора или объекта.

Привожу пример решения для справочников. Т.е., по переданному ЭтаФорма ищем справочник, которому эта форма принадлежит и вызываем нашу обработку:

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

Конечно, самый железный метод - сравнивать полученную форму с любой формой в конфигурации. Но это как-то жестоко...

Файлы обработки:

-