In
MorphX macros are not commonly used. A few places make use of macros such as
keeping track of the list of fields stored when using dialogs. It is recommended
only to use macros to define constants. Also supports code, but is not
recommended as reusing code from macros is not flexible.
Defining Constants:
In the second Macro call, the table has not been specified so text will be printed to the Infolog.
Example(2): Create and use an AOT Macro
The
main difference between a macro and a method is that a macro has no variable
declaration part, and the code in a macro is not validated for errors before
executed from a method. This is another reasons for not putting code in macros.
When
using macros in your code, the macros must be declared after the variable declaration.
And the common place to put the definition is in the ClassDeclaration of a class,
form or a report. This will make the macro definition available for all parts
of the object.
Macro commands:
For writing macros a set of simple macro commands are used. Below are few examples.
For writing macros a set of simple macro commands are used. Below are few examples.
Command | Description |
#define | Used to define a constant. |
AxExample: See macro HRMConstants. | |
Syntax: #define.myConstant100('100') | |
#if.empty |
Will return true if the macro has not been called with the parameter validated in the statement. |
#if.notempty |
Will return true if the macro has been called with the parameter validated in the statement. |
AxExample: See macro InventDimJoin | |
Syntax: #if.notempty(%3) print %3; #endif | |
#endif |
Ends a #if.empty or a #if.notempty statement. |
AxExample: See macro InventDimJoin | |
Syntax: #endif (following any if statement) | |
#globalmacro |
No difference whether declaring the start of a macro with #localmacro or #globalmacro. #globalmacro is not used in the standard package, consider using #localmacro instead. |
#localmacro |
Specify the start of a local macro. |
AxExample: See macro BOM | |
Syntax: #localmacro.BOMDateSelect (((BOM.fromDate <= %1 || ! BOM.fromDate) && (BOM.toDate >= %1 || ! BOM.toDate)) || ! %1 ) #endmacro | |
#endmacro |
Ends a #LOCALMACRO or a #GLOBALMACRO. |
#linenumber |
Returns the current line number of the macro. Can be used while debugging, but not of must use. |
#macrolib |
Used to load an AOT macro from code. |
AxExample: See class method BOMHierarchy.searchDownBOM() | |
Syntax: #macrolib.MyMacro | |
#undef |
Undefine a constant declared with #DEFINE. A defined constant cannot be used if #undef is called with the define name. |
Syntax: #define.MyConstant(100) print #MyConstant; #undef.MyConstant print #MyConstant; // will fail, as #MyConstant is not defined. |
Instead
of using text in your code it is strongly recommend defining your text as
constants. Often you will need an integer or a text for setting a value. If you
are going to set RGB color it is not easy to read the following:
myStringColor(255, 255, 255)
Instead
you should consider defining a constant with a descriptive name:
myStringColor(#RBGColorWhite)
Using
a macro as a constant rather than entering the value in code makes it easier to maintain.
A good way to organize the constants used in your modifications is by creating
a macro in the AOT for keeping all your constants in one place, one good
example is HRMConstants.
Creating Macros:
Macros
are either created directly in the code, or put in an AOT macro and then the AOT
macro is declared in the code.
Example(1):
#localmacro created in the code
static void Macros_LocalMacro(Args _args)
{
CustTable custTable;
;
#localmacro.selectCustTable //Macro definition starts here
#ifnot.empty(%1)
while select %1
#ifnot.empty(%3)
order by %3
#endif
{
info(queryValue(%1.%2));
}
#endif
#if.empty(%1)
info("No table specified.");
#endif
#endmacro
//Macro definition ends here
#selectCustTable(CustTable, accountNum) //Calling Macro with valid parameters
#selectCustTable //Calling Macro with no parameters – output will
be text “No table specified” as per the validation.
}
The
macro will select records from a table ‘CustTable’ and print a field from the same
as the table to be fetched, and the fields (%1, %2, %3) to be printed are
specified in the parameters for the first Macro call. In the second Macro call, the table has not been specified so text will be printed to the Infolog.
As you
cannot declare variables in a macro, integer values prefixed with a percentage
sign such as %1 are used instead. This is the common way of using the macros.
The validations must be before calling the macro. Notice that you can call a macro
without entering the parentheses after the macro name.
Example(2): Create and use an AOT Macro
If
your macro is going to be used in several places it would make sense creating
the macro in the AOT as you will then be able to reuse the macro.
To create a new macro in the AOT:
To create a new macro in the AOT:
1. Unfold the Macro node, right-click and choose New Macro.
2. A new empty macro node will be created. You can rename the new
macro by opening the property sheet to “MyFirstMacro”
3. Now paste the code of the #localmacro (from above) to your new
macro.
4. Save the Macro, and it is ready to use.
To use
the macro created in the AOT the macro command #macrolib is used. Here the AOT
macro is name MyFirstMacro, and it can be used in the code as shown below.
static void Macros_MacroLib(Args _args)
{
CustTable custTable;
;
#macrolib.MyFirstMacro
#selectCustTable(CustTable, accountNum)
#selectCustTable
}
Even
this will result in the same output as explained above, the only difference is
that we are calling a Macro created in AOT using #macrolib command.