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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 12.09.2022, 19:42   #1  
Mirta is offline
Mirta
Участник
 
12 / 52 (2) ++++
Регистрация: 23.11.2011
D365FO: GER Заказы со строками и проводками
Помимо привычных отчетов, содержащих итоговые данные, а также отчетов шапка-строки по какому-либо документу, иногда возникает необходимость построить отчет по списку документов, каждый из которых содержит шапку и строки. Такой отчет можно построить с помощью GER достаточно легко и быстро.

Рассмотрим быстрый способ создания отчета с тройной вложенностью. Возьмем для примера заказы на продажу, строки и проводки.

Создаем модель TrainerITSalesOrders. Добавляем корень SalesReport.
Создаем поля модели:
Название: 1.png
Просмотров: 271

Размер: 39.5 Кб

Lines является дочерним узлом для SalesOrders
InventTrans является дочерним узлом для Lines

Создаем сопоставление модели
Нажмите на изображение для увеличения
Название: 2.png
Просмотров: 6
Размер:	28.8 Кб
ID:	13427

По этой кнопке создается сопоставление модели с БД. Можно в дереве модели создать отдельно сопоставление. Это лучше тем, что до него быстрее добираться из дерева (не заходя в модель), и к тому же если мы захотим использовать эту модель для импорта или для других экспортов, то сопоставление лучше чтобы было отдельно, ибо тогда будет галка Использовать сопоставление по умолчанию. Ну пока нам хватит и такого сопоставления.

Для выборки данных из связанных таблиц мы будем пользоваться отношениями на таблицах в АХ (релейшенами).
Добавляем в качестве источника данных Записи таблицы SalesTable
Нажмите на изображение для увеличения
Название: 3.png
Просмотров: 4
Размер:	14.8 Кб
ID:	13428

Ставим галку Запросить запрос - это позволит увидеть расширенный фильтр в диалоге вызова отчета. И галку Точка интеграции - для возможности вызова отчета через пункт меню.
Название: 4.png
Просмотров: 268

Размер: 18.7 Кб

Для преобразования ЕНУМа Status в заказе добавим Перечисление АХ:
Название: 5.png
Просмотров: 266

Размер: 12.5 Кб

Есть 3 способа преобразования перечисления:
1. В модель добавляется только перечисление АХ, далее оно преобразовывается в явно прописанные строковые значения с помощью формул
2. В модель добавляется перечисление АХ и перечисление модели данных. Затем с помощью формулы значениям перечисления АХ сопоставляются значения перечисления модели данных.
3. В модель добавляется перечисление АХ, а также вычисляемые поля, позволяющие с помощью формул преобразовать значение ЕНУМа в его аксаптовую метку. Этот способ самый сложный, но и самый результативный - даже если перечисление изменится в АХ, в GER его значения менять не придется.
Мы воспользуемся первым способом.

Связываем источники данных с полями модели:
Нажмите на изображение для увеличения
Название: 6.png
Просмотров: 14
Размер:	66.6 Кб
ID:	13431

Нажмите на изображение для увеличения
Название: 7.png
Просмотров: 8
Размер:	39.6 Кб
ID:	13432

Поле Worker связываем с полем из релейшенов:
Нажмите на изображение для увеличения
Название: 8.png
Просмотров: 5
Размер:	17.3 Кб
ID:	13433

Нажмите на изображение для увеличения
Название: 9.png
Просмотров: 4
Размер:	22.3 Кб
ID:	13434

Из DirPerson_FK берем поле Name

Для поля Status задаем формулу

Код:
CASE(@.SalesStatus, 
    Enums.SalesStatusEnum.Canceled, "Отменено",
    Enums.SalesStatusEnum.Delivered, "Доставлено",
    Enums.SalesStatusEnum.Invoiced, "Выставлен счет",
    Enums.SalesStatusEnum.None, "",
    Enums.SalesStatusEnum.Backorder, "Открытый заказ"
)
Для строк заказа возьмем SalesLine из релейшенов таблицы SalesTable
Название: 10.png
Просмотров: 264

