Доброго времени суток.
Если кто встречался подскажите пожалуйста а то что-то ничего в голову нормального не приходит.
Вопрос:
У нас есть дерево значений с колонками Иерархия , ИмяПоляИерархии и количество,
Пример:

```1c
    Иерархия ИмяПоляИерархии Количество
    +Заказ №1 (Заказ)
    +Продукция 1 (Продукция) 5
    -Комплектующая 1 (Комплектующая) 10 (по 2 на 1 продукцию)
    +Комплектующая 2 (Продукция) 3
```

Необходимо при обходе дерева значений заполнить ТЗ следующими образом:

```1c
    1. заказ №1 Копмплектующая 1 10
    2. заказ №1 Копмплектующая 2 3
```

Не могу придумать обход так чтобы заполнить ТЗ вот таким образом=(( Зарание спасибо за Помощь!
---
vetaldober, если правильно понял:

```1c
    ТЗ = Новый ТаблицаЗначений;

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

    ЗаполнитьТЗ(ДЗ.Строки, ТЗ, Истина);

    Функция ЗаполнитьТЗ(СтрокиДЗ, ТЗ, ЭтоКорень= Ложь)

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

    КонецФункции
```
---
vetaldober, если правильно понял:

```1c
    ТЗ = Новый ТаблицаЗначений;

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

    ЗаполнитьТЗ(ДЗ.Строки, ТЗ, Истина);

    Функция ЗаполнитьТЗ(СтрокиДЗ, ТЗ, ЭтоКорень= Ложь)

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

    КонецФункции
```
---
Allexe8.1,
Поидее то что нужно. сейчас попробую=)
---
Allexe8.1,
Не подошло но Вы натолкнули на идею=))) отдаю вознаграждение=)
---
Так а не понятно, почему
+Комплектующая 2 (Продукция) 3
должно сваливаться в ТЗ, если у него ИмяПоляИерархии=(Продукция)
Вы уж поясните, что Вам надо, искусственный интеллект или решение корректно поставленной задачи?
---
Может это Вам поможет?
http://infostart.ru/public/73969/
---
Если есть ещё ответы или готовые рещения пишите вознаграждение тоже!
---
vetaldober, (4) - это копирование всех строк "ДЗ" в "ТЗ". Вам то что надо?
Простите, но пример в (1) выглядит как шарада.
---
agrustny, ну вот такие странные задачи бывают. переписывать полностью логику построения "дерева" займет очень много времени т.к. там сложный механизм заполнения. а вот обработать необходимо такую кучу... смысл этой кучи... есть заказ по нему может быть как продукция так и материалы,если это пробукция то она добавлеяется как продукция с расшифровкой материалов если это материал то он добавляется как продукция без расшифровки,и это дерево необходимо перенести в таблицу значений для обработки т.к. простым обходом дерева обработать данные очень тяжело.
---
Количество уровней в дереве определенное? Несколько комплектующих могут входить в 1 продукцию?
Вообщем, суть в том, чтобы обходить все строки дерева и проверять, количество элементов вложенной колекции ТекущаяСтрокаДерева.Строки.Количество(). Если она равна нулю - перед нами искомая комплектующая, ее и добавляем в ТЗ, иначе начинаем новый цикл по ее элементам.
Обход организуем вложенными циклами, количеством равным максимальной вложенности дерева. Или рекурсивным вызовом функции, обходящей вложенную коллекцию, что оптимальнее, но менее наглядно и сложнее для реализации.
---
mymyka, Да могут не ограничего.
---
mymyka, а все предыдущие данные такие как заказ, каким образом я заполню в добавленную строку?
---
сохраняйте в локальную переменную модуля при обходе строк 1 уровня
что-то типа такого(на работоспособность не проверял)

```1c
    Перем ТЗ Экспорт;
    Перем ТекущийЗаказ Экспорт;

    Процедура ВыполнитьНажатие()
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Заказ");
    ТЗ.Колонки.Добавить("Номенклатура");
    ТЗ.Колонки.Добавить("Количество");
    Для Каждого Ветвь из Дерево.Строки Цикл
    ТекущийЗаказ = Ветвь.Иерархия;
    ОбходПодчиненнойКолллекции(Ветвь,ТЗ);
    КонецЦикла;
    КонецПроцедуры;
    Функция ОбходПодчиненнойКолллекции(Ветвь,ТЗ,)
    Для Каждого Подветвь из Ветвь.Строки Цикл
    Если Подветвь.Строки.Количество() > 0 Тогда
    ОбходПодчиненнойКолллекции(Подветвь,ТЗ);
    Иначе
    НовСтр = ТЗ.Добавить();
    НовСтр.Заказ = ТекущийЗаказ;
    НовСтр.Номенклатура = Подветвь.Иерархия;
    НовСтр.КОличетсво = Подветвь.Количество;
    КонецЕсли;
    КонецЦикла;
    КонецФункции
```
---
mymyka, как бы все хорошо но структура может менятся например исчезнет заказ или перед заказом появится контрагент. по этому не хочу привязыватся к переменным.хочу заполнять тз универсально
(18) Allexe8.1, Да Вы правы.
---
как бы все хорошо но структура может менятся например исчезнет заказ или перед заказом появится контрагент
Тогда Вам нужен ИскуственныйРазум, его пока не изобрели.
Сформулируйте четко условия задачи (если еще нужна помощь). Без этого можно только кидаться в Вас обрывками каких-то кодов.
---
Сделал вот-так почти то что хотел нужно будет кое что подправить...
Всем спасибо за помщь дополнительно вознаграждение дал agrustny Спасибо=)
(24) обошелся без искуственного интелекта=)

