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

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

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

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

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

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

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

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

//некий код

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

&НаСервереБезКонтекста
Функция ГенераторИерархическогоНомера(Уровень, КоллекцияНомеров, Обнуление)
ТекОктетНомера = КоллекцияНомеров.Получить(Уровень);
Префикс = "";

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

Возврат Префикс + Строка(ТекОктетНомера) + ".";
КонецФункции

 

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

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

10 Comments

  1. Steelvan

    Вроде интересно, с ходу по коду трудно понять.

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

    Подпишусь на тему 🙂

    Reply
  2. makc2k

    Ок, слеплю обработочку под справочник номенклатура.

    Reply
  3. makc2k

    Вот пример обработки с неуправляемой формой: Файл обработки . Надеюсь можно загрузить будет из комментария, не хочется статью переводить в черновик и снова отправлять на модерацию.

    Reply
  4. vec435

    с помощью СКД не получится?

    Reply
  5. makc2k

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

    Reply
  6. Bell

    Этот вариант нумератора предлагался:

    http://infostart.ru/public/14058/

    Reply
  7. makc2k

    Дошел до него сам, впрочем сказал , что не оригинален по данному вопросу.

    Reply
  8. DrAku1a

    Мдя… Рекурсией это сделать намного проще… Хотя и минус в производительности… Несколько десятков/сотен миллисекунд…

    Процедура ЗаполнитьУровниИерархии(Строки, ИмяКолонки, Префикс=»»)
    сч = 0;
    Для каждого Строка из Строки Цикл
    сч = сч + 1;
    ТекНомер = Префикс + СтрЗаменить(«»+сч, Символы.НПП, «») + «.»;
    Строка[ИмяКолонки] = ТекНомер;
    ЗаполнитьУровниИерархии(Строка.Строки, ИмяКолонки, ТекНомер);
    КонецЦикла;
    КонецПроцедуры
    
    //Вызов:
    ЗаполнитьУровниИерархии(ДеревоЗначений.Строки, «НомерСтроки»);

    Показать

    Reply
  9. makc2k

    Как раз я и задумывал не прибегать к рекурсии.

    Reply
  10. vasyak319

    Вместо

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

    должно быть

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

    Вот это лишнее:

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

    и вот это тоже:

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

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *