Каталог решений - Получаем уровень группировки ячейки табличного документа

Получаем уровень группировки ячейки табличного документа

Получаем уровень группировки ячейки табличного документа

В наличии

Табличные документы отчетов часто формируются с разными уровнями группировок и иногда требуется определить номер уровня ячейки. Предлагаю свои функции, которые позволяют определить, как горизонтальный, так и вертикальный уровень группировки любой ячейки табличного документа.

Категория:

Описание

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

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

Единственное, что я нашёл подходящее для моей задачи, это была вот эта статья: //sale.itcity.ru/public/182115/. В данной разработке использовалась функция определения уровня ячейки. Но при использовании обнаружил следующее:

  •  в ней нет функции определении уровня группировок колонок, а только функция определения уровня группировки строк;
  •   при наличии в табличном документе группировок колонок функция определения уровня строк перестаёт работать.

Далее я натолкнулся на хорошую статья //sale.itcity.ru/public/562724/, где используется сериализация и разбор структуры табличного документа. И мне захотелось просто сделать функции, куда передаёшь координаты ячейки и получаешь уровни колонок и строк группировок.

Итак, у вас есть форма обработки и на ней размещен  реквизит формы табличный документ (ТабДок), далее становимся на любую ячейку и нажимаем кнопку "ПолучитьУровниТекущейЯчейки". Выводятся сообщения с номерами уровней группировки  строк и колонок ячейки.  Если ячейка не входят в группировки, то её уровень равен. 1 (единица).

Вот код: 

&НаКлиенте
Процедура ПолучитьУровниТекущейЯчейки(Команда)
	
	//ТабДок - рекизит на форме (Табличный документ)
	//и вынесен на форму в элемент "ТабДок"
	НомерСтроки = Элементы.ТабДок.ТекущаяОбласть.Верх;
	НомерКолонки = Элементы.ТабДок.ТекущаяОбласть.Лево;
	
	УровеньЯчейки = ПолучитьУровеньГруппировкиЯчейки(ТабДок,НомерСтроки,НомерКолонки);
	
	Сообщить("Уровни группировок ячейки (" + НомерСтроки + "," + НомерКолонки + "," + НомерСтроки +"," + НомерКолонки + ")");
	Сообщить(Символы.Таб + "Уровень строки: " + УровеньЯчейки.УровеньСтроки);
	Сообщить(Символы.Таб + "Уровень колонки: " + УровеньЯчейки.УровеньКолонки);
	
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьУровеньГруппировкиЯчейки(ТабДок, НомерСтроки,НомерКолонки)
	
	Перем УровеньЯчейки;
	
	УровеньЯчейки = Новый Структура("УровеньСтроки,УровеньКолонки",1,1);
	
	мЗапись = Новый ЗаписьXML;
	мЗапись.УстановитьСтроку("UTF-8");
	
	СериализаторXDTO.ЗаписатьXML(мЗапись,ТабДок);
	
	ТекстXML = мЗапись.Закрыть();
	
	мЧтение = Новый ЧтениеXML;
	мЧтение.УстановитьСтроку(ТекстXML);
	ПострDOM = Новый ПостроительDOM;
	ДанныеDOM = ПострDOM.Прочитать(мЧтение);
	
	//уровни строк
	ТаблицаУровнейПоСтрокам = ПолучитьТаблицуУровнейПоСтрокам(ДанныеDOM);
	строкаУровняПоСтрокам = ТаблицаУровнейПоСтрокам.Найти(НомерСтроки,"Номер");
	Если строкаУровняПоСтрокам <> Неопределено Тогда
		УровеньЯчейки.УровеньСтроки = строкаУровняПоСтрокам.Уровень;
	КонецЕсли;	
	
    //уровни колонок
	ТаблицаУровнейПоКолонкам = ПолучитьТаблицуУровнейПоКолонкам(ДанныеDOM);
	строкиУровнейКолонокПоНомерамСтрок = ТаблицаУровнейПоКолонкам.НайтиСтроки(Новый Структура("НомерСтроки,ЕстьУровни", НомерСтроки,Истина));
	Если строкиУровнейКолонокПоНомерамСтрок.Количество() > 0 Тогда
		ТаблицаКолонок = строкиУровнейКолонокПоНомерамСтрок[0].ТаблицаКолонок;
		строкаУровняКолонки = ТаблицаКолонок.Найти(НомерКолонки, "Номер");
		Если строкаУровняКолонки <> Неопределено Тогда
			УровеньЯчейки.УровеньКолонки = строкаУровняКолонки.Уровень;
		КонецЕсли;	
	КонецЕсли;
	
	Возврат УровеньЯчейки;
	