```1c
    ТЗ = Новый ТаблицаЗначений;
    МассивТипов = Новый Массив;
    ЗаполнитьМассивТипов(Дерево.Строки, МассивТипов);

    Для Каждого ЭлементМассива ИЗ МассивТипов Цикл
    ТЗ.Колонки.Добавить(ЭлементМассива);
    КонецЦикла;

    Для Каждого СтрокаДерева ИЗ Дерево.Строки Цикл
    СтрокаТЗ = ТЗ.Добавить();
    СтрокаТЗ[СтрокаДерева.ТипПоля] = СтрокаДерева.Иерархия;
    ЗаполнитьТЗ(СтрокаДерева.Строки, СтрокаТЗ, ТЗ);
    КонецЦикла;

    Функция ЗаполнитьМассивТипов(СтрокиДЗ, МассивТипов)

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

    КонецФункции

    Функция ЗаполнитьТЗ(СтрокиДЗ, СтрокаТЗ, ТЗ)

    Для й = 0 ПО СтрокиДЗ.Количество()-1 Цикл
    СтрокаТЗ[СтрокиДЗ[й].ТипПоля] = СтрокиДЗ[й].Иерархия;
    ЗаполнитьТЗ(СтрокиДЗ[й].Строки , СтрокаТЗ, ТЗ);
    Если й <> СтрокиДЗ.Количество()-1 Тогда
    НоваяСтрока = Тз.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
    СтрокаТЗ = НоваяСтрока;
    КонецЕсли;
    КонецЦикла;

    КонецФункции
```
---
Благодарствую, пойду куплю пивка+)
---
agrustny, =) больше не могу т.к. у самого маловато осталось=(((
---
vetaldober, тогда как-то так:

```1c
    Процедура КнопкаВыполнитьНажатие(Кнопка)

    Если Ложь Тогда
    ДЗ = Новый ДеревоЗначений;
    КонецЕсли;

    ТЗ = Новый ТаблицаЗначений;
    СтруктураКолонок = Новый Структура;
    ЗаполнитьСтруктуруКолонокТЗ(СтруктураКолонок, ДЗ.Строки, ТЗ);

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

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

    КонецПроцедуры

    //
    //
    Функция ЗаполнитьСтруктуруКолонокТЗ(СтруктураКолонок, СтрокиДЗ, ТЗ)

    Для Каждого СтрокаДЗ ИЗ СтрокиДЗ Цикл

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

    КонецЦикла;

    КонецФункции

    Функция ЗаполнитьТЗ(СтрокаДЗ, ТЗ, СтруктураЗначенийДерева)

    СтруктураЗначенийДерева.Вставить(СтрокаДЗ.ИмяПоляИерархии, СтрокаДЗ.Иерархия);

    Если СтрокаДЗ.Строки.Количество() = 0 Тогда
    СтрокаТЗ = ТЗ.Добавить();
    ЗаполнитьЗначенияСвойств(СтрокаТЗ, СтруктураЗначенийДерева);
    СтрокаТЗ.Количество = СтрокаДЗ.Количество;
    КонецЕсли;

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

    КонецФункции
```
---
Allexe8.1, Вот это интересно=) не зря вознаграждение сразу дал=) Спасибо!
---
Allexe8.1, Только при заполнении структуры колонок нужно было рекурсию добавить и тз не обязательно передавать=)
---
vetaldober, да, точно. Пропустил)
---
Allexe8.1, Ещё чучуть копеек подкинул=)Ещё раз спасибо=) тема закрыта!
---
Allexe8.1, Отработало как и мой код только у Вас более изящно и типы значений добавляются в тз (очень удобно)=) без лишних разговоров человек выдал решение=) спасибо огромное!
---
100% согласен, (26) - реально профессиональное решение. Но я тоже на пиво не зря заслужил, т.к. строчки

```1c
    СтруктураЗначенийДерева.Вставить(СтрокаДЗ.ИмяПоляИерархии, СтрокаДЗ.Иерархия);
```

```1c
    ЗаполнитьТЗ(СтрокаПотомок, ТЗ, СтруктураЗначенийДерева)
```

