gifts2017

Набор данных Объект в СКД для решения задач сортировки, нумерации и вывода в отчет произвольных наборов данных

Опубликовал Александр Лопатин (lopatin) в раздел Программирование - Практика программирования

Использование набора данных Объект в СКД, может добавить вашему отчету новые интересные возможности. В этой статье я покажу, как я использовал набор данных Объект при решении одной задачи.

Задача, которую я решил используя набор данных Объект, состояла в следующем:

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

Решение задачи.

1. Для начала в отчет необходимо добавить новый набор данных - Объект и описать его поля:

 

Зададим нашему набору данных Имя объекта, содержащего данные тзПорядок.

2. Не забудем задать связь наборов данных:

 

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

3. Добавляем условие отбора на основной запрос:

 

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

4.  Укажем для нашего параметра &НоменклатурныеГруппы доступность ввода списка значений:

 

 5. На данном этапе работа с конструктором схемы компоновки данных заканчивается и мы перемещаемся в модуль объекта, нашего отчета. Для дальнейшей реализации поставленной задачи, придется формировать отчет программно. Для этого реализуем процедуру ПриКомпоновкеРезультата.

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

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

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

7. Для этого мы вносим изменения в уже внесенный код в процедуре ПриКомпоновкеРезультата:

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

После получения макета компоновки данных и перед процессом компоновки данных, мы производим определение нашего Набора данных. Для этого, создается структура ВнешниеНаборыДанных и в неё добавляется в качестве таблицы значений элемент, которому присваивается имя тзПорядок, ранее мы указывали это имя при создании набора данных.

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

Инициализацию Процессора компоновки данных необходимо производить с передачей Внешних наборов данных(второй параметр метода Инициализировать).

8. Теперь вернемся в конструктор Схемы компоновки данных и настроим сортировку для нашего отчета. Для начала укажем наше поле Порядок в качестве ресурса отчета:

 

После перейдем на вкладку Настройки и в настройках отчета(группировки) перейдем на вкладку Сортировка. Выберем в качестве поля сортировки поле Порядок. Не забываем снять галочку с Авто

 

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

9. Проверим результат формирования нашего отчета.

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

И сформируем отчет.

 

Мы видим, что столбцы Номенклатурных групп выстроились в том порядке, в каком мы их выбрали(в отчет не вывелись номенклатурные группы по которым не было оборотов за период). Не сложно увидеть, что Ячмень без пленок встал на первое место, потому что мы так выбрали его в параметр. Хотя согласно алфавиту наименования на Я должны были бы идти в конце списка, следовательно наша сортировка заработала.

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Сергей Лесовой (Synoecium) 07.07.16 09:55
Можно сделать попроще, программно формировать текст пользовательского поля в виде конструкции когда..тогда..., расставив приоритет согласно порядку отбора, и по этому полю поставить сортировку в СКД.
2. Александр Лопатин (lopatin) 07.07.16 10:05
(1) Synoecium, Не думаю, что программное редактирование запроса проще. К тому же НаборДанных это стандартное средство, а программное ковыряние запроса это изобретение велосипеда. И компоновка данных сама наилучшим образом сформирует запрос, из всех наборов данных, как ей надо.
3. Сергей Лесовой (Synoecium) 07.07.16 11:01
(2) lopatin, причем здесь редактирование запроса, у вас лишнее соединение средствами СКД, а так пользовательское поле с выражением, что однозначно быстрее.
4. Александр Лопатин (lopatin) 07.07.16 11:11
(3) Synoecium, Не очень не понимаю, как в пользовательском получить номер порядка для текущего значения в строке?
5. Александр Лопатин (lopatin) 07.07.16 11:13
(3) Synoecium, Понял, вы программно предлагаете заполнять заранее добавленное пользовательское поле.
6. Александр Лопатин (lopatin) 07.07.16 12:05
(1) Synoecium, Если будет возможность, хотелось бы увидеть реализацию предложенного варианта
7. Николай Зайков (Mortiferus) 07.07.16 15:37
(1) Synoecium, как раз наоборот - в статье метод проще некуда.
8. Сергей Лесовой (Synoecium) 08.07.16 08:32
(7) Mortiferus, подправить текст по формированию отчета:
ПараметрНоменклатурныеГруппы = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("НоменклатурныеГруппы"));	
	СписокНоменклатурныхГрупп = ПараметрНоменклатурныеГруппы.Значение;
	полеПорядка = Схема.ВычисляемыеПоля.Найти("ПорядокНГ");
	текстПорядка = "Выбор ";
	индПорядка = 1;
	Для каждого элСписка ИЗ СписокНоменклатурныхГрупп Цикл
		НГ = элСписка.Значение;
		текстПорядка = текстПорядка+"Когда НоменклатурнаяГруппа.Код = "+НГ.Код+" Тогда "+индПорядка+" ";
		индПорядка = индПорядка + 1;
	КонецЦикла;
	текстПорядка = текстПорядка + "Иначе "+индПорядка+" Конец";
	Если СписокНоменклатурныхГрупп.Количество()>0 Тогда
		полеПорядка.Выражение = текстПорядка;
	КонецЕсли;
...Показать Скрыть

и убрать лишние наборы данных вообще, куда уж проще то.
MorningStalker; +1 Ответить