I'm at my wit's end and need some help coming up with a definitive solution to this problem that I've seen pop up on these discussion forums multiple times.
I have a Survey123 Connect form where one of the entries is a number that needs to be inputted as a decimal value with a precision of 2 decimal places. After searching on these discussion forums, I have found multiple potential responses and none of them seem to work. Here's a breakdown of what I've tried. If someone can poke some holes and/or confirm these, I would be grateful.
1. Format for decimal numbers
Using this method, recommended by James Tedrick, to input the constraint as
seems like it should work. It's a simple check to see if the current value, multiplied by 100 matches the integer value of the same thing. If it's not 2 digits, the first part will still have a decimal point and, therefore, won't match. Unfortunately, there's either a bug in this or I'm not reading through this correctly because *most* numbers to 2 decimal places work except for 1.09, 1.10, and on up to 1.16 don't work. Typing in 1.08 or 1.17 is accepted fine but not anything in between. Even 2.09, 10.09, and 101.09 work, just not 1.09. I have no other constraints set (the quote is copy/pasted from James' post into my sheet and then into this comment) and no other fields on the XLSForm filled other than type (decimal), name, and label with a constraint and constraint message. There may be more very specific numbers that don't work but I haven't been able to find any others in my random testing.
2. survey 123 decimal places
This post advises the use of an input mask which is mildly helpful with the big caveat that numbers have to match the mask exactly so a mask of '9999.99' will only allow 4 digits before and 2 digits after the decimal. That means that numbers need to be padded if they're not large enough (e.g., 0001.15 using the example number from above) and they cannot be larger than the number of digits in the mask (e.g., 10,015.15 is not possible as an entry for the mask '9999.99'). Another user recommends a regex expression but I'll cover that below. Based on the link provided by Ismael Chivite, there is only the option to use the input mask for *required* digits, not optional. Our specific use case could be as little as 0.05 and as much as 10,000.00 (possibly more but it's never happened).
3. Creating a constraint for 3 digits after the decimal in Survey123
This post suggests a regex expression (which was also suggested in the previous thread, although with a different expression) so I attempted again with this expression:
regex(., '^[0-9]+\.[0-9]{2}$')
Based on that expression, it should be looking for one or more numbers at the start of the input followed by a decimal and then exactly 2 digits. It works for the example case of 1.15, 1.09, and also 101.15 but it fails with 1.10 and 1.20 or any other input that ends in 0, despite the fact that this should be allowed by the regex expression. Modifying the end of the expression from {2} to {1,2} allows for 1.10 and 1.20 but then it won't allow 1.00 or 2.00. It seems like the regex filter can't deal with 0's at the ends of strings properly. The post linked above also mentions this non-zero issue but there's not really a solution for it in any comments that I could find.
There is a suggestion mentioned at the bottom, by James again, that gives some arithmetic checks that should give the format desired:
Another way to multiply the number by the number of digits you are looking for and
- check to see if there is any decimal component left (${q}*1000 - int(${q})*1000) > 0
- check that the last digit is non-zero (${q}*1000) mod 10 > 0
but I wasn't able to convert or translate those into any reasonable constraints that worked for the conditions I tried. I tried using an 'and' operator to combine those 2 statements (.*100-int(.)*100)>0 and ((.*100) mod 10>0) but to no success. It still accepted 1.1 and 1.152 and anything else I threw at it.
------
All of this to ask: "What's the 'proper' way to enforce precision for decimal numbers?"
I've seen so many different responses on this and it seems like it should be something that's somewhat easy to implement and, most importantly, consistent. Unfortunately, I can't seem to find what's the "right" way to enforce this that lets me specify any number so long as it's precise to 2 decimal places.
HALP!