Имя: Пароль:
1C
 
ДеревоЗначений <-> ТаблицаЗначений
,
0 Sintson
 
26.03.09
18:29
Предлагаю процедуры перевода дерева значений в таблицу значений и обратно:

// Процедура выгружает данные из дерева значений в таблицу значений
//
Функция ВыгрузитьДеревоЗначенийВТаблицуЗначений(Дерево, Таблица = Неопределено) Экспорт

Если Таблица = Неопределено Тогда
   Таблица = Новый ТаблицаЗначений;
   Для Каждого Колонка Из Дерево.Колонки Цикл
   Таблица.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
   КонецЦикла;
КонецЕсли;

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

КонецФункции //ВыгрузитьДеревоЗначенийВТаблицуЗначений()

// Процедура выгружает данные из таблицы значений в дерево значений
//
Функция ВыгрузитьТаблицуЗначенийВДеревоЗначений(Таблица, КлючСтроки = "КлючСтроки", КлючСвязи = "КлючСвязи") Экспорт

Дерево = Новый ДеревоЗначений;
Для Каждого Колонка Из Таблица.Колонки Цикл
   Дерево.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
КонецЦикла;

Для Каждого СтрокаТаблицы Из Таблица Цикл
   СтрокаГруппировки = Дерево.Строки.Найти(СтрокаТаблицы[КлючСвязи], КлючСтроки,Истина);
   Если СтрокаГруппировки = Неопределено Тогда
   ЗаполнитьЗначенияСвойств(Дерево.Строки.Добавить(), СтрокаТаблицы);
   Иначе
   ЗаполнитьЗначенияСвойств(СтрокаГруппировки.Строки.Добавить(), СтрокаТаблицы);
   КонецЕсли;
КонецЦикла;

Возврат Дерево.Скопировать();

КонецФункции //ВыгрузитьТаблицуЗначенийВДеревоЗначений()
1 dimoff
 
26.03.09
19:15
Такое сокровище и бесплатно?
2 Defender aka LINN
 
26.03.09
19:23
(0) Спаситель ты наш!!!
Уж и не знаю, что бы мы без тебя делали...
3 Господин ПЖ
 
26.03.09
19:26
продай исходники...
4 vmv
 
26.03.09
20:17
(0) - не катит, ибо сплошной перебор без: анализа/отбора - узел/лист, обработки булевых или связаянных булевых и ...все такое.

да и работать с деревьями без рекурсий - плохой тон)

Чтобы не мучиться с деревьями постоянно - взял и написал общий модуль "Деревья", который расширяет станандартный функционал и решает, в том числе, и эту задачу)
5 nbIx
 
26.03.09
20:21
Вау!!!!!
А я уже всю неделю этот код пишу, ломаю голову, а тут на тебе...
6 Defender aka LINN
 
26.03.09
21:06
(4) Ну, вообще-то в (0) есть рекурсия.
7 Serg_1960
 
26.03.09
21:23
(0) Одобрям :) Отпечатай, вставь в рамочку и... любуйся :))
8 fisher
 
27.03.09
11:22
Какие все добрые...
Нормальный код из серии "простые приёмы разработки".
Новички спасибо скажут.
(0) Не обращай внимания. Тут так принято. Любой выложенный код почему-то воспринимается как вызов себе любимому.
9 Stepa86
 
27.03.09
11:30
(0) а в чем смысл Возврат Дерево.Скопировать(); почему просто не вернуть дерево???
10 Sintson
 
27.03.09
15:26
Спасибо за комментарии.
Я не претендую на идеальный код, просто долго мучался с этими деревьями.
Дерево.Скопировать() - нужно было для моей задачи, а потом, после переработки процедур просто забыл поправить.
Текст поставляется как говорится как есть.
Вообще говоря у меня целый модуль (разрабатываю отраслевое решение), может быть кому-нибудь и пригодится.
Удачи.

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ И ФУНКЦИИ ДЛЯ РАБОТЫ С ДЕРЕВОМ В ДОКУМЕНТАХ СТРОИТЕЛЬСТВА

// Функция формирует значение нового ключа строки табличной части.
//
// Параметры:
//  Дерево - дерево значений
//
Функция ПолучитьНовыйКлючСтрокиДерева(Дерево, СписокКлючей = Неопределено) Экспорт
   
   Если СписокКлючей = Неопределено Тогда
       СписокКлючей = Новый СписокЗначений;
   КонецЕсли;

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

КонецФункции // ПолучитьНовыйКлючСтрокиДерева()

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

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

// Процедура устанавливает значение во всем дереве значений
//
Процедура УстановитьЗначениеКолонкиДерева(Дерево, Колонка, Значение) Экспорт
   
   Для каждого СтрокаДерева Из Дерево.Строки Цикл
       СтрокаДерева[Колонка] = Значение;
       УстановитьЗначениеКолонкиДерева(СтрокаДерева, Колонка, Значение);
   КонецЦикла;
   