Размер: 9.5 Кб

Связываем SalesLine и Lines справа
Нажмите на изображение для увеличения
Название: 11.png
Просмотров: 10
Размер:	54.1 Кб
ID:	13436
Название: 12.png
Просмотров: 265

Размер: 14.1 Кб
Нажмите на изображение для увеличения
Название: 13.png
Просмотров: 5
Размер:	14.6 Кб
ID:	13438

Через InventTransOrigin
Название: 14.png
Просмотров: 264

Размер: 7.8 Кб

Обращаемся к InventTrans и связываем с InventTrans справа
Нажмите на изображение для увеличения
Название: 15.png
Просмотров: 10
Размер:	65.8 Кб
ID:	13440

Номер лота берем из InventTransOrigin
Нажмите на изображение для увеличения
Название: 16.png
Просмотров: 8
Размер:	91.7 Кб
ID:	13441

Кол-во - из InventTrans
Нажмите на изображение для увеличения
Название: 17.png
Просмотров: 4
Размер:	39.4 Кб
ID:	13442

Складские аналитики возьмем из InventDim
Название: 18.png
Просмотров: 262

Размер: 11.4 Кб

Нажмите на изображение для увеличения
Название: 19.png
Просмотров: 10
Размер:	83.5 Кб
ID:	13444

Последний раз редактировалось Mirta; 12.09.2022 в 19:51.
Старый 12.09.2022, 19:47   #2  
Mirta is offline
Mirta
Участник
 
12 / 52 (2) ++++
Регистрация: 23.11.2011
Теперь добавлям входной параметр для фильтрации заказов по клиенту
Нажмите на изображение для увеличения
Название: 20.png
Просмотров: 4
Размер:	23.3 Кб
ID:	13445

Указываем имя и ЕДТ
Нажмите на изображение для увеличения
Название: 21.png
Просмотров: 4
Размер:	27.3 Кб
ID:	13446

Здесь же можем управлять формулами для опций Только чтение и Значение по умолчанию (эти две опции появились только в версии 10.0.27) для вх.параметра

Теперь создаем вычисляемое поле FilterCustAccount
Нажмите на изображение для увеличения
Название: 22.png
Просмотров: 4
Размер:	38.4 Кб
ID:	13447

C формулой

Код:
IF(CustAccount="",SalesTable,FILTER(SalesTable, SalesTable.CustAccount = CustAccount))
Использование проверки позволит не фильтровать заказы по клиенту, если клиент не задан.

Теперь свяжем выч.поле FilterCustAccount слева и SalesOrders справа
На вопрос изменить ли привязку ответим "Да"
Нажмите на изображение для увеличения
Название: 23.png
Просмотров: 6
Размер:	39.6 Кб
ID:	13448

Сохраняем изменения, завершаем модель

Подготовим шаблон для выгрузки отчета
У нас должно быть три диапазон - на проводки, на строки и на весь заказ в целом.
Нажмите на изображение для увеличения
Название: 24.png
Просмотров: 18
Размер:	66.5 Кб
ID:	13449

И именованные ячейки для каждого поля:
Нажмите на изображение для увеличения
Название: 25.png
Просмотров: 4
Размер:	6.7 Кб
ID:	13450

Создаем формат для нашей модели, назовем его TrainerITSalesOrdersFormat, загрузим в него наш файл
У нас создадутся диапазоны, поддиапазоны и ячейки в соответствии с шаблоном.
Переходим на вкладку Сопоставление и связываем диапазоны со списками записей, а ячейки с полями.
Получим картинку:
Нажмите на изображение для увеличения
Название: 26.png
Просмотров: 10
Размер:	96.3 Кб
ID:	13451

Сохраняем и завершаем формат.

В итоге у нас получается вот такая выгрузка:
Нажмите на изображение для увеличения
Название: 27.png
Просмотров: 4
Размер:	107.4 Кб
ID:	13452

