Pages

Thursday, May 12, 2016

A dynamic strFmt call

In the communities a users asked about a way to make a dynamic strFmt call, not knowing the number of parameters up front.

With some good critical tests from Levgen Miroshnikov (blog) I think I have managed to write a class method that does that.

Regular StrFmt will round decimal value and change the decimal point to whatever fits your windows locale. This method has a parameter allowing you to keep the formatting of decimal values.

Here is the code for it:
public str dynamicStrFmt(
    str         _expression,
    container   _args = conNull(),
    boolean     _keepRealsDecimals = false)
{
    str         ret;
    Counter     counter;
    str         argStr;
    char        argChar;

    if (_args == conNull())
    {
        return strFmt(_expression);
    }

    for (counter = 1; counter <= strLen(_expression); counter++)
    {
        if (subStr(_expression, counter, 1) != '%')
        {
            ret += subStr(_expression, counter, 1);
        }
        else
        {
            // This is a point in the string where an argument starts
            // Find the end of the argument
            argStr  = '';
            argChar = subStr(_expression, counter + 1, 1);
            while (argChar && argChar == strKeep(argChar, '0123456789'))
            {
                argStr += argChar;
                argChar = subStr(_expression, counter + strLen(argStr) + 1, 1);
            }

            // Lookup and insert the value to the result
            if (argStr)
            {
                // Check that the argument is within the bounds of the number of supplied argument values
                if (str2Int(argStr) <= conLen(_args)) 
                {
                    if (typeOf(conPeek(_args, str2Int(argStr))) == Types::Real && _keepRealsDecimals)
                    {
                        ret += num2str(conPeek(_args, str2Int(argStr)), -1, numOfDec(conPeek(_args, str2Int(argStr))), 1, 0);
                    }
                    else
                    {
                        ret += strFmt('%1', conPeek(_args, str2Int(argStr)));
                    }
                }
                else
                {
                    // The argument is not within the bounds of the supplied argument values. Keep the argument unchanged.
                    ret += subStr(_expression, counter, 1) + argStr;
                }
                // Move the current position in the _expression string to a position after the argument
                counter += strLen(argStr);
            }
            else
            {
                // Didn't find the argument to be meningfull, so just add the argument character as-is
                ret += subStr(_expression, counter, 1);
            }
        }
    }

    return ret;
}

And a main method for a quick demo:
public static void main(Args _args)
{
    aaaStrFmtBuilder    demo = new aaaStrFmtBuilder();

    info (demo.dynamicStrFmt("%1 + %1 = %2", [2, 4]));
    info(demo.dynamicStrFmt("%1/(%2*%1)", [1000, 0.135], true));
    info(demo.dynamicStrFmt("%2 %3 %1", ['AX', 'Microsoft', 'Dynamics']));
}

And here you can download a project with the class and unit tests for it:
 

The two classes are prefixed with 'aaa', making it easier for you to find them in the AOT :-)
Please change the names if you are going to use the code for something real.

Monday, May 9, 2016

Use Visual Studio to merge code for an AX 2012 CU

Here is a great explanation about how you use Visual Studios merge tool to merge files: https://roadtoalm.com/2013/10/22/use-visual-studio-as-your-diff-and-merging-tool-for-local-files/

You can find of plenty other tools for compare and merge on the Internet, but you probably already have a Visual Studio license. Here is an overview of other tools: https://en.wikipedia.org/wiki/Comparison_of_file_comparison_tools