Monday, August 23, 2010

Introduction to Role Center

Role Centers are default home pages for AX client and EP that provide an overview of the information that pertains to the work of people such as CFOs, CEOs, Accountants... It consist of the following web parts:

1 - Work list
2 – Activities
3 - Frequently used links
4 - Business intelligence information.
a) KPIs (Business Overview webpart)
b) KPI Reports

There is difference between the Role center page that displays on AX Client and on EP. Client Forms will not be visible and cannot be opened from the EP but can be accessed from the AX Client.

1 – Unified Work list web part:
The Dynamics Unified Work list Web part displays the list of activities, alerts, workflow approvals, and workflow tasks.
It can be added using
a - Add a web part on EP page
b – Select Dynamics AX and Select ‘Unified work list’ webpart.

2 – AX Report web part:
The AX report web part is usually used to show reports on a role center.

3 – Quick Links web part
Quick links web part provides a quick access to EP pages, reports and forms. Usually we group Quick Links into two parts.
a - Form Links
b - Report Links
AX Client Form links can be accessed only from the Role Center. AX forms cannot be accessed from the EP.

4 – Activity web part
The activity web part can be used to see the information in terms of statistical data. The activity web part shows the information according the query defined for it.

Sunday, August 15, 2010

show container values in a hierarchy

There is an existing form 'SysConView' that is used to retrieve values from container to show on a form. Here is a simple example how to show a hierarchical structure on a form. conView method is used to display container values that exist in a Global class.

container myContainer;
container myChildContainer;

myContainer = [1, 2, 3, 4, 5];
myChildContainer = [6, 7, 8, 9, 10];
/* Add a child container in myContainer*/
myContainer += [myChildContainer];
myContainer += ['Sohail'];

conView(myContainer);

Monday, August 9, 2010

union vs unionAll

There is a difference between Union and UnionAll for UnionType enum. Here is the simple example of UnionAll and Union.

lets suppose we have two sets (tables).
A = {a, b, c, e, f}, B = {g, h, i, j, k, f, c}

In the example above you can see 'f' and 'c' are common in both sets.

So, If we take Union the result would be

A Union B = {a, b,c, e, f, g, h, i, j, k}

Here you can see nothing is repeated but if we take UnionAll it will repeat both in a result set.

A UnionAll B = {a,b,c,e,f,g,h,i,j,k,f,c}

Union in a Query

There are two methods to specify QueryType and UnionType in a Query and QueryBuildDataSource respectively. You can define the fields for each datasource that you want to include in a union query.
Given below is the simple example of Union query.

static void Job4(Args _args)
{
Query query = new Query();
QueryRun queryRun;
QueryBuildDataSource qbdsCustTable;
QueryBuildDataSource qbdsVendTable;
CustVendTable mapCustVendTable;


query.queryType(QueryType::Union);

qbdsCustTable = query.addDataSource(tablenum(CustTable));
qbdsCustTable.fields().clearFieldList();
qbdsCustTable.fields().addField(fieldnum(CustTable, AccountNum));
qbdsCustTable.fields().addField(fieldnum(CustTable, CustGroup));

qbdsVendTable = query.addDataSource(tablenum(VendTable));
//qbdsVendTable.unionType(UnionType::Union);
qbdsVendTable.unionType(UnionType::UnionAll);
qbdsVendTable.fields().clearFieldList();
qbdsVendTable.fields().addField(fieldnum(VendTable, AccountNum));
qbdsVendTable.fields().addField(fieldnum(VendTable, VendGroup));

queryRun = new QueryRun(query);

while(queryRun.next())
{
mapCustVendTable = queryRun.get(tablenum(CustTable));

info(strfmt('Account num = %1, Group = %2',mapCustVendTable.AccountNum, mapCustVendTable.GroupId));
}
}

Friday, July 23, 2010

periodic call in axapta

Suppose if at the client level i want to call method periodically I can achieve this task via setTimeOut method. This method will call the method specified in the argument after the provided interval.

Suppose.

if i write the line.

this.setTimeOut(identifierstr(method1), 5000, true)

The setTimeOut method will call method1 after the 5 second when the form is idle. If we want to call method1 with the no restrictions of idle then we don't need to provide true in the 3rd argument.

this.setTimeOut(identifierstr(method1), 5000)

Thursday, July 8, 2010

fetch selected data from grid

When you are on form and want to select the selected data from the grid, You can get from the table datasource from the form by using ****_ds.getFirst(true). It will provide the reference of the respective table buffer.
for example if i select some rows from the CustTable form and I want to show it in an infolog.

Use the following Code.

CustTable custTable1;


super();

for (custTable1 = custTable_ds.getFirst(true); custTable1; custTable1 = custTable_ds.getNext())
{
info(strfmt('%1', custTable1.AccountNum));
}



If you will not provide true in custTable_ds.getFirst(), it will fetch all the records.

so to fetch all records from the grid.

change the for loop line.

for (custTable1 = custTable_ds.getFirst(true); custTable1; custTable1 = custTable_ds.getNext())

Friday, June 25, 2010

sql query in ax

create a connection using connection object, don't need to assign any parameter here, this will help to run query. Create an statement object and assign a query in an execute method of it. Before that you need to create an SQlStatementExecutePermission that will allow to use SQL in a X++, then call assert that declares the calling code to invoke an API that is protected by a permission. after execute query a resultset is generated that you can access via .get(Datatype) method.

example is given below.



Connection con = new Connection();
Statement stmt = con.createStatement();
str sqlPassStr1;
ResultSet sqlres;
SqlStatementExecutePermission sqlStatementExecutePermission;
;

sqlPassStr1 = 'select ACCOUNTNUM, CUSTGROUP from CustTable';

sqlStatementExecutePermission = new SqlStatementExecutePermission(sqlPassStr1);
sqlStatementExecutePermission.assert();

sqlres = stmt.executeQuery( sqlPassStr1);
while(sqlres.next())
{
info(strfmt('%1 %2', sqlres.getString(1), sqlres.getString(2)));
}

Wednesday, June 23, 2010

add group by and fields selection in query

QueryBuildDataSource provides addSelectionField and addGroupByField to add fields and group on a query.

Further, what the aggregate function that you want to apply on a field you can provide it in a addSelectionField method that supports base enum SelectionField with some basic statistical operations. A sample code is given below.


Query q = new Query();
QueryBuildDataSource queryBuildDataSource;
QueryRun queryRun;
LedgerJournalTrans ledgerJournalTrans;

queryBuildDataSource = q.addDataSource(tablenum(LedgerJournalTrans));

queryBuildDataSource.addSelectionField(fieldnum(LedgerJournalTrans, JournalNum));
queryBuildDataSource.addSelectionField(fieldnum(LedgerJournalTrans,AmountCurDebit), SelectionField::Sum);
queryBuildDataSource.addSelectionField(fieldnum(LedgerJournalTrans, AmountCurCredit), SelectionField::Sum);
queryBuildDataSource.addGroupByField(fieldnum(LedgerJournalTrans, JournalNum));

queryRun = new QueryRun(q);

while(queryRun.next())
{
ledgerJournalTrans = queryRun.get(tablenum(LedgerJournalTrans));

info(strfmt('Journal Num = %1 Debit = %2 Credit = %3', ledgerJournalTrans.JournalNum, ledgerJournalTrans.AmountCurDebit, ledgerJournalTrans.AmountCurCredit));

}


An equivalent SQL query is given below.

select Journalnum, sum(AmountCurDebit), SUM(AmountCurCredit)
from LEDGERJOURNALTRANS
group by JOURNALNUM


Further you can filter the records using the addRange method in a QueryBuildDataSource class.

e.g.

queryBuildDataSource.addRange(fieldnum(LedgerJournalTrans, JournalNum)).value('000033_444')

the above statement filters the journal number '000033_444'.

Thursday, June 17, 2010

min and max in ax

Use minof and maxof to find minimum and maximum values of a table field. minof finds the minimum value of a specific field and maxof finds the maximum value of a specific field.

here's the example below.

LedgerTrans ledgerTrans;

select minof(TransDate) from ledgerTrans;

info(strfmt('%1', ledgertrans.TransDate));

select maxof(TransDate) from ledgerTrans;

info(strfmt('%1', ledgertrans.TransDate));


equivalent SQL queries for minimum and maximum date respectively.

select min(transdate) from LedgerTrans

select max(transdate) from LedgerTrans

add query range in a query object

First we need to find the datasource where we want to apply the range. Query.datasourceTable provides the reference of a querybuilddatasource. After getting the reference we can use the addRange method to add range and value in it.

Here's the demo. CustTable is a query object exist in AOT. No range is applied in a AOT query object, here the range is applied on a accountnum field of CustTable.

Query query = new Query(querystr(CustTable));
QueryRun queryRun;
QueryBuildDataSource queryBuildDataSource;
CustTable custTable;

//finding the reference of datasource.
queryBuildDataSource = query.dataSourceTable(tablenum(CustTable));

//adding range and providing the value for the range.
queryBuildDataSource.addRange(fieldnum(CustTable, AccountNum)).value('4000');

queryRun = new QueryRun(query);

while(queryRun.next())
{
custTable = queryRun.get(tablenum(CustTable));

info(strfmt('%1 ', custTable.AccountNum));

}

Thursday, May 27, 2010

create comma seperated file.

Use CommaIO file to create comma separated records or create CSV file.

create an instance of CommaIO and provide the operating mode.

These are the following modes, you can find it in FILE Macro under io_write.
'R' - Read
'W' - Write
'A' - Append
'T' - Translate
'B' - Binary

You need to assign the value of inrecorddelimeter.
and then use write method to write it. Multiple arguments can be passed in the write method of CommaIO.
CommaIO commaIO;
CustTable custTable;

//File name with the operating mode append.
commaIO = new CommaIO(@"C:\Cust.txt", 'A');
commaIO.inRecordDelimiter('\n');


while select CustTable
{
commaIO.write(custTable.AccountNum,custTable.AccountStatement, custTable.CashDisc);
}
Find the sample here.

read text file in axapta

TextBuffer is used to read the whole text file. Load file using textBuffer.fromFile and fetch the whole file string from the .getText

TextBuffer textBuffer;

textBuffer = new TextBuffer();
textBuffer.fromFile(@"C:\sohail.txt");
print textBuffer.getText();
pause;

Find the sample here.

create text file in axapta


Use BinData class to create a simple text file using axapta.
Firstly create an instance of a TextBuffer class and append text using textBuffer.AppendText. Pass it to binData what you want to write using binData.setStrData and then write using binData.saveFile.

Sample

BinData binData;
TextBuffer textBuffer;

textBuffer = new TextBuffer();
textBuffer.setText('This is a demo program');

binData = new BinData();
binData.setStrData(textBuffer.getText());
binData.saveFile(@"c:\sohail.txt");

Demo is attached here.