Правда, это уже в формате pdf (автоматическое преобразование). Но в Excel выглядит идентично.

И наконец создадим класс для выгрузки нашего отчета программно, а не из конфигурации эл.отчетности

X++:
using Microsoft.Dynamics365.LocalizationFramework;

internal final class SalesOrdersHeaderLines
{
    static void main(Args  _args)
    {
        SalesOrdersHeaderLines  salesOrdersHeaderLines = new SalesOrdersHeaderLines();
        CustTable     custTable = _args.record();
        CustAccount   custAccount = custTable.AccountNum;
        salesOrdersHeaderLines.run(custAccount);
    }

    public void run(CustAccount   _custAccount)
    {
        ERFormatMappingTable    formatMapping;
        ERFormatMappingId       formatMappingId;
        select firstonly formatMapping
            where formatMapping.Name == "TrainerITSalesOrdersFormat";
        formatMappingId = formatMapping.Format;
        const str modelStr = "model";
        const str custAccountStr = "CustAccount";

        try
        {
            ERModelDefinitionInputParametersAction  eRModelDefinitionInputParametersAction = new ERModelDefinitionInputParametersAction();
            eRModelDefinitionInputParametersAction.addParameter(ERPath::Combine(modelStr, custAccountStr), _custAccount);
            ERObjectsFactory::createFormatMappingRunByFormatMappingId(formatMappingId)
                .withParameter(eRModelDefinitionInputParametersAction)
                .withFileDestination(ERObjectsFactory::createFileDestinationBrowser()).run();
        }
        catch
        {
            error("Ошибка");
        }
    }

}
Теперь данный класс можно как запустить самостоятельно, так и привязать к MenuItem, вывести этот MenuItem на расширение формы клиентов и получить отчет, показывающий заказы для выбранного клиента.

Последний раз редактировалось Mirta; 12.09.2022 в 19:50.
За это сообщение автора поблагодарили: EVGL (10), skuull (5).
Старый 12.09.2022, 20:20   #3  
EVGL is offline
EVGL
Участник
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,433 / 3016 (109) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
Очевидно, сначала создается вычисляемое поле FilterCustAccount, а потом из него извлекаются данные с глубиной в 3 таблицы. Можно было и без вычисляемого поля совсем, а с возможностью произвольного запроса по таблице SalesTable ("Запросить запрос").
Старый 13.09.2022, 00:16   #4  
skuull is offline
skuull
Участник
Most Valuable Professional
Лучший по профессии 2014
 
696 / 747 (26) +++++++
Регистрация: 08.03.2013
Адрес: ХЗ
А можно еще постраничную разбивку ? Каждый заказа с новой страници, а то сликшом часто спрашивают, а хороших примеров чтобы показать нет.
Старый 13.09.2022, 06:25   #5  
EVGL is offline
EVGL
Участник
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,433 / 3016 (109) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
Для этого непосредственно в формате нужно добавить элемент Page и сопоставить с записью в данном случае SalesTable, а уже внутрь добавлять строки как Range.

Напротив, элемент Page Break как минимум в Excel доказанно не работает.
Старый 13.09.2022, 07:09   #6  
skuull is offline
skuull
Участник
Most Valuable Professional
Лучший по профессии 2014
 
696 / 747 (26) +++++++
Регистрация: 08.03.2013
Адрес: ХЗ
https://docs.microsoft.com/en-us/dyn...ent-pagination
Документация то есть, но ее понять "могут не только лишь все, мало кто может это делать".
Там никаких Page Break не надо, только Range c no replication.
За это сообщение автора поблагодарили: axm2017 (5).
Старый 13.09.2022, 12:53   #7  
Mirta is offline
Mirta
Участник
 
