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

Чтение группировок табличного документа

Чтение группировок табличного документа

В наличии

Есть mxl, табличный документ, в котором сделана группировка строк, и надо прочитать из него данные с учётом этих группировок, т.е. иерархически. Сам документ читаем по ячейкам, но как быть с иерархией? На помощь приходит сериализация.

Категория:

Описание

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

Представленный вариант — для толстого клиента или для сервера. Желающие могут превратить таблицу и дерево значений в коллекции или данные формы, сути это не меняет. Суть очень проста — сериализовать в XDTO, через XML в DOM и прочитать сведения об иерархии по нужным узлам-тегам. Производительность на больших объёмах будет, естественно, не ахти, что надо учитывать; ну и если построитель DOM не потянет, придётся копать последовательным чтением XML. Мысль публикации лишь в том, что, хотя во встроенном языке нет возможности выяснить уровень области, данные об этом любой табличный документ хранит. Я поработал с группировками строк, нечто подобное можно сделать и для группировок колонок — это, к примеру, для любителей курочить выходной таб.документ СКД.

Итак:

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

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

P.S.  Если это баян, киньте в меня тапочком ссылкой.

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