Hello, I know this is an older question, but I want to give my solution to the stated problem, given other people might find this thread helpful later.
I faced a similar problem of counting species in repeating groups while preserving a continuous species ID. This ID is used to mark samples in the field, the ID shown to the data collector must be the same as the one submitted with the form.
Having 134 species of fish in the list of choices makes it cumbersome to keep one or two variables per species.
Disclaimer: I'm not 100 % sure this approach is fully functional, but some initial testing seems to show both options below preserve species ID's correctly.
Let me know how I could improve this approach, I'm not very familiar with the use of ODK and XLSForms yet.
Option 1 (only works in ODK Collect, not in Enketo):
I used a string-array as suggested by Mathieu, but counting grouped occurrences with regex is unfortunately not supported in ODK. Neither is string substitution, we can only have character substitution with the (poorly named?) translate()
My solution was to join together a string database but buffering each species' abbreviation with the symbol '#' to a 10-character string. Note that ODK Collect joins together variables inside nested repeat groups differently than Enketo. The latter joins occurrences within the whole form, it seems.
For each individual species entry, I then use an internal repeat to iterate through all previous db entries (all 10 characters wide) and compare it to the current string. For each match, I create a new string-array that contains 'x' for each matching species in earlier repetitions.
The use of once()
at the start of a repetition to get a current snapshot of the database, causes a small problem as it means we can't go back and re-edit previous entries. If somebody does, the ID sequence breaks and sample labels will not be correct. So users have to be told not to go back and change repetitions while filling the form.
Enketo, unfortunately, has a bug that nested repeat groups do not update properly, which makes Option 1 only usable in ODK Collect: https://github.com/enketo/enketo-core/issues/830
example_countrepeat.xlsx (21.4 KB)
Option 2 (works in both ODK Collect and Enketo)
I used a similar approach as in option 1, but instead of having a single 'db' with all joined strings, I have one string array for each species. Entries to these species-arrays are made on every repetition, either 'x' for a match or '-' for no match. I then used translate()
and string-length()
to get which ID the current species should have. Here I also had to use once()
to keep track of the state of the string-arrays at the start of the repetition.
I didn't attach a xlsx for option 2 due to limited time. I can provide that later if somebody is interested.
Edit: small clarifications and formatting