Выборочная свертка группировок для СКД

16.01.23

Разработка - СКД

Методика разработки отчета на СКД с возможностью свёртки части группировок по заданному программно условию. - свертка по значению поля (неотрицательные - сворачиваются); - свертка подчиненных в иерархии с произвольным количеством уровней.

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Пример отчетов - заказы на номенклатуру по дате отгрузки
.zip 30,34Kb
8 2 500 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

Задача: создать отчет на СКД таким образом, чтобы в нем некоторые группировки вывелись свернутыми.

Далее рассматриваются два примера — свертка всех группировок по условию на поле (свернуть все группы с неотрицательным значением по родительской группировке) и свертка подчиненной группировки у группировок с иерархией с произвольным количеством уровней.

Решать такую задачу без СКД просто — при выводе очередной строчки отчета требуется использовать методы НачатьГруппуСтрок/ЗакончитьГруппуСтрок. При использовании СКД возникают проблемы:

  • необходимость перехвата вывода определенных группировок
  • отключение автонастройки свертки/развертки групп.
  • анализ изменений в структуре.

Далее в статье используется функция ПолучитьМакетГруппировкиПоПолюГруппировки из типового модуля СтандартныеОтчеты (БП 2.0) / БухгалтерскиеОтчеты (БП 3.0). Если вы делаете отчет для базы, в которой нет этих модулей, текст этих функций вам потребуется перенести в модуль объекта (либо общий модуль, доступный из объекта).

 
 Текст функции, (с) 1с Бухгалтерия Предприятия

Конкретный пример — показать заказы на номенклатуру на дату отгрузки, структура — Номенклатура/Заказы.

 
 СКД, используемая для примера

Отчет формируется типовым образом:

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

Задача 0) Для начала рассмотрим более простую задачу — свернуть именованную группировку, которая может оказаться на любом (заранее неизвестном) уровне в структуре. Для сворачивания используется метод ПоказатьУровеньГруппировокСтрок объекта типа ТабличныйДокумент. Этот метод принимает параметр - уровень группировки, аналогичный уровню, показываемому в контекстном меню в разделе "уровни группировок", только нумерация начинается с нуля.

 
 текст для примера, считается что структура "лесенкой" и в группировке поле поиска идет первым.

Задачи 1 и 2) Общая часть.

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

Метод Следующий последовательно возвращает объекты типа ЭлементРезультатаКомпоновкиДанных.

Для решения задач используются следующие свойства этого объекта: полная информация о данных выводимой строчки в коллекции «ЗначенияПараметров», имя макета и тип элемента.

Имена макетов и параметров формализованы — все макеты именуются в виде «Макет#», и все параметры - «П#», где # это номер от одного и далее.

Для того чтобы понять, какая группировка выводится, используется функция ПолучитьМакетГруппировкиПоПолюГруппировки, которая возвращает массив объектов типа ОписаниеМакетаОбластиМакетаКомпоновкиДанных, содержащих данную группировку. Этот массив мы перезаписываем в массив строковых имен вида «Макет#», для удобства поиска.


	МакетГруппировкиНом = ПолучитьМакетГруппировкиПоПолюГруппировки(МакетКомпоновкиДанных, "Номенклатура");
	МакетНом = Новый Массив;
	Для Каждого МакетГруппировки Из МакетГруппировкиНом Цикл
		МакетНом.Добавить(МакетГруппировки.Имя);
	КонецЦикла;
	
	МакетГруппировкиЗаказ = ПолучитьМакетГруппировкиПоПолюГруппировки(МакетКомпоновкиДанных, "Заказ");
	МакетЗаказ = Новый Массив;
	Для Каждого МакетГруппировки Из МакетГруппировкиЗаказ Цикл
		МакетЗаказ.Добавить(МакетГруппировки.Имя);
	КонецЦикла;

Для того, чтобы получить данные о соблюдении условия свертки анализируется значение параметра П#, относящегося к полю, определяющему проверяемое значение и здесь у нас проблема — нет способа привязать параметр П к полю, как мы это сделали с макетами. Значение Параметра только содержит свойство Выражение, в котором прописано вычисляемое выражение. Для полей, описанных в разделе «Наборы данных», выражение имеет вид «НазваниеНабораДанных.НазваниеПоля», например НаборДанных1.Номенклатура, для вычисляемых же полей свойство «Выражение» содержит нормализованное значение в колонке «выражение»  - добавлена функция «Представление()», расставлены пробелы, регистры для функций, удалены лишние нули в числах, к каждому параметру добавлен набор данных. Поэтому даже просто скопировать значение из этой колонки не всегда получится. Я предлагаю в начало выражения Вычисляемого поля добавить маркер «0 +» и искать по фрагменту "(0 +" - скобка от того что в начале у вас после преобразования будет "Представление(0 +....".

