Книга знаний

1С:Предприятие / v8 / Приемы программирования

v8: Универсальное сохранение/восстановление деревьев

Универсальный алгоритм сохранения\восстановления деревьев на форме.Автор статьи: Violently
Последняя редакция №1 от 30.01.07
URL: http://kb.mista.ru/article.php?id=459

Ключевые слова: Дерево, сохранить, восстановить, записать, построить


В данной статье я предлагаю рассмотреть универсальный алгоритм восстановления деревьев.
Введение:
  На начальной стадии моей работы так сложилось, что мне постоянно давали делать документы, у которых на форме необходимо было представлять данные в иерархическом виде. В связи с этим при сохранении документа необходимо было как-то запоминать дерево. Намучавшись вдоволь с индивидуальным для каждого документа алгоритмом, было решено разработать универсальный.
Описание универсального алгоритма сохранения:
Чтобы реализовать алгоритм, потребуется следующее:
1.    Предположим, что дерево на форме у Вас уже есть и оно как-то заполняется, либо Вы его заполняете сами – неважно.
2.    Добавляем на форму в дерево две колонки, у меня это будет: «ИндексНачало» и «ИндексКонец», они будут иметь строковое представление в 200 символов. (Данные колонки затем рекомендуется просто скрыть, так как они носят чисто служебный характер).
3.    Создаем табличную часть у документа, которая будет содержать реквизиты, количество и тип которых будут зависеть от количества и типа колонок на дереве формы. (Грубо говоря, переносим колонки в  табличную часть).
4.    После чего на процедуре «ПриЗаписи» (вообще по Вашему усмотрению) будем сохранять дерево в табличную часть.
Например, я покажу как это сделано у меня:
4.1.    Сначала вызывается процедура «СохранитьДеревья»:
   
Процедура СохранитьДеревья()
     ВосстановлениеДерева.Очистить(); //чистим табличную часть
    СохранитьДерево(ДеревоНаФорме); //вызываем процедуру сохранения
    КонецПроцедуры

4.2 Сохраняем:
   
Процедура СохранитьДерево (Дерево)
    Сч = 0;
    Для каждого Стр из Дерево.Строки Цикл        
        Индекс     = ДеревоНаФорме.Строки.Индекс(Стр);
        
        Буква         = ВернутьБуквуПоЧислу(Стр.Уровень());
        ТекРодитель = Стр.Родитель;
        Если ТекРодитель = Неопределено Тогда
            ИндексНачало     = "" + Буква + Сч;
            Приставка         = "";
        Иначе
            ИндексНачало     = ТекРодитель.ИндексКонец;
            Приставка         = ИндексНачало;
        КонецЕсли;
        ИндексКонец = "" + Буква + Сч + Приставка;
        Стр.ИндексНачало     = ИндексНачало;
        Стр.ИндексКонец     = ИндексКонец;
        
        // заполнение табличной части
        СтрП = ВосстановлениеДерева.Добавить();
        СтрП.СтатьиКалькуляции          = Стр.СтатьиКалькуляции;
        СтрП.СтруктураИзделий          = Стр.СтруктураИзделий;
        СтрП.ЕдиницыИзмерения          = Стр.ЕдиницыИзмерения;
        СтрП.Количество                          = Стр.Количество;     
        СтрП.ИндексНачало          = ИндексНачало;
        СтрП.ИндексКонец              = ИндексКонец;
        СохранитьДерево (Стр);
        Сч = Сч + 1;
    КонецЦикла;        
КонецПроцедуры

Функция ВернутьБуквуПоЧислу(НомерБуквы)
    НомерБуквы1 = НомерБуквы + 1;
    СтрокаБукв     = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
    Если НомерБуквы1 > 33 Тогда
        НомерБуквы2 = НомерБуквы1 - 33;
        Буква1         = ВернутьБуквуПоЧислу(НомерБуквы2);
        Буква         = Сред(СтрокаБукв, 1, 1) + Буква1;
    Иначе
        Буква         = Сред(СтрокаБукв, НомерБуквы1, 1);
    КонецЕсли;
    Возврат Буква;
КонецФункции


Пункт 4.2. состоит из Процедуры и Функции. Функция нужна для того, чтобы получить код для последующего восстановления дерева.

5.    Восстанавливаем дерево, прописав следующий на процедуре «ПриОткрытии»:
Процедура ПриОткрытии()
Сп = Новый СписокЗначений();
    Сп.Очистить();
    Для Каждого Стр Из ВосстановлениеДерева Цикл
        Если Стр.ИндексНачало = Стр.ИндексКонец Тогда
            Сп.Добавить(Стр);
        КонецЕсли;
    КонецЦикла;
    
    Для Каждого СтрСп Из Сп Цикл
        ВосстановитьДерево(СтрСп.Значение, ДеревоНаФорме);
    КонецЦикла;
КонецПроцедуры


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


Вот и все. После всех вышеперечисленных действий сохранение должно работать без проблем.


Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2024 | Mista.ru

Яндекс.Метрика