Имя: Пароль:
1C
 
Рекурсивное заполнение элементов иерархического справчника
0 mmmstr
 
05.11.08
22:00
вопрос: как реализовать с помощью рекурсии заполнение 6-ти уровневого справочника. при чем атрибут, требующий заполнения, текстовый и имеет следующий формат: например для элемента первого уровня: 01.00.00.00.00.00
1 mmmstr
 
05.11.08
22:00
так вас устроит, господа?
2 Привратник
 
05.11.08
22:03
Процедура Рекурсия(Род)
   ТМЦ=СоздатьОбъект("Справочник.Номенклатура");
   ТМЦ.использоватьРодителя(Род);
   тмц.ВыбратьЭлементы();
   Пока ТМЦ.ПолучитьЭлемент()=1 Цикл
       Если ТМЦ.Родитель=Род Тогда
           Если ТМЦ.ЭтоГруппа()=1 Тогда
               Рекурсия(ТМЦ.ТекущийЭлемент());
           Иначе    
               ПроставитьРеквизит(ТМЦ.ТекущийЭлемент());
           КонецЕсли;
       КонецЕсли;    
   КонецЦикла;
КонецПроцедуры    

Процедура Сформировать()
   Рекурсия(ПолучитьПустоеЗначение("Справочник.Номенклатура"));
КонецПроцедуры
//
примерно так, правда отбор по родителю весьма неоптимален
3 mmmstr
 
05.11.08
22:04
то есть все-таки в любом случае цикл по всем элементам справочника?... понятно. спаисбо. именно этот вопрос меня и интересовал.
4 vde69
 
05.11.08
22:07
функция РасчитатьРеквизит(эл);
 Результат = "";
 Если ПустоеЗначение(эл.Родитель)=0 Тогда
   Результат = Результат + "." + РасчитатьРеквизит(эл);
 Иначе
  Результат = эл.Код;
 КонецЕсли;

 Возврат Результат;
КонецФункции;






спр = СоздатьОбъект("Справочник.х");
спр.ВыюратьЭлементы();
Пока спр.получитьЭлемент() = 1 Цикл
 спр.Реквизит = РасчитатьРеквизит(Спр.ТекущийЭлемент());
 спр.Записать();
КонецЦикла;


писал с листа, без проверки
5 Ковычки
 
05.11.08
22:08
(3) можно без цикла, но все равно это цикл
6 Дядя Васька
 
05.11.08
22:10
Если ПустоеЗначение(эл.Родитель)=0 Тогда
   Результат =  РасчитатьРеквизит(эл)+ "." + Результат; // здесь скорее так
 Иначе
  Результат = эл.Код; // а это кто такой?
 КонецЕсли;
Если я правильно понял, надо замутить что-то типа код в пределах подчинения, только вместо подчинения родитель, и кодов вообще нет никаких (или есть но левые), и все нужные надо рассчитать...
7 mmmstr
 
05.11.08
22:11
vde69, какое решение интересное! попробую сейчас!
8 Дядя Васька
 
05.11.08
22:11
(3) Можно не по всем, можно только по первому уровню, а дальше рекурсией нырять. Скорее всего как-то так и надо.
9 Дядя Васька
 
05.11.08
22:12
(7) но неправильное ))
10 mmmstr
 
05.11.08
22:12
если с праками дядюшки, то рекурсии тут нет
11 vde69
 
05.11.08
22:14
(9) по оптимальности надо дерево обходить, но там придеться записывать в транкзации по веткам, а (0) вероятно требуеться для разовой обработки! по этому я и предложил более читабельный и простой (но не оптимальный по скорости) вариант
12 mmmstr
 
05.11.08
22:16
Процедура ЗаполнитьЭлементы(Уровень,ТекЭлем)
   //вот тут и встряла, потому что первый же элемент, который сюда передается - родитель - 0
   
   
   ЗаполнитьЭлементы(Уровень+1,ТекЭлем?????);
   
КонецПроцедуры

Процедура Сформировать()
   спр = создатьОбъект("Справочник.Материалы");
   инк=0;
   спр.ВыбратьЭлементы();
   Пока Спр.ПолучитьЭлемент()>0 Цикл
       Уровень = спр.текущийЭлемент().Уровень();
       Если спр.ТекущийЭлемент().Уровень()=1 Тогда
           инк=инк+1;
           спр.УстановитьАтрибут("Шрифт","0"+Строка(Инк)+".00.00.00.00");
           спр.записать();
       конецЕсли;
       
       ЗаполнитьЭлементы(Уровень, спр.текущийЭлемент());
       
       
   КонецЦикла;
КонецПроцедуры
13 vde69
 
05.11.08
22:16
можно вообще в 2 строки все сделать

1 строка получить волный код
2 строка замена разделителей

на память синтаксис не помню а клюшек под рукой нету
14 Ковычки
 
05.11.08
22:18
все в одной процедуре, без циклов
15 Ковычки
 