- фактическая реализация того, что написано в (20) (согласен, немного с другого бока, но Вы же задачу четко не поставили)
Единственное, остался некий "осадок": а нужно ли таскать с собой по всей этой рекурсии ТЗ, в которую мы все скидываем? Если это только ссылка на нее, то разницы точно нет, к тому же мы все равно носим "ветки дерева"... В общем, как вариант - сделать

```1c
    перем ТЗ;
```

и никуда ее не передавать, т.к. мы только добавляем в нее - вначале колонки, а потом строки.
10 плюсов и медаль ордена Славы Allexe8.1!
---
agrustny, Согласен! можно вынести, но самое главное что я понял как это можно вообще провернуть, а оптимизация потом=) т.к. у меня в голове что-то не укладывалось=) маленький нюанс остался, но эт уже мелочи, когда мы наполняем структуру повторно если измерения продукции нет (т.е. идет иерархия заказ --- комплектующая) то оно остается с прошлой структуры. но т.к. моя цель добратся до комплектующей я это упущу хотя нужно будет доделать т.к. механизм буду применять дальше=)
---
vetaldober, т.е. колонки ТЗ нужно брать из значений поля ИмяПоляИерархии? Т.е. в данном примере ТЗ будет содержать колонки Заказ, Продукция, Комплектующая, Количество?
---
Заказ и Продукцию можно передавать через параметры рекурсивной функции, т.е.

```1c
    Функция ЗаполнитьТЗ(СтрокиДЗ, ТЗ, ЭтоКорень= Ложь, Заказ=Неопределено, Продукция=Неопределено)
```

Соответственно вызов из самой себя
ЗаполнитьТЗ(СтрокаДЗ.Строки , ТЗ, Ложь, Заказ, Продукция);
Ну и естественно если в текущей строке ИмяПоляИерархии=(Заказ) или ИмяПоляИерархии=(Продукция), то подменять в вызове один из этих новых параметров на вынутый из текущей строки.
Вариант из (16) сработает, но это неграмотно с точки зрения структурного программирования, эти параметры не тянут на глобальную переменную.
---
Ну дак уберите Экспорт, будут локальные. Да и таскать переменную, которая может и не использоваться в данном вызове функции, через параметры, тот еще моветон. Наличие множества мПеременных в модулях как бэ намекают.
(21)Не будет работать начиная с некоторого уровня вложенности
это с какого например? будет работать ровно до тех пор, пока на первом уровне Заказ, а на последнем Комплектующая.
Неправильно методологически
А в (3), посоветованном вами, дак просто образец, с двойным полным перебором дерева перед каждой операцией, вместо банальной обработки запросом/скд.
---
Под "глобальной" я понимал общую для модуля. Тут же именно случай, когда параметры имеют отношение только к данной функции и используются - на нижнем уровне. Конечно, если 100500 уровней вложенности, то все это будет сидеть в кэше, но тогда и с 1 параметром возникнут проблемы, не правда ли? (благо написать зацикленную рекурсию ума много не надо). В общем, разводить холлливар из-за этого, второго пункта, не будем, ладно?
---
mymyka, рекурсия это, конечно, невероятно сложно, особенно после (4) или того же самого по сути (но более навороченного) по ссылке в (3). Не учите неправильным решениям: если заказчик бьет себя в грудь, что учет будет вестить по 1 конторе, послезавтра их наверняка будет больше...по известным причинам.
---
ну в 4 как раз нет заполнения заказа из первого уровня, человек не разобрался с рекурсией, судя по
Не подошло
и уж тем более, не разобрался со статьей в (3)
для чего я и разжевал, что именно делает (4). Этот алгоритм можно реализовать рекурсивно, либо вложенными циклами при известном уровне вложенности, циклы явно нагляднее и проще. + не требуют использования локальных переменных модуля.
Не учите неправильным решениям
что именно я неправильного подсказал?
---
что именно я неправильного подсказал?
1) Использовать циклы вместо рекурсии
2) Использовать глобальные переменнные вместо параметров
Почему неправильно?
1) Не будет работать начиная с некоторого уровня вложенности
2) Неправильно методологически (т.н. г-код)

Заметьте, награда выдана именно (4), а почему "не подошло" - потому что задача была чуть более сложная/обширная.
---
блин
---
Извиняюсь не правильно объяснил... сам уже путаюсь... запарило это дерево!

```1c
    Иерархия ИмяПоляИерархии Количество
    +Заказ №1 (Заказ)
    +Продукция 1 (Продукция) 5
    -Комплектующая 1 (Комплектующая) 10 (по 2 на 1 продукцию)
    +Комплектующая 2 (Комплектующая) 3
```

вот так.
---
Не раздражайтесь, задача вроде элементарная, только ее нужно четко сформулировать.
Если я правильно понял из примера - нужно выгрузить только (Комплектующая), поэтому добавьте в цикл в коде (4) проверку ИмяПоляИерархии=(Комплектующая), вот сюда

```1c
    ИначеЕсли Не ЭтоКорень Тогда
```