Jun 6, 2010

..................................................................................................................................................................

X++ code to write data to Event viewer

X++ code to write data to Event viewer.
Usually it will be difficult to monitor/debug Batch Jobs running on server . For e.g if something goes wrong than we can't find out why.
So we can make use of Eventviewer instead of infolog and monitor the status by checking the eventviewr .
Following Job illustrates how to write to event viewer.

static void Dev_Write2EventViewer(Args _args)
{
System.Diagnostics.EventLog eventlog;
Str logSource;
Str logName;
;

logSource = "Dynamics Ax";
logName = "Dynamics Ax Log";

// check if the log already exists
if(!System.Diagnostics.EventLog::SourceExists(logSource))
{
// create new log
System.Diagnostics.EventLog::CreateEventSource(logSource, logName);
}

eventlog = new System.Diagnostics.EventLog();
eventlog.set_Source(logSource);


eventlog.WriteEntry("Info Message");
eventlog.WriteEntry("Warning Message" , System.Diagnostics.EventLogEntryType::Warning);
eventlog.WriteEntry("Error! Please check the stack trace below. \n\n" +
con2str(xSession::xppCallStack()), System.Diagnostics.EventLogEntryType::Error);

info("Check the event viewer!");


}

Code to Display Expiry date Message at Status Bar.

Code to Display Expiry date Message at Status Bar.
Following job illustrates how you can display custom message in the status bar next to alerts. ( Mean , At bottom where you will find company,layer,currency info).

static void Dev_setStatusLineText(Args _args)
{
str msg;
;

msg = "Expiry date :"+date2str(xinfo::expireDate(),123,2,4,2,4,2);

// Force the text to be shown
xUserInfo::statusLine_CustomText(true);
infolog.writeCustomStatlineItem(msg);

}

TextBuffer Class to replace the special characters in string.

TextBuffer Class to replace the special characters in string.
TextBuffer class can be used to replace the text/characters in the string.
Usually its used to replace the special character with escape sequence so that string(data with special character) can be inserted into the database.

Following job illustrates how to achieve this.

static void Dev_ReplaceTxt(Args _args)
{
TextBuffer buffer = new TextBuffer();
Str message;
;

message = " hi hello's how r u's ";
message += " How r u doing........................";

buffer.setText(message);
buffer.replace("[*?']","\\'"); // replace special character with escape sequence
info(buffer.getText());

}

X++ Code to Create Purchase Order and Post the Invoice.

X++ Code to Create Purchase Order and Post the Invoice.
Following Job creates the Purchase order from code and post the invoice by making use of PurchFormLetter class.
If you don't have demo data , please test with your input values.


static void Dev_CreatePO_and_Invoice(Args _args)
{
NumberSeq numberSeq;
Purchtable Purchtable;
PurchLine PurchLine;
PurchFormLetter purchFormLetter;

;

ttsbegin;
numberSeq = NumberSeq::newGetNumFromCode(purchParameters::numRefPurchaseOrderId().NumberSequence,true);

// Initialize Purchase order values
Purchtable.initValue();
Purchtable.PurchId = numberSeq.num();
Purchtable.OrderAccount = '3000';
Purchtable.initFromVendTable();

if (!Purchtable.validateWrite())
{
throw Exception::Error;
}
Purchtable.insert();

// Initialize Purchase Line items
PurchLine.PurchId = Purchtable.PurchId;
PurchLine.ItemId = 'B-R14';
PurchLine.createLine(true, true, true, true, true, false);
ttscommit;

purchFormLetter = purchFormLetter::construct(DocumentStatus::Invoice);
purchFormLetter.update(purchtable, // Purchase record Buffer
"Inv_"+purchTable.PurchId, // Invoice Number
systemdateget()); // Transaction date


if (PurchTable::find(purchTable.PurchId).DocumentStatus == DocumentStatus::Invoice)
{
info(strfmt("Posted invoiced journal for purchase order %1",purchTable.PurchId));
}
}

Change the documentstatus to packingSlip , if you want to post packing slip.

Connecting MSSQL DataBase with X++ Code.

