Получить консультацию

Как сделать отчет на СКД с внешним набором данных?

В данном материале мы рассмотрим, как сформировать отчет на СКД с использованием внешних наборов данных. В этом нам поможет Набор данных – Объект. Зачем такое может понадобиться? Далеко не всегда данные для отчета можно вытянуть из базы запросом. Иногда требуется сложная обработка, например, распределение по партиям или документам расчетов, а иногда данные и вовсе могут содержаться не в 1С, а получаться откуда-то извне.

Чтобы было интереснее, наш отчет будет получать http-запросом данные о курсах валют, и выводить их в виде таблицы и диаграммы (график курса валют).

Создаем отчет с внешним набором данных

Для начала создадим внешний отчет, и добавим в него набор данных Объект. В наборе описываем все поля, которые нам нужны. В отличие от набора данных-запроса, автоматически поля не настраиваются, и каждое поле нам придется прописать вручную. Название набора выбираем произвольное, но так чтобы нам самим было понятно, что это за набор. Например “ТаблицаКотировок”. Кроме того, нам нужно указать имя внешнего набора, откуда мы будем получать данные.

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

Отчет на СКД с набором данных Объект

Дальше на вкладке Ресурсы определим один ресурс – Курс. Выражение также прописываем Курс.

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

После этого создадим группировку Диаграмма. У диаграммы в точки поместим Дата, а в серии – Валюта. Перейдем на вкладку Другие настройки, и выберем тип диаграммы График.

Отчет на СКД с внешним набором данных

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

Метод процессора компоновки Инициализировать может принимать необязательный параметр – ВнешниеНаборыДанных. Это должна быть структура, в которой ключи будут соответствовать именам, которые мы указали при создании наборов данных, а значения – собственно сами наборы данных.
В нашем примере набор данных всего один, и имя объекта с данными у него ТаблицаКорректировок. Значит и ключ должен быть ТаблицаКорректировок. А в значение мы поместим саму таблицу значений.

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

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

Собираем таблицу с курсами валют при помощи http-запроса

Есть множество сервисов, публикующих курсы валют, например, веб сервис Центробанка. Небольшой пример работы с SOAP сервисами можно подсмотреть по ссылке, в разделе Использование внешних веб-сервисов через WS-ссылки. Но во внешнем отчете мы воспользоваться WS-ссылками не можем (ведь нет гарантии, что в конкретной конфигурации эта WS-ссылка существует). Поэтому будем использовать другой сервис – http-сервис с ресурса cbr-xml-daily.ru.

Сам сервис не очень удобный, т.к. он возвращает курсы валют только на конкретную дату, и нам придется многократно его вызывать, передавая новую дату, что конечно же, отразится на быстродействии.
По ссылке вида https://www.cbr-xml-daily.ru/archive/2023/11/14/daily_json.js сервис вернет JSON с курсами на 14.11.2023.
Есть и другие сервисы, но они как правило, требуют авторизации и наличия API-ключа.

Мы прочитаем JSON, и на основе его данных соберем таблицу значений с тремя колонками. В отчет добавим реквизит ПериодОтчета с типом Стандартный период. В цикле по датам обратимся к сервису, получим курсы на конкретную дату, и добавим их в таблицу. Более подробно о работе с JSON можно прочитать в отдельной статье.

ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
БезопасноеСоединение = Новый HTTPСоединение("www.cbr-xml-daily.ru",443,,,,,ЗащищенноеСоединение,);
ДатаКотировок = ПериодОтчета.ДатаНачала;
ТаблицаКотировок = Новый ТаблицаЗначений;
ТаблицаКотировок.Колонки.Добавить("Валюта");
ТаблицаКотировок.Колонки.Добавить("Дата");
ТаблицаКотировок.Колонки.Добавить("Курс");
Пока ДатаКотировок <= ПериодОтчета.ДатаОкончания Цикл
	ДатаКотировокСтрока = Формат(ДатаКотировок, "ДФ=yyyy/MM/dd");
	Ответ = БезопасноеСоединение.Получить(Новый HTTPЗапрос(СтрШаблон("/archive/%1/daily_json.js", ДатаКотировокСтрока)));
	Если Ответ.КодСостояния = 200 Тогда
		СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
		ЧтениеJSON = Новый ЧтениеJSON;
		ЧтениеJSON.УстановитьСтроку(СтрокаОтвет);
		ОбъектОтвет = ПрочитатьJSON(ЧтениеJSON,,"Date",ФорматДатыJSON.ISO);
		Для Каждого СтрокаВалюты Из ОбъектОтвет.Valute Цикл
			Значение = СтрокаВалюты.Значение;
			СтрокаКотировок = ТаблицаКотировок.Добавить();
			СтрокаКотировок.Валюта = Значение.CharCode;
			СтрокаКотировок.Курс = Значение.Value;
			СтрокаКотировок.Дата = НачалоДня(ОбъектОтвет.Date);
		КонецЦикла;
	КонецЕсли;
	ДатаКотировок = ДатаКотировок + 86400;
