v8: Универсальное сохранение/восстановление деревьев Ключевые слова: Дерево, сохранить, восстановить, записать, построить
В данной статье я предлагаю рассмотреть универсальный алгоритм восстановления деревьев.
Введение:
На начальной стадии моей работы так сложилось, что мне постоянно давали делать документы, у которых на форме необходимо было представлять данные в иерархическом виде. В связи с этим при сохранении документа необходимо было как-то запоминать дерево. Намучавшись вдоволь с индивидуальным для каждого документа алгоритмом, было решено разработать универсальный.
Описание универсального алгоритма сохранения:
Чтобы реализовать алгоритм, потребуется следующее:
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. Восстанавливаем дерево, прописав следующий на процедуре «ПриОткрытии»:
Процедура ПриОткрытии()
Сп = Новый СписокЗначений();
Сп.Очистить();
Для Каждого Стр Из ВосстановлениеДерева Цикл
Если Стр.ИндексНачало = Стр.ИндексКонец Тогда
Сп.Добавить(Стр);
КонецЕсли;
КонецЦикла;
Для Каждого СтрСп Из Сп Цикл
ВосстановитьДерево(СтрСп.Значение, ДеревоНаФорме);
КонецЦикла;
КонецПроцедуры
Процедура ВосстановитьДерево (ТекСтр, ТекРодитель)
Стр = ТекРодитель.Строки.Добавить();
Стр.СтатьиКалькуляции = ТекСтр.СтатьиКалькуляции;
Стр.СтруктураИзделий = ТекСтр.СтруктураИзделий;
Стр.ЕдиницыИзмерения = ТекСтр.ЕдиницыИзмерения;
Стр.Количество = ТекСтр.Количество;
Стр.ИндексНачало = ТекСтр.ИндексНачало;
Стр.ИндексКонец = ТекСтр.ИндексКонец;
Сп = Новый Структура();
Сп.Очистить();
Сп.Вставить("ИндексНачало", ТекСтр.ИндексКонец);
Массив = ВосстановлениеДерева.НайтиСтроки(Сп);
Для Каждого СтрМ Из Массив Цикл
Если СтрМ <> ТекСтр Тогда
ВосстановитьДерево (СтрМ, Стр);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Вот и все. После всех вышеперечисленных действий сохранение должно работать без проблем.
|