Приветствую Вас ГостьВоскресенье, 05.05.2024, 15:17

Каталог статей


Создание произвольного отбора в управляемой форме с использованием СКД

Мысль была следующая: сделать отдельную форму, в которой можно будет установить настройки отбора, полей и сортировки для разных объектов (справочников и документов).

Что пришлось учитывать:

  1. Что возвращать? Если таблицу значений, то на клиент ей передать нельзя. Так же надо учитывать, что количество отобранных элементов может исчисляться в тысячах, и переносить с сервера на клиент, а потом обратно на сервер для обработки эту кучу данных очень затратно. Так же надо учитывать, что возвращать потребуется различное количество колонок или просто массив. В результате было принято решение результат отбора помещать во временное хранилище, и возвращать адрес временного хранилища. Был добавлен параметр формы "ТипВозвращаемогоЗначения", который может принимать значения "Массив" или "ТаблицаЗначений". Если параметр равен "Массив", то надо возвращать только массив ссылок, в противном случае таблицу значений.
  2. Где хранить СКД для отбора? Проблема в том, что объекты могут запрашиваться разные. В форме хранить значение типа СКД нельзя, можно только объект типа КомпоновщикНастроекКомпоновкиДанных. Если создать макет отбора и его программно менять, то его изменения не запоминаются. Было принято решение создавать СДК программно (запрос, поля выбора, группировки и условия отбора). СКД будет создаваться дважды: первый раз при создании формы, чтобы сформировать компоновщик настроек, второй раз при закрытии формы, чтобы получить результаты отбора по сделанным настройкам. Возможно есть более простой вариант.
  3. Создание объекта типа ИсточникДоступныхНастроекКомпоновкиДанных. Есть 2 конструктора для этого типа: по СКД и на основании URL. В управляемой форме не получиться создать по СКД, поэтому  помещаем СКД в временное хранилище, а потом создаем ИсточникДоступныхНастроек на основании URL, и в качестве параметра передаем адрес в хранилище.

Реализация

1. Создали произвольную формы "ФормаОтбора". Для формы определили 2 параметра:

  • ИмяОбъектаДанных
  • ТипВозвращаемогоЗначения

2. Создали реквизиты:

  •  ИмяОбъектаДанных - для передачи значения параметра
  • ТипВозвращаемогоЗначения - для передачи значения параметра
  • ЭтоДокумент - логическое. Если имя объекта находится в ветке Метаданные.Документы, то равно Истина.
  • ЭтоСправочник - логическое. Если имя объекта находится в ветке Метаданные.Справочники, то равно Истина.

3. Создали реквизит КомпановщикНастроек типа "КомпоновщикНастроекКомпоновкиДанных"

4. Разместили на форме объекты  "КомпановщикНастроекНастройкиВыбор", "КомпановщикНастроекНастройкиОтбор", "КомпановщикНастроекНастройкиПорядок", чтобы иметь возможность определять список полей, отбор и сортировку.

5. В модуле формы создали процедуру ПриСозданииНаСервере()

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    //Заполняем реквизиты формы, чтобы потом обращаться к ним при формировании СКД
    Если Параметры.Свойство("ИмяОбъектаДанных") Тогда
        ИмяОбъектаДанных = Параметры.ИмяОбъектаДанных;
        ЭтоСправочник = (Метаданные.Справочники.Найти(Параметры.ИмяОбъектаДанных) <> Неопределено);
        ЭтоДокумент = (Метаданные.Документы.Найти(Параметры.ИмяОбъектаДанных) <> Неопределено);
    КонецЕсли;
    //если не нашли объект по имени ни в спавочниках, ни в документах, то выходим
    Если НЕ ЭтоСправочник И НЕ ЭтоДокумент Тогда
        Возврат;
    КонецЕсли;
    
    ТипВозвращаемогоЗначения = "ТаблицаЗначений";
    Если Параметры.Свойство("ТипВозвращаемогоЗначения") Тогда
        ТипВозвращаемогоЗначения = ПАраметры.ТипВозвращаемогоЗначения;
    КонецЕсли;

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

В процедуре используются функция СоздатьМакетСКД(Настройки), в которой, в свою очередь, используются функции СформироватьТекстЗапроса() и ДобавитьПолеВСКД(пНаборДанных, пНастройки, ИмяПоля)

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

КонецФункции

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

КонецФункции

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

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

Если кратко, то создаем новую СКД, формируем в ней источник данных, набор данных типа "Запрос", добавляем поля набора данных и поля выбора в настройке, добавляем группировку детальных записей для вывода всех полей, добавляем отбор "Пометка удаления = Ложь".

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

Для справочников по умолчанию получаем Ссылку и код, для документов, Ссылку, номер и дату.

6. На форме отбора создаем команду "ОбработатьВыбор". В обработчике команды пишем:

&НаКлиенте
Процедура ОбработатьВыбор(Команда)
    АдресВХ = ПоместитьДанныеВХранилище();
    Закрыть(АдресВХ);
КонецПроцедуры

 

&НаСервере
Функция ПоместитьДанныеВХранилище()
    
    Настройки = Неопределено;
    СКД = СоздатьМакетСКД(Настройки);
    
    НастройкиКопмановки = КомпановщикНастроек.ПолучитьНастройки();    
    КомпановщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпановки = КомпановщикМакета.Выполнить(СКД,НастройкиКопмановки,,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
    ПроцессорКомпановки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпановки.Инициализировать(МакетКомпановки);
    ПроцессорВывода = Новый     ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    ТЗ = Новый ТаблицаЗначений;
    ПроцессорВывода.УстановитьОбъект(ТЗ);
    ПроцессорВывода.Вывести(ПроцессорКомпановки);
    
    Если ТипВозвращаемогоЗначения = "Массив" Тогда
        АдресВХ = ПоместитьВоВременноеХранилище(ТЗ.ВыгрузитьКолонку("Ссылка"));  
    Иначе
        АдресВХ = ПоместитьВоВременноеХранилище(ТЗ);
    КонецЕсли; 
    
    Возврат АдресВХ;
    
КонецФункции

Краткое описание:

Создаем СКД так же как при создании формы. Применяем к ней сделанные в форме настройки и формируем таблицу значений с помощью СКД. Результат отбора помещаем во временное хранилище, либо таблицу значений, либо массив ссылок. Закрываем форму и возвращаем адрес временного хранилища

7. На основной форме обработки создаем команду "ЗаполнитьПоНастройкам". На клиенте получаем форму, передаем в неё параметры "ИмяОбъектаДанных" и "ТипВозвращаемогоЗначения", настраиваем описание оповещения при закрытии и обрабатываем закрытие. В примере получаем список пользователей и заполняем список значений "СписокПользователей".

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

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

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

Пример формы настройки отбора:

Сформировать выборку запроса по настройкам СКД

Выше описан способ получения таблицы значений по настройкам отбора СКД. Иногда это невыгодно делать, так как таблица значений может занимать большую часть памяти. Вместо формирования таблицы значений можно сформировать выборку по запросу и обрабатывать каждую запись отдельно (подсмотрено в УПП).

Для этого формируем компоновщик макета компоновки данных по настройкам. Из макета получаем текст запроса и создаем объект "Запрос". Далее надо заполнит параметры запроса и выполнить запрос. Получить список параметров можно с помощью метода НайтиПараметры(). Далее обходим параметры в цикле и переносим их в запрос.

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

Категория: СКД | Добавил: leshic (24.01.2022)
Просмотров: 381 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Вход на сайт
Поиск
Категории раздела
СКД [48]
Регистры [7]
Формы [40]
Администрирование [34]
Запросы [10]
Объекты конфигурации и типы данных [20]
Взаимодействие с другими базами, приложениями и источниками данных [16]
Программирование [29]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0