Google Query - Show TOTAL Row as blank or 0% cells if Query table returns empty rows or #VALUE! error - stack

I am calculating a TOTAL's row for an FTR table that i want to stack below the FTR table like this:
=ArrayFormula(
{
FTR Table ;
TOTAL
}
The FTR Table is also calculated via Google Query. The table contains some cells having 0%. For a particular Year, say 2018 (Cell C1), the FTR Table may look like below:
+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+
| FTR % | 2018-Jan | 2018-Feb | 2018-Mar | 2018-Apr | 2018-May | 2018-Jun | 2018-Jul | 2018-Aug | 2018-Sep | 2018-Oct | 2018-Nov | 2018-Dec |
+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+
| Allana | | | | | | | | 0.00% | | 76.92% | 85.00% | 83.72% |
| Mark | | | | 0.00% | | | 0.00% | 75.00% | 86.21% | 76.32% | 90.16% | 91.43% |
| Jane | | 57.50% | 68.97% | 89.47% | 81.82% | 81.36% | 91.11% | 90.24% | 85.71% | 88.89% | 82.69% | 89.61% |
| Santorin | | | | 0.00% | | | | | | | | |
| Lamaiye | | | | | | | | | | | | 85.71% |
| Suez | 80.00% | | 86.67% | 75.00% | 81.08% | 87.27% | 91.80% | 79.69% | 81.43% | 81.40% | 71.70% | 76.00% |
+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+----------+
and the TOTAL row may show as AVERAGE % of each Year-Month Column :
+-------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| TOTAL | 80.00% | 57.50% | 77.82% | 82.24% | 81.45% | 84.31% | 91.46% | 81.64% | 84.45% | 80.88% | 82.39% | 85.29% |
+-------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
Note: See 2018-July & 2018-Aug where there are 0%'s but the AVERAGE is calculated correctly.
2018-July = 91.46%
2018-Aug = 81.64%
But for a particular Year 2017, the table may just show 0% and blank Column Headers also, to maintain Column structure of the stacked tables (one above the other).
+-------+--+--+--+----------+----------+
| FTR % | | | | 2017-Aug | 2017-Dec |
+-------+--+--+--+----------+----------+
| Mark | | | | | 0.00% |
| Jane | | | | 0.00% | |
+-------+--+--+--+----------+----------+
However, the problem arises here for the TOTAL row as it results in
+---------+
| #VALUE! |
+---------+
with error description: Error:Unable to parse query string for Function QUERY parameter 2: AVG_SUM_ONLY_NUMERIC
This single cell value for the TOTAL row breaks the Tables Column structure and the above stacked Tables e.g. the FTR Table also does not show up. I need to have some way to show the TOTAL row Column cells as BLANKS or 0%'s (like as shown below) whenever there is such kind of error:
+-------+-------+-------+-------+-------+-------+
| TOTAL | 0.00% | 0.00% | 0.00% | 0.00% | 0.00% |
+-------+-------+-------+-------+-------+-------+
I cannot share any Spreadsheet due to legal restrictions on my laptop, so I am pasting the Google Query for the TOTAL's row only as it is similar to the FTR table, except for a few changes:
=ARRAYFORMULA(TRANSPOSE(QUERY(QUERY(QUERY({QUERY(
{TEXT('Study Report'!G1:G,"yyyy-mmm;;")&"♦"&'Study Report'!N1:N, 'Study Report'!B1:F, TEXT('Study Report'!G1:G,"yyyy;;"), TEXT('Study Report'!G1:G,"yyyy-mm;;"), 'Study Report'!H1:T, TEXT('Study Report'!G1:G,"yyyy-mm;;")&
IF('Study Report'!G1:G="",,"♥"&TEXT('Study Report'!G1:G, "yyyy-mmm;;"))},"select Col1,Col8,Col15,Col22,count(Col2) where Col8 is not null and Col7 = '"&C1&"' and Col13 != 'Cancelled' group by Col1,Col8,Col15,Col22 order by Col8"),
IFNA(VLOOKUP(QUERY({TEXT('Study Report'!G1:G,"yyyy-mmm;;")&"♦"&'Study Report'!N1:N, 'Study Report'!B1:F, TEXT('Study Report'!G1:G,"yyyy;;"), TEXT('Study Report'!G1:G,"yyyy-mm;;"), 'Study Report'!H1:T, TEXT('Study Report'!G1:G,"yyyy-mm;;")&IF('Study Report'!G1:G="",,"♥"&TEXT('Study Report'!G1:G, "yyyy-mmm;;"))},
"select Col1,Col8,Col15,Col22,count(Col2) where Col8 is not null and Col7 = '"&C1&"' and Col13 != 'Cancelled' group by Col1,Col8,Col15,Col22 order by Col8")
,QUERY({TEXT('Study Report'!G1:G,"yyyy-mmm;;")&"♦"&'Study Report'!N1:N, 'Study Report'!B1:F, TEXT('Study Report'!G1:G,"yyyy;;"), TEXT('Study Report'!G1:G,"yyyy-mm;;"), 'Study Report'!H1:T, TEXT('Study Report'!G1:G,"yyyy-mm;;")&
IF('Study Report'!G1:G="",,"♥"&TEXT('Study Report'!G1:G, "yyyy-mmm;;"))},
"select Col1,count(Col2) where Col8 is not null and Col7 = '"&C1&"' and Col13 != 'Cancelled' and Col16!= 'NO - all fine' AND Col16!='-' group by Col8,Col1")
,2,0))
}
,"SELECT Col1,Col2,Col3,Col4,(1-Col6/Col5 * 1) WHERE (1-Col6/Col5 * 1)>0 label Col1 'A', Col2 'B', Col3 'C', Col4 'D', (1-Col6/Col5 * 1) 'diff'"),
"SELECT Col4, AVG(Col5) GROUP BY Col4 LABEL AVG(Col5) 'TOTAL' FORMAT AVG(Col5) '0.00%'"),"SELECT Col2")))
Credits: Thanks to #player0 for showing me this method of Stacking Tables whilst maintaining the Column structure.
EDIT:
I tried the below solution with an IFERROR() function (also shown earlier by #Player0, which adds a blank row between two tables), for generating the TOTAL row if no data or on error:
=TRANSPOSE(
QUERY(
TRANSPOSE(
IFERROR(
ARRAYFORMULA(TRANSPOSE(QUERY(QUERY(QUERY({QUERY( {TEXT('Study Report'!G1:G,"yyyy-mmm;;")&"♦"&'Study Report'!N1:N, 'Study Report'!B1:F, TEXT('Study Report'!G1:G,"yyyy;;"), TEXT('Study Report'!G1:G,"yyyy-mm;;"), 'Study Report'!H1:T, TEXT('Study Report'!G1:G,"yyyy-mm;;")& IF('Study Report'!G1:G="",,"♥"&TEXT('Study Report'!G1:G, "yyyy-mmm;;"))},"select Col1,Col8,Col15,Col22,count(Col2) where Col8 is not null and Col7 = '"&C1&"' and Col13 != 'Cancelled' group by Col1,Col8,Col15,Col22 order by Col8"), IFNA(VLOOKUP(QUERY({TEXT('Study Report'!G1:G,"yyyy-mmm;;")&"♦"&'Study Report'!N1:N, 'Study Report'!B1:F, TEXT('Study Report'!G1:G,"yyyy;;"), TEXT('Study Report'!G1:G,"yyyy-mm;;"), 'Study Report'!H1:T, TEXT('Study Report'!G1:G,"yyyy-mm;;")&IF('Study Report'!G1:G="",,"♥"&TEXT('Study Report'!G1:G, "yyyy-mmm;;"))}, "select Col1,Col8,Col15,Col22,count(Col2) where Col8 is not null and Col7 = '"&C1&"' and Col13 != 'Cancelled' group by Col1,Col8,Col15,Col22 order by Col8") ,QUERY({TEXT('Study Report'!G1:G,"yyyy-mmm;;")&"♦"&'Study Report'!N1:N, 'Study Report'!B1:F, TEXT('Study Report'!G1:G,"yyyy;;"), TEXT('Study Report'!G1:G,"yyyy-mm;;"), 'Study Report'!H1:T, TEXT('Study Report'!G1:G,"yyyy-mm;;")& IF('Study Report'!G1:G="",,"♥"&TEXT('Study Report'!G1:G, "yyyy-mmm;;"))}, "select Col1,count(Col2) where Col8 is not null and Col7 = '"&C1&"' and Col13 != 'Cancelled' and Col16!= 'NO - all fine' AND Col16!='-' group by Col8,Col1") ,2,0)) } ,"SELECT Col1,Col2,Col3,Col4,(1-Col6/Col5 * 1) WHERE (1-Col6/Col5 * 1)>0 label Col1 'A', Col2 'B', Col3 'C', Col4 'D', (1-Col6/Col5 * 1) 'diff'"), "SELECT Col4, AVG(Col5) GROUP BY Col4 LABEL AVG(Col5) 'TOTAL' FORMAT AVG(Col5) '0.00%'"),"SELECT Col2 FORMAT Col2 '0.00%'"))),
ARRAYFORMULA(SPLIT(REPT("TOTAL ♠", COLUMNS(TRANSPOSE(QUERY({TEXT('Study Report'!G1:G,"yyyy-mmm;;")&"♦"&'Study Report'!N1:N, 'Study Report'!B1:F, TEXT('Study Report'!G1:G,"yyyy;;"), TEXT('Study Report'!G1:G,"yyyy-mm;;"), 'Study Report'!H1:T, TEXT('Study Report'!G1:G,"yyyy-mm;;")& IF('Study Report'!G1:G="",,"♥"&TEXT('Study Report'!G1:G, "yyyy-mmm;;"))},"select Col22,count(Col2) where Col8 is not null and Col7 = '"&C1&"' and Col13 != 'Cancelled' group by Col22")))), "♠") ))),"SELECT Col1 FORMAT Col1 '0.00%'"))
The Only issue is that all the Values will show the word TOTAL for all cells, instead of only 1st cell and rest cells as 0.00%:
+--------+--------+--------+--------+--------+--------+
| TOTAL | TOTAL | TOTAL | TOTAL | TOTAL | TOTAL |
+--------+--------+--------+--------+--------+--------+
Any better idea instead to show it like below:
+-------+-------+-------+-------+-------+-------+
| TOTAL | 0.00% | 0.00% | 0.00% | 0.00% | 0.00% |
+-------+-------+-------+-------+-------+-------+

Related

Count all element occurences in list in cell(by list I mean a string with seperators) in google docs

I have two tables
Table 1:
| list_of_ids |
1 | 1; 2 |
2 | 3 |
3 | 4; 5; 1 |
Table 2:
| id | count |
1 | 1 | 2 |
2 | 2 | 1 |
3 | 4 | 1 |
4 | 6 | 0 |
how do I automatically fill in count?
I currently have a very unsatisfying and hacky way of doing it like this:
list_of_ids is formatted like ;id;id;id; instead of id; id; id
count =COUNTIF(range, "*"&";"&id_cell&";"&"*")
is there a way to do it more properly, so to not force users to write ids in such a way?
try:
=INDEX(QUERY(FLATTEN(SPLIT(TEXTJOIN(";"; 1; A:A); ";"));
"select Col1,count(Col1)
where Col1 is not null
group by Col1
label count(Col1)''"))
or:
=ARRAYFORMULA(IF(C2:C="";;IFNA(VLOOKUP(C2:C;
QUERY(FLATTEN(SPLIT(TEXTJOIN(";"; 1; A:A); ";"));
"select Col1,count(Col1)
where Col1 is not null
group by Col1
label count(Col1)''"); 2; 0); 0)))

Group table, count rows, pad columns with spaces, and concat everything into one big string in a Google Sheet

I have already come up with a working formula but I feel like it is horribly inefficient. I feel like there is probably a better way to do this.
I have a table like so:
| ID | Name | Status |
|-------|--------|-----------|
| ID001 | User 3 | closed |
| ID002 | User 5 | cancelled |
| ID003 | User 2 | closed |
| ID004 | User 3 | pending |
| ID005 | User 3 | closed |
| ID006 | User 1 | closed |
| ID007 | User 3 | hold |
| ID008 | User 5 | hold |
| ID009 | User 4 | closed |
| ID010 | User 3 | closed |
| ID011 | User 4 | pending |
| ID012 | User 4 | pending |
| ID013 | User 2 | hold |
| ID014 | User 3 | closed |
| ID015 | User 2 | pending |
| ID016 | User 2 | closed |
| ID017 | User 1 | pending |
| ID018 | User 5 | pending |
| ID019 | User 2 | open |
| ID020 | User 4 | hold |
| ID021 | User 2 | open |
| ID022 | User 2 | pending |
| ID023 | User 5 | closed |
| ID024 | User 3 | closed |
| ID025 | User 5 | open |
| ID026 | User 5 | closed |
| ID027 | User 4 | cancelled |
| ID028 | User 1 | hold |
| ID029 | User 4 | open |
| ID030 | User 1 | pending |
| ID031 | User 5 | pending |
| ID032 | User 3 | cancelled |
| ID033 | User 2 | closed |
| ID034 | User 5 | open |
| ID035 | User 2 | open |
| ID036 | User 2 | pending |
| ID037 | User 3 | hold |
| ID038 | User 4 | open |
| ID039 | User 5 | open |
| ID040 | User 2 | pending |
| ID041 | User 3 | pending |
| ID042 | User 5 | cancelled |
| ID043 | User 2 | pending |
| ID044 | User 2 | cancelled |
| ID045 | User 1 | open |
| ID046 | User 2 | pending |
| ID047 | User 1 | pending |
| ID048 | User 2 | cancelled |
| ID049 | User 2 | pending |
I want to group by Name, count the number of rows where Status is not cancelled, closed, or hold. So, using a simple query I get this:
=QUERY(
A2:C,
"
SELECT
B,
COUNT(A)
WHERE
A IS NOT NULL AND
C != 'hold' AND
C != 'cancelled' AND
C != 'closed'
GROUP BY
B
LABEL
COUNT(A) ''
"
)
Becomes:
| User 1 | 4 |
|--------|---:|
| User 2 | 10 |
| User 3 | 2 |
| User 4 | 4 |
| User 5 | 5 |
Then I want to concatenate everything into one big string -- but the Name column should be padded with spaces on the right such that the numbers on the left line up (when using a monospace font), and then pad the total so it is right aligned (when using a monospace font).
The idea is, the total/summary table should be in one call whose font will be set to monospace.
I came up with the below formula that works (screenshots below). But I am wondering if there is a better, more efficient way to do this.
=JOIN(
CHAR(10)
, QUERY(
TRANSPOSE(
SORT(
{
UNIQUE(
FILTER(
IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B) & REPT(
" ",
MAX(
FILTER(
LEN(Sheet1!B2:B)
, Sheet1!A2:A <> ""
, Sheet1!C2:C <> "closed"
, Sheet1!C2:C <> "cancelled"
, Sheet1!C2:C <> "hold"
)
) - LEN(IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B))
) & " :"
, Sheet1!A2:A <> ""
, Sheet1!C2:C <> "closed"
, Sheet1!C2:C <> "cancelled"
, Sheet1!C2:C <> "hold"
)
)
, ARRAYFORMULA(
REPT(
" ",
MAX(
LEN(
COUNTIFS(
IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B)
, UNIQUE(
FILTER(
IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B)
, Sheet1!A2:A <> ""
, Sheet1!C2:C <> "closed"
, Sheet1!C2:C <> "cancelled"
, Sheet1!C2:C <> "hold"
)
)
, Sheet1!A2:A
, "<>"
, Sheet1!C2:C
, "<>closed"
, Sheet1!C2:C
, "<>cancelled"
, Sheet1!C2:C
, "<>hold"
)
)
)
- LEN(
COUNTIFS(
IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B)
, UNIQUE(
FILTER(
IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B)
, Sheet1!A2:A <> ""
, Sheet1!C2:C <> "closed"
, Sheet1!C2:C <> "cancelled"
, Sheet1!C2:C <> "hold"
)
)
, Sheet1!A2:A
, "<>"
, Sheet1!C2:C
, "<>closed"
, Sheet1!C2:C
, "<>cancelled"
, Sheet1!C2:C
, "<>hold"
)
)
)
& COUNTIFS(
IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B)
, UNIQUE(
FILTER(
IF(Sheet1!B2:B = "", "!!! UNASSIGNED !!!", Sheet1!B2:B)
, Sheet1!A2:A <> ""
, Sheet1!C2:C <> "closed"
, Sheet1!C2:C <> "cancelled"
, Sheet1!C2:C <> "hold"
)
)
, Sheet1!A2:A
, "<>"
, Sheet1!C2:C
, "<>closed"
, Sheet1!C2:C
, "<>cancelled"
, Sheet1!C2:C
, "<>hold"
)
)
}
, 1
, TRUE
)
)
,
, 999^99
)
)
Given your answers to my questions in comments, this is what I came up with (without spending hours at least):
=ArrayFormula(JOIN(CHAR(10),SORT(UNIQUE(FILTER(B2:B&REPT(" ",(MAX(LEN(B2:B)+1)-LEN(B2:B))),B2:B<>"")),1,1)&":"&(REPT(" ",(MAX(LEN(COUNTIF(FILTER(B2:B,NOT(ISNUMBER(SEARCH(C2:C,"cancelled/closed/hold")))),FILTER(B2:B,NOT(ISNUMBER(SEARCH(C2:C,"cancelled/closed/hold")))))))+1)-LEN(QUERY(FILTER({B2:B,C2:C},NOT(ISNUMBER(SEARCH(C2:C,"cancelled/closed/hold")))),"Select COUNT(Col2) GROUP BY Col1 LABEL COUNT(Col2) ''"))))&QUERY(FILTER({B2:B,C2:C},NOT(ISNUMBER(SEARCH(C2:C,"cancelled/closed/hold")))),"Select COUNT(Col2) GROUP BY Col1 LABEL COUNT(Col2) ''")))
It cuts your formula down by 433 non-space characters (i.e. by nearly half).
Typically, I explain my formulas. But in this case, I trust you won't mind if I leave it to you to tear apart and study the formula.
** EDIT BY IMTheNachoMan **
Unminified formula:
=ArrayFormula(
JOIN(
CHAR(10),
SORT(
UNIQUE(
FILTER(
B2:B
&
REPT(
" ",
(
MAX(
LEN(B2:B) + 1
)
-
LEN(B2:B)
)
),
B2:B <> ""
)
),
1,
1
)
& ":" &
(
REPT(
" ",
(
MAX(
LEN(
COUNTIF(
FILTER(
B2:B,
NOT(
ISNUMBER(
SEARCH(
C2:C,
"cancelled/closed/hold"
)
)
)
),
FILTER(
B2:B,
NOT(
ISNUMBER(
SEARCH(
C2:C,
"cancelled/closed/hold"
)
)
)
)
)
)
) + 1
)
-
LEN(
QUERY(
FILTER(
{
B2:B,
C2:C
},
NOT(
ISNUMBER(
SEARCH(
C2:C,
"cancelled/closed/hold"
)
)
)
),
"Select COUNT(Col2) GROUP BY Col1 LABEL COUNT(Col2) ''"
)
)
)
)
&
QUERY(
FILTER(
{
B2:B,
C2:C
},
NOT(
ISNUMBER(
SEARCH(
C2:C,
"cancelled/closed/hold"
)
)
)
),
"Select COUNT(Col2) GROUP BY Col1 LABEL COUNT(Col2) ''"
)
)
)

Transferring rows from a table to join similar rows in the same table [duplicate]

I'm trying to merge rows with same IDs in Google Sheets
From:
ID | Category
Augur | A1
Augur | A2
Augur | A3
Augur1 | A1
Augur1 | A2
Augur1 | A3
To:
ID | Category
Augur | A1; A2; A3
Augur1 | A1; A2; A3
Is there an automatic way to do it in Google Sheets itself, using its native functions?
=ARRAYFORMULA(QUERY({INDEX(QUERY(A1:B,
"select A,count(A) where A is not null group by A pivot B", 0), , 1),
REGEXREPLACE(TRIM(TRANSPOSE(QUERY(TRANSPOSE(IF(ISNUMBER(QUERY(A1:B,
"select count(A) where A is not null group by A pivot B", 0)), INDEX(QUERY({A1:A,B1:B&";"},
"select count(Col1) where Col1 is not null group by Col1 pivot Col2 offset 1", 0), 1,), ))
, , 999^99))), ";$", )}, "offset 1", 0))

How to count a value from a cell which contains multiple values?

I have a table with cells which contain comma-separated multiple values as follows:
+----------+
| Column A |
|----------|
| a, b |
|----------|
| a, b, d |
|----------|
| b, c |
|----------|
| c, d, e |
+----------+
I would like to get a table which counts the number of a, b, ..., e as follows:
+-----------------------+
| Column A | Column B |
|-----------------------|
| a | 2 |
|-----------------------|
| b | 3 |
|-----------------------|
| c | 2 |
|-----------------------|
| d | 2 |
|-----------------------|
| e | 1 |
+-----------------------+
Is there any Google Sheets or LibreOffice Calc spreadsheet formula to do this?
C1: =UNIQUE(TRANSPOSE(SPLIT(TEXTJOIN(" ,",1,A:A)," ,")))
D1: =ARRAYFORMULA(IF(LEN(C:C),COUNTIF(A:A,"=*"&C:C&"*"),))
=QUERY(TRANSPOSE(SPLIT(TEXTJOIN(" ,",1,A:A)," ,")),
"select Col1, count(Col1)
where Col1 is not null
group by Col1
label count(Col1) ''")
={UNIQUE(TRANSPOSE(SPLIT(TEXTJOIN(" ,",1,A:A)," ,"))),
ARRAYFORMULA(IF(LEN(UNIQUE(TRANSPOSE(SPLIT(TEXTJOIN(" ,",1,A:A)," ,")))),
COUNTIF(A:A,"=*"&UNIQUE(TRANSPOSE(SPLIT(TEXTJOIN(" ,",1,A:A)," ,")))&"*"),))}

Search Data for matching row/array

I want to search a set of data to see if it contains a matching set of values eg.
+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------+------+
| A | B | C | D |
+------+------+------+------+
would match the last row in
+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------+------+
| B | C | D | A |
| A | D | B | C |
| A | B | B | D |
| D | C | B | A |
| A | B | C | D |
+------+------+------+------+
A boolean return would be fine.
Any pointers would be greatly appreciated.
Cheers
Assumptions
Columns to check: A:D
Values to check are in F1:I1
Result in K1 - boolean
Code
=NOT(ISERROR(
QUERY({ArrayFormula(A1:A&B1:B&C1:C&D1:D)},
"select * where Col1='"&JOIN("",F1:I1)&"'",0)
)
)
Picture

Resources