Skip to main content

Code Examples

Practical X++ code patterns for working with base enumerations and extended data types.


Base Enum Usage

SalesStatus status = SalesStatus::Invoiced;

if (salesTable.SalesStatus == SalesStatus::Open)
{
info("Order is still open");
}

Always compare against the symbolic constant, never a raw integer:

// Correct
select salesTable where salesTable.SalesStatus == SalesStatus::Invoiced;

// Incorrect — fragile if values change
select salesTable where salesTable.SalesStatus == 3;

Handling Extensible Enums

When an enum is extensible, consuming code should handle unknown values in switch statements:

switch (salesTable.SalesStatus)
{
case SalesStatus::Open:
// handle open
break;
case SalesStatus::Invoiced:
// handle invoiced
break;
default:
// Handle values added by extensions gracefully
warning(strFmt("Unhandled status: %1", salesTable.SalesStatus));
break;
}

Iterating Over Enum Values

DictEnum dictEnum = new DictEnum(enumNum(SalesStatus));
int i;

for (i = 0; i < dictEnum.values(); i++)
{
info(strFmt("Name: %1, Value: %2, Label: %3",
dictEnum.index2Name(i),
dictEnum.index2Value(i),
dictEnum.index2Label(i)));
}

Converting Between Enum and Integer

// Enum to integer
int statusInt = enum2int(SalesStatus::Invoiced);

// Integer to enum
SalesStatus status = int2enum(statusInt);

// Enum to string (symbolic name)
str statusName = enum2Str(SalesStatus::Invoiced); // "Invoiced"

// String to enum
SalesStatus fromStr = str2Enum(SalesStatus::Open, "Invoiced");

Using Enums in Select Statements

SalesTable salesTable;

// Filter by enum value
select firstonly salesTable
where salesTable.SalesStatus == SalesStatus::Open;

// Use enum ranges
select count(RecId) from salesTable
where salesTable.SalesStatus >= SalesStatus::Open
&& salesTable.SalesStatus <= SalesStatus::Invoiced;

EDT Variable Declarations

// Declaring variables using EDTs
CustAccount customerAccount;
TransDate transactionDate;
AmountMST amount;
ItemId itemId;

// EDT types provide semantic meaning in method signatures
public void postInvoice(CustAccount _custAccount, TransDate _transDate, AmountMST _amount)
{
// Parameters are self-documenting via their EDT names
}

EDT Inheritance in Practice

// CustAccount extends AccountNum extends EDT String
// Assignment from child to parent is always valid:
CustAccount custAcct = "CUST-001";
AccountNum acctNum = custAcct;

// Define a method that accepts the parent EDT
public void processAccount(AccountNum _accountNum)
{
info(strFmt("Processing account: %1", _accountNum));
}

// Call it with a child EDT — valid because CustAccount extends AccountNum
this.processAccount(custAcct);

Working with EDT Relations

// When CustAccount EDT has a relation to CustTable.AccountNum,
// fields using CustAccount EDT automatically get a lookup to CustTable.

CustTable custTable = CustTable::find(salesTable.CustAccount);
info(strFmt("Customer name: %1", custTable.name()));

Inspecting EDT Metadata at Runtime

DictType dictType = new DictType(extendedTypeNum(CustAccount));

info(strFmt("EDT Name: %1", dictType.name()));
info(strFmt("Label: %1", dictType.label()));
info(strFmt("Help Text: %1", dictType.help()));
info(strFmt("String Size: %1", dictType.stringLen()));
info(strFmt("Extends: %1", dictType.extendedBy() ? "Yes" : "No"));