D2:condition and IF functions unique for program indicators and not program rules?

Hi all,

I’ve been trying to set up an ‘assign value’ type of program rule that requires the use of d2:condition / If functions. However, I keep getting the error message that these functions are not supported. I checked in the DHIS2 documentation here and it seems to confirm that there is a difference in the syntax used by PI and PR expression engines - is this correct? If so, is this a recent development? And is there an alternative way I can replicate these funtions for PRs?

Many thanks in advance!

Monika

Hi there @monika! In program rules there will definitively be a way of doing this without d2:condition. Can you provide some more details on how your assignment should work?

Markus

2 Likes

Hi @Markus,

Ah ok, good to know! Essentially, I need to concatenate text from 5 different DEs into a 6th output DE with values separated by a comma. I have a working Assign value PR with the following expression:
d2:concatenate( #{DE1},‘,’, #{DE2},‘,’, #{DE3},‘,’, #{DE4},‘,’, #{DE5})

It works, but it is not very elegant. For example, if the end user enters text in only the first two DEs, the output DE has lots of commas trailing after it for the blank fields.

I was thinking of adding a d2:condition or IF function so that only if the next DE has a value, to add the comma that separates the text, otherwise show a blank. Is there another way to write this PR?

Many thanks,

Monika

Ah, then I see why you experimented with the d2:condition :slight_smile:

The d2:condition is not fully supported in program rules unfortunately, and that is why its not documented.

One strategy I have seen employed is to make one rule per data element, and one calculated program rule variable per data element. #{DE1_TEXT}, #{DE2_TEXT}, #{DE3_TEXT} and #{DE4_TEXT} for example.
Each program rule assigns #{DEx_TEXT} only if DEx has a value, and the assigned string will be d2:concatenate(#{DEx}, ‘,’).

Then you will end up with 4 calculated program rule variables, containing either nothing, or a string and a comma. For example they might be assigned like this(in my example DE2 contains “foo” and DE4 contains “bar”;
#{DE1_TEXT}: empty
#{DE2_TEXT}: “foo,”
#{DE3_TEXT}: empty
#{DE4_TEXT}: “bar,”
Then, you can run a fifth rule to concatenate the 4 strings and assign them to the data element you wanted:
d2:concatenate(#{DE1_TEXT},#{DE2_TEXT},#{DE3_TEXT},#{DE4_TEXT})

This would of course make a comma at the end, that you might not want. Sometimes its even necessary to put an “and” in between the second to last and last value. Removing the comma can be done with a combination of d2:length and d2:left. If you need to have a better language, with an “and” between the two last DEx_TEXTS instead of a comma, this will increase the complexity a bit, but would be doable.

Make sure if you try the strategy above that the 4 rules for assigning the helper program rule variables #{DEx_TEXT} is executed before the fifth rule to concatenate everything. This is done by adding a priority to the first 4 rules, and a lower priority or no prority to the fifth rule. Rules 1-4 can all have priority 1 for example, and rule 5 might have a blank priority.


For the future we will also add this thread to the consideration for wether to build full support for d2:condition, which might have made this easier :slight_smile: Or even a d2:join function, allowing the user to directly join all non null values from a list, adding a delimiter between each joined element.

Markus

1 Like

Hi @Markus,

Thank you so much for taking the time to detail an alternative way to set up this PR! This will take me some time to wrap my ahead around, but I appreciate that it is possible! If there are any JIRA tickets or feature requests that speak to your last points, I would love to vote/follow these tickets :slight_smile:

Many thanks,

Monika

1 Like