Вложенные группировки выводятся не просто по очереди а в следующем формате:
( (Р) < ( ( (п) ) [( (п) ) ...] ) > ),
где ( - элемент результата со свойством «ТипЭлемента» = ТипЭлементаРезультатаКомпоновкиДанных.Начало,
) - элемент результата со свойством «ТипЭлемента» = ТипЭлементаРезультатаКомпоновкиДанных.Конец,
(Р) — элемент результата для родительской группировки, имеющий свойство «ТипЭлемента» = ТипЭлементаРезультатаКомпоновкиДанных.НачалоИКонец,
(п) — ... для подчиненной группировки (см. (Р) ),
<, > - я обозначил те места между элементами результатов куда следует добавить НачатьГруппуСтрок/ЗакончитьГруппуСтрок соответственно.

То есть каждая группировка имеет тип НачалоИКонец, и обрамляется элементами Начало и Конец, после чего следуют подчиненные группировки, имеющие тип НачалоИКонец, все вместе обрамленные элементами Начало и Конец и каждая по отдельности обрамлена элементами Начало и Конец.

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

Общая идея такая — при получении результата типа НачалоИКонец и соблюдении нашего условия мы сразу ставим  НачатьГруппуСтрок, выводим все подчиненные группировки, после чего, соблюдая парность, ставим ЗакончитьГруппуСтрок.

Задача 1) Для отчета в разрезе Номенклатура/Заказ свернуть все группировки номенклатуры без дефицита (то есть таких, для которых остаток товара больше объема заказов).

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

Прим. При поиске используется Попытка потому что не каждый Параметр имеет поле Выражение. Но это тема для отдельной статьи.

Пример результата данного отчета:

 

 

Задача 2) Для отчета в разрезе Номенклатура/Заказ свернуть все группировки номенклатуры с подчиненными заказами.

В приведенной выше структуре надо поставить тип группировки номенклатуры - Иерархия.

Значения параметров имеют скалярные типы, и номенклатуру мы получаем в виде строки с наименованием. Обычно существует опасность что в базе может быть несколько элементов номенклатуры с одинаковым наименованием, поэтому искать ссылку по наименованию не предлагается. Вместо этого сначала помещаем все результаты в массив. Потом делаем вывод результатов из этого массива, проверяя, не является ли третий результат впереди группировкой «Заказ».

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

			Если МакетНом.Найти(ЭлементРезультата.Макет) <> Неопределено Тогда

				// Если у вас в номенклатуре гарантированно уникальные наименования номенклатуры тогда можно
				// не помещать результаты в массив а использовать проверку вида
				//ЗначРод = ЭлементРезультата.ЗначенияПараметров["П1"].Значение;
				//СсылкаРод = Справочники.Номенклатура.НайтиПоНаименованию(ЗначРод,Истина);
				//Если НЕ СсылкаРод.ЭтоГруппа Тогда
				
				СледЭлт = мРезультат[х+3];
				Если МакетЗаказ.Найти(СледЭлт.Макет) <> Неопределено Тогда

					ДокументРезультат.НачатьГруппуСтрок(ЭлементРезультата.ЗначенияПараметров.П1.Значение,Ложь);

					//( (Н)!( ( (з) ) ( (з) ) )!)
					УровеньНачала = 0;
					Пока Истина Цикл
						х = х+1;
						ЭлементРезультата = мРезультат[х];
						Если ЭлементРезультата.ТипЭлемента = ТипЭлементаРезультатаКомпоновкиДанных.Начало Тогда
							УровеньНачала = УровеньНачала + 1;
						ИначеЕсли ЭлементРезультата.ТипЭлемента = ТипЭлементаРезультатаКомпоновкиДанных.Конец Тогда
							УровеньНачала = УровеньНачала - 1;
						КонецЕсли;
						ПроцессорВывода.ВывестиЭлемент(ЭлементРезультата);
						Если УровеньНачала = 0 Тогда Прервать КонецЕсли;
					КонецЦикла;
					
					ДокументРезультат.ЗакончитьГруппуСтрок();
					
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	ПроцессорВывода.ЗакончитьВывод();
	
КонецПроцедуры

Пример результата:

 

 

К статье прикрепрен примерный СКД, созданный под задачи организации: заказы берутся без пометки на удаление, заказ на который уже выписана реализация считается полностью отгруженным (нет резервирования для допоставки). В группировке Заказ типовое представление заменено на наименование Партнера. Для конфиденциальности на образцах наименования обрезаны. Отчеты работают в УТ11, ERP 2, если необходим вариант для УТ10, напишите в комментариях.

Отчеты тестировались на версии Платформы 1С:Предприятие 8.3 (8.3.21.1622), хотя старые версии отчета работали в УТ10 с платформ версии 8.3.5. Теоретически должно работать на любой платформе с поддержкой СКД.

P.S. отправной точкой послужила статья СКД: вывод некоторых группировок свернутыми

Вступайте в нашу телеграмм-группу Инфостарт

СКД система компоновки данных группировка макет параметр свертка строк. процессор вывода

См. также

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта 1С:Предприятие 8 Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

16500 руб.

02.09.2020    244661    1341    419    

1122

Инструментарий разработчика СКД Программист 1С 8.3 Бесплатно (free)

В этой статье представлен СКДБилдер — общий модуль-обёртка над объектной моделью СКД, который сокращает код в 3-4 раза и делает его читаемым.

29.01.2026    4686    262    shapa_pro    25    

63

СКД Программист 1С:Предприятие 8 Бесплатно (free)

Статья написана по результатам проведенного внутреннего обучающего вебинара для разработчиков ГК «СофтБаланс». Если осилить 25 000 знаков - задача для вас непосильная, где-то на бескрайних просторах интернета видео есть (или будет). Но здесь информация точнее. Разберем, чем запрос для СКД принципиально отличается от обычного запроса и как модифицируется в зависимости от настроек. Изучим «базовый рецепт» написания запроса для СКД, сформируем чек-лист. Полезно будет всем – от стажеров до тех. лидов. Всем, кто не снимает галку «автозаполнение» и пишет запросы для отчетов в консоли запросов – читать (вдумчиво) обязательно.

29.10.2025    15219    ovetgana    112    

105

СКД Программист 1С:Предприятие 8 Бесплатно (free)

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

01.07.2025    8957    krasnoshchekovpavel    5    

66

СКД Программист Стажер 1С:Предприятие 8 Россия Бесплатно (free)

Несколько способов управления формами выбора параметров и отборов СКД.

10.04.2025    8172    Neti    0    

41

СКД Программист 1С:Предприятие 8 Бесплатно (free)

Хорошая отчетная форма - сродни искусству. Есть какое-то невероятное эстетическое удовольствие в том, чтобы разобраться в логике учета и анализируемых показателях, спроектировать архитектуру хранения данных так, чтобы оптимально собрать эти показатели вместе с аналитическими разрезами в запросе, а затем настроить отображение так, чтобы, глядя на результат, сразу было понятно, что это за отчет и какие задачи он призван решать. Система компоновки данных - это моя первая, главная и, наверное, единственная "рабочая" любовь. Ее я использую везде, где только можно и где нельзя тоже. Хочу поделиться с вами некоторыми практическими приемами в работе с отчетами на СКД, которые, надеюсь, будут полезны.

27.02.2025    15377    ovetgana    50    

93

СКД Программист 1С:Предприятие 8 Бесплатно (free)

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

24.12.2024    12992    Akcium    17    

46

СКД Механизмы типовых конфигураций Запросы Программист 1С:Предприятие 8 1С:Зарплата и кадры государственного учреждения 3 1С:Зарплата и Управление Персоналом 3.x Россия Бесплатно (free)

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

20.08.2024    9394    AlexeyPROSTO_1C    1    

32
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. evn-zorin 34 19.01.23 09:55 Сейчас в теме
Интересно, век живи, век учись)
3. schthaxe 56 19.01.23 14:14 Сейчас в теме
(1) Вообще говоря мой самый первый вариант работал так: я делал копию отчета через процессор вывода в ДЗ в дерево, дерево перегонял в ТЗ, и потом вместо анализа типа результата как в статье - анализировал получившуюся ТЗ, обходя вместе с выводом макетов эту ТЗ.
Конечно по сравнению с старой версией эта - сама элегантность ))) Обычно на эти типы результата никто не смотрит, а зря...
cleaner_it; +1 Ответить
2. AllexSoft 19.01.23 10:41 Сейчас в теме
Любопытно, надо с этим поиграться... вот правда поддерживать такие вещи сложно, кто то поле тебя придет и ничего не поймет зачем так сделано и как это работает.
sys1c; cleaner_it; evn-zorin; +3 Ответить
4. Smollsan 06.10.23 13:58 Сейчас в теме
Респект автору, который погружается в такие адские дебри!
В моем случае нужно было просто свернуть все группировки при выводе, метод ДокументРезультат.ПоказатьУровеньГруппировокСтрок() не помогал. Использовал часть кода из статьи - заработало!
schthaxe; +1 Ответить
5. schthaxe 56 13.10.23 17:33 Сейчас в теме
(4) Вы знаете у меня такое очень смутное ощущение что в группировках СКД просто используется типовой механизм автогруппировки. То есть при формировании СКД отчета неявно но принудительно вызываются методы
НачатьАвтогруппировкуСтрок()/ЗакончитьАвтогруппировкуСтрок().
Либо это те же самые методы, либо очень похожие но отдельно для СКД.
А то, что написано в статье - это просто попытка работать внутри автогруппировки.
Но это моя гипотеза.
6. user2013846 19.03.24 23:12 Сейчас в теме
Если у отчета нет своей формы, то в общей форме ФормаОтчета все переделывается в В БП 3.0 (3.0.147.25)
7. NenavizhySKD 06.08.24 12:22 Сейчас в теме
Зачем в "Задача 0)" вот этот код?
СтрРод = стр.Родитель;
Где эта переменная СтрРод используется?
8. DmitriyLipetsk94 15.08.25 13:21 Сейчас в теме
Добрый день! Отличная статья! Адаптировал под свои нужды, но по какой то причине ничего не сворачивает, хотя в код захожу, ошибок нет. Мучаюсь с отчетом 4-й день)
Для отправки сообщения требуется регистрация/авторизация