КонецФункции	

&НаСервереБезКонтекста
Функция ПолучитьТаблицуУровнейПоСтрокам(ДанныеDOMТабДок)
	
	ТаблицаУровней = Новый ТаблицаЗначений;
	ТаблицаУровней.Колонки.Добавить("Номер",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0))); 
	ТаблицаУровней.Колонки.Добавить("Уровень",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0))); 
	
	УзлыУровнейDOMТабДок =  ДанныеDOMТабДок.ПолучитьЭлементыПоИмени("vg");
	ПредКонецГруппировки = 0;
	Для инд = 0 по УзлыУровнейDOMТабДок.Количество() - 1 Цикл
		
		УзелГруппы = УзлыУровнейDOMТабДок[инд];
		
		НачалоГруппировки = 0;
		КонецГруппировки = 0;
		
		Для н = 0 По УзелГруппы.ДочерниеУзлы.Количество() - 1 Цикл
			ПодУзел =  УзелГруппы.ДочерниеУзлы[н];
			Если ПодУзел.ИмяУзла = "b" Тогда
				НачалоГруппировки = Число(СокрЛП(ПодУзел.ТекстовоеСодержимое));
			ИначеЕсли ПодУзел.ИмяУзла = "e" Тогда
				КонецГруппировки = Число(СокрЛП(ПодУзел.ТекстовоеСодержимое));
			КонецЕсли;
		КонецЦикла;
		
		Если НачалоГруппировки = 0 Тогда Продолжить КонецЕсли;
		
		// если конца группировки не оказалось, то одна позиция в подгруппе
		Если КонецГруппировки = 0 Тогда
			КонецГруппировки = НачалоГруппировки
		КонецЕсли; 
		
		//конец область увеличить нужно на 1 
		КонецГруппировки = КонецГруппировки + 1; 
		РодительскийУровень = 0;
		Для Номер = НачалоГруппировки по КонецГруппировки Цикл
				
			строкаТаблицы = ТаблицаУровней.Найти(Номер, "Номер");
			Если строкаТаблицы = Неопределено Тогда
				строкаТаблицы = ТаблицаУровней.Добавить();
				строкаТаблицы.Номер = Номер;
				строкаТаблицы.Уровень = РодительскийУровень + 1;
				Если Номер = НачалоГруппировки Тогда
					РодительскийУровень = 1;
				КонецЕсли;	
			Иначе
				Если Номер = НачалоГруппировки Тогда
					РодительскийУровень = строкаТаблицы.Уровень
				Иначе
					строкаТаблицы.Уровень = РодительскийУровень + 1;	
				КонецЕсли;	
				
			КонецЕсли;
				
		КонецЦикла;	
		
	КонецЦикла;
	
	Возврат ТаблицаУровней;
	
КонецФункции

