Posts Tagged ‘X++’
Crosscompany
Yesterday I talked about executing code/getting records in several companies. Now the changecompany is not the only method. You can also get data out of several companies by using the keyword crosscompany in your select statement.
Example:
1 2 3 4 5 6 7 8 9 | Address address; container conCompanies = [ 'cee', 'dat' ]; ; while select crossCompany :conCompanies address order by dataAreaId { //Do something } |
Execute a job on data in several companies
There is a verry simple trick to loop through some companies and execute some code in them.
Just write:
DataArea dataArea; ; while select dataArea where !dataArea.isVirtual { changecompany(dataArea.id) { // Do Something... } }
Note! Make sure that you clear the table variable after each companychange (common = null;).
Batch job performance boost
Did you ever have trouble with the performance of your batch-job? Well maybe this small trick can shorten the time your batch runs.
The big idea: Try to split up your gigantic batch in smaller pieces. Launch a batchjob that produces many smaller batchjobs (tasks) that can handle a subset of the data you need to process. For example you can create a batch that creates a batch with sub-tasks for each company.
How do you plan a batch from code?
1 2 3 4 5 6 7 8 9 10 11 12 | BatchHeader batHeader; BatchInfo batInfo; TstRunBase rbbTask; ; rbbTask = TstMyBatch::construct(); batInfo = rbbTask.batchInfo(); batInfo.parmCaption("MyBatch"); batInfo.parmGroupId(""); batHeader = BatchHeader::construct(); batHeader.addTask(rbbTask); batHeader.save(); info(batInfo.parmCaption()); |
You can download a quick example I made. This is a job you can schedule and it will produce a new Batch job with a task for each company when you don’t select a company while shedualing (Class_TstRunBase.xpo). I hope this can help you.
Tip for overriding methods
There is a simple and generic way to force overriding a method you created. To do so you just need create your new method and place a ‘throw error’ statement in it. To finish you can add the static method missingOverride from the error class and the funcName() to your error. Now when this method is called or the super() in you child class is called, you will get a error that you need to override your method.
public identifiername myMethod() { throw error(Error::missingOverride(funcName())); }
When you use this peace of code you will get the following error:

Note: The error-class also has some other usefull static methods like: missingFormActiveBuffer, missingOverload, missingOverride, missingParameter, missingRecord and my favorite wrongUseOfFunction
Expressions in query ranges – limitations
When you want to construct a query-object that contains OR-conditions, you can construct something like this:
1 2 3 4 5 6 | queryBuildRange.value(strFmt('((%1 == %2) || ((%1 == %3) && (%4 == "%5")))', fieldStr(InventTable, ItemType), any2int(ItemType::Service), any2int(ItemType::Item), fieldStr(InventTable, ProjCategoryId), queryValue("Spares"))); |
(you can find more info on Axaptapedia: Expressions in query ranges)
Now there is a limitation to this way of working. When the generated string in the queryBuildRange.value is longer than 250 characters (the length of the range EDT), Ax cuts the generated string off when you open the ‘modify query’ dialog. I have tried to enlarging the EDT, but is not a good solution. The error does not occure when you open the ‘modify query’ dialog, but it occures when you close it.
A small (but limited) work-around could be to make the name of the datasources on the form/report where you want to apply this trick smaller. I hope to find a better solution, but this does the trick for now.
Channel9 : X++ into .Net
I accidentally found this interesting video about future architecture where you can run X++ in .Net.
Test if a configuration key is enabled in X++ code
How do you execute code when a Configuration key is enabled?
It is pritty easy. Ax x++ has a build-in function ‘isConfigurationKeyEnabled’, witch you can use to check a configuration key.
Small example:
if (isConfigurationKeyEnabled(configurationkeynum(AIF))) { // Do something... }
Setting propperties on a FormControl without AutoDeclaration
When you want to set a property of a control on a form without setting the property AutoDeclaration = yes. You can address the control trough the following code, knowing that element is a FormRun-object:
element.design().controlName("btnOk").visible(false);
Create class from code
Did you know that you can build/modify classes from code? It is actually not so hard, just use the ClassBuild-class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | static void JeDoe_testClassBuild(Args _args) { ClassBuild classBuild; ClassNode classNode; Str myCode; ; myCode = @" static void Main(Args _args) { ; info('Hello World!'); } "; classBuild = new ClassBuild("MyTest", false); classBuild.addMethod("Main", myCode); classNode = classBuild.classNode(); classNode.AOTcompile(); classNode.AOTrun(); } |
The sample above will create a new class MyTest with a ‘Hello World’ Main-method and will actually save compile/save the code in the AOT and then run it. Cool?
Note: The SysDictClass/SysDictMethod-class can also help you creating proper classes and methods. Maybe I’ll blog about this later.
Catching a key-press
When you want to catch a key-stroke on a form, you can override the method task()
The default method will look like this:
public int task(int _taskId) { int ret; ret = super(_taskId); // write you're code here return ret; }
Now you just need to check the _taskId, to know witch key you have stroke. You can compare this withe the values from the Task-macro.
// Task-ID values, to be used with formControl's // return value from the method task() //-------------------------------------------------------- #define.taskF1(257) #define.taskCtrlQ(264) #define.taskEnter(288) #define.taskShiftEnter(307) #define.taskNew(260) #define.taskSave(272) #define.taskShortCutMenuKey(519) #define.taskAlt(520) #define.taskCut(770) #define.taskCopy(771) #define.taskPaste(772) #define.taskDeleteKey(773) #define.taskSelectAll(778) #define.taskUndo(769) #define.taskRedo(791) #define.taskArrowUp(1281) #define.taskArrowDown(1282) #define.taskArrowLeft(1283) #define.taskArrowRight(1284) // PgUp and PgDn are the numerical keyboard page up and page down commands. #define.taskPgUp(1285) #define.taskPgDn(1286) #define.taskEsc(1313) #define.taskNextRecord(2817) #define.taskPrevRecord(2818) #define.taskDeleteRecord(2832) #define.taskPageDown(2819) #define.taskPageUp(2820) #define.taskTab(2827) #define.taskNext(2827) #define.taskPrev(2828) #define.taskShortCutMenuFilter(2844) #define.taskShortCutMenuFind(799) #define.taskFilter(2837) // max task id #define.taskLast(8191)



