Как передать таблицу значений в запрос СКД и вывести недостающие строки с нулевыми остатками?

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

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

Способ 1. Передача таблицы значений в запрос СКД через Менеджер временных таблиц

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

Разберем по шагам, как реализовать этот механизм в модуле отчета:

  1. В процедуре ПриКомпоновкеРезультата создадим объект МенеджерВременныхТаблиц.
  2. С помощью обычного запроса поместим нашу таблицу значений во временную таблицу в созданном менеджере.
  3. В тексте запроса набора данных СКД обратимся к этой временной таблице по имени и выполним любые соединения (ЛЕВОЕ, ПОЛНОЕ) или проверки через ЕСТЬNULL.
  4. Инициализируем процессор компоновки данных, передав менеджер временных таблиц шестым параметром.

Посмотрим на пример программного кода в модуле объекта отчета:


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

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

В схеме компоновки данных текст запроса будет выглядеть следующим образом:


ВЫБРАТЬ
	ЭталонныеСчета.Ссылка КАК Счет,
	ВТ.Организация КАК Организация,
	ЕСТЬNULL(ВТ.СуммаОстаток, 0) КАК СуммаОстаток
ИЗ
	ПланСчетов.Хозрасчетный КАК ЭталонныеСчета
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДанныеВнешнейБазы КАК ВТ
		ПО ЭталонныеСчета.Код = ВТ.Счет
ГДЕ
	ЭталонныеСчета.Ссылка В ИЕРАРХИИ(&ГруппаСчетов)

Важный момент: чтобы в конструкторе СКД запрос сохранялся без ошибок, для полей временной таблицы в запросе схемы рекомендуется использовать явное приведение типов с помощью функции ВЫРАЗИТЬ().

Способ 2. Корректная настройка связей между наборами данных

Если мы используем два набора данных типа Объект (например, НаборДанныхЭталон и НаборДанныхФакт), СКД объединяет их через вкладку Связи наборов данных. Связь между наборами данных всегда работает по принципу левого соединения от источника к приемнику.

Разберем типичные ошибки при такой настройке:

  1. Неправильно выбран ведущий набор: Источником связи (ведущим) должен выступать набор данных с полным списком счетов, а приемником — набор с суммами из внешней базы.
  2. Обработка отсутствующих значений: Для вывода нулевых остатков на вкладке Ресурсы необходимо указать выражение вида: ЕСТЬNULL(Сумма(СуммаОстаток), 0). Также можно добавить вычисляемое поле с выражением ЕСТЬNULL(СуммаОстаток, 0).
  3. Влияние отборов: Если пользователь установит отбор по полю приемника (например, по реквизиту из зависимой таблицы), СКД автоматически трансформирует соединение во внутреннее, исключая строки со значением NULL. Отборы следует накладывать только на поля ведущего набора или вычисляемые поля.

Способ 3. Использование набора данных «Объединение»

Еще один удобный вариант без использования запросов — объединение двух наборов данных типа Объект внутри элемента Набор данных - Объединение.

  1. Создаем структуру Набор данных - Объединение.
  2. Внутрь помещаем два набора-объекта: НаборЭталон (содержит полный перечень счетов с нулевой суммой) и НаборФакт (фактические данные).
  3. Называем поля в обоих наборах идентично: Счет, СуммаОстаток, Организация.
  4. На вкладке Ресурсы настраиваем агрегацию: Сумма(СуммаОстаток).

При группировке по полю Счет платформа объединит строки: по счетам с остатками сложится ноль и факт, а по отсутствующим останется строка с нулем.

Требования к типизации таблицы значений

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

← На главную