API
@-Formulas
JavaScript
LotusScript
Reg Exp
Web Design
Notes Client
XPages
 
Using @For in Input Validation
For a recent project, developed exclusively in Notes 6, there was extensive use of reader fields for security. The users could put in who they wanted to see the documents. Naturally, the users would put in a flat name, or an internet email address, or something else that Notes wouldn't recognize for granting access. So we wanted to validate all the names for the reader field.

Since the client base was exclusively Notes 6, we could make use of @For to validate all the names individually. This allowed us to give a better error message to the user. For example, prior to looping in the Notes client formula language, you could easily look for the presence of an "@" sign in one of the entries in a multiple value field, but pulling it out to show to the user was a bit of a pain (although not impossible). With looping, it's a lot easier to follow and support.

But, you have to be careful where you put your @Failure in your formula. If you put it inside your loop, it will actually never execute. So the best thing to do is keep a message with the failure. If the message is empty, then it's a success. Here's an example of the input validation for a readers field:

N := @ThisValue;
Msg := "";
@For(i := 1; i <= @Elements(N); i := i+1;
    @If(@Contains(N[i]; "@"); Msg := "Error! You cannot have the \"@\" sign in any of your reader names for access to be properly granted. The name \"" + N[i] + "\" is invalid."; (!@Matches(N[i]; "*/*")); Msg := "Error! The reader names must be fully qualified for access to be properly granted. You should enter names in a format like \"" + @Name(Abbreviate; @UserName) + "\". The name \"" + N[i] + "\" is not fully qualified."; 0)
);
@If(Msg = ""; @Success; @Failure(Msg))

So, we loop through the values in the current field (note the use of the new 6 formula @ThisValue). Every time we find an error, we update the variable Msg and continue (note that in 6 we can reuse variables by just assigning them again - no need to use @Set any more). So we are technically finding the last error if there are multiple names incorrect. Each message is a description of the error, plus an indicator of which element is incorrect (note the use of the new 6 way of getting at elements of an array). Also note how we use the current user's abbreviated name as an example when a name is not fully qualified. It shows the user what format is needed, in a way they can understand.

When we are finished going through all the names individually, if Msg has not been updated, then the validation formula succeeds. If it was updated, the validation formula fails and we give the user the already-built message.

Note that if you like using @Transform, this is a perfect candidate for using that formula. Here's the same validation formula, but using @Transform:

Msg := "";
@Transform(@ThisValue; "X"; @If(@Contains(X; "@"); Msg := "Error! You cannot have the \"@\" sign in any of your reader names for access to be properly granted. The name \"" + X + "\" is invalid."; (!@Matches(X; "*/*")); Msg := "Error! The reader names must be fully qualified for access to be properly granted. You should enter names in a format like \"" + @Name(Abbreviate; @UserName) + "\". The name \"" + X + "\" is not fully qualified."; 0));
@If(Msg = ""; @Success; @Failure(Msg))

Since we just refer to a temporary variable for each of the elements of the field, we don't need to define our own temporary variable and simply include @ThisValue once. Again, we update the temporary variable Msg if we find something that will fail validation. And the final value of this variable is either one of the messages, or the empty string, which we use to perform the actual validation.