Friday, January 10, 2014

How to Restrict Multiple Time login of a same user

X++ Code to restrict user login multiple times in ax2009

Copy Paste the Following Code in startupPost method of info class in AOT

void startupPost()
{
// To restrict user login form second login
xSession session;
SysClientSessions SysClientSessions;
UserId currentUserId;
int counter;
;
currentUserId = curUserId();
if(currentUserId!="Admin")// Allow Admin User to login multiple time
{
while select SysClientSessions
where SysClientSessions.userId == currentUserId &&
SysClientSessions.Status == 1 // 1 : Login 0 : Logout
{
session = new xSession(SysClientSessions.SessionId, true);
if (session && session.userId())
{
counter++;
}
}
if(counter>=2)
{
Box::stop("Already Logged-in : The same user id can't log in twice.");
infolog.shutDown(true);
}
}
}

Please take backup of your application before copying code

Iace Technologies & Services...!!!

How to Read/Write an Excel file through X++ code


In This Post you will found two code sample
1.Write data in excel through X++ code.
2. Read from an Excel through X++ code


1.Write data in excel through X++ code.

static void thaAxapta_Write2Excel(Args _args)
{

InventTable inventTable;
SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
SysExcelCell cell;
int row;
;
application = SysExcelApplication::construct();
workbooks = application.workbooks();
workbook = workbooks.add();
worksheets = workbook.worksheets();
worksheet = worksheets.itemFromNum(1);
cells = worksheet.cells();
cells.range('A:A').numberFormat('@');
cell = cells.item(1,1);
cell.value("Item");
cell = cells.item(1,2);
cell.value("Name");
row = 1;
while select inventTable
{
    row++;
    cell = cells.item(row, 1);
    cell.value(inventTable.ItemId);
    cell = cells.item(row, 2);
    cell.value(inventTable.ItemName);
}
application.visible(true);
}


2. Read from an Excel through X++ code

static void theAxapta_ReadExcel(Args _args)
{

SysExcelApplication application;
SysExcelWorkbooks workbooks;
SysExcelWorkbook workbook;
SysExcelWorksheets worksheets;
SysExcelWorksheet worksheet;
SysExcelCells cells;
COMVariantType type;
int row;
ItemId itemid;
Name name;
FileName filename;
;
application = SysExcelApplication::construct();
workbooks = application.workbooks();
//specify the file path that you want to read
filename = "C:\\item.xls";
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();
do
{
    row++;
    itemId = cells.item(row, 1).value().bStr();
    name = cells.item(row, 2).value().bStr();
    info(strfmt('%1 - %2', itemId, name));
    type = cells.item(row+1, 1).value().variantType();
}
while (type != COMVariantType::VT_EMPTY);
application.quit();
}




Iace technologies & Services...!!!

How to Create Number Sequence In Ax2012

Simple Steps To Create Number Sequence In Ax2012



It is same as like as we know in Ax2009 but small steps is added in AX2012.don't worry just follow the below steps simply we will get number sequence in AX2012.

We will Take a EDT name as "Car Id" and create in number sequence.For that first we should select a module for new number sequence for example project module.

Steps

1. Create an edt : CarId .
AOT >> Extended Data Types >> New >> Properties >> Name >> Car Id.



2. Write a code on lode module() on NumberSeqModuleProject

{
     datatype.parmDatatypeId(extendedTypeNum(Car Id));
     datatype.parmReferenceHelp(literalStr("@SYS334483"));
     datatype.parmWizardIsManual(NoYes::No);
     datatype.parmWizardIsChangeDownAllowed(NoYes::No);
     datatype.parmWizardIsChangeUpAllowed(NoYes::No);
     datatype.parmWizardHighest(999999);
     datatype.parmSortField(20);
     datatype.addParameterType(NumberSeqParameterType::DataArea, true,        false);
     this.create(datatype);
}

3. Write a method on Projparameters Table

    client server static NumberSequenceReference numRefcarId()
     {
      return NumberSeqReference::findReference(extendedTypeNum(car Id));
     }


4. Write a job and run that

static void Carid(Args _args)
{
    NumberSeqModuleProject  NumberSeqModuleProject = new NumberSeqModuleProject();
    ;
    NumberSeqModuleProject.load();
}


5. Then run the wizard
Organization Administration >> CommonForms >> Numbersequences>>Numbersequences>> Generate >> run the wizard.

6. Now we have to check the number sequence  is correctly working  for that write a job:

static void number(Args _args)
{
    NumberSeq  numberSeq;
    CarId num;
    ;
    numberSeq = NumberSeq::newGetNum(ProjParameters::numRefcarId());
    num = numberSeq.num();
    info(num);
}

7. Now we want that Number Sequence in form level(Car Table):

Declare the number sequence On Form Declaration:
 
public class FormRun extends ObjectRun
{
    NumberSeqFormHandler numberSeqFormHandler;

}

 8. Write the NumberSeqFormHandler() in form methods node.

NumberSeqFormHandler numberSeqFormHandler()
{
    if (!numberSeqFormHandler)
    {
        numberSeqFormHandler = NumberSeqFormHandler::newForm(ProjParameters::numRefcarId      ().NumberSequenceId,
                                                             element,
                                                             CarTable_DS,
                                                             fieldNum(CarTable, Car Id)
                                                            );
    }
    return numberSeqFormHandler;
}
9.Write the close() on the form methods node.

void close()
{
    if (numberSeqFormHandler)
    {
        numberSeqFormHandler.formMethodClose();
    }
    super();
}

10. Then final add the below methods on data source methods node
Create()

void create(boolean append = false,
            boolean extern = false)  // If created externally
{
    element.numberSeqFormHandler().formMethodDataSourceCreatePre();

    super(append);

    if (!extern)
    {
        element.numberSeqFormHandler().formMethodDataSourceCreate(true);
    }
}

Delete()

public void delete()
{
    element.numberSeqFormHandler().formMethodDataSourceDelete();
    super();
}

Write()

public void write()
{
    super();
    element.numberSeqFormHandler().formMethodDataSourceWrite();
}

Validate Write()

public boolean validateWrite()
{
    boolean         ret;
    ret = super();
    ret = element.numberSeqFormHandler().formMethodDataSourceValidateWrite(ret) && ret;
    if (ret)
    {
        CarTable.validateWrite();
    }
    return ret;
}

Link Active()

public void linkActive()
{
    ;
    element.numberSeqFormHandler().formMethodDataSourceLinkActive();
    super();
}
Now our numberseqence is generated .

*** Set the field or Tabpage Allowedit property to No.
***Check the continues on wizard.




Inventory Transfer Journal through X++ code


Here is a small code for Invent Transfer journal Posting...


static void CreateTransferJournal(Args _args)
{
InventJournalTable inventJournalTable;
InventJournalTrans inventJournalTrans;
InventJournalCheckPost inventJournalCheckPost;
NumberSeq num;
boolean _throwserror=true;
boolean _showinforesult=true;
InventDim frominventDim,ToinventDim;
;
ttsbegin; 

inventJournalTable.clear();
num = new NumberSeq();
num = NumberSeq::newGetNum
(InventParameters::numRefTransferId());
inventJournalTable.initFromInventJournalName(InventJournalName::find
(InventParameters::find().TransferJournalNameId));
inventJournalTable.Description = “Inventory Transfer Journal”;
inventJournalTable.SystemBlocked = true;
inventJournalTable.insert(); 

inventJournalTrans.clear();
inventJournalTrans.initFromInventJournalTable(inventJournalTable);
inventJournalTrans.ItemId = “xxxxxx”;
frominventDim.InventLocationId=”xx”;
frominventDim.inventSiteId =”xx”;
ToinventDim.InventLocationId = “xxxx”;
ToinventDim.InventSiteId = “xx”;
ToinventDim = InventDim::findOrCreate(ToinventDim); 

frominventDim = InventDim::findOrCreate(frominventDim); 
inventJournalTrans.InventDimId = frominventDim.inventDimId;
inventJournalTrans.initFromInventTable(InventTable::find(“1101″));
inventJournalTrans.Qty = 10;
inventJournalTrans.ToInventDimId = ToinventDim.inventDimId;
inventJournalTrans.TransDate = SystemDateget();
inventJournalTrans.insert();
 

inventJournalCheckPost =
InventJournalCheckPost::newJournalCheckPost
(JournalCheckpostType::Post,inventJournalTable);
inventJournalCheckPost.parmThrowCheckFailed(_throwserror);
inventJournalCheckPost.parmShowInfoResult(_showinforesult);
inventJournalCheckPost.run(); 

inventJournalTable.SystemBlocked = false;
inventJournalTable.update(); 

ttscommit;
}





Iace Technologies & Services.....!!!

Extended Query Range in Dynamics AX


Extended Query Range in Dynamics AX

Many developers often stuck while they try to apply range to the dynamics ax query to filter records based on some conditions. We will try to explore the query ranges in this article and will try to play with some examples to learn how we can apply query ranges using x++ to the Dynamics AX queries.
Lets discussed different cases...


Query                          q;
QueryBuildDataSource           qbd;
QueryBuildRange                qbr;
q = new Query();
qbd = q.addDataSource(TableNum(CustTable));
qbr = qbd.addRange(FieldNum(CustTable, AccountNum));
qbr.value('4005, 4006');


The above x++ code will generate following SQL statement.

"SELECT * FROM CustTable WHERE ((AccountNum = N'4005' OR AccountNum = N'4006'))"

qbr.value(strFmt('((AccountNum == "%1")
(AccountNum == "%2"))',
QueryValue('4005'),
QueryValue('4006')));

The above x++ code will generate following SQL statement.

"SELECT * FROM CustTable WHERE ((((AccountNum == "4005") || (AccountNum == "4006"))))"

Let's say we want to apply "OR" range on a DIFFERENT fields
You can use the following x++ code to apply the OR range to the different fields


qbr = qbd.addRange(FieldNum(CustTable, DataAreaId));
qbr.value(strFmt('((%1 == "4000")
(%2 == "The Bulb"))',
fieldStr(CustTable, AccountNum),
fieldStr(CustTable, Name)));

The above code will generate following sql statement

"SELECT * FROM CustTable WHERE ((((AccountNum == "4000") || (Name == "The Axapta"))))"

Note: We have used DataAreaId field above to apply the range however, the actual range is on AccountName and AccountNum field. This means when you use range value expressions you can use any field to obtain range object and use it to insert your range in the query. Using DataAreaId field for this purpose is the best practice.


Iace Technologies & Services...!!

Print PDF files from AX X++ code

Print External PDF file from AX 

This job illustrates how we can print an external PDF file to a printer chosen in AX through X++ code. Here a code sample (X++ job) to do this.


static void theAxapta_pdfprint(Args _args)
{ 
    PrintJobSettings    printJobSettings = new PrintJobSettings(); 
    Dialog              dialog = new Dialog(); 
    DialogField         dialogFileName; 
    str                 adobeExe; 
    str                 adobeParm; 
;
    dialogFilename  = dialog.addField(typeid(FilenameOpen));

    if (dialog.run()) 
    {     
        printJobSettings.printerSettings('SysPrintForm');     
        adobeExe = WinAPI::findExecutable(dialogFileName.value());
       
        adobeParm = strFmt(' /t "%1" "%2" "%3" "%4"',
                           dialogFileName.value(),
                           printJobSettings.printerPrinterName(),
                           printJobSettings.printerDriverName(),
                           printJobSettings.printerPortName());

        winAPI::shellExecute(adobeExe,  adobeParm); 
    }
}



Iace Technologies & Services....!!!

Join Two Tables at Run Time


static void theAxapta_JoinTables(Args _args)
{
    Query                     query;
    QueryBuildDataSource      queryBuildDataSource1,
                              queryBuildDataSource2;
    QueryBuildRange           queryBuildRange;
    QueryBuildLink            queryBuildLink;
    ;
    // Create a new query object
    query = new Query();
    // Add the first data source to the query
    queryBuildDataSource1 = query.addDataSource(tablenum(CarTable));
    // Add the range to this first data source
    queryBuildRange = queryBuildDataSource1.addRange(fieldnum(CarTable, ModelYear));
    // Add the second datasource to the first data source
    queryBuildDataSource2 =   queryBuildDataSource1.addDataSource(tablen
    um(RentalTable));
    // Add the link from the child data source to the 
    //parent data 
    source
    queryBuildLink = queryBuildDataSource2.addLink(fieldnum(CarTable, 
    CarId),fieldnum(RentalTable, CarId));
}


Note:
This process (query through X++ code) is very similar to create a query directly through AOT node.
AOT -> Query -> Right Click -> New Query
I would suggest first create a query through query node, than go for this code.


This posting is provided "Iace Technologies & Services"...!!!

How to use Complex Query Ranges in Dynamics AX


Adding a query with athe Datasource to query.

query = new Query();
dsInventTable = query.addDataSource(tableNum(InventTable));
// Add our range
queryBuildRange = dsInventTable.addRange(fieldNum(InventTable, DataAreaId));

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)));

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")));



This posting is provided "Iace Technologies & Services"...!!!

AX2012 R2 RunAs and Global::RunClassMethodIL

Just a quick note on using RunAs in AX2012: The static method being called by RunAs should have a container parameter in the method declaration. Otherwise, system will complain that the static method was not found. So:
?
// This would fail with static method not found error.
public static void methodWithoutParm()
{
}
// This would work!
public static void methodWithContainerParm(container _c)
{
}
In fact, the same can be said to Global::RunClassMethodIL. However, the error throw by Global::RunClassMethodIL is more helpful. It'll complain that the parameter passed into the static method is incorrect. Seeing that a third parameter of type container is mandatory for Global::RunClassMethodIL, it's easier to get the idea to try adding the container parameter in the target static method. =]


This posting is provided "Iace Technologies & Services" .