Connecting MSSQL DataBase with X++ Code.
As part of Customer requirements , sometimes we need to connect to DataBase otherthan Axapta DataBase. So let us explore how it can be done with X++ code.
In Ax using ODBCConnection and LoginProp its possible to connect to Database on remote server, as illustrated in the following example.I tried the following code on MSSQL Server.

static void test_ODBCConnection(Args _args)
{
LoginProperty loginProp;
ODBCConnection conn;
Resultset resultSet, resultSetCount; // get record
Statement statement1, statement2; // Create SQL Statement
ResultSetMetaData metaData ; // get Record metadate like columnname.
;

// Set Server Database
loginProp = new LoginProperty();
loginProp.setServer('SON15092');
loginProp.setDatabase('AdventureWorksDW');

// Create Connection and SQL Statement
conn = new ODBCConnection(loginProp);
statement1 = conn.createStatement();
resultSet = statement1.executeQuery("SELECT * from DimTime");

while (resultSet.next())
{
metaData = resultSet.getMetaData();
info("Column Name :"+metaData.getColumnName(1)+" Value ="+resultSet.getString(1));
}
}

File Operation using WinAPI in Dynamics Ax

File Operation using WinAPI in Dynamics Ax
Finding files with WinAPI

Axapta’s WinAPI class has a bunch of static methods to handle files. The code example below shows how to utilize some of these methods to find files.

The two methods used to fetch all files matching the search criteria are findFirstFile() and findNextFile(). Don’t forget to clean up after yourself with findClose().

The code also uses three different find methods:

*
fileExists(_name) returns true, if _name is an existing file
*
folderExists(_name) returns true, if _name is an existing file or folder
*
pathExists(_name) returns true, if _name is an existing folder

The example uses the infolog for output. As with any infolog beware of performance and limitation to 10.000 lines.


