Format note summary for repeats in collect and enketo

Hi,
How can I get one or more summary notes with data from a repeat question, when the number of repeats is not known beforehand? In the attached form I'm creating the notes and then show them depending on the count of the repeat. But with this approach I basically have to set a maximum number of repeats that will be shown in the summary. Is there a way to show all the summaries independent of number of repeats?

Additional questions:

  1. What is the best way to have newlines in notes that works for both Collect and Enketo? In the documents I see I can use markdown, and this StackOverflow question shows different ways of having newlines in markdown. But I haven't found one way that works consistently for both collect and enketo. Using <br /> works for collect, using 2 spaces and then 2 newlines works for enketo, but gives an extra newline in collect. (screenshots below)

  2. Is it possible to use instance() to get the data from a repeat? @LN you showed me how to use instance instead of pulldata so that I can use it directly in the label of the note, is something similar possible with repeats?

  3. I can upload and use the form in Kobo, but ODK Central version v2023.5.1 gives me an error:

The XLSForm could not be converted: ODK Validate Errors:
>> Something broke the parser. See above for a hint.
Error evaluating field 'pn1' (${pn1}[1]): error in evaluation of xpath function [choice-name] => java.lang.NullPointerException[null]
Caused by: org.javarosa.core.log.WrappedException: error in evaluation of xpath function [choice-name] => java.lang.NullPointerException[null]
	... 10 more

The following files failed validation:
${Hydrophonic} Control Sheet.xml

Result: Invalid

Hydrophonic Control Sheet.xlsx (451.1 KB)

Screenshots using Notepad++ to show the newlines and spaces:
Using <br/> and having one single line in the cell show correctly in Collect but shows the <br/> tag in enketo:


collect-collect 1
enketo-collect1

To show correctly in enketo I have to use 2 spaces and 2 newlines
npp summaryenk1
enketo-enketo-1
But then it shows an extra newline in collect:
collect-enketo-1

In the xlsform I've tested other options for newlines, but it seems that I'll have to go with the option of showing correctly in Enketo and have an extra newline in Collect, unless I use the deviceid to check if the form is using collect or not, to show one note or the other.

Yes, but in Collect each repeat instance's summary would be on a different page. You'd accomplish this by wrapping the summary information in a repeat with a repeat_count. Instead of using fixed indexes to look up different values in the editable repeat, you'd use the position in the summary repeat (similar to this documentation). I can share an example if you need more details than that.

Most of the summary screens we've seen involve computations of some kind: sums, averages, values that were skipped (e.g. if not all plot names are represented). In this case, it looks like you want to show exactly the same data, is that right? Can you say more about your workflow and why you want to show this data in a read-only summary? Maybe there's a lot more to the form that wouldn't be included in the summary? @aly has recently worked on some mockups of a built-in summary screen so this is interesting to see.

I don't believe there's an approach that results in a consistent display, unfortunately. This has bothered me before but I don't think I've ever seen any other complaints about it! We have it tracked as part of a broader issue around styling between the Collect and Enketo in the Collect/Enketo differences tracker. I usually just use newlines and don't mind the vertical spacing in Collect. What's going on there is that Collect replaces the newline with a paragraph break.

The instance function is to specify which choice list or external file to look values up in. After the instance call, there's an expression to look values up like /root/item[name=${id}]/property. You can use this same kind of lookup in a repeat and that is what the indexed-repeat does under the hood.

An example from your form:
indexed-repeat(${plotname}, ${plotinfo}, 1)
can also be expressed as
${plotinfo}[position() = 1]/datagrp/plotname
or
/data/plotinfo[position() = 1]/datagrp/plotname

Notice that when you write expressions in this more raw way, you need to explicitly include any groups that contain the value you're interested in. You can read more about these kinds of expressions in the documentation.

This looks like it's related to a recent pyxform change. Are you sure that the form worked as expected in older versions? If it really did work, we can look deeper into it but the expression does not look correct to me because the second argument in quotes doesn't specify an index.

Here's how I would express it instead:

  • Change the name of your select_one to select a plot to plot or something like that.
  • Add a calculate with name plot_name in the repeat after the select one.
  • Give that calculate the calculation jr:choice-name(${plot}, '${plot}')
  • Change the pn1 calculation to be indexed-repeat(${plotname}, ${plotinfo}, 1) (or ${plotinfo}[position() = 1]/datagrp/plotname)

This puts the choice name lookup in the repeat which simplifies the expressions.

Even though I've found another solution to create the summary, I just want to double check this:

I can use those in a calculation, but when putting directly in the label for a note they don't work. So would it be possible to use the instance function? I tried with a couple of variations, but all gave errors. For example instance('data')/plotinfo[position() = 1]/datagrp/plotname.

As for the workflow and the need of a summary, it's just to have a single page where you can see the information entered and can double check some of the information.

From Generate a PDF for saving/printing inside the form I found the way to create the final summary by creating part of the summary in each repeat and then join them after the repeat. In the new form I create a text summary to show in the note and a html summary to create the pdf, I will have to check if I can create a single summary that I can use in both the note and for the PDF.

Well, add me as a complainer, but because I will probably use only Collect, I'll be able to live with formatting it for Collect only. If I need to use Enketo I'll use a relevant to check if the deviceid starts with collect or not.

I didn't test on an older version of Central, I made this form last week to demo something for a friend and then tested with an account on Kobo, where it worked. When I tested on Central it gave me the error. I modified it using you suggestions, and now that part works on both Central and Kobo (but it seems Kobo Collect doesn't print pdfs yet).

New version of the form
Hydrophonic Control Sheet.xlsx (578.6 KB)

Yes, sorry, I meant an older version of pyxform, the library that converts XLSForms into a format Collect and Enketo can use. We maintain pyxform and typically keep it up-to-date in Central. Kobo is currently still using an older version that predates the pyxform change I mentioned.

I've confirmed that that change was indeed what resulted in the error that you see. I do think the structure you've ended up with where the choice-name calls are in the repeat is better. But we also try not to break forms that used to work if at all possible. I have put in a change that will make the old structure work and we'll try to get that released soon.

Did you see an example of the type of expression that you tried to use somewhere? I'd like to change any documentation or examples we have that might show it.

Ah yes, I see. This is an XLSForm limitation, currently. We detect ${} and instance expressions but expressions of this shape are a little trickier to identify correctly. I've filed an issue at https://github.com/XLSForm/pyxform/issues/703

I don't remember if I saw it in documentation or in some example here on the forum.

1 Like