Conditional count over rows over multiple criteria - excel

I want to answer this question: How many patients have had more than 1 scan? Pseudocode:
Countif >1 (Ans = 2. Two patients have 2 or more scans)
For each Patient ID, count if "scan" nonblank (Ans: a=1, b=2, c=2, d=1)
A | B | C
01 Patient ID | Scan | Other data etc
02 a | |
03 a | 1/1/15 |
04 b | 2/2/15 |
05 b | |
06 b | 3/2/16 |
07 c | 1/3/14 |
08 d | 2/1/12 |
09 c | 1/7/14 |
10 d | |
This is easy to do for just one patient. I.e., =Countifs(A1:10,"a",B1:10,"<>"). How do you count this for all patients?
Help much appreciated!

You will require a helper column - refer the formula below
Helper column =IF(AND(COUNTIF($A$2:$A$10,A2)>1,NOT(ISBLANK(B2)) ),A2,"-")
=IF(COUNTIF(C2:C10,"-")>0,SUMPRODUCT(1/COUNTIF(C2:C10,C2:C10))-1,SUMPRODUCT(1/COUNTIF(C2:C10,C2:C10)))

The formula will need to be entered as an array (once copy and pasted while still in the formula bar hit CTRL+SHIFT+ENTER)
=SUM(--(FREQUENCY(IF(B2:B10<>"",MATCH(A2:A10,A2:A10,0)),ROW(A2:A10)-ROW(A2)+1)>1))

If you have a sheet with every patient you can add a column and use your formula =Countifs(A1:10,"patient_id",B1:10,"<>") to count the number of scans for each patient and then use the same type of formula to count every sum of scans that are greater than 1.
Patient sheet
A | B
01 Patient ID | Scans
02 a | =COUNTIFS(scans!A2:A10; A2;scans!B2:B10;"<>")
03 b | 2
04 c | 2
05 d | 1
06 e | 0
07 f | 0
Scan sheet
A | B | C
01 Patient ID | Scan | Other data etc
02 a | |
03 a | 1/1/15 |
04 b | 2/2/15 |
05 b | |
06 b | 3/2/16 |
07 c | 1/3/14 |
08 d | 2/1/12 |
09 c | 1/7/14 |
10 d | |
Where you want
=COUNTIF(patients!B2:B6;">1")

Related

Can you select the MIN row to display across all "Results Grid" values? (Generic Inquiry)

I have the following tables:
(Example data)
PMProjects
| ContractID | ContractCD | Customer |
| :-------- | :----------| :------- |
| 01 | PR00001 | ABC-Customer |
| 02 | PR00002 | XYZ-Customer |
PMTasks
| Task ID | Project ID| Task CD | Description |
| :--------| :---------| :---------| :-------- |
| 39 | 01 | 01 First | Zulu |
| 40 | 01 | 02 Second | Foxtrot |
| 41 | 01 | 03 Third | Delta |
| 42 | 01 | 04 Fourth | Alpha |
| 55 | 02 | 01 First | Zulu |
| 56 | 02 | 02 Second | Foxtrot |
| 57 | 02 | 03 Third | Delta |
| 58 | 02 | 04 Fourth | Alpha |
I have successfully joined PMTasks to PMProjects on PMProjects.ContractID = PMTasks.ProjectID.
And, I am grouping by PMProjects.ContractID
On the GI, I need to display the MIN TaskID row for each Project.
My GI - Aggregate Functions by MIN value
Result -
When I use the MIN value on the PMTasks.Description field it pulls the value "Alpha".
GI Results
| ContractID | ContractCD | Customer | Task ID | Task CD | Description |
| :--------- | :--------- | :----------- | :------- | :-------- | :---------- |
| 01 | PR00001 | ABC-Customer | 39 | 01 First | Alpha |
| 02 | PR00002 | XYZ-Customer | 55 | 01 First | Alpha |
Documentation - Aggregate Function Descriptions
I see from the documentation that the MIN aggregate function, "Returns the minimum value of all values of the group."
Has anyone found a way to join many-to-one in an Acumatica Generic Inquiry using the MIN (or MAX) value of a row?
Or to put it a different way - has anyone found a way to join one of many rows to a table and have the results grid display only the values from the same row?
I hope this makes sense. Please feel free to ask any clarification questions.
Thanks for any and all feedback.
Example GI related to the question. Please excuse the error under Results Grid - PMProjects.CustomerCD_Description does not need to be aggregated.
You need to add a group by PMContract.ContractID and then add the Min() function in the Data Field

CSE formula to sum the result of a complex formula applied to all rows

I have the following three tables (table header are on line 01):
Table1: Subscriptions based on dates
| A | B | C | D |
---|-----------|--------------|------------|---------------------|
01 | ID | Type | Start Date | End Date |
02 | ID1 | T1 | 17.4.1 | |
03 | ID2 | T2 | 17.9.1 | 18.5.15 |
04 | ID3 | T1 | 20.6.1 | |
...
Table2: Monthly cost per subscription type
| A | B
---|-------------|---------------
01 | Type | Yearly Cost
02 | T1 | 120
03 | T2 | 144
...
Table3: Expenses Projections
| A | B
---|-----------|------------
01 | Year | Expense s
02 | 2017 | 138 (T1 9 months: 90 + T2 4 months: 48)
03 | 2018 | 180 (T1 12 months: 120 + T2 5 months 60)
04 | 2019 | 120 (T1 12 months)
05 | 2020 | 190 (T1 12 months + 7 months)
06 | 2021 | 1240 (T1 24 months)
...
I would like to compute the column B of the third table automatically (without using helper columns, currently it is done using a helper table...)
I know that it cannot be done using sumif(), but is it possible to achieve this using an array formula ?
I have the following pseudo code of the formula to place in table 3:
for each line of table 2
'
'
' case 1: start date in year, end date not in year
'
if and(table3[year]=year(table1[startdate]), or(isblank(year(table1[enddate]),table3[year] < year(table1[enddate]))) then
'
' count months from startdate to end of year then multiply with monthlyrate
'
addtosum (12-month(table1[startdate]))*index(Table2,match(Table1[#[Type]],Table2[Type],0),2)
'
'
' case 2: startdate in year, enddate in year
'
elseif and(table3[year]=year(table1[startdate]),table3[year] = year(table1[enddate])) then
'
' count months between startdate and enddate then multiply with monthlyrate
'
addtosum (month(table1[enddate])-month(table1[startdate]))*index(Table2,match(Table1[#[Type]],Table2[Type],0),2)
'
'
' case 3: year larger than startdate, enddate is not reached
'
elseif and(table3[year]>year(table1[startdate]), or(isblank(year(table1[enddate]),table3[year]<year(table1[enddate]))) then
'
' multiply 12 months with monthlyrate
'
addtosum 12*index(Table2,match(Table1[#[Type]],Table2[Type],0),2)
'
'
' case 4: year larger than startdate, enddate is reached
'
elseif and(table3[year]>year(table1[startdate]),table3[year]=year(table1[enddate])) then
'
' count months from begining of year to enddate then multiply with monthlyrate
'
addtosum (month(table1[enddate])) * index(Table2,match(Table1[#[Type]],Table2[Type],0),2)
end if
end for each
Here is the helper table I created:
Table3: Expenses Projections
| J | K | L | M | N ...
---|-------|----|------|-----| ----- ...
01 | Year | | ID1 | ID2 | ID3
02 | 2017 | | 90 | 48 |
03 | 2018 | | 120 | 60 |
04 | 2019 | | 120 | 0 |
05 | 2020 | | 190 | |
...
And this is the formula I currently have in cell L2 (this is copied to L2:U5):
' Note: when calling index, column 4 is the Type, 5 is startdate, 6 is enddate)
=IF(NOT(ISBLANK(INDEX(Table1,MATCH(L$1,Table1[ID],0),5))),
IF(AND($J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), OR(ISBLANK(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)),$J2 < YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)))),
(12+1-MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),5))),
IF(AND($J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), $J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))),
(MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))-MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),5))),
IF(AND($J2 > YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), OR(ISBLANK(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)),$J2 < YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)))),
12,
IF(AND($J2 > YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), $J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))),
(MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))),
0
)
)
)
)*INDEX(Table2,MATCH(INDEX(Table1,MATCH(L$1,Table1[ID],0),4),Table2[Type],0),2)/12,
0
)
Thanks in advance for your help,
You asked for a formula. Use this array formula:
=SUMPRODUCT(((J2>=YEAR($C$2:$C$4))*((J2<=YEAR($D$2:$D$4))+($D$2:$D$4=""))),
SUMIFS($G$2:$G$3,$F$2:$F$3,$B$2:$B$4),
((DATEDIF(IF($C$2:$C$4>DATE(J2,12,31),0,$C$2:$C$4),DATE(J2,12,31),"m")+1>12)*12-IF($D$2:$D$4<>"",MONTH(D1:D3)+2,0))+
(DATEDIF(IF($C$2:$C$4>DATE(J2,12,31),0,$C$2:$C$4),DATE(J2,12,31),"m")+1<=12)*
((DATEDIF(IF($C$2:$C$4>DATE(J2,12,31),0,$C$2:$C$4),DATE(J2,12,31),"m")+1)--IF($D$2:$D$4<>"",MONTH(D1:D3)+2,0)))
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode.
Here's another solution:
=SUM(IF(ISBLANK(Table1[End Date]),IF(YEAR(Table1[Start Date])<Table3[#Year],12,IF(YEAR(Table1[Start Date])=Table3[#Year],13-MONTH(Table1[Start Date]),0)),IF(Table3[#Year]<YEAR(Table1[Start Date]),0,IF(Table3[#Year]=YEAR(Table1[Start Date]),IF(Table3[#Year]<YEAR(Table1[End Date]),13-MONTH(Table1[Start Date]),IF(Table3[#Year]=YEAR(Table1[End Date]),MONTH(Table1[End Date])-MONTH(Table1[Start Date])+1,0)),IF(Table3[#Year]<YEAR(Table1[End Date]),12,IF(Table3[#Year]=YEAR(Table1[End Date]),MONTH(Table1[End Date]),0)))))*SUMIFS(Table2[Monthly Cost],Table2[Type],Table1[Type]))
This is an array formula CTRL-SHIFT-ENTER.
Hope that helps

Marking "Ambidextrous" in Excel

This is an example that illustrates my problem
So I have a table of participants, each with their own unique ID number. They all do a writing test and their time, in minutes, is recorded in the fourth column as an integer. Some patients have repeated the test, there is no maximum number of repeats.
+============+===========+===============+======+
| Patient ID | Hand Used | Ambidextrous? | Time |
+============+===========+===============+======+
| 01 | Right | Yes | 12 |
+------------+-----------+---------------+------+
| 01 | Right | Yes | 10 |
+------------+-----------+---------------+------+
| 01 | Right | Yes | 11 |
+------------+-----------+---------------+------+
| 01 | Left | Yes | 13 |
+------------+-----------+---------------+------+
| 01 | Right | Yes | 12 |
+------------+-----------+---------------+------+
| 02 | Right | No | 9 |
+------------+-----------+---------------+------+
| 02 | Right | No | 7 |
+------------+-----------+---------------+------+
| 02 | Right | No | 8 |
+------------+-----------+---------------+------+
| 03 | Left | Yes | 8 |
+------------+-----------+---------------+------+
| 03 | Right | Yes | 8 |
+------------+-----------+---------------+------+
I want the "Ambidextrous?" column to be a formula. I've been trying to accomplish this with INDEX() and MATCH(), to no avail. It needs to check the "Hand Used" column, if there is both a Right handed and Left handed test for a particular Patient ID, we say "Yes".
Use:
=IF(COUNTIFS(A:A,A2,B:B,IF(B2="Right","Left","Right")),"Yes","No")

How to average difference between many value pairs by index

and thanks for your help! Without helper columns/rows I'm trying to find the average difference in LVEDi between first and last visits of the patients.
E.g., by hand you would work it out as:
(diff for patient a + diff for pt b + diff for pt c)/3 =
((55-45) + (40-31) + (25-31))/3 =
(10 + 9 + (-6))/3 =
13/3 =
4.333
I'm sure the answer involves indexing with an array function, but I can't get started on how to tackle it!
Any help?
Thanks!
A | B | C | D | E
01 Patient ID | Date | First-Last | LVEDi | LOTS of similar cols
02 a | 3/3/03 | LAST | 55
03 a | 1/1/01 | FIRST | 45
04 a | 2/2/02 | | 65
05 b | | |
06 b | 3/2/16 | LAST | 40
07 b | | |
08 b | | |
09 b | 2/1/12 | FIRST | 31
10 c | 1/7/14 | LAST | 25
11 c | | |
12 c | 2/2/03 | FIRST | 31
13 c | 2/2/08 | | 46
You can use the * as and AND criterion in arrays, so with MATCH you search for the instance, where both conditions multiplied are TRUE (i.e. 1). The rest is just filling in your calculation:
{=((INDEX(D2:D13,MATCH(1,(A2:A13="a")*(C2:C13="LAST"),0))-INDEX(D2:D13,MATCH(1,(A2:A13="a")*(C2:C13="FIRST"),0)))+(INDEX(D2:D13,MATCH(1,(A2:A13="b")*(C2:C13="LAST"),0))-INDEX(D2:D13,MATCH(1,(A2:A13="b")*(C2:C13="FIRST"),0)))+(INDEX(D2:D13,MATCH(1,(A2:A13="c")*(C2:C13="LAST"),0))-INDEX(D2:D13,MATCH(1,(A2:A13="c")*(C2:C13="FIRST"),0))))/3}
And remember to use CTRL + SHIFT + ENTER to enter the array.
Found a slightly less verbose method:
=SUM(SUMIFS(D:D,C:C,"LAST",A:A,{"a","b","c"})-SUMIFS(D:D,C:C,"FIRST",A:A,{"a","b","c"}))/3
EDIT 1
Building on Lukas' comment:
=(SUMIF(C:C,"LAST",D:D)-SUMIF(C:C,"FIRST",D:D))/COUNTIF(C:C,"LAST")

COUNTIF Function, reset count if value equals a specific value

I need to list a running count in column A of each occurrence of the value "4A" in column B, but the count needs to reset to 0 if the value in column B equals "2B".
I have attached a sample of my workbook, column A shows how I need the count to operate. I am open to using VB or a formula.
Or in text format:
| A | B |
+---+----+
| 0 | 2B |
| | 3A |
| 1 | 4A |
| | 4B |
| | 4B |
| 2 | 4A |
| | 4B |
| 3 | 4A |
| | 9A |
| 0 | 2B |
| | 3A |
| 1 | 4A |
| | 4C |
| 2 | 4A |
| | 9A |
| 0 | 2B |
| | 3A |
| 1 | 4A |
| | 9A |
| 0 | 2B |
| | 3A |
| 1 | 4A |
| | 4C |
| | 9A |
| | 9B |
| | 9Z |
EDIT:
#Jeeped and #trincot proposed better non-array versions. I modified them slightly here:
#Jeeped's formula:
=IF(OR(B1={"2B","4A"}), COUNTIF(INDEX(B:B,AGGREGATE(14, 6, ROW(B$1:B1)/(B$1:B1="2B"), 1)):B1, "4A"),"")
After modification it uses LARGE function in the aggregate rather than SMALL and "" instead of TEXT(,).
#trincot's formula:
=IF(OR(B2={"2B","4A"}),(B2="4A")*(1+IFERROR(INDEX(G:G,MATCH(MAX(G$1:OFFSET(G2,-1,0))+1,G$1:OFFSET(G2,-1,0))),0)),"")
Compared to original, it's been rearranged slightly 'IF-wise', I also replaced magic 9999 with MAX([...]) + 1 and made it so that you can just paste it in 1st cell and drag down rather than have two separate formulas for first cell and the consecutive ones.
My original version:
I think it has the benefit of perhaps being the easiest to understand (? - I am obviously biased here so I might be wrong) and it's physically the shortest of all.
It has the obvious drawback of being an array-formula.
In cell "A1" you can write:
=IF(OR(B1="2B",B1="4A"),SUM((B$1:B1="4A")*(ROW(B$1:B1)>MAX(ROW(B$1:B1)*(B$1:B1="2B")))),"")
It's an array formula so you have to confirm it with ctrl + shift + enter.
Then you can drag it down.
Basically it counts number of occurrences of "4A" in a range extending from current row to the first provided that rows of counted "4A" are larger than that last row of "2B".
Here is a way with standard (non-array) formulas:
In A1 put:
=IF(B1="4A",1,0)
In A2 put:
=IF(B2="2B",IF(INDEX(A:A,MATCH(9999,A$1:A1))>0,0,""),
IF(B2="4A",1+INDEX(A:A,MATCH(9999,A$1:A1)),""))
Drag/copy A2 down to the remaining cells in the A column.
This will produce blanks where otherwise the same value would be displayed.
If repeating values don't need to be suppressed, then you can simplify the formula in A2 to:
=IF(B2="2B",0,IF(B2="4A",1+A1,A1))
... and copy it down.

Resources