Conditional Default Values

Sometimes you want the default value of a field to be dependent upon a condition. However, there isn’t any direct functionality to support IF statements in the default values of fields. Substituting a rule for a default value only gets you so far, as the rule is only applied when that field that changes, not the fields that the rule depends on. Updating the field whenever any dependent field is changed would require you to copy the rule to each field.  This is not very maintainable, so below I will describe two approaches to avoiding this.

The first approach is simple, but it has some limitations and caveats.  The second approach is more complicated, but should work in all cases. 

Method 1: Using the union and array indexer operators

The first approach is to use the union operator ‘|’ along with an array indexer ‘[]’ to select the proper value.  For example,

if (BoolCondition) {
} else {


(TrueResult | ElseResult) [(BoolCondition) + 1]

You can see that (TrueResult | ElseResult) creates a node set, while [(BoolCondition) + 1] selects which node to choose.  BoolCondition will evaluate to 0 or 1 (depending on its truth value).  Then 1 is added because the node set is 1-based, not 0-based. 

As a simple example, say that you want to set field3 to field2 if field2 is 10 greater than field1; otherwise set field3 to field1.  On field3’s default value, the expression would be

(../my:field1 | ../my:field2)[( ../my:field2 > ../my:field1 + 10) + 1]


There are two caveats to using this approach:

1) The node set will always be returned in document order. It does not matter what the order is in the parenthesis, as (field1 | field2) == (field2 | field1). Since you cannot change the node set ordering, you may have to modify your BoolCondition to be NOT-ed. For more information on document order, you can visit the page on XPaths.
2) Inside of the parenthesis, you must only have nodes; you cannot have strings or any other type. So (field1 | “hello world”) will not work.

Method 2: Using concat, substring and string-length

To overcome these caveats, you can use the second approach here.  That is to use concat, substring and string-length.  For example, the same generic if statement from the previous approach converts to


substring(TrueResult, 1, (BoolCondition) * string-length(TrueResult)),

substring(ElseResult, 1, (not(BoolCondition)) * string-length(ElseResult)))

The key here is that BoolCondition will evaluate to 0 or 1.  Therefore, the first substring will either take no characters (if BoolCondition is false), or it will take all of the characters (if it is true) of the TrueResult.  Conversely, the second substring is evaluated with the “not” condition.  Therefore, either the TrueResult or the ElseResult will be returned in their entirety, but not both. 

Let’s say that we want to use the same example as the first approach above,


substring(../my:field2, 1, (../my:field2 > ../my:field1 + 10) * string-length(../my:field2)),

substring(../my:field1, 1, (not(../my:field2 > ../my:field1 + 10)) * string-length(../my:field1)))

The major advantage to this approach is that you can use strings, numbers or anything else as the TrueResult and ElseResult.  For example, we could have placed “Success” and “Undefined” instead of ../my:field1 and ../my:field2. 

That is all you need to create conditional statements in your default values! I'm attaching a sample form template that has this technique implemented (save the XSN locally before opening it). This method works on InfoPath 2003, 2007, and in browser-enabled form templates. 

Thanks to Alexei Levenkov and Gary Hsu for their assistance on this article. 

Nicholas Lovell
Software Design Engineer