static void Test_WINAPI(Args _args)
{

#File

FileName fullFileName(FileName _path, FileName _fileName)
{
FileName pathName;
FileName fileName;
FileName fileExtension;
;
[pathName,fileName,fileExtension] = fileNameSplit(_fileName);
return _path + '\\' + fileName + fileExtension;
}

void findFiles(FileName _path,
FileName _fileName,
boolean _inclSubDir = true,
FileName _prefix = fullFileName(_path,_fileName))

{

FileName fileName;
int hdl;
;
setprefix(_prefix);
if (WinAPI::folderExists(_path))
{
[hdl,fileName] = WinApi::findFirstFile(fullFileName(_path,_fileName));
while (fileName)
{
if (WinAPI::fileExists(fullFileName(_path,fileName)))
info(fileName);
fileName = WinApi::findNextFile(hdl);
}
WinApi::findClose(hdl);
if (_inclSubDir)
{
[hdl, fileName] = WinAPI::findFirstFile(_path+'\\'+#AllFiles);
while (fileName)
{
if (strlwr(fileName) != strlwr(_fileName) &&
strlwr(fileName) != strlwr('.') &&
strlwr(fileName) != strlwr('..') &&
WinAPI::pathExists(fullFileName(_path,fileName)))

findFiles(fullFileName(_path,fileName), _fileName, _inclSubDir,
fileName);


fileName = WinApi::findNextFile(hdl);

}
WinApi::findClose(hdl);

}
}
}
findFiles('c:\\Program Files','*.doc');

}

X++ Code to find OnHand Stock for Item

X++ Code to find OnHand Stock for Item
In Dynamics Ax , use InventOnHand class for finding the stock of an item as shownbelow



static void findOnHand(Args _args)
{
InventDim inventDim;
InventDimParm inventDimParm;
Itemid itemid;
InventOnHand inventOnHand = new InventOnHand();
;

// take a sample item for testing
itemid = "20 MM RMC";

// take a combination of dimension , against which you want to find the stock
inventDim.InventLocationId = "GW";

//Set the flag for the selected dimensions as active.
inventDimParm.initFromInventDim(inventDim);

//initialize the inventonhand with item,dimension and dim paramter

inventOnHand.parmItemId(itemid);
inventOnHand.parmInventDim(inventDim);
inventOnHand.parmInventDimParm(inventDimParm);

// Retrieve the onhand info
info(strfmt("Available Physical: %1",
inventOnhand.availPhysical()));
info(strfmt("On order: %1",inventOnhand.onOrder()));

}

X++ code to find the Stock of Item by Date

X++ code to find the Stock of Item by Date
static void findOnHand_ByDate(Args _args)
{
InventDim inventDim;
InventDimParm inventDimParm;
Itemid itemid;
InventOnHand inventOnHand = new InventOnHand();
InventSumDateDim inventSumDateDim;
TransDate transDate;
;

// take a sample item for testing
itemid = "20 MM RMC";
transDate = 13\01\2010;

// take a combination of dimension , against which you want to find the stock
inventDim.InventLocationId = "GW";

//Set the flag for the selected dimensions as active.
inventDimParm.initFromInventDim(inventDim);

//initialize the inventSumDateDim with Date,item,dimension and dim paramter

inventSumDateDim = InventSumDateDim::newParameters(transDate,
itemid,
inventDim,
inventDimParm);


// Retrieve the onhand info
info(strfmt("PostedQty: %1",inventSumDateDim.postedQty()));
info(strfmt("DeductedQty: %1",inventSumDateDim.deductedQty()));
info(strfmt("ReceivedQty: %1",inventSumDateDim.receivedQty()));

}

X++ code to create a customized lookup on form

X++ code to create a customized lookup on form
Override the lookup method on Formdatasource field(on which you want to show lookup) , and copy the following code to your method.
Comment the super() method in the lookup.

public void lookup(FormControl _formControl, str _filterStr)
{
SysTableLookup sysTableLookup; // systemclass to create //customlookup
Query query;
QueryBuildDataSource qbd;

;
sysTableLookup = SysTableLookup::newParameters(
tablenum(InventTable),
_formcontrol);

// Construct query on the table,
// whose records you want to show as lookup.
query = new Query();
qbd = query.addDataSource(tablenum(InventTable));
qbd.addRange(fieldnum(InventTable,ItemType)).value(SysQuery::value(enum2str
(ItemType::Item)));

// add the fields to the lookup list
sysTableLookup.addLookupfield(fieldnum(InventTable,ItemId));
sysTableLookup.addLookupfield(fieldnum(InventTable,ItemName));

// pass the query as parameter
// system will show the records in the lookup
// as per your query
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();

}

X++ code to create and post Inventory Movement Journal

X++ code to create and post Inventory Movement Journal
Following is the sample job to show how we can create and post movement journal by making use of available api's in the Dynamics Ax.

static void createMovJournal(Args _args)
{ InventJournalTable journalTable;
InventJournalTrans journalTrans;
InventJournalTableData journalTableData;
InventJournalTransData journalTransData;
InventTable inventTable;
InventDim inventDim;
Counter cnt;
InventJournalCheckPost journalCheckPost = new InventJournalCheckPost();
;

journalTableData = JournalTableData::newTable(journalTable);
journalTransData = journalTableData.journalStatic().newJournalTransData(journalTrans,journalTableData);

// Init JournalTable

journalTable.clear();

journalTable.JournalId = journalTableData.nextJournalId();
journalTable.JournalType = InventJournalType::Movement;
journalTable.JournalNameId = journalTableData.journalStatic().standardJournalNameId(journalTable.JournalType);

journalTableData.initFromJournalName(journalTableData.journalStatic().findJournalName(journalTable.JournalNameId));

// Init JournalTrans
select firstonly inventTable;
for(cnt=1;cnt<10;cnt++)
{
journalTrans.clear();
journalTransData.initFromJournalTable();

journalTrans.TransDate = systemdateget() + 1 div 2;
journalTrans.ItemId = inventTable.ItemId;
journalTrans.Qty = 100;
journalTrans.CostAmount = 100;

// Dimension details

inventDim.InventLocationId = 'GW';
journalTrans.InventDimId = InventDim::findOrCreate(inventDim).inventDimId;

journalTransData.create();



}

journalTable.insert();

// Call the static method to post the journal
if(InventJournalCheckPost::newPostJournal(journalTable).validate())
InventJournalCheckPost::newPostJournal(journalTable).run();


}

X++ code to Read/Write Dynamics Ax data to excel

X++ code to Read/Write Dynamics Ax data to excel
Writing Data to Excel file
How it works
1. Use SysExcelApplication class to create excel file.
2. Use SysExcelWorkbooks and SysExcelWorkbook to create a blank workbook(by
default 3 worksheets will be available).
3. Use SysExcelWorkSheets to select worksheet for writing data.
4. SysExcelCells to select the cells in the excel for writing the data.
5. SysExcelCell to write the data in the selected cells.
6. Once you done with write operation use SysExcelApplication.visible to open
file.

static void Write2ExcelFile(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);
}

