Calculate and updated a score according to selected answer - odk

I am new to ODK and XLSForms.
I have several questions and based on the answers, I need to calculate a score.
I have 17 questions, each time a person answer yes, I need to add 2 points into an integer field.
So I have:
type name label appearnce required
select_one yes_no1 q1 //question here //appearance quick //required yes
...
select_one yes_no17 q17 ...
And here is the score field:
type name label
calculate total Total
This is my first assignment in my job, and can't figure how to calculate and change value according to selected answer.
EDIT
I added a calculation expression but can't know how to get the result because it didn't worked:
if ((${q8} = 'yes' or ${q9} ='yes' or ${q11}='yes'), 2, 0)
So if question 8, 9 or 11 are answered as yes, add 2 points to current value, but the field didn't appeared at all. And still need to add if question 10, 12, 13 and 14 are answered with yes to add 1 point for each.

The simple but tedious way to do this is to create a calculation for each question with an if() statement that sets the calculated value to either 2 or 0. The final result can be obtained by adding up the calculated items.
The cool way to do this is to do it all in one XPath expression. Basically you want to create a nodeset that contains all 17 questions, filter these to the ones with value 'yes', count the filtered nodeset and multiply by 2. You can do this in XLSForm, but Im not sure if you can use the ${node} shorthand.
You'd have to put all your question in a group (doesn't need a group label) after which you can do something like:
count(${grp}/*[text() = 'yes']) * 2
or without ${node} shortcut (check the XForm for the correct path):
count(/myform/grp/*[text() = 'yes']) * 2
I'm not sure if the use of text() will pass ODK Validate though. If not there is probably an expression that will pass and does the same. (However, the above syntax would work in Enketo).

Related

Excel formula to return a value if two values are true and one of two other things are true

I'm trying to write a formula in Excel where if value in B is “Eligible/Previously Eligible” and value in C is more than 365 days before today and value in D contains either 10 or 20, then return the value in A. I’ve been searching around and have written this:
=IFERROR(INDEX($A:$A,SMALL(IF((COUNTIFS($B:$B,"Eligible/Previously Eligible",$C:$C,"<"&TODAY()-365,$D:$D,{"*10*","*40*"})),ROW($A:$D)-MIN(ROW($A:$D))+1),ROW(A1)),COLUMN(A1)),"")
And have activated with the CTRL+Shift+Enter combo, but it just pulls in everything from A regardless of what is in B, C, or D:
#Solar Mike and #Scott Craner, thanks! This has gotten me closer but not quite there. I have a formula now that works to return the ID numbers that meet the criteria:
=IF(AND(B2="Eligible/Previously Eligible",D2<TODAY()-365,D2<>"",OR(SUM(COUNTIF(C2,{"*10*","*20*"})))),A2,"")
But I still can't get it to give me a list without white space. So, I can get what's in the "ID Numbers with Problems" column, but what do I need to write to get it to show the way I've done it manually in the "What I want" column?
image of what
Add a helper column:
=and(find("*elig",B2,1)>=1,now()-c2>=365,D2/10<=2)
Drag down to test each row. Then a results table based on those that give true.
Or use sumproduct() with column A to give the IDs.

SSRS - Sum of an aggregated field

I have a report, that shows the individual sales commission for each employee.
The expression for the Sales Commission is:
=Sum(Fields!Total_Comission.Value)*Parameters!Distribution_Factor.Value*Fields!Individual_Factor.Value
Now I want to add a total for this field. If I just right click the cell and click on Add Total, it works but gives out the wrong total.
If I try to sum the field like this:
=Sum(Reportitems!GO_Prov.Value)
I get the error:
The Value expression for the textrun 'Textbox93.Paragraphs[0].TextRuns[0]' uses an aggregate function on a report item. Aggregate functions can be used only on report items contained in page headers and footers.
Is there a workaround to sum the aggregated field of this tablix? Maybe with a code?
Thanks in advance.
Update1:
Unfortunately i don't know how to write custom codes. But I found this code:
Public Total_lookup_Sum As Integer = 0
Public Function Lookup_Sum(ByVal value As Integer) As Integer
Total_lookup_Sum = Total_lookup_Sum + value
Return value
End Function
The expression i used for the Sales Commission is now:
=Code.Lookup_Sum((Sum(Fields!Total_Comission.Value)*Parameters!Distribution_Factor.Value*Fields!Individual_Factor.Value))
And the expression for the field where i would like to get the sum is:
=Code.Total_lookup_Sum
Now i get the error:
There is an error on line 0 of custom code: [BC30205] End of
statement expected.
Is there a way to solve this?
Scenarios like these can be tricky in SSRS. From your description (even though the screenshot doesn't really show everything), I'm guessing that you've got rows grouped by salesperson. In your column that's calculating the commission, you've got a sum of "Total_commission", but you've just got the "Individual_Factor" value not aggregated. Again, having a guess, but each underlying row (by employee) must have the same "Individual_Factor" value (so actually using Min(Individual_Factor) would give the same result).
But then, when you try and just take the same formula (or even a derivation of the formula), and make an overall aggregate of all of the rows, how does SSRS know which "Individual_Factor" value to use? You don't want Min() or Max(), because that would just be the lowest or highest value across all of the salespeople.
Your suggestion of a workaround via code is generally the way that I approach this. You need a report variable, something like "Commission_Grand_Total", and then you need a function in the report code that accepts 1 parameter, and in the function you'll add the parameter value to the variable. The easiest thing to do is to make the parameter the return value of the function.
Then, in the field where you currently have your commission formula (on the salesperson row), the expression in that field becomes =TheFunctionYouCreate((Sum(Fields!Total_Comission.Value)*Parameters!Distribution_Factor.Value*Fields!Individual_Factor.Value))
By passing the formula to the function, you're achieving two things:
The function will take each salesperson's calculated commission and add it to your report variable
The function will output the parameter value that you passed in (since you want to display the calculated commission amount on each salesperson's row)
Lastly, to display the overall total, the expression for that field is just the report variable that holds the overall total (that has been cumulatively added to as SSRS wrote out each salesperson's record)
TIP: I sometimes do this same sort of thing, but if I don't want the row-by-row value to be shown (I just want the cumulative total to be calculated), just put the expression that calls the function in a hidden column. SSRS will still run the function as it renders each row, but obviously it's just not displaying the result of the function.
Some MS reference for report variables and code
https://learn.microsoft.com/en-us/sql/reporting-services/report-design/built-in-collections-report-and-group-variables-references-report-builder?view=sql-server-ver15
https://learn.microsoft.com/en-us/sql/reporting-services/report-design/add-code-to-a-report-ssrs?view=sql-server-ver15
This is untested unfortunately but...
assuming you have a rowgroup for employee called EmployeeGroup then the expression would look like this...
=SUM(
Sum(Fields!Total_Comission.Value, "EmployeeGroup")
* Parameters!Distribution_Factor.Value
* FIRST(Fields!Individual_Factor.Value, "EmployeeGroup")
)
The inner expression reads as
Sum of Total_Comission with current employee group
... multiplied by Distribution Factor
... multiplied by the first individual factor with the current employee group
The outer expression just sums all the individual employee level sums.

Salesforce number field default value to (highest number in a record) + 1

I'm new to Salesforce and I'm trying to make a field for an account number. It will be a unique number that increases. But I would like its default value to be an increment from the highest number of current records since I'm going to import data and those data have some unused account numbers in between.
For example, I have a data with account numbers: 1, 4, 10, 13, 14 -> then the next one's default value would be 14 + 1 = 15.
What's the simplest solution to this? I tried MAX(Account_Number) + 1, but it's not allowing me to use its own value.
I had this issue once and solved it by setting the field as an auto-increment and then creating and deleting large quantities of records to reach my starting number.
If you are importing and want to retain the previous values, this will not work, unfortunately.
You can use a trigger or flow to populate the account number after a record is created.
For the quick and dirty, make a flow and call it from a process builder. If you have the ability to use sandbox and create a trigger, by all means.
Essentially, you would query the sObject with SORT BY AccountNumber__c DESC LIMIT 1 (or whatever the field is named) and access that highest value and increment it and use that to set the value of the record you are creating.
Makes sense?

Select Row values based on values in another row

I have a table that has an auto-incrementing identity "Reference" field and a pair of other fields that determine the sort order. What I need to do is find the 'next' item in the table when sorted based on the pair of fields based on the reference field of an initial item.
So my data looks like this when sorted by SortParent.SortChild:
Reference SortParent SortChild Data
------------------------------------------
9 1 2 Fred
7 1 3 Jim
11 1 4 Sheila
4 2 1 Micro
5 2 2 Archimedes
12 2 3 Electron
So in this example the "Jim" row (Reference=7) comes after "Fred" (Reference=9) even though it's reference is smaller.
So i want to be able to find which row comes after Fred by searching based on Jim's reference
At the moment in code I do a query to find the values for Fred's row:
SELECT SortParent,SortChild From MyTable WHERE Reference=9
Which returns 1,2. Then do a search for the first row that comes after 1,2:
SELECT * FROM MyTable
WHERE ((SortParent=1 and SortChild>2) OR (SortParent>2))
ORDER BY SortParent,SortChild
Which will therefore come back with the row having reference 7 and sort values 1,3
I'm pretty sure this can be done in a single query, but i'm stumped on the best way.
Incidentally, if anyone has any suggestions on alternate way of handling the two part sort columns that would make this easier, please feel free to help!
I believe You are looking at the LEAD or LAG windowed function:
https://msdn.microsoft.com/en-US/library/hh213125.aspx
SELECT
NextReference
FROM
(SELECT
reference
, LEAD(reference, 1,0) OVER (ORDER BY SortParent,SortChild) AS NextReference
, *
FROM
mytable
) newTable
WHERE
reference = 9
I used LEAD, but try it with LAG if you are looking in the other direction for the row
I havn't tested this particular query, so my not be syntactically sound, but let me know if you have any troubles with it and I'll go over it a bit more once I'm back at my desk
EDIT: Used the wrong sql from your question as my base
EDIT2: Put the lead into a subquery to allow us to query on it

Using Aggregate Function in SubTable in Visual Studio

I am trying to put together a Subtable on my report in Visual Studio 2008 with SSRS. The problem I am running into is using a function correctly and referencing a report item via my main report. On my report I have an expression that color codes, when a specific value is returned from the main query. In my Subtable, I want to count each instance of a specific value so for example:
Main Report
Supervisor Employee Ranking
Supervisor 1 Employee 1 Meets (Labeled Orange)
Supervisor 1 Employee 2 Outstanding (Labeled Yellow)
Supervisor 2 Employee 3 Meets
Supervisor 2 Employee 4 Meets
Subtable Outstanding Meets
Supervisor 1 1 1
Supervisor 2 0 2
I have tried using the following formulas
=count(Reportitems!Ranking.Value, "Meets", 0)
=count(Reportitems!Ranking.Value, "Orange", 0)
=count(Reportitems!Ranking.Value = "Meets")
=count(Reportitems!Ranking.Value = "Orange")
I have also changed =count to =countrows and =countdistinct
Can someone help? I am open to anything, I just want the report and Subtable to work correctly.
Once you've got a table grouped by Supervisor (and it looks like you do), you'll need to add a couple of columns with two conditional expressions:
Outstanding column:
=Sum(IIf(Fields!Ranking.Value = "Outstanding", 1, 0))
Meets column:
=Sum(IIf(Fields!Ranking.Value = "Meets", 1, 0))
These will count the occurrences of Outstanding and Meets for each Supervisor that is returned.
This assumes that Ranking is just column in your Dataset - you mention colour coding based on this, but we are only interested in the base value, not the colour.
Edit after comment
If Ranking is based off an expression, you can simply add this into the original expressions above, i.e. something like:
=Sum(IIf(<MyExpression> = "Outstanding", 1, 0))
It's a bit of a generic answer since I don't know what your specific example is, but you can certainly nest expressions in other expressions without issue.
For a more elegant solution, you should consider adding a Calculated Field to your dataset - this defines the expression once in the dataset, then you can use it like a normal field within the report itself. This way you would create a Calculated Field called Ranking in your dataset, then you can use expressions like the ones in the original answer referencing this new calculated Ranking field.

Resources