Бодаемся с отображением отборов на управляемых формах

Рассмотрим в статье, как настроить отображение пользовательских отборов на форме по своему желанию.

Как известно многим, дьявол всегда кроется в мелочах. Одной из таких мелочей всплыло замечание пользователей о том, что при добавлении отборов при настройке списка не всегда отображается вид сравнения.

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

 

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

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

Если смотреть свойства динамического списка через палитру, можно найти две зацепки для решения нашей задачи:

1) Во-первых, это свойство "Группа пользовательских настроек". В данном свойстве указывается группа формы, которая выступит родителем для всех добавляемых элементов с отображением отборов.

 

 

2) Во-вторых, это событие списка "ПриОбновленииСоставаПользовательскихНастроекНаСервере".

 

 

Именно сюда вы попадёте если будете грешить после нажатия кнопки "Завершить редактирование" в форме настройки списка. При создании процедуры у неё есть лишь один параметр — использовать стандартную обработку или нет. При стандартной обработке будет вызван метод расширения формы динамического списка (т.е. элемента) СоздатьЭлементыФормыПользовательскихНастроек, который формирует все поля отборов на форме. На этом моменте у нас есть два выбора: или сформировать все поля через Элементы.Список.СоздатьЭлементыФормыПользовательскихНастроек(), а потом проставить видимость элементов, или взять дело целиком в свои руки и отрисовать поля самим. Я выбрал второй вариант, хотя, думаю, вы сможете реализовать и первый, зная, что откуда растёт. В любом случае не забудьте, что стандартная обработка должна быть выключена!

Рассмотрим программное создание полей на примере рабочего кода:

 

    // Иначе магия не заработает
СтандартнаяОбработка = Ложь;

// Очищаем все созданные элементы с отборами, через удаление главной группы
Для Каждого Эл Из Элементы.СписокКомпоновщикНастроекПользовательскиеНастройки.ПодчиненныеЭлементы Цикл
Элементы.Удалить(Эл);
КонецЦикла;

// Получаем настройки, смотрим количество настроек
Настройки = Список.КомпоновщикНастроек.ПолучитьНастройки();
КоличествоОтборов = Настройки.Отбор.Элементы.Количество();

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

// Разделяем главную группу на 2 подгруппы, чтобы хватало места всем отборам
ОтборыКолонка1   = ЭтаФорма.Элементы.Добавить("ОтборыКолонка1", Тип("ГруппаФормы"), ПолеОтборы);
ОтборыКолонка1.Вид = ВидГруппыФормы.ОбычнаяГруппа;
ОтборыКолонка1.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
ОтборыКолонка1.ОтображатьЗаголовок  = Ложь;
ОтборыКолонка1.СквозноеВыравнивание = СквозноеВыравнивание.Использовать;

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

// Разделяем имеющиеся отборы по колонкам, заполнение начнём с первой
НастроекНаКолонку = Окр(КоличествоОтборов/2, 0, РежимОкругления.Окр15как20);
Колонка = ОтборыКолонка1;

// Начинаем добавлять настройки на форму
НомерЭлемента = 0;
Для каждого ЭлОтбора из Настройки.Отбор.Элементы Цикл

//  Проверяем, не пора ли менять колонку
Если НомерЭлемента = НастроекНаКолонку Тогда
Колонка = ОтборыКолонка2;
КонецЕсли;

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

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

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

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

НомерЭлемента = НомерЭлемента+1;
КонецЦикла;

 

Как видите, алгоритм не очень сложен, дольше всего я провозился с путём к данным с настройками — первый массив, в который мы попадаем (который жёстко прописан в пути) содержит информацию по отборам, а последующие массивы уже информацию ко конкретным настройкам отбора. 

В итоге мы имеем стройный ряд настроек, который можно поменять в любой момент:

 