Reading Data from Excel File
static void 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();
}

X++ code to write data to XML File

X++ code to write data to XML File
static void CreateXml(Args _args)
{
XmlDocument xmlDoc; //to create blank XMLDocument
XmlElement xmlRoot; // XML root node
XmlElement xmlField;
XmlElement xmlRecord;
XMLWriter xmlWriter;
InventTable inventTable;
DictTable dTable = new DictTable(tablenum(InventTable));
DictField dField;
int i, fieldId;
str value;
#InventTags
;

xmlDoc = XmlDocument::newBlank();
xmlRoot = xmlDoc.createElement(#ItemRootNode);

// Loop through all the records in the inventTable
while select inventTable
where inventTable.ItemGroupId == "Parts"
{
// Create a XmlElement (record) to hold the
// contents of the current record.
xmlRecord = xmlDoc.createElement(#ItemRecords);
// Loop through all the fields in the record
for (i=1; i<=dTable.fieldCnt(); i++)
{
fieldId = dTable.fieldCnt2Id(i);
// Find the DictField object that matches
// the fieldId
dField = dTable.fieldObject(fieldId);

// Skip system fields
if (dField.isSystem())
continue;
// Create a new XmlElement (field) and
// have the name equal to the name of the
// dictField
xmlField = xmlDoc.createElement(dField.name());
// Convert values to string. I have just added
// a couple of conversion as an example.
// Use tableName.(fieldId) instead of fieldname
// to get the content of the field.
switch (dField.baseType())
{
case Types::Int64 :
value = int642str(inventTable.(fieldId));
break;
case Types::Integer :
value = int2str(inventTable.(fieldId));
break;
default :
value = inventTable.(fieldId);
break;
}
// Set the innerText of the XmlElement (field)
// to the value from the table
xmlField.innerText(value);
// Append the field as a child node to the record
xmlRecord.appendChild(xmlField);
}
// Add the record as a child node to the root
xmlRoot.appendChild(xmlRecord);
}
// Add the root to the XmlDocument
xmlDoc.appendChild(xmlRoot);
// Create a new object of the XmlWriter class
// in order to be able to write the xml to a file
xmlWriter = XMLWriter::newFile(@"c:\Items.xml");
// Write the content of the XmlDocument to the
// file as specified by the XmlWriter
xmlDoc.writeTo(xmlWriter);

//Open the file in Internet Explorer
WINAPI::shellExecute("c:\Items.xml");
}

Dynamics Ax Systemclass for RECID

Dynamics Ax Systemclass for RECID
As you all know that Dynamics Ax uses recid(Record Id)to uniquelly identify a record in the database.
Advantage of RecId
1.By default system uses Recid as primary index,so if query optimizer didn't find any index to use then it will use RecId.

Dyamics Ax uses SystemSequence class(AOT->SystemDocumentation->Classes) to generate recId for table.
Using SystemSequence class you can reserve RECID's for your table.
Ax Kernel uses SystemSequences Table to generate the Recid for table as shown below
Goto AOT->SystemDocumentation->Tables->SystemSequences ,

Security Keys in Ax

Security Keys in Ax
Dynamics Ax provides following keys to provide the security for application

1.License Keys :
First Level Security , specifies what all featues/modules/developemnt tools we can access in the standard product.License Keys will be used after installation to unlock the product.License Keys will be issued by the microsoft for partners/vendors to develop vertical/generic solutions.

2.Configuration Keys :
Second Level Security , To Enable/Disable the object/feature for all the users.

3.Security Keys :
If you want to enable/disable object/features to group of users.

4. Record Level security :
Basically it deals with the data , if you want to restrict the viewing of records per user group than we setup record level security.

X++ Layout

X++ Layout
General Guidelines
Only one statement per line.

Break up complex expressions that are more than one line - make it visually clear.

Use a single blank line to separate entities.

Do not use parentheses around the case constants.

Do not use parentheses around where expressions.

Add one space between if, switch, for, while and the expressions starting parentheses. For example:

if (creditNote)

Use braces around all code blocks, except for around case clauses in a switch statement. Use braces even if there is only one statement in the block.

Indentation
An indentation is equivalent to four (4) characters, which corresponds to one tab in the X++ editor. You must not start a new line in columns 2, 3 or 4.

Put opening and closing braces, { and }, on the same level, on separate lines, and aligned with the command creating the block. They must be at the start of a line, and in a tab column position (1, 5, 9 etc.). Braces must be on a dedicated line unless a opening brace is followed by a semicolon ( {; ) or a closing brace is followed by a while ( }while ).

The following reserved words should be placed at the beginning of a line: case, catch, changeCompany, continue, default, else, for, if, retry, return, switch, try, ttsAbort, ttsBegin, ttsCommit, while.

The exceptions to this rule are:

case: … (reserved words in a case statement)

default: … (reserved words in a default statement)

else if

}while

If a line of code starts with any other reserved word, or with an alphabetical character, the line should start in a tab column position (1, 5, 9 etc). The following reserved words must be placed in a tab column position: case, catch, changeCompany, continue, default, else, for, if, retry, return, switch, try, ttsAbort, ttsBegin, ttsCommit, while.

The exceptions to these rules are:

case: … (reserved words in a case statement)

default: … (reserved words in a default statement)

else if

}while