05.11.08
22:18
рекурсивной процедуре
16 mmmstr
 
05.11.08
22:19
да дело втом, что нет кода то! эта разовая обработка и должна заполнить поле Шифр во всех элементах справочника. надо из первого уровня доставать остальные - но как?
17 Дядя Васька
 
05.11.08
22:20
(13) Это институтская задачка, нужна именно рекурсия.
18 mmmstr
 
05.11.08
22:20
нужна именно рекурсия
19 Привратник
 
05.11.08
22:24
(12)Первый цикл не по всем элементам, а только по неимеющим родителя - элементам и группам верхнего уровня. Далее берем группы верхнего уровня и для каждой смотрим подчиненные ей группы и элементы. Для элементов считаем реквизит, группы передаем снова в рекурсию. В (2) не цикл по всем элементам справочника, а отбор элементов справочника, имеющих определенного родителя.
20 mmmstr
 
05.11.08
22:29
согласна, что первый цикл только по неимеющим родителям. как посмотреть подчиненные группе элементы, т оесть нижние?
21 vde69
 
05.11.08
22:43
20 еще не сделала?

перем сп;

функция РасчитатьРеквизит(эл);
   ТекЗнач = сп.ПолучитьЗначение(эл.Уровень()) + 1;
   Результат = ТекЗнач;
   Если ПустоеЗначение(эл.Родитель)=0 Тогда
       Результат = РасчитатьРеквизит(эл)+ "." + Результат;
   КонецЕсли;
   сп.УстановитьЗначение(эл.Уровень(), ТекЗнач);
   Возврат Результат;
КонецФункции;

Процедура КнопкаВыполнитьНажатие(Кнопка)
   сп = СоздатьОбъект("СписокЗначений");
   сп.УдалитьВсе();
   
   спр = СоздатьОбъект("Справочник.х");
   спр.ВыбратьЭлементы();
   Пока спр.получитьЭлемент() = 1 Цикл
     спр.Код = РасчитатьРеквизит(Спр.ТекущийЭлемент());
   КонецЦикла;
КонецПроцедуры
22 Ковычки
 
05.11.08
22:49
вот вам и вся рекурсия ))))

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

Процедура Сформировать()
   Сп=СоздатьОбъект("СписокЗначений");
   Спр=СоздатьОбъект("Справочник.Номенклатура");
   Рекурсия(Спр,Сп);
КонецПроцедуры
23 mmmstr
 
05.11.08
22:53
ТекЗнач = сп.ПолучитьЗначение(эл.Уровень()) + 1;
тут постоянно пусто. это раз. второе: Если ПустоеЗначение(эл.Родитель)=0 Тогда
- вот тут сразу же зарубается и все - Шифр мой пустой
24 Дядя Васька
 
05.11.08
22:54
Да не то это все... Держи, отлажено:
Перем ВсегоУровней;

Процедура НумеруемПодгруппу(Родитель="", КодРодителя=0)
   Спр=СоздатьОбъект("Справочник.ТвойСправочник");
   Если ПустоеЗначение(Родитель)=0 Тогда
       Спр.ИспользоватьРодителя(Родитель.ТекущийЭлемент());
   КонецЕсли;
   Сч=0;
   Спр.ВыбратьЭлементы();
   Пока Спр.ПолучитьЭлемент(0)=1 Цикл
       Сообщить(Спр.ТекущийЭлемент());
       Сч=Сч+1;
       КодЭлемента=Лев(КодРодителя, (Спр.Уровень()-1)*4);
       КодЭлемента=КодЭлемента+Формат(Сч,"Ч(0)3");
       СчУровней=0;
       Для СчУровней=Спр.Уровень()+1 По ВсегоУровней Цикл
           КодЭлемента=КодЭлемента+".000"
       КонецЦикла;
       Сообщить(КодЭлемента);
       Если Спр.ЭтоГруппа()=1 Тогда
           НумеруемПодгруппу(Спр.ТекущийЭлемент(), КодЭлемента);
       КонецЕсли;
   КонецЦикла;
КонецПроцедуры

Процедура Сформировать()
   НумеруемПодгруппу()
КонецПроцедуры

ВсегоУровней=6;
25 Дядя Васька
 
05.11.08
22:55
+(24) Ну вместо Сообщить() там просто присвоение поставь, и Записать() добавь..
26 sam_sam
 
05.11.08
22:55
(22) лучше всех, тока список зачем? ей же не это надо. или это как пример?
27 mmmstr
 
05.11.08
22:58
ага список не нужен, его можно использовать, когда без рекукрсии - стэк своеобразный. сейчас, дядюшка, посомтрю:)
28 mmmstr
 
05.11.08
22:59
Если ПустоеЗначение(Родитель)=0 Тогда
       Спр.ИспользоватьРодителя(Родитель.ТекущийЭлемент());
   КонецЕсли; - даа! во тут нет косорезика! ай ,да Василий!
29 mmmstr
 
05.11.08
23:05
спасибо!