Strange CurrFieldNo behavior

This is the first "auto-blog" in my holiday ... if good, I arrived in Los Angeles and I should be heading to Las Vegas .. with the Camper.

But anyway ...

A while ago, I promised a good friend to blog something he noticed and investigated. Gary Winter is the name, and I'm sure some of you will certainly know him ... especially those who visit conferences once in a while ... he's always there Smile.

He noticed a strange behavior of the internal "CurrFieldNo" functionality, which might need your attention, because it can have an impact on your developments. In fact, I'm sure that people have been writing code in their applications, without even knowing or realizing there is an issue with this ... which you should watch out for... .

What's the fuss?

Simple. You often write code on table-level (or at least, I hope you do). You do this usually OnValidate. When using this trigger, you can use the CURRFIELDNO. This statement is useful when you want code (functions) to behave differently when called from certain fields ... or like "help" describes:

This variable specifies the field number of the current field in the current form.

Now, let's put his code for example in the OnValidate trigger of the Description-field in the Sales Line table:


VALIDATE("Description 2");


You'll see that the code behaves like it should behave. Two times, it gives a messages with 11 being the result. Now, let's put this beautiful piece of business logic in a codeunit and pass the record by reference, so that the code looks like this in my codeunit:

ValidateDescription2(VAR SalesLine: Record "Sales Line")

SalesLine.VALIDATE("Description 2");

and in my Sales Line table:

Description - OnValidate()




If you run it now, you'll see that the CurrFieldNo is LOST. Second message results in "0". You can imagine that code like this has been written by ISV's all over the place. You want to write good code, so you don't want to stuff all your extra code into the standard object, but handle it nicely outside in your own codeunit. But when you come back ... the CurrFIeldNo is lost!

Oops .. didn't realize that. Is there a way to code around it?

Yes there is. Just add two lines of code in your function of the codeunit, so your codeunit would look like this:

ValidateDescription2(VAR SalesLine: Record "Sales Line")

SalesLine2 := SalesLine;

SalesLine2.VALIDATE("Description 2");

SalesLine := SalesLine2;

So, just use a temporary variable to do your validation of "Description 2". Only when you do it like this, the CurrFieldNo will be restored.

Is that all?

Well, actually not. There is one more oddity to it .. . You see that I have validated the field "Description 2". With that particular field, the CurrFieldNo might actually NOT be destroyed at all, because ... Because there is no code in the OnValidate trigger of the field "Description 2". And if there's no code in a trigger, NAV seems not to run through it at all, which has the side effect of the CurrFieldNo variable also not being touched. So, there's different program behavior on account of there being code in a trigger or not....

I don't know if this was clear to you ... but I do hope it got you thinking about it .. or made you aware of it.

Good luck and thanks Gary!

Here you can download some objects, which illustrate the CurrFieldNo-behaviour nicely...

Comment List
  • uhm .. I didn't .. :-/

  • Thank you,

    that saved me a lot of time.

    Did nobody reported it to Microsoft yet so that it would be fixed? At least I could not find a KB article mentioning it.

  • That's indeed one other way to code around it.

    I have been testing it in 4.0, 5.0 and 2009, so it must have been there for a while.  I didn't know either, but I must say, I try to avoid having to use the currfieldno ...

  • That's interesting. I never saw this before. (I wont try it because I trust you).

    I wonder if this has always worked like this? I use currfieldno a lot, and I never saw this problem maybe its in a newer version. I assume you tested in 2009?

    Also knowing this now, I would rather save currfieldno before calling the function, like

    Description - OnValidate()

    CurrentField := CURRFIELDNO;

    MESSAGE('First Time: %1',CurrentField);


    MESSAGE('Second Time: %1',CurrentField);

    To me that would be more clear and simple.