Comments (25)

  1. DavidAir says:

    There could be a third caveat for the first approach: it might cause extra postbacks in browser-enabled form templates (something to be verified). Form performance is always an important consideration for those so sometimes a more cumbersome method could yield fewer postbacks.

  2. Similar to performing elapsed time calculations, creating a new date or time value based on a previous

  3. When the BoolCondition is a bool xml element which can be null, the result of Method 2 will be an empty string.

    To resolved this problem, the condition should be modified like this:


    substring("Yes", 1, not(not(IsTrue)) * 3),

    substring("No", 1, not(IsTrue) * 2)


    The double not() function will convert null value to false, then the result will be right.

  4. jeff.arrington says:

    For selecting the default values this does work as desired, however if the user then changes the field value, it will revert back to the True or false value accordingly. There are no rules applied nor data validation being applied. Why will it not accept the new value and why would it possibly be revering back to resulting default value?

  5. JasonEley says:

    Excellent post. Another caveat to Method 1….the expression is not supported by Form Server (MOSS 2007). The expression in Method 2 is however.

  6. UPDATE: Due to the number of requests for adding more columns to this sample, I have re-designed how

  7. ElenaS says:

    Not sure if you can help me, but I am trying to work with a repeating table from a Batch data source and I want the table to automatically populate with values already existing on the form. The problem is that on this repeating table I cannot see on the Design side all the fields in the revolving table…It automatically picks up the field names from the Batch file when I do a preview.

    What i would like to be able to do is say:

    when FieldName="Title" then FieldValue=Field1

    when FieldName="FirstName" then FieldValue=Field2


    but it tells me that FieldName (it writes it as @Name) is not a valid field or group (probably because it is not assigned a specific value, it contains 4-5 rows).

    Is there any type of logic I can write to fix this issue?



  8. infopath says:

    Hi Elena,

    I provided an answer to this quesstion in the Submitting to a SharePoint list post.


  9. Elfoamerican says:

    I believe there is also Method 3 in addition to Method 2 where you can do the same but without error prone hardcoding of symbol positions. I have the working example here:

  10. Waltervonallmen says:

    Hi (Scott ?)

    I adopted the example with the concat and substring function to the following:

    concat("Inbetriebnahme der "; tbxGerInfName; " Firewall des Herstellers "; tbxGerInfHersteller; "."; substring("Softwareupdate auf die Version " + tbxGerInfSWVersion; 1; (string-length(lbxGerInfSWUpdate) = 2) * string-length("Softwareupdate auf die Version " + tbxGerInfSWVersion)); substring(" "; 1; (not(string-length(lbxGerInfSWUpdate) = 2)) * string-length(" ")))

    But I always get following output:

    Inbetriebnahme der "tbxGerInfName" des Herstellers "tbxGerInfHersteller".NaN

    So the first sentence is absolutly right. But what’s the meening of "NaN" in the second sentence?


  11. infopath says:

    Hi Walter,

    "NaN" means "Not a Number" – so your expression is returning something that is not recognized as numeric value.


  12. Waltervonallmen says:

    OK, and do you know what might be the reason for this in the snippet above?


  13. infopath says:

    Hi Walter,

    Not offhand…so I would suggest starting fresh with your expression and just bring in the parts piece-by-piece to see where it fails.


  14. KLF says:

    Along the lines of conditional values- I am creating a form to be accessed in a browser and I am trying to set conditional formatting. I want to make a set of check boxes appear if one certain check box is checked (for instance field 1 is a check box- if they check box 1- fields 2 and 3 appear and are also check boxes). I have tried to set a rule and it's not letting me. Please help!

  15. Mark says:

    The disconnect between InfoPath 2010 and SharePoint seems very large.  IF statement functionality is allowed for default values in Sharepoint list fields.  Simply opening a form in InfoPath, making a minor layout change and publishing, breaks your default value because InfoPath 2010 does not allow IF statement functionality.

    Metadata fields don't even try to work in InfoPath 2010.  As a customer, it's very disheartening when you want to make a simple change in Sharepoint and it forces you to open up another tool (in this case InfoPath), and then the tool does not have what the user sees as basic functionality, or the functionality is completely different.

    It seems like the Sharepoint and InfoPath teams at Microsoft are working independently of each other, and there's a major disjoint between the products.  Which, a user is expecting to be seemless between the products because SP forces InfoPath on the user.

  16. Jeff Mather says:

    Here's a formula for the name of a day of the week, using the above technique, in case anyone could use it:

    concat(substring("Sunday", 1, (@DayOfWeek = 1) * string-length("Sunday")), substring("Monday", 1, (@DayOfWeek = 2) * string-length("Monday")), substring("Tuesday", 1, (@DayOfWeek = 3) * string-length("Tuesday")), substring("Wednesday", 1, (@DayOfWeek = 4) * string-length("Wednesday")), substring("Thursday", 1, (@DayOfWeek = 5) * string-length("Thursday")), substring("Friday", 1, (@DayOfWeek = 6) * string-length("Friday")), substring("Saturday", 1, (@DayOfWeek = 7) * string-length("Saturday")))

    I wish InfoPath didn't make us jump through such awkward hoops to accomplish simple stuff like this!

  17. Joe says:

    How do I go about an situation like the following

    I want to create a conditional expression which will give a result with the following conditions

    If field1 < 29 = A

    If field1 >29 and <39 = B

    If field1 >39 and <49 = C

  18. Scott Heim says:

    Hi Joe,

    This example will only work when there is one test and the result is true or false…in your example, there are multiple tests. So the best way to accomplish what you need is to use a Rule on field1 (with 3 conditions) that sets the value of field2 based on the conditions you have in the Rule.

    Here is what I have as a sample:

    – Main Data Source:




    – 3 Rules on field1 as follows:

    Rule 1:

        Condition: field1 < 29

        Action: Set a field's value: field2 = "A"

    Rule 2:

        Condition: field1 > 29 and field1 < 39

        Action: Set a field's value: field2 = "B"

    Rule 3:

        Condition: field1 > 39 and field1 < 49

        Action: Set a field's value: field2 = "C"


  19. Mojtaba Aliakbari says:

    The expression

    if (BoolCondition) {


    } else {




    (ElseResult | TrueResult ) [(BoolCondition) + 1]


    (TrueResult | ElseResult ) [(BoolCondition) + 1]

  20. Nicholas Lovell says:

    Actually, (ElseResult | TrueResult) == (TrueResult | ElseResult).  Check out the caveat noted above:

    … The node set will always be returned in document order. It does not matter what the order is in the parenthesis, as (field1 | field2) == (field2 | field1). Since you cannot change the node set ordering, you may have to modify your BoolCondition to be NOT-ed. For more information on document order, you can visit the page on XPaths.

  21. Corrie Sigler says:

    I am trying to do something similar but can't figure it out.  

    If Field A contains data display in Field C otherwise display Field B.  Can you give me an example to resolve please.

    Many thanks!

  22. Scott Heim says:

    Hi Corrie,

    I should be able to assist but I would like to get a bit more information. So you have 3 fields on your View: FieldA, FieldB, FieldC. If "FieldA" contains data, you want to display that data in "FieldC"? Then if "FieldA" is blank you want to display "FieldB"? I just want to be sure I follow what you are trying to accomplish.


  23. Jim Gagliardo says:

    Thanks for this post.  Not much documentation out there for this.

  24. Thinley says:

    I am designing a form in Microsoft Infopath. I need itself to automatically generate the end of project date once I type the date of start and duration of the projects in months. For instance, my project starts on 25/07/2013 (Field-1) for the duration of 3 months (Field-2). What should the formula be in the Field-3, so that project end date is automatically generated in Field-3?

  25. Anon says:

    Thanks for taking the time to write this! Really helpful.

Skip to main content