14 Comments

  1. Fragster

    Либо отказаться от указания группы пользовательских настроек в свойствах формы и создать их в две колонки в нужной группе одной строкой кода указав третий параметр процедуры

    Расширение таблицы формы для динамического списка (Form table extension for dynamic list)

    СоздатьЭлементыФормыПользовательскихНастроек (CreateUserSettingsFormItems)

    Синтаксис:

    СоздатьЭлементыФормыПользовательскихНастроек(<ГруппаПользовательскихНастроек>, <Режим>, <КоличествоКолонок>)

    Параметры:

    <ГруппаПользовательскихНастроек> (необязательный)

    Тип: ГруппаФормы.

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

    Значение по умолчанию: Неопределено.

    <Режим> (необязательный)

    Тип: РежимОтображенияНастроекКомпоновкиДанных.

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

    Значение по умолчанию: Неопределено.

    <КоличествоКолонок> (необязательный)

    Тип: Число.

    Задает количество колонок, в которых размещаются элементы формы в группе редактирования пользовательских настроек.

    Если параметр не задан, то элементы группы размещаются в двух колонках.

    Описание:

    Создает элементы формы для редактирования пользовательских настроек динамического списка.

    Показать

    Reply ↓
  2. lemz

    (2)

    Либо отказаться от указания группы пользовательских настроек в свойствах формы и создать их в две колонки в нужной группе одной строкой кода указав третий параметр процедуры

    Да, про этот вариант я упомянул, но после него для решения поставленной задачи (всегда отображать вид сравнения) вам нужно обходить эти созданные элементы чтобы проставить видимость. Огород начинается в тот момент, когда вам необходимо определить уровень вложенности элемента (если отбор только один, то колонки не создаются). Но в целом рабочий вариант с этим методом слепить можно.

    Reply ↓
  3. Fragster

    (3) ну, простейшая рекурсивная функция справится с обходом, получается в разы меньше кода. Единственный нюанс — у группы для настроек нужно убрать флажок «Разрешить пользовательское изменение состава группы, РазрешитьИзменениеСостава, EnableContentChange»

    Примерный код такой:

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

    Показать

    Reply ↓
  4. Fragster

    (4) Нашел у себя косяк — поскольку видмость устанавливается пользовательскими настройками формы, а мы к ним не имеем прямого доступа, нужно не устанавливать видимость, а все-таки клонировать элементы. Вот рабочий вариант (кода также не очень много):

    &НаСервере
    Процедура УстановитьВидимостьНастроек(ГруппаНастроек)
    МассивКлонируемыхЭлементов = Новый Массив;
    Для каждого ПодчиненныйЭлемент Из ГруппаНастроек.ПодчиненныеЭлементы Цикл
    Если ТипЗнч(ПодчиненныйЭлемент) = Тип(«ГруппаФормы») Тогда
    УстановитьВидимостьНастроек(ПодчиненныйЭлемент);
    Иначе
    Если СтрНайти(ПодчиненныйЭлемент.Имя, «ВидСравнения») <> 0 Тогда
    МассивКлонируемыхЭлементов.Добавить(ПодчиненныйЭлемент);
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
    Для каждого КлонируемыйЭлемент Из МассивКлонируемыхЭлементов Цикл
    Клон = ЭтаФорма.Элементы.Вставить(КлонируемыйЭлемент.Имя + «Клон», ТипЗнч(КлонируемыйЭлемент), КлонируемыйЭлемент.Родитель, КлонируемыйЭлемент);
    ЗаполнитьЗначенияСвойств(Клон, КлонируемыйЭлемент, «Вид, ПоложениеЗаголовка, РастягиватьПоГоризонтали, ПутьКДанным»);
    КлонируемыйЭлемент.Видимость = Ложь;
    КонецЦикла;
    КонецПроцедуры

    Показать

    Reply ↓
  5. allgorhythm

    Кручу верчу сравнить хочу!

    Reply ↓
  6. Поручик

    Плохо, что для исправления косяка от 1С, приходится добавлять форму для отчёта на СКД.

    Reply ↓
  7. MorningStalker

    Автору спасибо большое за идею!

    Реализовал у себя, буду теперь использовать.

    Нашел в коде ошибку (видимо осталось от реализации предыдущих вариантов), облегчу реализацию тем, кто воспользуется этим способом:

    ПолеЗначение.ПутьКДанным = «Список.КомпоновщикНастроек.ПользовательскиеНастройки[0][«+НомерЭлемента+»].Значение»;

    это работать не будет, так как в результате получится конструкция Список.КомпоновщикНастроек.ПользовательскиеНастройки[0][0].Значение

    правильно так:

    ПолеЗначение.ПутьКДанным = «Список.КомпоновщикНастроек.ПользовательскиеНастройки[» + НомерЭлемента + «].Значение»;

    Соответственно это справедливо для Использование и ВидСравнения

    Reply ↓
  8. lemz

    (10) Странно что у вас сработал именно такой вариант, так как в моём случае жёстко прописать первый массив пришлось из-за того, что в нём лежит информация по всем отборам, а уже внутри него проходя по номерам мы получаем конкретные значения этих отборов

    Reply ↓
  9. anig99

    Спасибо за указание направления. Написал свой более сложный и универсальный вариант.

    Reply ↓
  10. ward_ed

    Правильно будет определить индекс элемента, следующим образом

    НомерЭлемента = Настройки.Отбор.Элементы.Индекс(ЭлОтбора);.

    Это в том случае если что-то нужно исключить при создании.

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

    Reply ↓
  11. AzagTot

    Автору спасибо за идею!

    Реализовал в точности так, как указано в теме, однако поля отбора недоступны для редактирования. Попробовал для каждого элемента явно указать доступность — все равно та же ситуация. Использование стоит везде. У группы с отборами свойство «Только просмотр» Ложь.

    Ума не приложу, куда еще копать… Может сталкивался кто?

    Платформа 8.3.14, такое же поведение на 8.3.15.

    Reply ↓
  12. AzagTot

    (14) Причина была найдена. Оказывается, если задать предопределенный отбор в конфигураторе и включить ему галочку (включить в пользовательские настройки), то этот отбор сделает недоступными и пользовательские отборы, и сам себя.

    Есть ли возможность полечить это?

    Reply ↓
  13. lemz

    (14) Группой пользовательских настроек для списка у вас выставлен стандартный для форм списка элемент «СписокКомпоновщикНастроекПользовательскиеНастройки»? У него по доступности ничего не залочено?

    Reply ↓
  14. lemz

    (15) Действительно, есть такое. Могу только приметить, что если предопределённый отбор не помечать включенным в пользовательские настройки, в данной реализации он выведется на форму всё равно, при этом ничего не ломая ни со своей доступностью, ни с пользовательскими настройками

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *