Skip to main content

Posts

Showing posts from April, 2012

Connect External Data Base in Dynamics Ax 2009

This is the example to connect the External Database to Ax void ODBCConnection() { LoginProperty LP = new LoginProperty(); OdbcConnection myConnection; TableName TableName; Statement myStatement; ResultSet myResult; #define.Constring(“DSN=DSNNAME;UID=USERID;PWD=PASSWORD“) try { LP.setOther(#Constring); myConnection = new OdbcConnection(LP); } catch { info(“Check username/password.”); return; } myStatement = myConnection.createStatement(); new SqlStatementExecutePermission(“SELECT * from TableNamewhere bImportflag = 0″).assert(); myResult = myStatement.executeQuery(“SELECT * from TableNamewhere bImportflag = 0″); CodeAccessPermission::revertAssert(); while (myResult.next()) { TableName.nMember = Member; TableName.tMemberName = MembName; TableName.tMemberAddress = Address; TableName.tRescountry = Country; TableName.tRes

Create LookUps Using X++

public void lookup() { //super(); // Added by Vasanth Arivali // Declaration Query LookupQuery = new Query(); QueryBuildDataSource LookupQueryBuildDataSource; QueryBuildRange LookupQueryBuildRange; SysTableLookup CustomSysTableLookup = SysTableLookup::newParameters(tableNum(InventTable), this); ; // Add fields that you want in Lookups CustomSysTableLookup.addLookupField(fieldNum(InventTable, ItemId)); CustomSysTableLookup.addLookupField(fieldNum(InventTable,ItemName)); CustomSysTableLookup.addLookupField(fieldNum(InventTable,ItemGroupId)); CustomSysTableLookup.addLookupField(fieldNum(InventTable,NameAlias)); CustomSysTableLookup.addLookupField(fieldNum(InventTable,ItemType)); CustomSysTableLookup.addLookupField(fieldNum(InventTable,DimGroupId)); // Add DataSource, Range and Value LookupQueryBuildDataSource =LookupQuery.addDataSource(tableNum(InventTable)); LookupQueryBuildRange=LookupQueryBuildDataSource.addRange(fieldNum(InventTable,ItemVisibili

Using AOT Query Object in X++ Code

Steps: 1) Create a AOT Query Object as your requirement. 2) Create a Job and paste the below code to check the Query Object. static void ExecuteAOTQuery(Args _args) { QueryRun queryRun; Counter totalRecords; ; queryRun = new QueryRun(queryStr(CreatedAOTQueryName)); if (queryRun.prompt()) { while (queryRun.next()) { totalRecords++; } } info(strFmt(“Total Records : %1”, totalRecords)); }

Dynamic Query Using Aggregative Functions and Joins

Here i written the code to use the Aggregate functions and Joins in Dynamic Query in spite of using normal Select statement in Ax 2009 Normal Select Statement: while select sum(qty) from inventTrans where inventTrans.ItemId ==“OL-2500” join inventDimgroup by inventBatchId where inventDim.InventDimId == inventTrans.InventDimId { // Our Code Here } Dynamic Query: static void Vasanth_Query_Eg1(Args _args) { Query query; QueryBuildDataSource queryBuildDataSource; QueryBuildRange queryBuildRange; QueryRun queryRun; Qty total; InventTrans inventTrans; ; query = new Query(); queryBuildDataSource = query.addDataSource(tableNum(InventTrans)); queryBuildDataSource.addSelectionField(fieldNum(InventTrans,Qty),SelectionField::Sum); queryBuildDataSource.orderMode(OrderMode::GroupBy); queryBuildRange = queryBuildDataSource.addRange(fieldNum(InventTrans,ItemId)); queryBuildDataSource = queryBuildDataSource.a

Using Regular Expression in Ax 2009

Here i posted a small job , to explain how we use regular expressin in Axapta. Try it. static void RegularExpression_Test() { int nameLength,myStringLength; str myname = “Vasanth”; str myString = “1234″; str formatString , formatString1; System.Text.RegularExpressions.Regex regEx; System.Text.RegularExpressions.Regex regEx1; System.Text.RegularExpressions.Match regMatch; InteropPermission permission = new InteropPermission(InteropKind::ClrInterop); boolean retVal, retVal1; ; nameLength = strLen(myname); myStringLength = strLen(myString); formatString = strfmt(@”^[0-9]{%1}”, myStringLength); formatString1 = strfmt(@”^[a-zA-Z ]{%1}”, nameLength); permission.assert(); //BP Deviation documented regEx = new System.Text.RegularExpression.Regex(formatString); regEx1 = new System.Text.RegularExpression.Regex(formatString1); regMatch = regEx.Match(myString); retVal = regMatch.get_Success(); print retVal; // Returns True; regMatch = regEx1.Match(myname); retVal1 = re

Go To Main Table Functionality in Axapta

We all know about “Go To Main Table” Option in our Axapta Forms and Tables. Here I wrote one sample for how to get that functionality in our forms or table. This is done by three ways: 1) By EDT Relations 2) By using JumpRef method 3) By using FormRef property in Table EDT Relations: If you use an EDT in tables which have relation with some other table fileds, that time you can able to navigate the main table or main form. FormRef Property: Select the Table and go to properties and select the required form in the FormRef property. JumpRef method: If you are not having that option, simply write a override the JumpRef method in a field of DataSource or in a Form Control. Here i show you a sample jumpRef method code: public void jumpRef() { Args args; MenuFunction menuFunction; ; args = new Args(); menuFunction = new MenuFunction(menuitemDisplayStr(“FormName”), MenuItemType::Display); args = new Args(menuFunction.object()); args.caller(element); args.recor

Argument Passing between Forms in Dynamics Ax 2009

Here a sample code to pass argument to one form to another form and using of Args() class. Steps: 1) Create two Forms named FormA and FormB 2)Use the EmplTable as the Datasource of both forms 3)Design FormA with one Grid and add 4 data fields to the Grid(EmplId,DEL_Name,Grade,EmplStatus…..) 4)Assign the datasource for the grid and the data fields 5)Add a Button in FormA 6)Override the Clicked() method and write the below code: void Clicked() { Args _args; FormRun _formRun; EmplId _empId; ; _empId = EmplTable.EmplId; // Selected employee id in the Grid is assigned to the variable which is pass to the next form _args = new Args(); // creating a object for args class _args.name(formstr(VA_FormB)); // Form Menuitem _args.caller(this); // Form Caller(Current Form is mentioned as this) _args.parm(_empId); // Employee Number is passed to next form[but parm() is not a best practise] _args.record(EmplTable); // Table name is passed _formRun = ClassFactory.formRunClass(_args); //ne

Axapta file extensions

Axapta uses quite a number of file extensions for the files that are installed as part of Axapta. Even though at first sight, people will be bewildered with these te(o)ns acronyms/extensions, it follows a very good naming convention and once it’s understood, it is very easy to follow these file names and extensions. First Letter: owner of file: A Application K Kernel Second Letter: contents of file: L Label O Object (as is AOT) T Text (only TKD) D Developer Documentation H Online Help Third Letter: Type of file. D Data I Index C Cache T Temporary So a file with extension .ald is ApplicationLabelData file. Thanks to Michael Fruergaard Pontoppidan (who came out this table) and Tao Wang (who provided this info to me)

Passing parameter from a form to a report

I figured out a sligtly different solution that works. On the Button Clicked method: void clicked() { Args args = new args(); ReportRun reportRun; ; args.parm(SMAServiceOrderTable.ServiceOrderId); args.name(reportstr(GAB_ServiceOrder_NO)); reportRun = classFactory.reportRunClass(args); reportRun.init(); reportrun.run(); super(); } And then on the init method on the report; public void init() { ; try { if(element.args().parm()) { this.query().dataSourceTable(tablenum(SMAServiceOrderTable)) .addRange(fieldnum(SMAServiceOrderTable,ServiceOrderID)).value(element.args().parm()); this.query().userUpdate(false); this.query().interactive(false); super(); } } catch(exception::Error) { info("Error in init method"); } }

Passing parameters from Managed code to X++ in dataset

In the user control code behing add an event handler to the CreatingDataSetRun event on the AxDataSource control protected void Page_Init(object sender, EventArgs e) { this.AxDataSource1.CreatingDataSetRun += new EventHandler (AxDataSource1_CreatingDataSetRun); } Set the param value to the event arugments void AxDataSource1_CreatingDataSetRun(object sender, CreatingDataSetRunEventArgs e) { e.DataSetRunArgs.parm = "4000"; } In AOT override or add method in the data set and use element.args().parm() to received the paramter public void executeQuery() { QueryBuildRange custRange; ; custRange = SysQuery::findOrCreateRange(this.query().dataSourceNo(1), fieldnum(CustTable, AccountNum)); custRange.value(element.args().parm()); super(); } You can also pass an Enum. For example void AxDataSource1_CreatingDataSetRun(object sender, CreatingDataSetRunEventArgs e) { e.DataSetRunArgs.parmEnumType = EnumMetadata.EnumNum(this.AxSession, "EPFo

X++ Server Threads

You can create threads in X++ to perform tasks in the background. Here is a vey simple class that demonstrates the basics. class ThreadDemo { static server void main() { Thread t; ; new ExecutePermission().assert(); //BP Deviation Documented t = new Thread(); t.run(classnum(ThreadDemo), staticmethodstr(ThreadDemo, run)); } static server void run(Thread t) { AsciiIo ai; // Change this to some path that your server will have access to str fileName = '\\t\\HelloWorld.txt'; ; sleep(5000); new FileIOPermission(fileName, 'w').assert(); //BP Deviation Documented ai = new AsciiIo(fileName, 'w'); ai.write('Hello World!'); } } I use the directory d:\t for temporary files. You will have to either create the directory or change the example to point to some other directory. In either case make sure that SYSTEM has

Creating a report in X++ code and running

static void MakeReportJob(Args _args) { #AOT str reportName = 'aaMakeReport'; tableid custTableId = tablenum(CustTable); TreeNode reportNode = TreeNode::findNode(#ReportsPath); Report areport; ReportDesign design; ReportAutoDesignSpecs specs; ReportSection section; ReportRun run; ; // Delete the report if it already exists areport = reportNode.AOTfindChild(reportName); if (areport) areport.AOTdelete(); // Build the report areport = reportNode.AOTadd(reportName); areport.query().addDataSource(custTableId); design = areport.addDesign('Design'); specs = design.autoDesignSpecs(); section = specs.addSection(ReportBlockType::Body, custTableId); section.addControl(custTableId, fieldnum(CustTable, AccountNum)); section.addControl(custTableId, fieldnum(CustTable, Name)); // Now the report will not prompt for user input areport.interactive(false); areport.query().interactive

Args and the Axapta Construction Pattern

When looking through Axapta code you will see a lot of references to the type Args. This type is used as a general method for sharing construction parameters. It works well because in the Axapta usage pattern because 1.the typical number of parameters is small 2.the types of parameters used is very similar 3.construction of the main objects often entails constructing multiple collaborating objects that need access to the same shared constructor arguments. In traditional OO code each object will have one or more constructors. These constructors would have different numbers of arguments and types, as required. For example, a class representing a form might have a default constructor that would simply show all the items in the table. It could also have a constructor that accepted a string that was used to highlight the row with a matching primary key, newSelect(str key). Or one that filtered all the values to match the provided range, newMinMax(str smin, str smax). Side note:

Passing values between forms

The code of button click event of FormA which calls FormB and passes some parameters to that form. void clicked() { // Args class is usually used in Axapta for passing parameters between forms Args args; FormRun formRun; // Our custom made class for passing complex set of parameters FormBParams formBParams = new FormBParams(); Array items = new Array( Types::String ); int i; ; args = new args(); // Our values which we want to pass to FormB // If we want pass just simple string we can use 'parm' method of 'Args' class args.parm( strValue.text() ); // We also can pass enum value to FormB args.parmEnum( NoYesEnumValue.selection() ); args.parmEnumType( EnumNum( NoYes ) ); // and also can pass a cursor pointing to some record (in our case it is EmplTable ) args.record( EmplTable ); // If we want pass more complex set of parameters we can develop our own class

Microsoft Dynamics AX 2009 : The MorphX Tools - Debugger

Like most development environments, MorphX features a debugger. The debugger is a stand-alone application, not part of the Dynamics AX shell like the rest of the tools . As a stand-alone application, the debugger allows you to debug X++ in any of the Dynamics AX components in the following list:• Microsoft Dynamics AX client • Application Object Server (AOS) • Enterprise Portal • Business Connector Using the Debugger For the debugger to start, a breakpoint must be hit during execution of X++ code. You set breakpoints by using the X++ code editor in the Microsoft Dynamics AX client. The debugger starts automatically when any component hits a breakpoint. You must enable debugging for each component as follows: • In the Microsoft Dynamics AX client, click the Microsoft Dynamics AX drop-down menu, point to Tools and then Options. On the Development tab, select When Breakpoint in the Debug Mode list. • For the AOS, open the Microsoft Dynamics AX Server Configuration utility under Start\Admi

"Like" with "AND" Operator through Query in Dynamics Ax

static void RAJ_AndLikeOperator(Args _args) Query query = new Query(); QueryRun queryRun; InventTable inventTable; ; query.addDataSource(tableNum(InventTable)).addRange(fieldNum(InventTable, ItemId)).value("100*, 110*, 120*"); queryRun = new QueryRun(query); while(queryRun.next()) inventTable = queryRun.get(tableNum(InventTable)); info(inventTable.ItemId); } }

Conversion of UTCDateTime in Dynamics AX 2009

public static void UTCDateTimeConversion() { UTCDateTime dateTime; date tmpDate; TimeOfDay tmpTime; CustTable cTable = CustTable::find("1101"); ; // Extracted date & Time from UTCDateTime datatype to individulal variable dateTime = cTable.createdDateTime; tmpDate = DateTimeUtil::date(dateTime); tmpTime = DateTimeUtil::time(DateTimeUtil::applyTimeZoneOffset(dateTime, DateTimeUtil::getUserPreferredTimeZone())); info(strfmt("Date: %1 and Time: %2.", tmpDate, time2str(tmpTime,1,2))); // assign UTCDateTime varriable by using two individual field dateTime = DateTimeUtil::newDateTime(12\05\2010, timeNow()); info(strfmt("UTCDateTime: %1.",dateTime)); }

UTCDateTime field Query Range by Date in Dynamics Ax

static void RAJ_UTCDateTimeQueryRange(Args _args) { Query q = new Query(); QueryRun qr; QueryBuildDataSource qbds; CustTable custTable; Transdate tmpCreatedDate = 02\02\2010; // dd-mm-yyyy ; qbds = q.addDataSource(tableNum(CustTable)); qbds.addRange(fieldNum(CustTable, CreatedDateTime)).value(date2StrUsr(tmpCreatedDate)); qr = new QueryRun(q); while(qr.next()) { custTable = qr.get(tableNum(CustTable)); info(strfmt("Account Num: %1, Name: %2", custTable.AccountNum, custTable.Name)); } }

Get the active company in AX 2009 - curExt()

Use the curExt() function to get the active company in AX; static void curExtExample(Args _arg) { str CompanyId; ; CompanyId = curExt(); Info(CompanyId); } You would also use the following with the same results. However, the above is much more elegant. static void curExtExample(Args _arg) { str CompanyId; ; CompanyId = CompanyInfo::Find().DataAreaId; Info(CompanyId); } Take Care!

Create loop from an AX form DataSet - Ax 2009

Sometimes we need to loop through values at the form level. The following code loops (for loop) the SalesParmTable in the CloseOk() Form method.                 //Create Lines         for (localSalesParmTable = salesParmTable_ds.getFirst();               localSalesParmTable;               localSalesParmTable = salesParmTable_ds.getNext())         {               ....Implementation....         }

AX 2009 Workflow - Run batch jobs through a Job

When working with Workflows, sometimes  have encountered a situation where my workflow item just don't run. This might be due to a problem on the Batch Server. To test (run) the workflow mimicking the batch server we can write the following job. static void workflowJobs(Args _args) {     SysWorkflowMessageQueueManager  queueManager;     WorkflowWorkItemDueDateJob      workItemDueDateJob;     ;     queueManager = SysWorkflowMessageQueueManager::construct();     queueManager.run();     workItemDueDateJob = new WorkflowWorkItemDueDateJob();     workItemDueDateJob.run(); } Another alternative is to go to AOT > Forms > Tutorial_WorkflowProcessor and click the start button.

Save a Microsoft Dynamics AX 2009 report to a PDF file (First Part)

The following code saves an Axapta report to a PDF file. This is the first article of 3. The next article will show how to save the file into a network share and pass a Sales Order dynamically, and the last part will be about attaching the PDF to an Outlook instance and create a dynamic subject. So, the titles of the three articles will be the same foe exception of the text in parenthesis. In my case, I'm having a lot of problems saving the file to a network file and then to attach it to Outlook. The code below saves the report to a local palce in your computer. static void Job10(Args _args) {    custConfirmJour     custInvoiceJour;   SalesFormLetter     salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation,  false);    PrintJobSettings    printJobSettings = new PrintJobSettings();    Args                args = new Args();    boolean             prompt = false;    boolean             printIt = true;    ;     printJobSettings.setTarget(PrintMedium::File);     pri

Set a Date Value to a Date Filed in AX 2009 with X++

I was faced with a requirement that I needed to set a date value to a custom date Filed in AX 2009 with X++, with the Purch Order Creation Date. I knew that the following could work: ... FormControl control; ; control = element.design().controlName('PurchTable_OrderDate')); control.Text = DateTimeUtil::ToStr(purchTable_ds.Object(fieldnum(PurchTable, CretationDateTime); ... However, I wanted to create a solution that would not be so dependant on the Form object as this can bring headaches when upgrading. Therefore, I decided to do it at the data source level as follow: purchTable_ds.object(fieldnum(PurchTable, OrderDate)).setValue(DateTimeUtil::date(purchTable.createdDateTime)); The above code is far more efficient and it needs to be set either in the Data Source (PurchTable) of the PurchTable form Init() or Active() method.

Pass the Data Source records to Class or pass the multiple records to class

http://axhelper.blogspot.com/ 1. Add a action MenuItem in a form as a MenuItemButton. 2.Take a clicked method() void clicked() { MenuFunction mf;Pass the Data Source records to Class or pass the multiple records to class args args = new Args(); ; args.record(Table1); mf = new menufunction(identifierstr(classParmData), MenuItemType::Action); mf.run(args); } 3.Take a class class ClassParmData { Table1 tb1;// table variable declaration } —- public static void main(Args args) { ClassParmData _ClassParmData; Table1 _table1; FormDataSource fds; ; if(args.record().TableId == tablenum(Table1)) _table1 = args.record(); // assigning the selected record fds = _table1.dataSource();// getting the datasource _ClassParmData = new ClassParmData(fds); //passing the datasource records to New() method /*_table1 = fds.getFirst(); // can loop all the record here also while(_table1)//fds.getNext()) { info(strfmt(_table1.Field1)); _table1 = fds.getNext(); }*/ } —– void new(FormDataSource fdst) // receving th

AX Data Export in XML file

static void XMLExport(Args _args) { XmlDocument doc; XmlElement nodeXml; XmlElement nodeTable; XmlElement nodeAccount; XmlElement nodeName; XmlElement nodeItemName; XmlElement nodeModelGroup; XmlElement nodeDimGroup; InventTable inventTable; #define.filename(‘C:\\Users\\varun.garg\\Desktop\\test.xml’) ; doc = XmlDocument::newBlank(); nodeXml = doc.createElement(‘xml’); doc.appendChild(nodeXml); while select inventTable { nodeTable = doc.createElement(tablestr(InventTable)); nodeTable.setAttribute( fieldstr(InventTable, RecId), int642str(inventTable.RecId)); nodeXml.appendChild(nodeTable); nodeAccount = doc.createElement( fieldstr(InventTable, ItemId)); nodeAccount.appendChild( doc.createTextNode(inventTable.ItemId)); nodeTable.appendChild(nodeAccount); nodeName = doc.createEleme

Create Movement Journal And Post from excel

static void MovementJournalImportExcel(Args _args) {      InventJournalTrans         inventJournalTrans;      InventDim                  inventDim;      InventJournalTable         inventJournalTable;      InventJournalCheckPost     journalCheckPost;      InventJournalId            journalId;      journalTableData           journalTabledata;      InventBatch                inventBatch;      InventBatch                localInventBatch;      NumberSeq                  numberSeq;      NumberSequenceReference    numberSequenceReference;      InventSerial               inventSerial;      InventSerial               localinventSerial;      int   j,countno=0,i,k;      real    Scarp;      FilenameOpen      filename;      Sysexcelapplication excelapp=sysexcelapplication::construct();      sysexcelworksheet excelworksheet;      sysexcelrange excelrange;      sysexcelcells excelcells;     // comvariant cellvalue=new comvariant();     ;     // Creating Journal Header    

How to display image in each line of a grid

Create ImageList in form.init(): imageList = new ImageList(ImageList::smallIconWidth(), ImageList::smallIconHeight(); Image image = new Image(); ; image.loadImage(filename) imageList.add(image); // … image.loadImage(filename-n) imageList.add(image); ImageList must be declared in ClassDEclaration section. Set AutoDaclaration property of Window field in the Grid to “Yes”. Set ImageList for the window field in the method init() of form: MyWindow.imageList(imageList); On the Table which you are using on the form create the display method. Something like this: display int status() { if(this.amount > 10) return 5; // 5th image from image list else return 6; } Set properties DataSource and DataMethod for your window control: DataSource = DataMethod = status

How to change company from X++

The changeCompany statement is used to alter the database settings to another (separate) company. The syntax of the statement is: changeCompany ( Expression ) Statement Here is the code static void main() { CustTable custTable; ; // Assume that you are running in company ‘aaa’. changeCompany(‘bbb’) // Default company is now ‘bbb’. { custTable = null; while select custTable { // custTable is now selected in company ‘bbb’. } } // Default company is again set back to ‘aaa’. changeCompany(‘ccc’) // Default company is now ‘ccc’. { // Clear custTable to let the select work // on the new default company. custTable = null; while select custTable { // custTable is now selected in company ‘ccc’. } } // Default company is again ‘aaa’. }

How to insert/remove image in a table

If you need to import an image from your desktop to a table in dynamics AX, then you need a field which extendedDataType is bitmap and here is a code that you can write in the clicked method of your form void clicked() { FilenameFilter filter = ['Image Files','*.bmp;*.jpg;*.gif;*.jpeg']; BinData binData = new BinData(); str extention, path, nameOfFile; super(); imageFilePathName = WinAPI::getOpenFileName(element.hWnd(),filter,”, “@SYS53008″, ”,”); if (imageFilePathname && WinAPI::fileExists(imageFilePathName)) { [path, nameOfFile, extention] = fileNameSplit(imageFilePathName); if (extention == ‘.bmp’ || extention == ‘.jpg’ || extention == ‘.gif’ || extention == ‘.jpeg’) { binData.loadFile(imageFilePathName); imageContainer = binData.getData(); element.showLogo(); Thy_InventSymbolsIcons.Image = imageContainer; } else { throw error(“@SYS89176″); } } element.Query_cntRecords(); } then if you want to remove an image : void clicked() { super(); element.delete(); } an

How to filter displaying data in a grid according to a parameter passed from another form

You need to override the init method of the data source of your form following this way for example: public void init() { SysDimension SysDimension; ; super(); if( element.args().parm()) { SysQuery::findOrCreateRange(this.query().dataSourceTable(tablenum(Dimensions)), fieldnum(Dimensions, DimensionCode)).value(queryValue(element.args().parm())); } else { SysQuery::findOrCreateRange(this.query().dataSourceTable(tablenum(Dimensions)), fieldnum(Dimensions, DimensionCode)).value(queryValue(SysDimension::Department)); } }