AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 02.08.2006, 11:01   #1  
Weez is offline
Weez
Участник
Axapta Retail User
 
250 / 84 (3) ++++
Регистрация: 18.01.2006
Адрес: Moscow city
перебор элементов в Tree
Добрый день, господа. Возникла следующая проблема - необходимо перебрать все элементы дерева, начиная с корня и проходя по всем child-элементам. Думаю что это будет какая-то рекурсивная функция, но с реализацией ее пока проблема... Если кто-то сталкивался с подобным - прошу помочь.
Старый 02.08.2006, 11:12   #2  
Lemming is offline
Lemming
Участник
Аватар для Lemming
 
1,144 / 343 (14) ++++++
Регистрация: 20.04.2004
Адрес: Москва, Чайнатаун в Люблино
Записей в блоге: 10
!
Правда нужна лицензия на crm

PHP код:
static void Tutorial_treeWalk(Args _args)
{

    
int             i;
    
smmSalesUnit    childSalesUnit;

    
void    runTree(smmSalesUnitId      _root "")
    {
        
smmSalesUnit            smmSalesUnit;
        
smmSalesUnitMembers     salesUnitMembers;
        ;

        while 
select salesUnitMembers
            where salesUnitMembers
.SalesUnitId == _root
            
{

                
info(strfmt("Группа: %1, Менеджер: %2"_root,  salesUnitMembers.SalesManId));
                
i++;
            }

        while 
select smmSalesUnit
            where smmSalesUnit
.ParentId == _root
        
{
            
select firstonly childSalesUnit
                where childSalesUnit
.ParentId == smmSalesUnit.SalesUnitId;

            if (
childSalesUnit.RecId != 0)
            {
                
runTree(smmSalesUnit.SalesUnitId);
            }
            else
            {
                while 
select salesUnitMembers
                    where salesUnitMembers
.SalesUnitId == smmSalesUnit.SalesUnitId
                
{
                    
info(strfmt("Группа: %1, Менеджер: %2"_root,  salesUnitMembers.SalesManId));
                }
            }
        }

    }
    ;
    
runTree("");
    
info(int2str(i));



Старый 02.08.2006, 11:45   #3  
Dudnik Anton is offline
Dudnik Anton
Участник
 
9 / 24 (1) +++
Регистрация: 23.03.2004
Код:
void rebuildSubnodes(TreeItemIdx _treeItemIdx = FormTreeAdd::Root)
{
    FormTreeItem    treeItem;
    TreeItemIdx     childIdx = treeControl.getChild(_treeItemIdx);

    while (childIdx)
    {
        treeItem = treeControl.getItem(childIdx);
        if (conFind(conCheckedNodes, treeItem.data()))
            treeItem.stateImage(imageListAppl.image(#ImageCheckAll));
        else
            treeItem.stateImage(imageListAppl.image(#ImageCheckNone));
        treeControl.setItem(treeItem);

        if (conFind(conBuiltNodes, treeItem.data()))
            this.rebuildSubnodes(treeItem.idx());

        childIdx = treeControl.getNextSibling(childIdx);
    }
}
Старый 02.08.2006, 11:47   #4  
Weez is offline
Weez
Участник
Axapta Retail User
 
250 / 84 (3) ++++
Регистрация: 18.01.2006
Адрес: Moscow city
Спасибо за ответ, думаю когда-нибудь он пригодится... Я наверно неправильно выразился, нужно было пройтись не по таблице, а по элементам контрола Tree. Решение только что нашел на форуме, ссылка прилагается
Работа с деревом
Старый 02.08.2006, 16:41   #5  
Weez is offline
Weez
Участник
Axapta Retail User
 
250 / 84 (3) ++++
Регистрация: 18.01.2006
Адрес: Moscow city
Еще один вопрос по деревьям
Как записать значение в Data() элемента formTreeItem?
В моем конкретном случае нужно записать enum, но думаю тут тип не влияет на результат.
Привожу псевдокод: (Tree - элемент дерево на форме)
Код:
formTreeItem                          Tmp;
DetailingOfSales                     detailing; //таблица
int                                         curr;

curr = tree.add(parent, 0, detailing.unitId);
Tmp = tree.getItem(curr);
Tmp.data(detailing.UnitType);
После этого заполняется Data() Tmp, но tree.getItem(curr).data() при этом выдает 0
Не знаю что делать, поиск не помог
Старый 02.08.2006, 16:59   #6  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Добавьте в ваш код
X++:
...
tree.setItem(Tmp);
__________________
Axapta v.3.0 sp5 kr2
Старый 02.08.2006, 17:23   #7  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Кстати, можно добавлять узлы так
X++:
curr = new FormTreeItem(detailing.unitId);
curr.data(map);
tree.addItem(parent, 0, curr);
__________________
Axapta v.3.0 sp5 kr2
Старый 03.08.2006, 11:33   #8  
Weez is offline
Weez
Участник
Axapta Retail User
 
250 / 84 (3) ++++
Регистрация: 18.01.2006
Адрес: Moscow city
Thumbs up
Благодарю, последний вариант подошел идеально
Старый 12.04.2013, 16:34   #9  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Вопрос по деревьям:

Строится отчёт Excel, есть поле Отдел продаж(salesUnitid), там дерево. Нужно сделать выборку по этому полю и чтобы в отчёт попадали те строки, которые соответствуют выбранному уровню, то есть, если выбран отдел продаж, нужно выбирать все строки, которые соответствуют нижнему уровню отдела продаж(БП,РФ,ДЗАт и т.д.), а если выбран один из нижних уровней - строки только нижнего уровня. То есть, чтобы раскрытие дерева шло вниз.

Посоветовали использовать List и в цикле прогонять каждый раз, но не совсем представляю как это сделать, показали пример на cte, но у меня запрос не на чистом sql, а на аксаптовском sql, если можно так выразиться, так что не думаю, что мне cte подойдёт.
Может кто подсказать в какую сторону копать и с чего начинать проход ?
Почитал на форуме ещё, что можно Map-ы использовать для этого дела...
Я так понимаю, по таблице SMMSALESUNIT и сравнивать PARENTID и SALESUNITID , но что-то голова не работает...

Что-то вроде

X++:
while select salesunitid  from SmmSalesUnit where .SmmSalesUnit salesunitid like  SmmSalesUnit .parentid
{
List.add(salesunitid);
}
В правильном ли направлении мыслю?

Последний раз редактировалось user_ax; 12.04.2013 в 16:53.
Старый 12.04.2013, 17:43   #10  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Никто не может подсказать хотя бы приблизительного решения?
Старый 12.04.2013, 17:56   #11  
plumbum is offline
plumbum
Участник
Соотечественники
 
182 / 86 (3) ++++
Регистрация: 07.12.2007
Адрес: Vienna, AT
Ну в общем Вы двигаетесь в правильном направлении.
Если я Вас правлиьно понял, Вам надо выбрать все дочерние записи отталкиваясь от определенного значения SalesUnitId,

тогда напишите рекурсивную функцию, которая, получая SalesUnitId как параметр, выбирает по очереди (while select) все дочерние записи, и, если какая нибудь из них тоже содержит дочерние, вызывается рекурсивно для этой конкретой дочерней записи.

Ну например:
X++:
static void Job45(Args _args)
{
    SMMSalesUnitId      salesUnitId;
    List                salesUnits = new List(Types::String);

    List getChildSalesUnit(SMMSalesUnitId _salesUnitIdParent)
    {
        SMMSalesUnit    salesUnit;
        List            childSalesUnit = new List(Types::String);
        
        //Add current sales unit to list
        childSalesUnit.addEnd(_salesUnitIdParent);
        
        //Check for child records
        select count(RecId)
            from salesUnit
            where salesUnit.ParentId == _salesUnitIdParent;

        if (!salesUnit)
        {
            return childSalesUnit;
        }
        //Go through child records and call recurent function
        while select SalesUnitId
            from salesUnit
            where salesUnit.ParentId == _salesUnitIdParent
        {
            //Merge list with the result list of all children
            childSalesUnit = List::merge(childSalesUnit, getChildSalesUnit(salesUnit.SalesUnitId));
        }
        return childSalesUnit;
    }
    ;
    
    salesUnitId = "any value";
    salesUnits  = getChildSalesUnit(salesUnitId);
}
__________________
http://www.axdevposts.blogspot.com
Пришел, уведел.... отойди, дай другому увидеть!

Последний раз редактировалось plumbum; 12.04.2013 в 18:07. Причина: Орфография... мда, 3 года всего учил русский в школе :)
За это сообщение автора поблагодарили: user_ax (1).
Старый 12.04.2013, 17:59   #12  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Цитата:
Сообщение от plumbum Посмотреть сообщение
Ну в общем Вы двигаетесь в правильном направлении.
Если я Вас правлиьно понял, Вам надо выбрать все дочерние записи отталкиваясь от определенного значения SalesUnitId,

тогда напишите рекурсивную функцию, которая, получая SalesUnitId как параметр, выбирает поочереди (while select) все дочерние записи, и, если какая нибудь из них тоже содержит дочернии, вызывается рекурсивно для этой конкретой дочерней записи.

Да, вы меня правильно поняли.
Если есть дочерние - выбирать их, если нет - выбирать текущее значение salesunitid, которые выделено.
Сейчас попробую ваш джобик)
Старый 12.04.2013, 18:08   #13  
plumbum is offline
plumbum
Участник
Соотечественники
 
182 / 86 (3) ++++
Регистрация: 07.12.2007
Адрес: Vienna, AT
Я прошу прощения, допустил в джобе ошибку. Критерий выборки конечно:

X++:
where salesUnit.ParentId == _salesUnitIdParent
в посте выше эта ошибка уже исправлена
__________________
http://www.axdevposts.blogspot.com
Пришел, уведел.... отойди, дай другому увидеть!
Старый 12.04.2013, 18:11   #14  
plumbum is offline
plumbum
Участник
Соотечественники
 
182 / 86 (3) ++++
Регистрация: 07.12.2007
Адрес: Vienna, AT
Как я уже написал, джобик я подправил.
Попробуйте так:

X++:
print (salesUnits.toString())
__________________
http://www.axdevposts.blogspot.com
Пришел, уведел.... отойди, дай другому увидеть!
Старый 12.04.2013, 18:11   #15  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Благодарю, поправил.

Хотел посмотреть дочерние элементы Отдела продаж, но почему-то не вывел, или это необходимо делать в цикле?

X++:
    salesUnitId = "Отдел продаж";
    salesUnits  = getChildSalesUnit(salesUnitId);
    print (salesUnitId);
    pause;
Старый 12.04.2013, 18:12   #16  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Цитата:
Сообщение от plumbum Посмотреть сообщение
Как я уже написал, джобик я подправил.
Попробуйте так:

X++:
print (salesUnits.toString())

Да, это то, что мне нужно, по идее. Как элементы указанного уровня так и дочерние. Теперь буду мудрить , дабы прикрутить это к моему запросу!
Старый 12.04.2013, 18:20   #17  
plumbum is offline
plumbum
Участник
Соотечественники
 
182 / 86 (3) ++++
Регистрация: 07.12.2007
Адрес: Vienna, AT
Можно про запрос по-подробнее?
Ели вам нужен этот список, как источник данных, переберите весь List итератором/энумератором, и повставляейте записи во временную таблицу. Тогда я еще бы посоветовал создавать List с типом элементов Record: не пришлось бы потом по ключу перевыбирать записи.

Удачи!
__________________
http://www.axdevposts.blogspot.com
Пришел, уведел.... отойди, дай другому увидеть!
Старый 15.04.2013, 09:40   #18  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Цитата:
Сообщение от plumbum Посмотреть сообщение
Можно про запрос по-подробнее?
Ели вам нужен этот список, как источник данных, переберите весь List итератором/энумератором, и повставляейте записи во временную таблицу. Тогда я еще бы посоветовал создавать List с типом элементов Record: не пришлось бы потом по ключу перевыбирать записи.

Удачи!
Мой запрос выбирает записи из нескольких таблиц по конкретным параметрам, один из них - элемент из Отдела продаж(smmsalesunitid).
По поводу enumerator читал, попробую, спасибо.

Вы имеете ввиду Types::Record ?
Старый 15.04.2013, 12:14   #19  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
599 / 39 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Теперь проблема иного характера.

Рекурсивный метод отрабатывает верно и выбирает все дочерние значения по отношению к выбранному.
Объявил строковую переменную в методе выборки данных, присвоил ей результат, который возвращает метод (строка строк), в условии выборки пишу

X++:
salesQuotationTable.SalesUnitId like salesunitid
в salesunitid у нас

X++:
<"Отдел продаж трансф.", "БП", "ДЗАТ", "ДЗБВА", "ДЗЕА", "РФ", "СРАЗ", "УБМ">
Но запрос не отрабатывает в принципе, если убрать условие с лайком, то запрос отрабатывает и отчёт строится, но по неверным данным.

Есть ли какие-то особенности лайка аксаптовского? Искал на форуме, ничего толкового не нашёл. Переменная, в которую попадает результирующая строка ограничена 500 символами.

Буду благодарен за любую подсказку
Старый 15.04.2013, 12:31   #20  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от user_ax Посмотреть сообщение
в salesunitid у нас

X++:
<"Отдел продаж трансф.", "БП", "ДЗАТ", "ДЗБВА", "ДЗЕА", "РФ", "СРАЗ", "УБМ">
Чего прям все сразу, в одной строке? LIKE так не умеет.

Так умеет QueryBuildRange
Теги
tree, дерево, построение дерева, раскрытие

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Как получить метки всех элементов всех форм (DAX 4) Qaz Qwerty DAX: Программирование 1 09.08.2008 05:39
Как поменять порядок элементов в Tree Lucky13 DAX: Программирование 3 16.02.2007 14:29
Tree. Проблема с data() alexbn DAX: Программирование 2 03.11.2005 14:39
Как работать с tree? Oz DAX: Программирование 3 23.08.2002 12:36
Динамическое добавление элементов в отчет Maxim Gorbunov DAX: База знаний и проекты 1 17.01.2002 14:48

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 17:17.