Practical D365 Finance & Operations insights for developers and consultants — X++ code, OData integration, data entities, plus functional setup and how-tos.
Tuesday, October 20, 2015
Tuesday, September 29, 2015
Changing report design via code SSRS
It is one of the normal development requirements you may came across where you want to change the report design name on the basis of some logic. The following example shows you how to achieve this.
The modification is done in Controller class "outputReport" method, before "super" call you need to set the updated design name based on some condition and its done.
/// <summary>
/// Executes the report for the print management setting that is currently loaded.
/// </summary>
/// <remarks>
/// The <c>outReports</c> method loops over print management settings and calls this method for each
/// print management setting loaded.
/// </remarks>
/// <exception cref="M:Exception::Error">
/// The print management object has not been initialized.
/// </exception>
public void outputReport()
{
reportDesign = 'MyReport.Report_DesignA';
this.parmReportName(reportDesign);
this.parmReportContract().parmReportName(reportDesign);
formLetterReport.parmReportRun().settingDetail().parmReportFormatName(reportDesign);
super();
}
The modification is done in Controller class "outputReport" method, before "super" call you need to set the updated design name based on some condition and its done.
/// <summary>
/// Executes the report for the print management setting that is currently loaded.
/// </summary>
/// <remarks>
/// The <c>outReports</c> method loops over print management settings and calls this method for each
/// print management setting loaded.
/// </remarks>
/// <exception cref="M:Exception::Error">
/// The print management object has not been initialized.
/// </exception>
public void outputReport()
{
reportDesign = 'MyReport.Report_DesignA';
this.parmReportName(reportDesign);
this.parmReportContract().parmReportName(reportDesign);
formLetterReport.parmReportRun().settingDetail().parmReportFormatName(reportDesign);
super();
}
Tuesday, September 22, 2015
Restoring missing DirPartyLocation info
I came into issue on one of the environment where somehow records of Vendor Contacts data was deleted from DirPartyLocation table and we need to restore the data without backup database as the backup database was way old to recover.
By looking into GAB framework which was introduced in AX 2012, I come to know that DirPartyTable maintains Primary contacts and address information in the following fields.
By looking into GAB framework which was introduced in AX 2012, I come to know that DirPartyTable maintains Primary contacts and address information in the following fields.
- PrimaryAddressLocation
- PrimaryContactEmail
- PrimaryContactFax
- PrimaryContactPhone
- PrimaryContactTelex
- PrimaryContactURL
Friday, May 15, 2015
SSRS Reports Excel merge cell issue
I found various blogs and forums discussing the Excel merging cells issue while exporting SSRS report to Excel. I found a simple and logical reason behind the issue.
In the above design consider Report Header Textbox with Grid in the details part. If Header Textbox does not align with Grid columns, Excel will start merging the difference of columns which is shown by red line in the picture. However, if you get it align with Grid column Excel will start a new column as there will be no difference in columns indicated by green line.
Thursday, May 7, 2015
Cheque modification in AX 2012
Cheque modification is a most common requirements in Dynamics AX world. In this post I will discuss the values which are prepared before these values are dumped in SSRS Report framework. All cheque values including Recipient name and address, Amount in words, Date, Slip transactions etc.
The class which needs to be modify in order to customize the values is "CustVendCheque".
The class which needs to be modify in order to customize the values is "CustVendCheque".
CustVendCheque class methods are generally
modified to get the cheque values customized:
- getSlipText or (fillSlipTxt which is obsolete in AX 2012)
- output
getSlipText method
is responsible for most of the data that is printed on the check slip lines;
the key point here is that it is sent as a single block of text which leaves
the developer very little room to actually modify the cheque without getting
into a stream of circular reference errors. So, whatever we need
to do as far as Text formatting (for check stubs) goes, we should get it done before
this text (‘chequeSlipTxt’) leaves the class.
Friday, May 1, 2015
Financial dimension lookup
While developing in AX "lookups" are the most common requirements you may come across. However, sometimes you may have to link your customized lookup to non-conventional datasets such as "Financial Dimensions".
This post will show you how to create custom lookup listing one of "Financial Dimension" on report dialog. For this requirement it requires "UI Builder" class.
This customized lookup function will be using "DimensionDefaultingLookup" from.
This post will show you how to create custom lookup listing one of "Financial Dimension" on report dialog. For this requirement it requires "UI Builder" class.
This customized lookup function will be using "DimensionDefaultingLookup" from.
Contract Class declaration :
[
DataContractAttribute, SysOperationContractProcessingAttribute(classStr(xxxxReportUIBuilder))
]
public class xxxxReportContract
{
Name dimensionValue;
}
Contract parameter :
[
DataMemberAttribute(identifierStr(dimensionValue)),
SysOperationLabelAttribute(literalstr('@SYS3794')),
SysOperationDisplayOrderAttribute('1')
]
public Name parmFinDimLocation(Name _dimensionValue = dimensionValue)
{
dimensionValue = _dimensionValue;
return dimensionValue;
}
Thursday, April 30, 2015
Reading excel file with progress bar
Reading an excel is most common requirement you may come across while developing in Axapta world. This post will show the code for reading an excel file with progress bar indicator.
static void excelReadWithProgressBarJob(Args _args)
{
SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
COMVariantType type;
int row, totalRowCount;
int numberOfRecordsCleaned;
int numberOfRecordsNotFound;
Dialog dialog;
DialogField dialogField;
Filename filename;
SysExcelRange range;
SysOperationProgress progress = new SysOperationProgress();
#Excel
#AviFiles
#define.Star('*')
#define.Space(' ')
VendAccount vendAccount;
VendTable vendTableLocal;
dialog = new Dialog("Caption of Dialog");
dialogfield = dialog.addField(extendedTypeStr(FilenameOpen), "Excel file");
dialog.filenameLookupFilter(["@SYS28576", #XLSX, "@SYS28576", "*.xls"]);
if (dialog.run())
{
filename = (dialogfield.value());
}
else
{
return;
}
progress.setCaption("Caption for progress bar");
progress.setAnimation(#AviUpdate);
application = SysExcelApplication::construct();
workbooks = application.workbooks();
try
{
workbooks.open(filename);
}
catch (Exception::Error)
{
throw error("File cannot be opened.");
}
workbook = workbooks.item(1);
worksheets = workbook.worksheets();
worksheet = worksheets.itemFromNum(1);
cells = worksheet.cells();
range = cells.range(#ExcelTotalRange);
try
{
// Finds the row where the first contents is found.
range = range.find(#Star, null, #xlFormulas, #xlWhole, #xlByRows, #xlPrevious);
totalRowCount = range.row();
progress.setTotal(totalRowCount);
}
catch (Exception::Error)
{
error("@SYS59926");
totalRowCount = 0;
progress.setTotal(totalRowCount);
}
do
{
row++;
//Vendor account
switch(cells.item(row, 1).value().variantType())
{
case COMVariantType::VT_BSTR:
vendAccount = strFmt("%1", cells.item(row, 1).value().bStr());
break;
case COMVariantType::VT_DECIMAL, COMVariantType::VT_R4, COMVariantType::VT_R8:
vendAccount = strFmt("%1", num2str(cells.item(row, 1).value().double(), -1, 0, DecimalSeparator::Auto, ThousandSeparator::None));
break;
case COMVariantType::VT_I1, COMVariantType::VT_I2, COMVariantType::VT_I4:
vendAccount = strFmt("%1", cells.item(row, 1).value().int());
break;
case COMVariantType::VT_UI1, COMVariantType::VT_UI2, COMVariantType::VT_UI4:
vendAccount = strFmt("%1", cells.item(row, 1).value().uLong());
break;
case COMVariantType::VT_EMPTY:
vendAccount = '';
break;
default:
throw error(strfmt('Unhandled variant type (%1).', cells.item(row, 3).value().variantType()));
}
vendTableLocal = VendTable::find(vendAccount);
if (vendTableLocal)
{
numberOfRecordsCleaned++;
}
else
{
numberOfRecordsNotFound++;
}
type = cells.item(row + 1, 1).value().variantType();
progress.setText(strfmt("Vendor : %1 (%2 / %3)", vendAccount, row, totalRowCount));
progress.setCount(row, 1);
}
while (type != COMVariantType::VT_EMPTY);
application.quit();
info(strFmt('%1 / %2 number of records found', numberOfRecordsCleaned, row));
info(strFmt('%1 / %2 number of records not found', numberOfRecordsNotFound, row));
}
static void excelReadWithProgressBarJob(Args _args)
{
SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
COMVariantType type;
int row, totalRowCount;
int numberOfRecordsCleaned;
int numberOfRecordsNotFound;
Dialog dialog;
DialogField dialogField;
Filename filename;
SysExcelRange range;
SysOperationProgress progress = new SysOperationProgress();
#Excel
#AviFiles
#define.Star('*')
#define.Space(' ')
VendAccount vendAccount;
VendTable vendTableLocal;
dialog = new Dialog("Caption of Dialog");
dialogfield = dialog.addField(extendedTypeStr(FilenameOpen), "Excel file");
dialog.filenameLookupFilter(["@SYS28576", #XLSX, "@SYS28576", "*.xls"]);
if (dialog.run())
{
filename = (dialogfield.value());
}
else
{
return;
}
progress.setCaption("Caption for progress bar");
progress.setAnimation(#AviUpdate);
application = SysExcelApplication::construct();
workbooks = application.workbooks();
try
{
workbooks.open(filename);
}
catch (Exception::Error)
{
throw error("File cannot be opened.");
}
workbook = workbooks.item(1);
worksheets = workbook.worksheets();
worksheet = worksheets.itemFromNum(1);
cells = worksheet.cells();
range = cells.range(#ExcelTotalRange);
try
{
// Finds the row where the first contents is found.
range = range.find(#Star, null, #xlFormulas, #xlWhole, #xlByRows, #xlPrevious);
totalRowCount = range.row();
progress.setTotal(totalRowCount);
}
catch (Exception::Error)
{
error("@SYS59926");
totalRowCount = 0;
progress.setTotal(totalRowCount);
}
do
{
row++;
//Vendor account
switch(cells.item(row, 1).value().variantType())
{
case COMVariantType::VT_BSTR:
vendAccount = strFmt("%1", cells.item(row, 1).value().bStr());
break;
case COMVariantType::VT_DECIMAL, COMVariantType::VT_R4, COMVariantType::VT_R8:
vendAccount = strFmt("%1", num2str(cells.item(row, 1).value().double(), -1, 0, DecimalSeparator::Auto, ThousandSeparator::None));
break;
case COMVariantType::VT_I1, COMVariantType::VT_I2, COMVariantType::VT_I4:
vendAccount = strFmt("%1", cells.item(row, 1).value().int());
break;
case COMVariantType::VT_UI1, COMVariantType::VT_UI2, COMVariantType::VT_UI4:
vendAccount = strFmt("%1", cells.item(row, 1).value().uLong());
break;
case COMVariantType::VT_EMPTY:
vendAccount = '';
break;
default:
throw error(strfmt('Unhandled variant type (%1).', cells.item(row, 3).value().variantType()));
}
vendTableLocal = VendTable::find(vendAccount);
if (vendTableLocal)
{
numberOfRecordsCleaned++;
}
else
{
numberOfRecordsNotFound++;
}
type = cells.item(row + 1, 1).value().variantType();
progress.setText(strfmt("Vendor : %1 (%2 / %3)", vendAccount, row, totalRowCount));
progress.setCount(row, 1);
}
while (type != COMVariantType::VT_EMPTY);
application.quit();
info(strFmt('%1 / %2 number of records found', numberOfRecordsCleaned, row));
info(strFmt('%1 / %2 number of records not found', numberOfRecordsNotFound, row));
}
Subscribe to:
Posts (Atom)

