This blog is dedicated to all my technical learnings and findings. As they say use all the brains you have and borrow all the brains you can, so this is my share of lending my learnings to all you guys out there. I would like to acknowledge here that some parts of these posts would be reproduced as a part of my web-browsing mainly because having it all in one place is far more convenient.
Friday, July 09, 2010
“System does not support setup 'continuous' of number sequence
Realized that the issue was that the getNewNum function was called without transaction processing
PYLEmplLeaveDetailsTable.LeaveAppNum = NumberSeq::newGetNum(HRMParameters::numRefLeaveAppNum()).num();
just got resolved by encapsulating the same within a transaction
ttsbegin;
PYLEmplLeaveDetailsTable.LeaveAppNum = NumberSeq::newGetNum(HRMParameters::numRefLeaveAppNum()).num();
ttscommit;
Deploying AOD files directly
One of the methods of deploying customizations onto an AX installation is by carrying the aod files and replacing them on the target installation. However there is one issue with this approach if the newly updated aod file contains some new security and configuration keys the same would not get registered in the security metadeta of AX which i believe is stored in the database.
So we might land up with a menu with missing menu items as the security is not recognized for them even for the Administrator.
the way to get around this issue is to disable and enable the concerned configuration key doing so will get it registered in the AX Security related tables
Thursday, July 08, 2010
Macros
Macros are strings which are substituted by the pre-compiler before they reach the compiler and it is this behavior which makes macros extremely powerful.
Hence macro substitutes a string in the source code which is then compiled and processed by the compiler.
A classic example of this behavior is the pack unpack pattern applied in AX. It starts with the definition of a macro which refers to all the memory variables we need to maintain state for. The pack method returns a container effectively before this source reaches the compiler the macro is substituted and the container list contains all the memory variables which are processed by the compiler and the actual memory values are composed into the container.
similarly in the unpack method when we say
[version,#CurrentList] = _packedClass;
before the above statement is processed by the compiler the macro is substituted by all the memory variables which then get initialized as this statement is executed.
Ideally the source code written once should not be repeated elsewhere coz as per the best practices it should be reused however if for some reason a piece of code needs to be duplicated through a routine the macros are the ideal candidates to maintain a single central copy of this source.
MorphX has a built-in macro-preprocessor. The purpose of macros is to make statements easy to reuse and you can declare macros wherever you can write X++ statements.
There are basically three kinds of macros: macros in macro libraries, stand-alone macros and (local) macros inside methods. All three types of macros have identical syntax and functionality. The only differences are that
A stand-alone macro is created using the macro-node of the Application Object Tree
A macro library is a stand-alone macro, which contains (local) macros
A local macro is declared within a method, or stand-alone macro
X++ has these macro constructs:
#DEFINE | This statement defines a macro variable, which can be used as a constant or to make macros perform differently according to the macro variable value. |
#UNDEF | This statement cancels a macro variable. |
#MACROLIB | Loads a macro library. Libraries must be loaded before the macros within them can be used. |
#GLOBALMACRO | Declares a global macro (header). A global macro can be used everywhere in MorphX after declaration. |
#LOCALMACRO | Declares a local macro (header). |
#ENDMACRO | Signals the end of a macro declaration. |
#IF | Tests if the macro variable following the #IF has as given value. Includes the statements between #IF and #ENDIF. |
#IF.EMPTY() | Tests the argument within the brackets, and includes the statements between #IF and #ENDIF if the argument is empty. |
#IFNOT.EMPTY() | Tests the argument within the brackets, and includes the statements between #IF and #ENDIF if the argument is not empty. |
#ENDIF | Signals the end of a conditional macro declaration (#IF). |
#LINENUMBER | Returns the current line number. Mainly useful for debugging |
Using define
You can use the define macro construct to declare symbolic constants in your program as follows:
#Define.MaxLength(100)
int intarray[#MaxLength]
Macro declaration
Macros are declared by this syntax:
Macrodeclaration = #localmacro. Macroname { text } #endmacro
Where text can be anything. Within the macro declaration, it is possible to use parameters. The parameters are named %1, %2, %3 etc. All macros are considered as text, and are unfolded before compilation. This means that there is no means of checking syntax or functionality within macros (all that appears is a compiler error in the macro with no specification of error location).
A local macro, called AnExample is declared as follows:
#localmacro.AnExample
// Some statements or text
#endmacro
A more complex macro using parameters is declared as follows:
#localmacro.ComplexMacro
#DEFINE.ARG(%1); // Defines a macro variable ARG
#IF.EMPTY(%1) // If parameter1 is empty
print “The first parameter is empty (not used)”;
#ENDIF
#IFNOT.EMPTY(%1) // If it is not empty
print “The first parameter is NOT empty, it is %1”;
#ENDIF
%2 = %3 + %4; // param2 is assigned
// param3+param4
#IF.ARG(1) // IF parameter1 is 1
print “Parameter1 has the value 1”;
#ENDIF
#UNDEF.ARG // The macro variable ARG is undefined
#endmacro
Referencing macros
You reference macros by their name prefixed with a hash mark (#). To reference the complex macro shown above, you would write:
#complexMacro(parameter1, parameter2, parameter3, parameter4)
The parameters (1-4) have a story: Parameter 1 is optional, as it is only used in the macro, if it exists (#IFNOT.EMPTY) whereas parameters 2, 3 and 4 are used unconditionally (in the statement %2 = %3 + %4) - and therefore must be included in the call. Assuming you have declared a variable called A, a valid reference would be):
ComplexMacro(1,a,3,4);
Which would expand the macro into the statements below:
#DEFINE.ARG(1); // Defines a macro variable
#IF.EMPTY(1) // If parameter1 is empty
print “The first parameter is empty (not used)”;
#ENDIF
#IFNOT.EMPTY(1) // If it is not empty
print “The first parameter is NOT empty, it is 1”;
#ENDIF
A = 3 + 4; // param2 is assigned param3+param4
#IF.ARG(1) // IF parameter1 is 1
print “Parameter1 has the value 1”;
#ENDIF
#UNDEF.ARG // The macrovariable ARG is undefined
The results of the above statements are two prints and an assignment.
A is assigned the value 7 and two lines are printed on the screen: “The first parameter is NOT empty, it is 1” and “Parameter1 has the value 1”.
If you referenced the complex macro without parameters 2-4, the result would have been:
= + ; // param2 is assigned param3+param4
And hence a compilation error occurs though you cannot see that the macro is actually expanded in this way (which makes the error harder to find).
Using macro libraries
To use a macro library, you must create the library (say TestMe) using the Application Object Tree and then load the macro using the following construct:
#TestMe;
A more preferred way of referring macro libraries is using the #macrolib keyword the advantage of using this keyword is that you will be able to reference macors with special characters and multiple lines look at the example below where a special character (") doube quote had to be used in a macro
1. #define.TableRead(select * from EmplTable where EmplTable.EmplCode == %1;)
#TableRead("E0006")
info( emplTable.EmplCode );
2. #localmacro.TableRead
select * from EmplTable where EmplTable.EmplCode == "%1";
#endmacro
#macrolib.training
#TableRead(E0006)
info( emplTable.EmplCode );
The second way is the preferred way of creating multi line macros also if the macro includes some special symbols like ) or " then the second method is preferred if you notice in the first method the double quote are passed in the parameter to the macro as they could not be a part of the macro as in the macro definition the macro would end at the first instance of the double quote.
Inheritance and Macros
The macros defined in the class declaration of the base class are available in the sub classes however if one of the class in the hierarcy undefines the macro then that point onwards the macro are not available in the child classes.
Sunday, July 04, 2010
37 "Signals" From 37 Signals
2) Writing a plan makes you feel in control of things you don’t actually control.
3) You have the most information when you’re doing something, not before you've done it.
4) Stuff that was impossible just a few years ago is simple today.
5) Failure is not a prerequisite for success.
6) Don’t make assumptions about how big you should be ahead of time.
7) Don’t sit around and wait for someone else to make the change you want to see.
8) When you build what you need, you can assess quality directly instead of by proxy.
9) Solving your own problem lets you fall in love with what you’re making.
10) What you do matters, not what you think or say or plan.
11) When you want something bad enough, you make the time.
12) The perfect time to start something never arrives.
13) Start a business, not a startup.
14) You need a committment strategy, not an exit strategy.
15) Huge organizations talk instead of act, and meet instead of do.
16) Build half a product, not a half-assed product.
17) Getting to greatness starts by cutting out stuff that’s merely good.
18) The real world isn’t a place, it's an excuse. It's a justification for not trying.
19) The big picture is all you should be worrying about in the beginning. Ignore the details.
20) Decide. You’re as likely to make a great call today as you are tomorrow.
21) The longer it takes to develop, the less likely it is to launch.
22) It’s the stuff you leave out that matters.
23) Focus on substance, not fashion. Focus on what won't change.
24) When good enough gets the job done, go for it.
25) When you make tiny decisions, you can't make big mistakes.
26) Pour yourself into your product.
27) You rarely regret saying no but you often regret saying yes.
28) Better your customers grow out of your product, than never grow into them.
29) You can’t paint over a bad experience with good marketing.
30) All companies have customers. Fortunate companies have audiences too.
31) Instead of out-spending your competitors, out-teach them.
32) Let customers look behind the curtain.
33) Leave the poetry in what you make, there is beauty in imperfection.
34) Marketing is not a department, it's the sum total of everything you do.
35) Don’t hire for pleasure; hire to kill pain.
36) Don’t make up problems you don’t have yet.
37) A business without a path to profit is a hobby.
Unlock a protected excel sheet
Came across this amazing macro which would disable the password and make the columns selectable.
http://mcgimpsey.com/excel/downloads/allinternalpasswords.xls
basically when this excel sheet was opened a new addin button is created which could be used to unlock the sheets.