gifts2017

Иерархическая нумерация (один из вариантов)

Опубликовал Makc *** (makc2k) в раздел Программирование - Универсальные функции

Данный механизм позволит пронумеровать ветви иерархической структуры в виде:
1.
1.1
    1.1.1
    1.1.2
1.2

Механизм основывается на коллекции уже созданных счетчиков (соответствие), куда записываются актуальные номера и сбрасываются в случае уменьшения уровня выборки. Нумерация подойдет для структур, выводимых запросом через иерархическую сортировку (не итоги).

Сортировка в запросе по иерархии

Построена на условии функции расчета и одной переменной - флага. Для наглядности предлагаю рассмотреть схему:

Схема формирования иерархического номера

Теперь собственно код:

СоотвНумерации = Новый Соответствие;
СоотвНумерации.Вставить(0, 0); //для нулевого уровня будет нулевой счетчик (до начала цикла)
ПрошлыйУровень = 0;//флаг уровня прошлой итерации цикла по выборке

//некий код

Пока Выборка.Следующий() Цикл
	Обнуление = ?(ПрошлыйУровень < Выборка.Уровень(), Истина, Ложь);//проверка условия сброса счетчика
	Номер = ГенераторИерархическогоНомера(Выборка.Уровень(), СоотвНумерации, Обнуление); //формирование номера
	ПрошлыйУровень = Выборка.Уровень();//запись текущего уровня выборки для следующей итерации цикла
КонецЦикла;

&НаСервереБезКонтекста
Функция ГенераторИерархическогоНомера(Уровень, КоллекцияНомеров, Обнуление)
	ТекОктетНомера = КоллекцияНомеров.Получить(Уровень);
	Префикс = "";
	
	//расчет префикса
	Для н = 0 По Уровень - 1 Цикл
		Префикс = Префикс + Строка(КоллекцияНомеров.Получить(н)) + ".";
	КонецЦикла;
	//Увеличение тек. номера на единицу или сброс в единицу
	Если Обнуление Тогда
		ТекОктетНомера = 1;
	Иначе
		ТекОктетНомера = КоллекцияНомеров.Получить(Уровень) + 1;
	КонецЕсли;
	КоллекцияНомеров.Удалить(Уровень);
	КоллекцияНомеров.Вставить(Уровень, ТекОктетНомера);
	
	Возврат Префикс + Строка(ТекОктетНомера) + ".";
КонецФункции

 

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

Не хочу претендовать на оригинальность, это просто один из способов.

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Игорь Steelvan (Steelvan) 17.07.15 13:35
Вроде интересно, с ходу по коду трудно понять.

Конфу с примером приложите пжл.

Подпишусь на тему :)
2. Makc *** (makc2k) 17.07.15 14:22
Ок, слеплю обработочку под справочник номенклатура.
3. Makc *** (makc2k) 17.07.15 14:46
Вот пример обработки с неуправляемой формой: Файл обработки . Надеюсь можно загрузить будет из комментария, не хочется статью переводить в черновик и снова отправлять на модерацию.
4. Владимир Чаклин (vec435) 22.07.15 08:39
с помощью СКД не получится?
5. Makc *** (makc2k) 22.07.15 11:26
У СКД своя сортировка и есть своя нумерация в служебных полях (НомерПоПорядкуВГруппировке, УровеньВГруппировке). Там в конструкторе запроса даже закладки сортировка нет. Конечно можно и вручную дописать, но зачем тогда СКД?
6. Александр (Bell) 22.07.15 20:41
Этот вариант нумератора предлагался:
http://infostart.ru/public/14058/
7. Makc *** (makc2k) 23.07.15 00:35
Дошел до него сам, впрочем сказал , что не оригинален по данному вопросу.
8. Андрей Акулов (DrAku1a) 23.07.15 05:08
Мдя... Рекурсией это сделать намного проще... Хотя и минус в производительности... Несколько десятков/сотен миллисекунд...
Процедура ЗаполнитьУровниИерархии(Строки, ИмяКолонки, Префикс="")
	сч = 0;
	Для каждого Строка из Строки Цикл
		сч = сч + 1;
		ТекНомер = Префикс + СтрЗаменить(""+сч, Символы.НПП, "") + ".";
		Строка[ИмяКолонки] = ТекНомер;
		ЗаполнитьУровниИерархии(Строка.Строки, ИмяКолонки, ТекНомер);
	КонецЦикла;    
КонецПроцедуры

//Вызов:
ЗаполнитьУровниИерархии(ДеревоЗначений.Строки, "НомерСтроки");
...Показать Скрыть
9. Makc *** (makc2k) 23.07.15 10:09
Как раз я и задумывал не прибегать к рекурсии.
10. Василий Коровин (vasyak319) 23.07.15 10:33
Вместо
Обнуление = ?(ПрошлыйУровень < Выборка.Уровень(), Истина, Ложь);

должно быть
Обнуление = ПрошлыйУровень < Выборка.Уровень();


Вот это лишнее:
ТекОктетНомера = КоллекцияНомеров.Получить(Уровень);

и вот это тоже:
КоллекцияНомеров.Удалить(Уровень);