12 / 52 (2) ++++
Регистрация: 23.11.2011
Цитата:
Сообщение от EVGL Посмотреть сообщение
Очевидно, сначала создается вычисляемое поле FilterCustAccount, а потом из него извлекаются данные с глубиной в 3 таблицы. Можно было и без вычисляемого поля совсем, а с возможностью произвольного запроса по таблице SalesTable ("Запросить запрос").
Да, это самое простое. Галочку "Запросить запрос" ставлю всегда у основной таблицы - хотя бы для возможности тестирования не на всей выборке, пока не добавлены пользовательские параметры. А без параметра тоже ведь никак не обойтись, если хочется показать пользователю "культурный" фильтр по полю. И тем более параметр нужен при вызове отчета через menu item.
Старый 13.09.2022, 22:58   #8  
Mirta is offline
Mirta
Участник
 
12 / 52 (2) ++++
Регистрация: 23.11.2011
Цитата:
Сообщение от EVGL Посмотреть сообщение
Для этого непосредственно в формате нужно добавить элемент Page и сопоставить с записью в данном случае SalesTable, а уже внутрь добавлять строки как Range.

Напротив, элемент Page Break как минимум в Excel доказанно не работает.
Все вроде бы верно, и для обычной разбивки на страницы действительно добавляем Page и на нее помещаем данные нашего отчета. Тут проблема возникнет при необходимости связки страницы с заказом, т.к. сама страница связываться не умеет.
Старый 27.10.2022, 10:12   #9  
EVGL is offline
EVGL
Участник
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,433 / 3016 (109) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
На днях пришлось использовать вашу идею с передачей параметра, при этом выяснил, что его в маппинге надо оставлять в "корне", а не прятать в отдельном контейнере, в противном случае ER не может его нормально найти по пути. Использовал GUID для поиска отчета:

X++:
    public static void main(Args args)
    {
        const str reportMappingGUID = "31716666-8662-45EF-BE58-8C71EC584132";
        const str paramPackageIdPath = "model/SPLPackageId";

        var erReport = ERObjectsFactory::createFormatMappingRunByFormatMappingId(ERFormatMappingTable::findByGUID(str2Guid(reportMappingGUID)).Format); 
        if (args && args.record())
        {
            SPLPackageTable packageTable = args.record() as SPLPackageTable;

            ERModelDefinitionInputParametersAction inputParameters = new ERModelDefinitionInputParametersAction();
            inputParameters.addParameter(paramPackageIdPath, packageTable.PackageId);

            erReport.withParameter(inputParameters).run();
        }
        else
        {
            erReport.run();
        }
    }
За это сообщение автора поблагодарили: sukhanchik (10).
Старый 27.10.2022, 21:06   #10  
Mirta is offline
Mirta
Участник
 
12 / 52 (2) ++++
Регистрация: 23.11.2011
А почему поиск именно по GUID, а не по формату?

Интересное замечание по входному параметру. Не приходилось создавать контейнеры для входных параметров, поэтому пока на такую фишку не напоролась. Какие только сюрпризы не преподносит GER)
Старый 27.10.2022, 21:16   #11  
EVGL is offline
EVGL
Участник
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,433 / 3016 (109) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
Имя, кажется, можно поменять, а GUID - только через XML.
Старый 31.10.2022, 00:19   #12  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2921 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Cool
Цитата:
Сообщение от EVGL Посмотреть сообщение
ER не может его нормально найти по пути.
насколько я помню, там "путь из путей": путь, каждый шаг которого является путем к источнику данных.

То есть надо что-то типа erpath::combine('model', erpath::combine('userinputparameters', 'my parameter'))
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
d365technext: D365FO Interview Question Blog bot DAX Blogs 2 10.09.2021 10:52
AX2012, D365FO: Способы ограничения финансовых аналитик sukhanchik DAX: Функционал 7 09.03.2021 02:58
sertandev: How to receive D365FO push notifications using Azure Notification Hubs Blog bot DAX Blogs 0 04.07.2019 18:11
sertandev: How to integrate D365FO with Microsoft Flow using the new Business Events Blog bot DAX Blogs 0 23.05.2019 16:11
erconsult: Copy-paste with keyboard script 2: from Excel to D365FO Blog bot DAX Blogs 0 03.08.2018 11:12
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:37.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.