This gives the information of method calls in the form level while
D365 for 365 days
Tuesday, May 31, 2022
Method Calling Sequence in D365/AX
Sunday, September 20, 2020
Customizing default filename when saving SSRS report (Ax 2012)
In this example, I show you how we can change the default file name proposal in the “Save As” dialog of a SSRS report in Ax 2012.
By default Dynamics Ax comes with a default file name proposal when we save a SSRS report, but this default name is not always usable, in case if we can print the report for each record in a grid with multi select options. In that case Dynamics Ax will propose the same report name for each selected record of the grid. In this example we made a change in the “Send Return Report” (path : Sales and Marketing | Common ” return orders | all return orders -> button ‘Return order’ .

When we have generated the report, we can save the report in divers formats like csv or pdf under the ‘diskette’ icon in the header bar of the report screen.

If we select for example PDF format, we see the default name suggestion, in this example the report name:

We would like to change this. Instead we would like to use the RMA number as RMA number is unique for each report, so that in case of multi select we can distinguish each saved report file . In order to perform this we have to make the following change in the parmReportCaption method of the the reports controller class of the report, which is the ReturnAcknowledgementAndDocController class. In the screenshot below you can see (yellow marked line no 17) the changes we need to made:

Then we have to run the incremental CIL:

When re-open the report and would like to save it we can see the suggested file name is the same as the reports RMA number:

Create default dimension using x++
//Change the arguments (variable) names and assign names as per your requirements
//Change in the function as well
public DimensionDefault createDefaultDimension(str department, str purpose, str costCenter)
{
DimensionAttributeValueSetStorage valueSetStorage = new DimensionAttributeValueSetStorage();
DimensionDefault result;
int i;
DimensionAttribute dimensionAttribute;
DimensionAttributeValue dimensionAttributeValue;
//Change the dimension names. Use the dimension name which are open and active in the system
//I have given Region, Purpose and Costcentre just for an example
container conAttr = ["Region", "Purpose", "Costcentre"];
//Change the values which you want to set in dimensions. Use values which are open and active in the system
//I have given the arguments of function as values for dimensions.
//Dimension name -> dimension value
//Region -> department
//Purpose -> purpose
//Costcentre -> costCenter
container conValue = [department, purpose, costCenter];
str dimValue;
for (i = 1; i <= conLen(conAttr); i++)
{
dimensionAttribute = dimensionAttribute::findByName(conPeek(conAttr,i));
if (dimensionAttribute.RecId == 0)
{
continue;
}
dimValue = conPeek(conValue,i);
if (dimValue != "")
{
dimensionAttributeValue = dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,dimValue,false,true);
valueSetStorage.addItem(dimensionAttributeValue);
}
}
result = valueSetStorage.save();
//It reutrns the value of type DimensionDefault
return result;
}
How to Show GST % PO report
purchTable = purchTable::find('02-000164');
taxDocument = TaxBusinessService::getTaxDocumentBySource(purchTable.TableId, purchTable.RecId);if(taxDocument)
{
componentLineEnumerator = taxDocument.componentLines();
while(componentLineEnumerator.moveNext())
{
componentLineObject = componentLineEnumerator.current();
taxComponent= componentLineObject.metaData().taxComponent();
taxValue = componentLineObject.getMeasure("Rate").value().value() * 100;
taxAmount = componentLineObject.getMeasure("Tax Amount").value().value();
info(strFmt("Component %1 ,Rate %2, Amount%3",taxComponent,taxValue,taxAmount));
}
}
Friday, September 4, 2020
SEND EMAIL IN D365 CODE X++ LOGIC
TABLE BROWSER IN D365
EVENT HANDLERS IN D365
1)
/// <summary>///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
[FormEventHandler(formStr(HcmPosition), FormEventType::Initialized)]
public static void HcmPosition_OnInitialized(xFormRun sender, FormEventArgs e)
{
FormDataSource hcmposition_ds = sender.dataSource(formDataSourceStr(HcmPosition, HcmPosition));
//you can also directly specify the datasource name - > //sender.dataSource('HcmPosition');
}
{
// Initialize the instance of this form extension handler now that the controls exist
FormRun positionMassUpdateForm = _sender as FormRun;
HcmPositionMassUpdateFormEventHandler extensionInstance = positionMassUpdateForm.getExtensionInstance(classStr(HcmPositionMassUpdateFormEventHandler));
extensionInstance.init();
}
Below code will give you the selected record in the hcmposition variable.
You can get the form run also.
[FormControlEventHandler(formControlStr(HcmPosition, HcmPositionNewPosition), FormControlEventType::Clicked)]
public static void HcmPositionNewPosition_OnClicked(FormControl sender, FormControlEventArgs e)
{
HcmPosition hcmposition = sender.formRun().dataSource(1).cursor();//hcmposition is the //primary datasource.
FormButtonControl callerButton = sender as FormButtonControl; //Retrieves the button
FormRun form = sender.formRun(); //Gets the formRun
In case you want to select any other datasource you can do the following
FormDataSource hcmWorker_ds = form.dataSource(formDataSourceStr(HcmWorker, HcmWorker)) as FormDataSource;
FormDataSource HcmPositionDetail_ds= form.dataSource(formDataSourceStr(HcmWorker, HcmPositionDetail)) as FormDataSource;
HcmWorker hcmWorker = hcmWorker_ds.cursor();
//Set up args with all of the information you've retrieved
}
3) In order to get the formrun use the below
FormRun formRun = sender.formRun() as FormRun;
4) In order to validate a std field you will have to use the below code.
/// <summary>
/// Event handler for the validated event on the BudgetPurposeType field on the HcmTmpBudgetPurposeType data source on the HcmPositionMassUpdate form.
/// </summary>
/// <param name="_sender">The form control raising the event.</param>
/// <param name="_e">Args for the event.</param>
[FormDataFieldEventHandler(formDataFieldStr(HcmPositionMassUpdate, HcmTmpBudgetPurposeType, BudgetPurposeType), FormDataFieldEventType::Validated)]
public static void BudgetPurposeType_OnValidated(FormDataObject _sender, FormDataFieldEventArgs _e)
{
HcmTmpBudgetPurposeType tmpBudgetPurposeTypeLocal;
HcmTmpBudgetPurposeType hcmTmpBudgetPurposeType = _sender.datasource().cursor();
// Validate for duplicates.
tmpBudgetPurposeTypeLocal.setTmpData(hcmTmpBudgetPurposeType);
select firstonly RecId from tmpBudgetPurposeTypeLocal
&& tmpBudgetPurposeTypeLocal.LegalEntity == hcmTmpBudgetPurposeType.LegalEntity;
if (tmpBudgetPurposeTypeLocal.RecId)
{
throw error("@Workforce:TheBudgetPurposeTypeIsAlreadyInUse");
}
}
3) Similarly if you want to write code on form modified or active on initialize you can use the below code
Sales Table Form --> Events --> OnActivated
////</summary>
////<param name="sender"></param>
////<param name="e"></param>
[FormDataSourceEventHandler(formDataSourceStr(SalesTable, SalesTable), FormDataSourceEventType::Activated)]
public static void SalesTable_OnActivated(FormDataSource sender, FormDataSourceEventArgs e)
{
boolean allowEdit = true;
SalesTable SalesTable = sender.cursor();
FormDataSource salesTable_ds = sender.formRun().dataSource("SalesTable");
FormControl ShippingDateRequested = element.design(0).controlName("Delivery_ShippingDateRequested");
if (ShippingDateRequested == datenull())
{
ShippingDateRequested.enabled(false);
}
else
{
ShippingDateRequested.enabled(true);
}
}
similarly you can write pre and post event handlers as below for different tables.
[PostHandlerFor(tableStr(InventTrans), tableMethodStr(InventTrans, AmountMst))]
public static void InventTrans_Post_anyValidateMethod(XppPrePostArgs args)
{
boolean ret = args.getReturnValue();
InventTrans InventTrans = args.getThis() as InventTrans;
if (InventJournalName::find(InventTrans.Qty > 0 && InventTrans.CostPrice == 0)
{
ret = checkFailed(strFmt("Cost Price is 0 for Line %1",InventTrans.LineNum));
}
args.setReturnValue(ret);
}
Below code executes after the standardd init method of the formMethodStr(HcmPositionMassUpdate, init)
if you wan to do somthing befoore the code execution write a pre event handler
/// <summary>
/// Post-event handler for the init method of the HcmPositionMassUpdate form.
/// </summary>
/// <param name="_args">Args for the event.</param>
[PostHandlerFor(formStr(HcmPositionMassUpdate), formMethodStr(HcmPositionMassUpdate, init))]
public static void HcmPositionMassUpdate_Post_init(XppPrePostArgs _args)
{
FormRun positionMassUpdateForm = _args.getThis();
HcmPositionMassUpdateBase positionMassUpdateBase = positionMassUpdateForm.parmPositionMassUpdateBase();
Args args = positionMassUpdateBase.parmFormArgs();
if (args.record() && args.record().TableId == tableNum(HcmPositionForecastScenario))
{
HcmPositionMassUpdateFormEventHandler::disableFinancialDimensionTab(args, positionMassUpdateForm);
}
}
[DataEventHandler(tableStr(HcmPositionWorkerAssignment), DataEventType::Deleted)]
public static void HcmPositionWorkerAssignment_onDeleted(Common _sender, DataEventArgs _e)
{
HcmWorkerHelper::getDepartmentRecIdsCacheClear();
}
[DataEventHandler(tableStr(HcmPositionWorkerAssignment), DataEventType::Inserted)]
public static void HcmPositionWorkerAssignment_onInserted(Common _sender, DataEventArgs _e)
{
HcmPositionWorkerAssignment positionWorkerAssignment = _sender as HcmPositionWorkerAssignment;
PayrollWorkerTaxRegion::refreshTaxRegionsForWorkerAtPosition(positionWorkerAssignment.Worker, positionWorkerAssignment.Position);
}
In case there are some changes which needs to be done in a standard method in between the code.
/// <summary>
/// </summary>
public void initForm()
{
next initForm();
//do something here.
}