&НаСервереБезКонтекста
Функция ПолучитьТаблицуУровнейПоКолонкам(ДанныеDOMТабДок)
	
	ТаблицаУровней = Новый ТаблицаЗначений;
	ТаблицаУровней.Колонки.Добавить("НомерСтроки",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0))); 
	ТаблицаУровней.Колонки.Добавить("columnsID",Новый ОписаниеТипов("Строка",Новый КвалификаторыСтроки(36))); 
	ТаблицаУровней.Колонки.Добавить("ТаблицаКолонок"); 
	ТаблицаУровней.Колонки.Добавить("Уровень",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0))); 
	ТаблицаУровней.Колонки.Добавить("ЕстьУровни",Новый ОписаниеТипов("Булево")); 
	
	//Определяем сколько строк
	//и идентификатор колонок columnsID, которые будут заполнены в тех строках
	//где своё количество колонок (новый формат строк)
	УзлыУровнейDOMТабДок =  ДанныеDOMТабДок.ПолучитьЭлементыПоИмени("rowsItem");
	Для инд = 0 по УзлыУровнейDOMТабДок.Количество() - 1 Цикл
		УзелГруппы = УзлыУровнейDOMТабДок[инд];
		

		строкаТаблицыНомерСтроки = ТаблицаУровней.Добавить();
		
		ТаблицаКолонок = Новый ТаблицаЗначений;
		ТаблицаКолонок.Колонки.Добавить("Номер",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0))); 
		ТаблицаКолонок.Колонки.Добавить("Уровень",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0))); 
		
		строкаТаблицыНомерСтроки.ТаблицаКолонок = ТаблицаКолонок;
		
		Для н = 0 По УзелГруппы.ДочерниеУзлы.Количество() - 1 Цикл
			ПодУзел =  УзелГруппы.ДочерниеУзлы[н];
			Если ПодУзел.ИмяУзла = "index" Тогда
				строкаТаблицыНомерСтроки.НомерСтроки = Число(ПодУзел.ТекстовоеСодержимое) + 1;
			ИначеЕсли ПодУзел.ИмяУзла = "row" Тогда
				ПодУзел2 = ПодУзел.ДочерниеУзлы;
				Для м = 0 по ПодУзел.ДочерниеУзлы.Количество() - 1 Цикл
					ПодУзел2 = ПодУзел.ДочерниеУзлы[м];
					Если ПодУзел2.ИмяУзла = "columnsID" Тогда
						строкаТаблицыНомерСтроки.columnsID = СокрЛП(ПодУзел.ТекстовоеСодержимое);
						Прервать;
					КонецЕсли;	
				КонецЦикла;	
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;	
	
	УзлыУровнейDOMТабДок =  ДанныеDOMТабДок.ПолучитьЭлементыПоИмени("hg");
	
	Для инд = 0 по УзлыУровнейDOMТабДок.Количество() - 1 Цикл
		
		УзелГруппы = УзлыУровнейDOMТабДок[инд];
		
		columnsID = Неопределено;
		НачалоГруппировки = 0;
		КонецГруппировки = 0;
		
		Для н = 0 По УзелГруппы.ДочерниеУзлы.Количество() - 1 Цикл
			ПодУзел =  УзелГруппы.ДочерниеУзлы[н];
			Если ПодУзел.ИмяУзла = "columnsID" Тогда
				columnsID = СокрЛП(ПодУзел.ТекстовоеСодержимое);
			ИначеЕсли ПодУзел.ИмяУзла = "b" Тогда
				НачалоГруппировки = Число(СокрЛП(ПодУзел.ТекстовоеСодержимое));
			ИначеЕсли ПодУзел.ИмяУзла = "e" Тогда
				КонецГруппировки = Число(СокрЛП(ПодУзел.ТекстовоеСодержимое));
			КонецЕсли;
		КонецЦикла;
		
		Если НачалоГруппировки = 0 Тогда Продолжить КонецЕсли;
		
		// если конца группировки не оказалось, то одна позиция в подгруппе
		Если КонецГруппировки = 0 Тогда
			КонецГруппировки = НачалоГруппировки
		КонецЕсли; 
		
		//конец область увеличить нужно на 1 
		КонецГруппировки = КонецГруппировки + 1;
		
		строкиКолонки = ТаблицаУровней.НайтиСтроки(Новый Структура("columnsID", columnsID));
		ПредКонецГруппировки = 0;
		Для НомерСтроки = 0 по строкиКолонки.Количество()  - 1 Цикл
			
			строкиКолонки.Получить(НомерСтроки).ЕстьУровни = Истина;
		    ТаблицаКолонок = строкиКолонки.Получить(НомерСтроки).ТаблицаКолонок;
			РодительскийУровень = 0;
			Для Номер = НачалоГруппировки по КонецГруппировки Цикл
				
				строкаТаблицы = ТаблицаКолонок.Найти(Номер, "Номер");
				Если строкаТаблицы = Неопределено Тогда
					строкаТаблицы = ТаблицаКолонок.Добавить();
					строкаТаблицы.Уровень = РодительскийУровень  + 1;
					строкаТаблицы.Номер = Номер;
					Если Номер = НачалоГруппировки Тогда
						РодительскийУровень = 1;
					КонецЕсли;	
				Иначе
					Если Номер = НачалоГруппировки Тогда
						РодительскийУровень = строкаТаблицы.Уровень
					Иначе
						строкаТаблицы.Уровень = РодительскийУровень + 1;	
					КонецЕсли;	
				КонецЕсли;
				
			КонецЦикла;	
			
		КонецЦикла;
		
	КонецЦикла;
	
	Возврат ТаблицаУровней;
	
КонецФункции

 

Проверял работает на 8.3, 8.2, должно работать и на 8.1. 

Не претендую на лаконичность кода, хотелось, чтобы бы всё было понятно.

has been added to your cart:
Оформление заказа