Search This Blog
December 13, 2022
Validate financial dimension combination
August 05, 2022
Create Code extension in D365FO
July 24, 2022
[Solved] Debugger not working, Symbols not loaded
July 22, 2021
QuickFix: Delete command button doesn't work as expected
December 20, 2020
[Solved] Table browser not working
Hi Folks,
Few days back I got a new dev box which was recently rolled out by one of a colleague. All of a sudden it started behaving strangely. Whenever browsing a table I was getting below error.
Access Denied: You do not have sufficient permissions to open the menu item systablebrowser. Please contact your system administrator.
I double checked all the access, I got full admin access on this server but still same issue. This created more confusion when I was trying to run the debugger, I started getting below error.
Access Denied: You do not have sufficient permissions to open the menu item sysclassrunner. Please contact your system administrator.
So to
overcome this issue, double-check if the developer configuration key is enabled,
in my case it was disabled and that was the root cause of these problems.
Now if you see the message on top of this form (Sysadmin > setup > License configuration) it is saying you cannot edit any record in the form until the server is in maintenance mode.
(See this
link for how
to enable maintenance mode in D365FO)
So first you need to enable maintenance mode on this server and then enable the development key.
Once than done, make sure you disable maintenance mode. And give it a try now, you should be able to browse a table. ( Also, the debugger is working fine as well 😊 )
Merry Christmas to all. Have a great holiday ahead.
-Harry
Follow us on Facebook to keep in rhythm
with us. https:fb.com/theaxapta
July 02, 2020
[Solved] Issue with data entity EcoResReleasedProductCreationV2Entity - Error executing code. The field with Id '0' does not exist in table 'InventTableModule
Hi Folks,
There are two data available in system EcoResReleasedProductV2Entity and EcoResReleasedProductCreationV2Entity with a similar appearance. Let’s first understand the use of each, To create release products in the system user has to use EcoResReleasedProductCreationV2Entity while updating release products user have to use EcoResReleasedProductV2Entity.
Now let's discuss the error which I was facing while using EcoResReleasedProductCreationV2Entity data entity to create release product. Below is the error message.
"Result: Error executing code. The field with Id '0' does not exist in table 'InventTableModule'. "
Now to fix this issue you need to install one hotfix in your system which is suggested by Microsoft. Go to your LCS project and search for KB4559650,
now you have to install this KB on your machine. On successful deployment, you should be able to use this data entity to release product import.
Cheers!!!
-Harry Follow us on Facebook to keep in rhythm with us. https:fb.com/theaxapta
June 14, 2020
AppChecker in Dynamics 365 Finance and operations
Hi Folks,
You may have seen one checkbox for AppChecker while doing a model build or while creating deployable packages OR maybe somewhere else in this lockdown. :)
Have you ever wondered what this all about and why it can be useful in your project. Well this tool is another check to ensure that your custom code meets all MS best practice and it behaves kind of a gatekeeper to ensure your coding standards are met to avoid any further upgrade issue with #MSDyn365FO.
In other words (I mean using copy-paste ;) it Allows you to get insights into what processes a particular application is performing, including stack traces and low level memory management data. It will complement Activity Tracking and will hopefully have its own dashboard in LCS where all of this data is overlaid for easy consumption.
You can get more details on AppChecker on below links
Biggest Takeaways From Microsoft BizApp Summit 2019
Enjoy home arrest for few more days..... No week or maybe another month.
Cheers!!!
Harry
-Harry Follow us on Facebook to keep in rhythm with us. https:fb.com/theaxapta
April 23, 2020
QuickFix -11: Extensible Data security in D365FO
October 15, 2018
Table Event handler methods in Dynamics 365 FO
In my last post Form Event hander methods in Dynamics 365 FO, we discussed different event handlers which available on Form. Let’s continue this discussion with Table event handler method today.
Let’s see the different type of event handler in today’s post.
You need to add a new class to write the event handler methods. I would recommend adding one class to one table. To make it easy for another developer postfix the name by EH or eventHander or Hander so your teammate can identify if they need to add more business logic than create a new class from scratch.
1. Table onValidateField event handler
2. Table OnValidated event hander (same logic you can try for many other event hander)
[DataEventHandler(tableStr(InventLocation), DataEventType::ValidatedField)]
public static void InventLocation_onValidatedField(Common sender, DataEventArgs e)
{
InventLocation inventLocation = sender as InventLocation;
ValidateFieldEventArgs fieldArgs = e;
boolean ret;
InventLocation inventLocationLoc;
switch(fieldArgs.parmFieldId())
{
case fieldNum(InventLocation, field1):
if(inventLocation.MyWorkerAssociate != '')
{
<Your code/ business ogic/validation>
<ret = true or false>
fieldArgs.parmValidateResult(ret);
}
}
}
Let me know if it helps you or you got some more example.
Cheers,
Harry
Follow us on Facebook to keep in rhythm with us. @Facebook
November 16, 2015
Use one table for creating multiple relation
After a long time I’m writing this new post.
Requirement: I need to use the single table to add multiple relation on a table. For eg. I have a parent table Table1 with field ItemId and ProcessItem. Now I need to add relation to InventTable to both fields. Hence I have to create two relation with InventTable.
How to do: Add two new relation in your table as shown below.
‘
You might get an error message after this,
'RelatedTableRole' conflicts with another 'RelatedTableRole' on relation InventTable_Item on table ProcessedItemTable.
Solution to this error:
Set below two properties to each relation
1. UseDefaultRoleNames- set it to “NO”
2. Role: Give any logical name here, for eg. “Item”
Now compile your table, error must gone.
Write your any query/feedback in comment box and help us to improve. Thanks..!!!
-Harry
May 05, 2015
Error while Unit Testing [AX 2012 R3]
I was facing below error while running test cases for a customization.
Solution: However i am not very much sure why this error was coming and what is the main reason for this, but I used below steps and its resolved this issue.
- Stop to AOS
- Delete AUC files from below path.
- Restart AOS.
-Harry
March 27, 2015
Auto Settlement of Sales Invoice in AX
1. By Sales parameter select auto settlement.
2. By select open transaction at the time of invoice posting
3. Through X++ code
1. By Sales parameter select auto settlement: Go to AR/Setup/Parameter under settlement tab you will found a check box for automatic settlement. Select this check box. And your system will auto settle your sales invoice.
This will settle a transaction whenever you post a payment journal.
2. By select open transaction at the time of invoice posting: You can also choose the open transaction at the time of invoice journal creation. At the time of invoicing click on “open transaction settle” button, this will open a new form to select records to be settle from open transaction of that customer.
3. Finally we have code as well (I love this part ;)): So here we are to do some tricky things. Yes, we can do the settlement by X++ code as well. Below code is an example in Job. You can use the same logic for any trigger point in AX.
static void theAxapta_AutosettlePayment(Args _args)
{
CustTable custTable;
CustTrans invCustTrans, payCustTrans;
SpecTransManager manager;
CustVendTransData custVendTransData;
;
custTable = CustTable::find("504411");
// Find the oldest unsettled invoice
select firstonly invCustTrans
order by TransDate asc
where invCustTrans.AccountNum == custTable.AccountNum &&
invCustTrans.TransType == LedgerTransType::Sales &&
!invCustTrans.closed;
// Find the oldest unsettled payment
select firstonly payCustTrans
order by TransDate asc
where payCustTrans.AccountNum == custTable.AccountNum &&
payCustTrans.TransType == LedgerTransType::Payment &&
!payCustTrans.closed;
ttsbegin;
// Create an object of the CustVendTransData class with the invoice transaction as parameter
custVendTransData = CustVendTransData::construct(invCustTrans);
// Mark it for settlement
custVendTransData.markForSettlement(CustTable);
// Create an object of the CustVendTransData class with the payment transaction as parameter
custVendTransData = CustVendTransData::construct(payCustTrans);
//mark it for settlement
custVendTransData.markForSettlement(CustTable);
ttscommit;
// Settle all marked transactions
if(CustTrans::settleTransact(custTable, null, true,
SettleDatePrinc::DaysDate, systemdateget()))
info("Transactions settled");
}
Enjoy…..
- Harry
March 03, 2015
The table WHSWorkLineCycleCount does not contain the method WHSWorkTable.
Today i just got this error message for "WHSWorkLineCycleCount" table. while there is no changes in standard objects. Have a look on below case and share your suggestion and feedback as well. Here i am sharing my experience with the same.
Compilation error:
The table WHSWorkLineCycleCount does not contain the method WHSWorkTable.
CIL Error:
CIL generation: Warning: CIL could not be generated for X++ method WHSWorkTableForm.sourceButton_clicked due to X++ compile errors. This method throws an exception if run as CIL.
Possible Reason:
After the configuration key "Warehouse and Transportation management" is disabled, you will get above compilation and CIL error on standard AX
Solutions:
1. Add one method in table WHSWorkLineCycleCount named WHSWorkTable
To fix it on your environment, simply create a method with name whsWorkTable() on the WHSWorkLineCycleCount table, that returns the corresponding work based on the relation field
2. You can also try below hotfix:
http://support2.microsoft.com/hotfix/KBHotfix.aspx?kbnum=3001197&kbln=en-in
-Harry
March 02, 2015
February 18, 2015
After upgrading my windows from 8 to 8.1, my dynamics ax is not working
Recently one of my collogue just update his OS from windows 8 to windows 8.1 and AX just stop working… :( When he trying to start my AOS services its gives below error message
If you open event log you will found this error
“Object Server 01: The home directory for Axapta (C:\WINDOWS\system32\) does not match the required structure or can not be accessed. Please check installation, configuration and access rights.”
AND
“Object Server 01: The directory "C:\WINDOWS\system32\\bin" does not exist or access to it has been denied by the operating system.”
AND
“Object Server 01: Error accessing registry: Cannot open key SYSTEM\CurrentControlSet\Services\Dynamics Server\6.0\01. Error code: 0”
Possible reason :
Open AX server configuration from administrator tools. Here you would see it completely empty
The problem is that registry keys located in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dynamics Server\ were deleted during the update.
To resolve this issue You can create manually registry entry (That can be a difficult task if you are not friendly with windows registry editor), OR just reinstall the AOS and it will work.
(To open registry editor open “RUN” enter “regedit” and hit enter)
BUT…. At the end of the day its not recommended for PROD or LIVE server you can do this R&D only and only on your local or DEV environment.
All the best guys…..
-Harry
January 09, 2015
How to add new fields/Methods in Listpage from in AX 2012
Here we use the Production Order list page for example
Open Production order list page from below link
Production control/Common/Production orders/All production orders
Now we need to add one new field “Serial Number” in this grid (Assuming there will be only one item in one Production order in every case).
This serial number is available in “Transaction” from of this production order.
Now to display new fields you can add a new display method in table and drag-drop this method in a grid as a field.
Add one new method in “ProdTable” table add copy below code
display InventSerialId inventTransInventSerialId()
{
InventTransOrigin InventTransOrigin;
InventTrans InventTrans;
;
select InventTrans join InventTransOrigin
where InventTrans.InventTransOrigin == InventTransOrigin.RecId &&
InventTrans.ItemId == InventTransOrigin.ItemId &&
InventTransOrigin.ReferenceId == this.ProdId &&
InventTransOrigin.ItemId == this.ItemId;
return InventDim::find(InventTrans.inventDimId).inventSerialId;
}
Now set DataSource property of this new field as ProdTable. Save your from and compile for any error.
Now open this from, here is your from
-Harry
September 11, 2013
How to use Complex Query Ranges in Dynamics AX
Use of Complex Query Ranges in
Dynamics AX
1.
Adding a query with a datasource.
query =
new Query();
dsInventTable = query.addDataSource(tableNum(InventTable));
// Add our range
queryBuildRange = dsInventTable.addRange(fieldNum(InventTable, DataAreaId));
2.
Simple criteria
Lets find the record where the value of ItemId
field is Item1. Take note of the single quotes and parenthesis surrounding the
entire expression.
queryBuildRange.value(strFmt('(ItemId
== "%1")', queryValue("Item1")));
Find records where the ItemType is Service. Note the use of any2int().
queryBuildRange.value(strFmt('(ItemType == %1)', any2int(ItemType::Service)));
Find records where the ItemType is Service or
the ItemId is Item1. Note the nesting of the parenthesis in this example.
queryBuildRange.value(strFmt('((ItemType
== %1) || (ItemId == "%2"))', any2int(ItemType::Service),
queryValue("Item1")));
Find records where the modified date is after
1st January 2000. Note the use of Date2StrXpp() to format the date correctly.
queryBuildRange.value(strFmt('(ModifiedDate
> %1)', Date2StrXpp(01012000)));
3.
Complex criteria with combined AND and OR
clauses
We need to find those records where the ItemType
is Service, or both the ItemType is Item and the ProjCategoryId is Spares. This
is not possible to achieve using the standard QueryRange syntax.
queryBuildRange.value(strFmt('((%1
== %2) || ((%1 == %3) && (%4 == "%5")))',fieldStr(InventTable,
ItemType),any2int(ItemType::Service),any2int(ItemType::Item),fieldStr(InventTable,
ProjCategoryId),queryValue("Spares")));
-Harry
Use of Complex Query Ranges in Dynamics AX
1. Adding a query with a datasource.
query = new Query();
dsInventTable = query.addDataSource(tableNum(InventTable));
// Add our range
queryBuildRange = dsInventTable.addRange(fieldNum(InventTable, DataAreaId));
Lets find the record where the value of ItemId field is Item1. Take note of the single quotes and parenthesis surrounding the entire expression.
queryBuildRange.value(strFmt('(ItemId == "%1")', queryValue("Item1")));
Find records where the ItemType is Service. Note the use of any2int().
queryBuildRange.value(strFmt('(ItemType == %1)', any2int(ItemType::Service)));
Find records where the ItemType is Service or the ItemId is Item1. Note the nesting of the parenthesis in this example.
queryBuildRange.value(strFmt('((ItemType == %1) || (ItemId == "%2"))', any2int(ItemType::Service), queryValue("Item1")));
Find records where the modified date is after 1st January 2000. Note the use of Date2StrXpp() to format the date correctly.
queryBuildRange.value(strFmt('(ModifiedDate > %1)', Date2StrXpp(01012000)));
We need to find those records where the ItemType is Service, or both the ItemType is Item and the ProjCategoryId is Spares. This is not possible to achieve using the standard QueryRange syntax.
queryBuildRange.value(strFmt('((%1 == %2) || ((%1 == %3) && (%4 == "%5")))',fieldStr(InventTable, ItemType),any2int(ItemType::Service),any2int(ItemType::Item),fieldStr(InventTable, ProjCategoryId),queryValue("Spares")));
March 15, 2013
Dynamics AX – Form lookups and how they work
That is a simple way to create a lookup. Another way to create a lookup is to write a dynamic lookup on the table in which the data is coming from. This method will be a static method and will require the passing of arguments – typically the formstringcontrol that is to be the point of lookup. I prefer this method and use it often.
This a very simple example of a static lookup from a table
static void lookupTruckLoadIdEndingInv(FormStringControl _ctrl)
{
SysTableLookup sysTableLookup = SysTableLookup::newParameters(tablenum(WfsRMTruckLoadStatus), _ctrl);
Query query = new Query();
QueryBuildRange qbr;
;
query.addDataSource(tablenum(WfsRMTruckLoadStatus));
sysTableLookup.addLookupfield(fieldnum(WfsRMTruckLoadStatus, truckLoadId ));
query.dataSourceTable(tablenum(WfsRMTruckLoadStatus)).addRange(fieldnum(WfsRMTruckLoadStatus,retTransferred)).value(SysQuery::value(NoYes::No));
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}
Joins can be peformed as well to pull back the desired data so you are not limited to querying on one table to return the proper data back to your lookup
static void lookupSettledTruckLoadIdCashier(FormStringControl _ctrl)
{
SysTableLookup sysTableLookup = SysTableLookup::newParameters(tablenum(WfsRMTruckLoadHeader), _ctrl);
Query query = new Query();
QueryBuildRange qbr;
queryBuildDataSource qbdsTruckLoadStatus,qbdsTruckLoadHeader,qbdsTenderSlipHeader;
;
qbdsTruckLoadHeader = query.addDataSource(tablenum(WfsRMTruckLoadHeader));
qbdsTruckLoadStatus = qbdsTruckLoadHeader.addDataSource(tablenum(WfsRMTruckLoadStatus));
qbdsTruckLoadStatus.relations(true);
qbdsTruckLoadStatus.addRange(fieldnum(WfsRMTruckLoadStatus,settled)).value(enum2str(NoYes::No));
qbdsTruckLoadStatus.addRange(fieldnum(WfsRMTruckLoadStatus,HHTruckLoadIdEnded)).value(enum2str(NoYes::Yes));
qbdsTruckLoadStatus.addRange(fieldnum(WfsRMTruckLoadStatus,RetTransferred)).value(enum2str(NoYes::Yes));
qbdsTenderSlipHeader = qbdsTruckLoadStatus.addDataSource(tablenum(wfsRMTenderSlipHeader));
//qbdsTenderSlipHeader.relations(true);
qbdsTenderSlipHeader.addLink(fieldnum(WfsRMTruckLoadStatus, truckLoadId),fieldnum(wfsRMTenderSlipHeader, truckLoadId));
qbdsTenderSlipHeader.joinMode(joinMode::NoExistsJoin);
sysTableLookup.addLookupfield(fieldnum(WfsRMTruckLoadHeader, truckLoadId));
sysTableLookup.addLookupfield(fieldnum(WfsRMTruckLoadHeader, routeId));
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}
Another way is to create an actual form and call it in a method on the table. You will still need to pass in the formstringcontrol object but in this case you will be calling an actual existing form that you have created. Now why do this? Well one reason may be that you want to be able to filter on a specific field in the lookup that maybe you could not on a typical lookup or maybe you need to add a field to the lookup that would otherwise not be possible like you can add a display method to a lookup but maybe you want to see the field referenced in the display method and have the ability to sort on the field or filter on the field. For example, like DirPartyTable.Name. Sure, you can access it using a display method but maybe you want to see it in your lookup and be able to filter on it.So you will create a form and call it like a lookup so you can have all the the filtering of a standard form
public client static void WfsRMlookupEmplIdCashier(Object _ctrl)
{
Args args;
FormRun formRun;
;
args = new Args();
args.name(formstr(WfsRMEmplIdLookupCashier));
args.caller(_ctrl);
formRun = classfactory.formRunClass(args);
formRun.init();
_ctrl.performFormLookup(formRun);
}
The standard lookups present in AX like the item number lookup and the customer lookup are very interesting in that you only see one field on the relation but no fields in the autolookup. In these cases the lookup fields are coming from the standard indexes on the table. Take note of what you see in the itemId lookup when unchanged and then reference the indexes coincidence not really. this can apply to any new lookup you create as well.You can also override the lookup on the datasource - field of a form or an actual field string edit control on a form and perform a lookupForm design object
public void lookup()
{
SysTableLookup sysTableLookup;
Query query=new Query();
QueryBuildDataSource qbds;
;
sysTableLookup=SysTableLookup::newParameters(tablenum(Dimensions),this);
sysTableLookup.addLookupfield(fieldnum(Dimensions,Num));
sysTableLookup.addLookupfield(fieldnum(Dimensions,Description));
qbds = query.addDataSource(tablenum(Dimensions));
qbds.addRange(fieldnum(Dimensions, DimensionCode)).value(queryValue(COSAllowedDimensions::getAllowedDimensionValue(sysDim)));
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}
//Lookup from a field on the form data source
public void lookup(FormControl _formControl, str _filterStr)
{
Args args;
FormRun formRun;
SysTableLookup sysTableLookup = sysTableLookup::newParameters(tablenum(InventTable),_formControl);
Query query = new Query();
QueryBuildDataSource queryBuildDataSource;
QueryBuildRange queryBuildRange;
;
sysTableLookup.addLookupfield(fieldnum(InventTable,ItemID));
sysTableLookup.addLookupfield(fieldnum(InventTable,ItemName));
sysTableLookup.addLookupfield(fieldnum(InventTable,ItemGroupID));
sysTableLookup.addLookupfield(fieldnum(InventTable,NameAlias));
sysTableLookup.addLookupfield(fieldnum(InventTable,ItemType));
sysTableLookup.addLookupfield(fieldnum(InventTable,DimGroupID));
queryBuildDataSource = query.addDataSource(tablenum(Inventtable));
queryBuildRange = queryBuildDataSource.addRange(fieldnum(InventTable,ItemGroupID));
//FGL, FGR, Returns
queryBuildRange.value('xxx');
queryBuildRange = queryBuildDataSource.addRange(fieldnum(InventTable,ItemGroupID));
queryBuildRange.value('yyy');
queryBuildRange = queryBuildDataSource.addRange(fieldnum(InventTable,ItemGroupID));
queryBuildRange.value('Returns');
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}
-Harry
March 01, 2013
Add multiple range and multiple table lookup
Add multiple range and multiple table lookup
public void lookup()
{
SysTableLookup tableLookup;
QueryBuildRange rangeTransDate;
QueryBuildRange vlgCode,ItemId,DistCode,talCode;
QueryBuildRange CropId;
QueryRun queryRun;
QueryBuildDataSource qbds,qbds1,qbr,qbr1,qbr2;
Query q = new Query();
Query q1 = new Query();
QueryBuildLink QueryBuildLink1,QueryBuildLink2;
_TmpLookup _TmpLookup1;
InventTable InventTable_1;
boolean flg;
;
tableLookup = SysTableLookup::newParameters(tableNum(_TableDetails),this);
qbr = q.addDataSource(tableNum(_TableDetails));
qbr2=qbr.addDataSource(tablenum(_Inspection1));
qbr2.joinMode(Joinmode::NoExistsJoin);
QueryBuildLink2 = qbr2.addLink(fieldnum(_TableDetails, _TableNo),fieldnum(_Inspection1,TableNo));
// qbr2.addRange(fieldnum(_TableDetails,_TableNo)).value(queryNotValue(SysQuery::valueEmptyString()));
qbr2.relations(true);
if(tmpfilter.DistrictCode != "" )
{
qbr.addRange(fieldnum(_TableDetails,_DistrictCd)).value(queryValue(tmpfilter.DistrictCode));
}
if(tmpfilter.talCode != "" )
{
qbr.addRange(fieldnum(_TableDetails,_talCd)).value(queryValue(tmpfilter.talCode));
}
if( tmpfilter.vlgCode != "")
{
qbr.addRange(fieldnum(_TableDetails,_vlgCd)).value(queryValue(tmpfilter.vlgCode));
}
if(tmpfilter.ItemId != "")
{
qbr.addRange(fieldnum(_TableDetails,ItemId)).value(queryValue(tmpfilter.ItemId));
}
// qbr2.addRange(fieldnum(_TableDetails,_TableNo)).value(queryValue(''));
//ss
//ss
// qbr.addRange(fieldnum(_TableDetails,_Area)).value(queryNotValue(0));
//ss
qbr1 = qbr.addDataSource(tablenum(_Table));
qbr1.joinMode(Joinmode::InnerJoin);
QueryBuildLink2 = qbr1.addLink(fieldnum(_TableDetails, RegId),fieldnum(_Table,RegId));
qbr1.relations(true);
if(enum2str(tmpfilter.Season) != "")
{
qbr1.addRange(fieldnum(_Table,_SeasonId)).value(queryValue(tmpfilter.Season));
}
if(tmpfilter.CustAccount != "")
{
qbr1.addRange(fieldnum(_Table,CustAccount)).value(queryValue(tmpfilter.CustAccount));
}
// qbr2.addRange(fieldnum(_TableDetails,_TableNo)).value(queryNotValue(""));
//ss
// qbr2.addRange(fieldnum(_TableDetails,_TableNo)).value(queryValue('090000004'));
//info(_Inspection1.TableNo);
//ss
tableLookup.parmQuery(q);
tableLookup.addLookupfield(fieldNum(_TableDetails,_TableNo));
tableLookup.addLookupfield(fieldNum(_TableDetails, ItemId));
tableLookup.addLookupfield(fieldNum(_TableDetails, ItemName));
tableLookup.setLabel("Name");
tableLookup.performFormLookup();
}
-Harry
February 28, 2013
Dynamics AX – Passing parameters between object – What is args??
ARGS is your friend in the world of AX (me also :) ). It allows you to pass records, the calling locations (form, report, query etc) , ENUMS and the list goes on!
Simple declaration of args
Args args = new Args();
Now lets try passing args an record.
select firstonly custTable where custTable.AccountNum == ‘XXXX’
if(custTable)
{
args.record(custTable);
}
Now lets view a snippet of code that passes in a record and runs a report using the record passed in.
I- Create an instance of the report run class.
Create a new Args instance to hold all of this information.
Pass the name of the report.
Instantiate the report run object and call the init and and run methods of the report.
II- Next override the init method of the report and put a condition that checks to see if a record was passed to the report from the args object. If so do not allow the user to be interactive with the report and sent the report straight to the screen.
III- Set a report variable eHeader to the record that was passed to the report. If there is no calling record to the report meaning the report is being launched from a menu or elsewhere besides a place with a calling record then allow interaction of the report query for the users to select the range criteria they want to use.
IV- Then override the fetch method and keep the super in place to allow the standard query to run however before the super use a condition to determine if a record has been passed into the report. If so then set a query of a key field to the a field from the record passed in.
V- You can use args to do the same with forms as well
You can pass in objects such as maps to run reports I have done this as well and I find it very helpful and useful
void printPickList(wfsEMPickListHeader wfsEMPickListHeader)
{
Args args = new args();
ReportRun reportRun;
;
args.name(reportStr(wfsEMExportPickList));
args.caller(this);
args.record(wfsEMPickListHeader);
reportRun = classfactory.reportRunClass(args);
reportRun.init();
reportRun.run();
}
public void init()
{
super();
if(element.args().record())
{
this.report().interactive(false);
this.query().interactive(false);
this.printJobSettings().preferredTarget(PrintMedium::Screen);
eHeader = element.args().record();
}
else
{
this.report().interactive(true);
this.query().interactive(true);
}
}
public boolean fetch()
{
boolean ret;
if(element.args().record())
{
element.query().dataSourceTable(tablenum(wfsEMPickListHeader)).
addRange(fieldnum(wfsEMPickListHeader,PickListId)).value(eHeader.PickListId);
}
ret = super();
return ret;
}
void wfsRMRunManualTruckLoadIdForm()
{
wfsWhseUser wfsWhseUser;
FormRun formRun;
Args args = new Args();
boolean ret = false;
;
args.record(this);
formRun = new MenuFunction(menuitemdisplaystr(wfsManualTruckLoadSelection),
MenuItemType::Display).create(args);
formRun.run();
formRun.wait();
}
-Harry