КонецПроцедуры //УстановитьЗначениеКолонкиДерева()

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

// Процедура переносит выделенные строки дерева значений в указанную ветку
//
Процедура ПеренестиСтрокиДереваЗначений(СтрокаПриемник, ВыделенныеСтроки) Экспорт

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

////////////////////////////////////////////////////////////////////////////////
// НУМЕРАЦИЯ ДЕРЕВА ЗНАЧЕНИЙ

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

// Функция перенумеровывает все позиции дерева значений
//
//
Функция ПеренумероватьЭлементыДереваСквозная(ДеревоЗначений, кНомерПозиции, НомерПозиции = 1, ВсеУровни)
   
   Если ВсеУровни Тогда    
       Для Каждого СтрокаДерева ИЗ ДеревоЗначений.Строки Цикл
           Если СтрокаДерева.Авторасчет Тогда
               Если НЕ СтрокаДерева.ЭтоГруппа Тогда
                   СтрокаДерева[кНомерПозиции] = Строка(НомерПозиции);
                   НомерПозиции = НомерПозиции + 1;
               Иначе
                   СтрокаДерева[кНомерПозиции] = "";
               КонецЕсли;
           Иначе
               Если НЕ СтрокаДерева.ЭтоГруппа Тогда
                   мНомерПозиции = НомерПозиции;
                   мНомерПозиции = НомерПозиции;
                   Попытка
                       НомерПозиции = Число(СтрокаДерева.НомерПозиции) + 1;
                   Исключение
                       НомерПозиции = мНомерПозиции;
                   КонецПопытки;
               Иначе
                   СтрокаДерева[кНомерПозиции] = "";
               КонецЕсли;
           КонецЕсли;
           ПеренумероватьЭлементыДереваСквозная(СтрокаДерева, кНомерПозиции, НомерПозиции, ВсеУровни);
       КонецЦикла;
   Иначе
       Для Каждого СтрокаДерева Из ДеревоЗначений.Строки Цикл
           Если СтрокаДерева.Авторасчет Тогда
               Если НЕ СтрокаДерева.ЭтоГруппа Тогда
                   СтрокаДерева[кНомерПозиции] = Строка(НомерПозиции);
                   НомерПозиции = НомерПозиции + 1;
               КонецЕсли;
           Иначе
               Попытка
                   НомерПозиции = Число(СтрокаДерева.НомерПозиции) + 1;
               Исключение
                   НомерПозиции = мНомерПозиции;
               КонецПопытки;                
           КонецЕсли;
       КонецЦикла;
   КонецЕсли;
                         
КонецФункции

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

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

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

   Если НумераторРасценок = Неопределено Тогда
       НумераторРасценок = Перечисления.этСпособыНумерацииЭлементовДереваЗначений.НумерацияЭлементовСквозная;
   КонецЕсли;
   
   Если НумераторРасценок = Перечисления.этСпособыНумерацииЭлементовДереваЗначений.НумерацияЭлементов Тогда
       ПеренумероватьЭлементыДерева(ДеревоЗначений, кНомерПозиции.Имя, , ВсеУровни);
   ИначеЕсли НумераторРасценок = Перечисления.этСпособыНумерацииЭлементовДереваЗначений.НумерацияЭлементовСквозная Тогда
       ПеренумероватьЭлементыДереваСквозная(ДеревоЗначений, кНомерПозиции.Имя, , ВсеУровни);
   ИначеЕсли НумераторРасценок = Перечисления.этСпособыНумерацииЭлементовДереваЗначений.НумерацияГрупп Тогда
       ПеренумероватьГруппыДерева(ДеревоЗначений, кНомерПозиции.Имя, , ВсеУровни);
   ИначеЕсли НумераторРасценок = Перечисления.этСпособыНумерацииЭлементовДереваЗначений.НумерацияГруппИЭлементов Тогда
       ПеренумероватьГруппыИЭлементыДереваВИерархии(ДеревоЗначений, кНомерПозиции.Имя, ВсеУровни);
   КонецЕсли;
   
КонецПроцедуры
11 Defender aka LINN
 
27.03.09
15:28
(10) У тебя брата нет? А то есть тут у нас один...
12 Sintson
 
27.03.09
15:29
О чем речь?
13 Defender aka LINN
 
27.03.09
15:31
(12) А Фиксине, конечно.
14 Sintson
 
27.03.09
15:31
Для "vmv"
Может поделишься кодом?
15 Sintson
 
27.03.09
15:32
(13) А Фиксине, конечно. - не понял?
Что такое Фиксине?
16 Defender aka LINN
 
27.03.09
15:33
(15) Гений 1С - знакомься. Есть подозрение, что это твой давно потеряный брат :)
17 Sintson
 
27.03.09
15:35
(16) Не брат он мне! Не знаю кто это.
Скромный, небось парень. :)
Выдавать глобальные идеи — это удовольствие; искать сволочные маленькие ошибки — вот настоящая работа. Фредерик Брукс-младший