The reserved word else must have a dedicated line unless you write else if.

switch-case statements: indent case and default statements by 1 level (with any code within these indented a further level) and indent break statements by two levels.

Indent where and other qualifiers to the select statement by one level.

If Booleans are used in a long expression, put them at the start of an indented new line.

Example switch-case Statement


switch (myEnum)
{
case ABC::A:
...
break;
case ABC::B
...
break;
default:
...
break;
}
Example select Statement


select myTable
index hint myIndex
where myTable.field1 == 1
&& myTable.field2 == 2;
Example Layout of Booleans in a Long Expression


select firstOnly utilElements
where utilElements.recordType == recordType
&& utilElements.parentId == parentID
&& utilElements.name == elementName;
Column Layout
Column layout should be used where more than one line has the same structure; for example, in declarations or assignments.

Do not use column layout when there is only one row, or if consecutive rows do not have the same structure.

Column format is defined using extra blanks.

Example Column Layout


tmpABC.refRecId = inventTable.recId;
tmpABC.itemGroupId = inventTable.itemGroupId;
tmpABC.itemId = inventTable.itemId;
tmpABC.amount = amount;
tmpABC.oldValue = this.getCategory(inventTable);
tmpABC write();
Layout for Methods
The starting parenthesis on method declarations and calls should be the character just after the method name (no space).

If there are one or two parameters, the parameters can be listed on the same line. If there are more than two parameters, move each parameter onto a new line, and indent by 4 spaces.

Example Layout for Method with One or Two Parameters



myMethod(parameter1, parameter2);

Example Layout for Method with Many Parameters

myMethod(
parameter1,
parameter2,
parameter3);

How to Use Temporary Table in Form

How to Use Temporary Table in Form
Temporary table(Table whose property temporary set to "yes") is not persistent media , so at run-time you have to populate the temporary table and attach the same to the form/report.
For illustration purpose ,I am using inventTable data and attaching the items whose group is Parts.
Steps

1. Create temporary table as TmpTestTable with 3 fields(ItemId,Itemname,ItemGroup).
2. Create a form as TempTestTable and attach the table as datasource
3. Create a new method on the form and copy the following code

TmpTestTable populateRecords(ItemGroupId _itemGroupId)
{
TmpTestTable tmpTable;
InventTable inventTable;
;

while select inventTable
where inventTable.ItemGroupId == _itemGroupId
{
tmpTable.Itemid = inventTable.ItemId;
tmpTable.ItemName = inventTable.ItemName;
tmpTable.Itemgroup = inventTable.ItemGroupId;
tmpTable.insert();
}

return tmpTable;
}