КонецЦикла;

Финальные штрихи и наведение красоты

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

Разумеется, возникнет вопрос о времени жизни кэша и условиях его очистки. Например, можно очищать его по кнопке, или проверять, что поменялись даты в реквизите ПериодОтчета, и т.д. В нашем учебном примере мы дополнительного усложнения не хотим, поэтому обойдемся простым кэшированием. Финальный вариант будет выглядеть так

Функция ПолучитьВнешниеНаборы()	
	Если ТаблицаКотировокКЭШ.Количество() <> 0 Тогда
		ТаблицаКотировок = ТаблицаКотировокКЭШ.Выгрузить();
	Иначе		
		ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
		БезопасноеСоединение = Новый HTTPСоединение("www.cbr-xml-daily.ru",443,,,,,ЗащищенноеСоединение,);
		ДатаКотировок = ПериодОтчета.ДатаНачала;
		ТаблицаКотировок = Новый ТаблицаЗначений;
		ТаблицаКотировок.Колонки.Добавить("Валюта");
		ТаблицаКотировок.Колонки.Добавить("Дата");
		ТаблицаКотировок.Колонки.Добавить("Курс");
		Пока ДатаКотировок <= ПериодОтчета.ДатаОкончания Цикл
			ДатаКотировокСтрока = Формат(ДатаКотировок, "ДФ=yyyy/MM/dd");
			Ответ = БезопасноеСоединение.Получить(Новый HTTPЗапрос(СтрШаблон("/archive/%1/daily_json.js", ДатаКотировокСтрока)));
			Если Ответ.КодСостояния = 200 Тогда
				СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
				ЧтениеJSON = Новый ЧтениеJSON;
				ЧтениеJSON.УстановитьСтроку(СтрокаОтвет);
				ОбъектОтвет = ПрочитатьJSON(ЧтениеJSON,,"Date",ФорматДатыJSON.ISO);
				Для Каждого СтрокаВалюты Из ОбъектОтвет.Valute Цикл
					Значение = СтрокаВалюты.Значение;
					СтрокаКотировок = ТаблицаКотировок.Добавить();
					СтрокаКотировок.Валюта = Значение.CharCode;
					СтрокаКотировок.Курс = Значение.Value;
					СтрокаКотировок.Дата = НачалоДня(ОбъектОтвет.Date);
				КонецЦикла;
			КонецЕсли;
			ДатаКотировок = ДатаКотировок + 86400;
		КонецЦикла;
		ТаблицаКотировокКЭШ.Загрузить(ТаблицаКотировок);
	КонецЕсли;
	СтруктураВнешнихНаборов = Новый Структура;
	СтруктураВнешнихНаборов.Вставить("ТаблицаКотировок", ТаблицаКотировок);	
	Возврат СтруктураВнешнихНаборов;	
КонецФункции

Готово! Можно сформировать отчет в пользовательском режиме и посмотреть что получилось. Чтобы отфильтровать нужные валюты, можно добавить отбор по полю Валюта с видом сравнения “В списке”.

Отчет на СКД набор данных объект 2

Мы рассмотрели пример, как на СКД сформировать отчет по внешнему набору данных. Основные тезисы:

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

Оставьте комментарий

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

пятнадцать + 17 =

К НАЧАЛУ