No valid document identified from the entity key

I recently encountered this problem while using the AIF framework in Dynamics AX 2009. I got it in the AIF Queue manager when one of my messages failed.
Since the message “No valid document identified from the entity key” doesn´t really give you a good clue of that the problem really is, I had to do some debugging. I found that the error occurred when the class AifConstraintListCollection did not contain any constraints and the message(document) was associated with a query.

Continue reading No valid document identified from the entity key

Hide the Content Pane in AX 2009

For developers the ‘Content Pane’ can contribute to a great deal of frustration.

Specially for does who are used to develope in AX 4 or earlier.

Here is a small job that will hide it for you:

1
2
3
4
5
6
7
8
9
10
11
12
static void Job1(Args _args)
{
    #WinAPI
    ;
 
    WinApi::showWindow(
        WinApi::findWindowEx(
            WinApi::findWindowEx(
                WinApi::findWindow('AxMainFrame', ''),
                    0, 'MDIClient', ''),
                        0, 'ContentFrame', ''), #SW_HIDE);
}

Replace #SW_HIDE with #SW_SHOW to show it again.

Using Regular Expressions in Dynamics AX

When working with strings, ex. replacing text, validating content or simply checking for existence, It can sometimes be a good idea to consider using Regular Expressions (RegExp), insted of using ordinary string manipulation methods.

X++ itself does not seem to support Regular Expressions, but we can use the .NET functionality.

Below is an example method of how to validate that an email address is written in a proper format.

1
2
3
4
5
6
7
8
9
10
11
Static Server boolean validateEmail(EMail   _eMail)
{
    Str MatchEmailPattern =
    @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$";
    System.Text.RegularExpressions.Match myMatch;
    ;
 
    myMatch = System.Text.RegularExpressions.Regex::Match(
    _eMail, MatchEmailPattern);
    return(myMatch.get_Success());
}

It simply returns true if the input is a properly formatted email.

To replace text in a string you could do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void Job1(Args _args)
{
    Str EmailPattern =
    @"\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b";
    Str ReplacedText;
    ;
 
    ReplacedText =
    System.Text.RegularExpressions.Regex::Replace(
    "My email address is: example@haxx.net",
    MatchEmailPattern,"blabla@haxx.net");
 
    print ReplacedText;
    pause;
 
}

This will replace ALL found email addresses.

Below is an example of how to “find” all matches.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static void Job6(Args _args)
{
    Str MatchEmailPattern =
    @"\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b";
    System.Text.RegularExpressions.Match myMatch;
    ;
 
    myMatch = System.Text.RegularExpressions.Regex::Match(
    "Your email: youremail@host.net, and my"
    +"email: myemail@anotherhost.com", MatchEmailPattern);
 
    while (myMatch.get_Success())
    {
        print myMatch.get_Value();
        myMatch = myMatch.NextMatch();
    }
 
    pause;
}

Notice the difference between the RegExp pattern in this example and the first example.

The first pattern checks if the input is valid.

And this pattern checks for ALL valid matches.

For more information about regular expressions visit:
www.regular-expressions.info

Problem with str2enum

Just found a strange behaviour in using the standard str2enum function. Consider the following code ;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static void TestOfEnumsWithFirstValueBlank(Args _args)
{
    ProjCategoryType selectedType;
    str              s;
    ;
 
    selectedType = ProjCategoryType::None;
    s = enum2str(selectedType); // get enum string
    print s; // shows nothing, since None has no label.
 
    selectedType = str2enum(selectedType,s); // convert back
 
    if(selectedType == ProjCategoryType::None)
        print "'None' selected";
    else
        print "undefined..."; // sadly this is printed..
 
    pause;
}

This example code prints undefined, NOT ‘None’ selected. This because str2enum does not handle an empty string in a correct way, even if one of the values in the choosen enum has the emptry string as it’s label. This means values to str2enum must always be validated first before each call..

Create class and methods in x++

This job does three things.

1. Creates a new class, compiles and saves it.

2. Finds the class and adds a new static method to it.

3. Calls the new method using DictClass.

Continue reading Create class and methods in x++

Simple field lookup in form

This is a simple way to add a custom form lookup to a new field with x++ code. This example is done with a test table named FO_TestTable that has the three fields “TestField1”, “TestField2” and “TestField3”. The table FO_TestTable has an index named “TestIdx”.

I have added a field on the table CustTable named TestField1. On this field that now can be found on CustTable form on the CustTable datasource node, I have added the “Override method” “lookup”.

Below you can see how I have edited the method lookup to fit my needs. Notice that the sysTableLookup is based on an ordinary query, this means that you can manipulate this query as you see fit.

Continue reading Simple field lookup in form

Sorting containers with multiple levels

I encountered a scenario where I wanted to find a record of a certain type somewhere in a big container. This got med thinking, and the result is the code below. I wanted to be able to loop through a container no matter how big it was or how many levels of new containers it contained.

This job searches through the container con1 and sorts the types Integer, Real and String into separate containers. In itself this job might not be very useful, but my goal was to build something that could easily be modified to work in many different cases when looking for different values in containers.

It also finds the specific records of VendTable, CustTable and SalesTable that I hid inside the container structure.
Continue reading Sorting containers with multiple levels

Total discount is calculated automatically – Bug

Update: This issue was reported and has a hotfix that can be downloaded from Microsoft. Just create a new support issue on the partnersource and ask for the following:

Knowledge Base ID: 953178

Original post

The following checkbox ”Total discount is calculated automatically” makes sure that every order has its total discount calculated before it is posted.

Accounts Recievable/Setup/Parameters/Prices tab

AR - Parameters - Prices

This is done in the “clicked method” that executes when the posting button is clicked, this means that total discount is calculated on the sales order even before you get the dropdown where you can choose the different types of posting i.e. Invoice or Confirmation. But as it turns out, this does not seem work if you multiselect in the sales order form(Click thumbnail below to see the form).

Continue reading Total discount is calculated automatically – Bug