4. Call the above method in init() after super as below
public void init()
{
super();

// Call the setTmpData method to attach records to datasource
TmpTestTable.setTmpData(element.populateRecords("Parts"));
}

Dynamics Ax 2009 layers

Dynamics Ax 2009 Layers
Dynamics AX 2009 consists of sixteen application object layers that contain all the
elements you see in the AOT.
These layers can be looked at as an onion with multiple layers. In the middle is the
core application in the SYS layer and the outermost layer is the user layer USR.
Therefore, when any application element is being executed the system will look at
the outermost code layer first to see if there is any code for that element; if not, it peels a layer off the onion, and tries the next layer. When it hits a layer where the element exists, it will use the code from this layer, and will not continue to peel off layers to find code for that element in the innermost layers.

Layers with their description

SYS The standard application is implemented at the lowest level,
the SYS layer.The application objects in the standard
application can never be deleted.

GLS Country/region specific changes will be developed in GLS
Layer.For e.g as you all know that Tax structure differs
from country to country.So such localization functionality
can be developed in GLS layer.

HFX HFX is an application object patch layer reserved by
Microsoft for future patching or other updates.

SL1, SL2,or SL3 A layer where the distributor can implement
vertical partner solutions.

BUS When a business partner creates their own generic solution,
their modifications are saved in the BUS layer and the top-
level application objects are used.

VAR Value Added Resellers (VAR) can make modifications or new
developments to the VAR layer as specified by the customers
or as a strategy of creating an industry-specific solution.
Such modifications are saved in the VAR layer.

CUS The supervisor or administrator of an end user installation
might want to make modifications that are generic to the
company. Such modifications are saved in the CUS (CUStomer)
layer.

USR End users might want to make their own modifications, such
as in their reports.These modifications are saved in the USR
layer.

How to create new number sequence though code in Ax.

To let any field to be generated sequentially you must do the following:

Suggest i have a table named NoobsTable and a field named NoobId, the extended data type for NoobId is NoobEDT
and i have a Form named NoobsForm

1) For example if the NoobsForm is located in Inventory managment Module you should find the class named NumberSeqReference_Inventory, then go to LoadModule method in that class and write the following at last:

numRef.dataTypeId = typeId2ExtendedTypeId(typeid(NoobEDT)); //Extended datatype related to NoobId.
numRef.referenceHelp = literalStr("HelpText"); // Your help text to be viewed in Parameters later.
numRef.wizardContinuous = true;
numRef.wizardManual = NoYes::No;
numRef.wizardAllowChangeDown = NoYes::No;
numRef.wizardAllowChangeUp = NoYes::No;
numRef.wizardHighest = 99999999;
numRef.sortField = 1;

this.create(numRef);

2)Then go to Table node and find InventParameters, go to methods node then add a new method and write the following:

server static NumberSequenceReference numRefNoobId()
{
return NumberSeqReference::findReference(typeId2ExtendedTypeId(typeid(NoobEDT))); //Extended datatype
}

3)Then go to Inventroy managment content pane --> Setup --> Parameters --> Number Sequences Tab
now here you will see the Extended Data type NoobEDT and an empty Sequence number code, right click the empty lookup and click Go to the main table Form.
Add a new number sequence code in the opened form and save it [for example]:
Number sequence code: NoobNumberSeq
Name: NoobNumberSeq
Smallest: 1
Largest: 99999999
Next: 1
Format: Noob_########
InUse: Checked

Return to previous Form "Parameters" and choose NoobNumberSeq that we have just created it from Number sequence code lookup to NoobEDT Reference

3)Last thing to do is Go to NoobsForm --> Datasources node --> NoobsTable --> Methods, and override method (create) and write the following:

public void create(boolean _append = false)
{
;
super(_append);

NoobsTable.NoobId = NumberSeq::newGetNum(InventParameters::numRefNoobId(),true).num(); //numRefNoobId() is a method created in step 2)
}

//End

Finally go to the form and create a new record and you will see your number is generated automatically and sequentially.

Note: go to NoobsTable and set NoobId field to( AllowEdit:No AllowEditOnCreate:No ) if you dont want anyone to edit the generated number.

Atrees