|
12.09.2022, 19:42 | #1 |
Участник
|
D365FO: GER Заказы со строками и проводками
Помимо привычных отчетов, содержащих итоговые данные, а также отчетов шапка-строки по какому-либо документу, иногда возникает необходимость построить отчет по списку документов, каждый из которых содержит шапку и строки. Такой отчет можно построить с помощью GER достаточно легко и быстро.
Рассмотрим быстрый способ создания отчета с тройной вложенностью. Возьмем для примера заказы на продажу, строки и проводки. Создаем модель TrainerITSalesOrders. Добавляем корень SalesReport. Создаем поля модели: Lines является дочерним узлом для SalesOrders InventTrans является дочерним узлом для Lines Создаем сопоставление модели По этой кнопке создается сопоставление модели с БД. Можно в дереве модели создать отдельно сопоставление. Это лучше тем, что до него быстрее добираться из дерева (не заходя в модель), и к тому же если мы захотим использовать эту модель для импорта или для других экспортов, то сопоставление лучше чтобы было отдельно, ибо тогда будет галка Использовать сопоставление по умолчанию. Ну пока нам хватит и такого сопоставления. Для выборки данных из связанных таблиц мы будем пользоваться отношениями на таблицах в АХ (релейшенами). Добавляем в качестве источника данных Записи таблицы SalesTable Ставим галку Запросить запрос - это позволит увидеть расширенный фильтр в диалоге вызова отчета. И галку Точка интеграции - для возможности вызова отчета через пункт меню. Для преобразования ЕНУМа Status в заказе добавим Перечисление АХ: Есть 3 способа преобразования перечисления: 1. В модель добавляется только перечисление АХ, далее оно преобразовывается в явно прописанные строковые значения с помощью формул 2. В модель добавляется перечисление АХ и перечисление модели данных. Затем с помощью формулы значениям перечисления АХ сопоставляются значения перечисления модели данных. 3. В модель добавляется перечисление АХ, а также вычисляемые поля, позволяющие с помощью формул преобразовать значение ЕНУМа в его аксаптовую метку. Этот способ самый сложный, но и самый результативный - даже если перечисление изменится в АХ, в GER его значения менять не придется. Мы воспользуемся первым способом. Связываем источники данных с полями модели: Поле Worker связываем с полем из релейшенов: Из DirPerson_FK берем поле Name Для поля Status задаем формулу Код: CASE(@.SalesStatus, Enums.SalesStatusEnum.Canceled, "Отменено", Enums.SalesStatusEnum.Delivered, "Доставлено", Enums.SalesStatusEnum.Invoiced, "Выставлен счет", Enums.SalesStatusEnum.None, "", Enums.SalesStatusEnum.Backorder, "Открытый заказ" ) Связываем SalesLine и Lines справа Через InventTransOrigin Обращаемся к InventTrans и связываем с InventTrans справа Номер лота берем из InventTransOrigin Кол-во - из InventTrans Складские аналитики возьмем из InventDim Последний раз редактировалось Mirta; 12.09.2022 в 19:51. |
|
12.09.2022, 19:47 | #2 |
Участник
|
Теперь добавлям входной параметр для фильтрации заказов по клиенту
Указываем имя и ЕДТ Здесь же можем управлять формулами для опций Только чтение и Значение по умолчанию (эти две опции появились только в версии 10.0.27) для вх.параметра Теперь создаем вычисляемое поле FilterCustAccount C формулой Код: IF(CustAccount="",SalesTable,FILTER(SalesTable, SalesTable.CustAccount = CustAccount)) Теперь свяжем выч.поле FilterCustAccount слева и SalesOrders справа На вопрос изменить ли привязку ответим "Да" Сохраняем изменения, завершаем модель Подготовим шаблон для выгрузки отчета У нас должно быть три диапазон - на проводки, на строки и на весь заказ в целом. И именованные ячейки для каждого поля: Создаем формат для нашей модели, назовем его TrainerITSalesOrdersFormat, загрузим в него наш файл У нас создадутся диапазоны, поддиапазоны и ячейки в соответствии с шаблоном. Переходим на вкладку Сопоставление и связываем диапазоны со списками записей, а ячейки с полями. Получим картинку: Сохраняем и завершаем формат. В итоге у нас получается вот такая выгрузка: Правда, это уже в формате 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("Ошибка"); } } } Последний раз редактировалось Mirta; 12.09.2022 в 19:50. |
|
|
За это сообщение автора поблагодарили: EVGL (10), skuull (5). |
12.09.2022, 20:20 | #3 |
Banned
|
Очевидно, сначала создается вычисляемое поле FilterCustAccount, а потом из него извлекаются данные с глубиной в 3 таблицы. Можно было и без вычисляемого поля совсем, а с возможностью произвольного запроса по таблице SalesTable ("Запросить запрос").
|
|
13.09.2022, 12:53 | #4 |
Участник
|
Да, это самое простое. Галочку "Запросить запрос" ставлю всегда у основной таблицы - хотя бы для возможности тестирования не на всей выборке, пока не добавлены пользовательские параметры. А без параметра тоже ведь никак не обойтись, если хочется показать пользователю "культурный" фильтр по полю. И тем более параметр нужен при вызове отчета через menu item.
|
|
13.09.2022, 00:16 | #5 |
Участник
|
А можно еще постраничную разбивку ? Каждый заказа с новой страници, а то сликшом часто спрашивают, а хороших примеров чтобы показать нет.
|
|
13.09.2022, 06:25 | #6 |
Banned
|
Для этого непосредственно в формате нужно добавить элемент Page и сопоставить с записью в данном случае SalesTable, а уже внутрь добавлять строки как Range.
Напротив, элемент Page Break как минимум в Excel доказанно не работает. |
|
13.09.2022, 22:58 | #7 |
Участник
|
Все вроде бы верно, и для обычной разбивки на страницы действительно добавляем Page и на нее помещаем данные нашего отчета. Тут проблема возникнет при необходимости связки страницы с заказом, т.к. сама страница связываться не умеет.
|
|
13.09.2022, 07:09 | #8 |
Участник
|
https://docs.microsoft.com/en-us/dyn...ent-pagination
Документация то есть, но ее понять "могут не только лишь все, мало кто может это делать". Там никаких Page Break не надо, только Range c no replication. |
|
|
За это сообщение автора поблагодарили: axm2017 (5). |
27.10.2022, 10:12 | #9 |
Banned
|
На днях пришлось использовать вашу идею с передачей параметра, при этом выяснил, что его в маппинге надо оставлять в "корне", а не прятать в отдельном контейнере, в противном случае 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 |
Участник
|
А почему поиск именно по GUID, а не по формату?
Интересное замечание по входному параметру. Не приходилось создавать контейнеры для входных параметров, поэтому пока на такую фишку не напоролась. Какие только сюрпризы не преподносит GER) |
|
31.10.2022, 00:19 | #11 |
Участник
|
|
|
27.10.2022, 21:16 | #12 |
Banned
|
Имя, кажется, можно поменять, а GUID - только через XML.
|
|
Теги |
electronic reporting, er, ger |
|
|