Indirect formula to find MIN of matching range - google-sheets

I have a spreadsheet with two sheets, first sheet contains Name (col:C), and Finish time (col:G), second sheet I have a column also called Name (col:A) , and a column called Personal Best Time (col:G).
Currently, in Sheet2:Col:G, i'm using a formula to search Sheet1 for the lowest Finish time value relating to that particular row's Name column (as below):
=ArrayFormula( min( if('Sheet1'!C:C = A2, 'Sheet1'!G:G) ) )
But for every row in Sheet2, this formula needs to be copied, with the only difference being the A2 reference (which is referring to the Name column of the current row).
So my hope was to create an indirect formula, where the specific range is entered in the header column, and automatically applied to each row.
So this is what I have so far:
=ArrayFormula( IF( ISBLANK(A:A), "", IF( ROW(G:G)=1, "Personal Best Time", ArrayFormula( min( if( 'Sheet1'!C:C = A2, 'Sheet1'!G:G ) ) ) )))
But how do I make it so that A2 changes depending on the row number?
I tried A:A, but if I'm right, that would be attempting to compare the whole Name column from Sheet2.

Does this formula work as you want:
=ArrayFormula( IF( ISBLANK(A:A), "", IF( ROW(A:A)=1, "Personal Best Time", ArrayFormula(Vlookup(A:A,SORT({Sheet1!C:C,Sheet1!G:G},2,1),2,0)))))

Related

Dynamically offset data of multiple rows to match the header column in Google Sheets

I'm trying to dynamically offset data of multiple rows to match the header column in Google Sheets. The first tab contains data of multiple fruits and how many are harvested on a particular day. Each fruit starts harvesting on different dates, and the dates might not be continuous.
The second tab, "Fruit bank", shows how many fruits are harvested in total for each day. Column D is a continuous set of dates. In cell E1, a QUERY formula dynamically pulls the names of the fruits so whenever a new fruit is added, it shows up here as well. In cell E2 and the rest of the row, I use VLOOKUP formulas to pull the data from the first tab. What I need help with is to write a formula on cell E2 that expands to the rest of the row so I don't have to manually type in the lookup range every time a new fruit is added.
Also, I suspect there're better functions to use than the VLOOKUP because the way VLOOKUP pulls data is very slow. I could literally see it loading even with this small dataset.
Yellow cells contain formula.
I appreciate anyone who can take a look at my spreadsheet (linked below) and see what's the best solution for this. The 3rd tab is editable.
https://docs.google.com/spreadsheets/d/14GeJKgxadInNWVVyft2gilae7HOIEvKXRop-Kz_On-Q/edit#gid=53523977
Thanks! J
Use filter(), like this:
=arrayformula(
ifna(
vlookup(
$D2:$D,
{
filter(
'Fruits data'!$B2:$AA,
'Fruits data'!$A1:$Z1 = E1
),
filter(
'Fruits data'!$A2:$Z,
'Fruits data'!$A1:$Z1 = E1
)
},
2, false
)
)
)
See your sample spreadsheet.
you can try either. added solutions here and here
=BYROW(D2:D,LAMBDA(dx,IF(dx="",,BYCOL(E1:1,LAMBDA(ex,IF(ex="",,XLOOKUP(dx,FILTER('Fruits data'!1:46,COLUMN('Fruits data'!1:1)=MATCH(ex,'Fruits data'!1:1,0)-1),FILTER('Fruits data'!1:46,'Fruits data'!1:1=ex),)))))))
OR
=MAKEARRAY(COUNTA(D2:D),COUNTA(E1:1),LAMBDA(r,c,XLOOKUP(INDEX(D2:D,r),FILTER('Fruits data'!1:46,COLUMN('Fruits data'!1:1)=MATCH(INDEX(E1:1,,c),'Fruits data'!1:1,0)-1),FILTER('Fruits data'!1:46,'Fruits data'!1:1=INDEX(E1:1,,c)),)))
try this with dates:
=ARRAYFORMULA(QUERY({
FLATTEN(FILTER('Fruits data'!A2:100, ISODD(COLUMN('Fruits data'!A2:2)))),
FLATTEN(FILTER('Fruits data'!A2:100, ISEVEN(COLUMN('Fruits data'!A2:2)))),
FLATTEN(IF(FILTER('Fruits data'!A2:100, ISEVEN(COLUMN('Fruits data'!A2:2)))="",,
FILTER('Fruits data'!A1:1, ISEVEN(COLUMN('Fruits data'!A2:2)))))},
"select Col1,sum(Col2) where Col2 is not null group by Col1 pivot Col3"))
which could be simplified:
=ARRAYFORMULA(LAMBDA(x, QUERY({
FLATTEN(FILTER(x, ISODD(COLUMN(X)))),
FLATTEN(FILTER(x, ISEVEN(COLUMN(x)))),
FLATTEN(IF(FILTER(x, ISEVEN(COLUMN(x)))="",,
FILTER(OFFSET(x, -1,,1), ISEVEN(COLUMN(x)))))},
"select Col1,sum(Col2) where Col2 is not null group by Col1
pivot Col3 label Col1'Date'"))('Fruits data'!A2:100))

Count Values under Columns with Same Name Google Sheets

I have a Google sheet which has columns with the same name and there are different values under each column. I want to count the same value that appear under the same column name.
1
2
3
1
2
R
B
C
R
D
D
C
R
B
D
For example, I would like to get the number "R" that appear under column "1", so I would expect a count of 2 for "R" appearing under columns 1.
Here is a link to Google Sheet with actual data.
I have tried countif and countifs in Google Sheets, but can't figure out how to get the count right based on column name.
Try this formula, it outputs an array which shows how many of each letters are contained in each column name:
=LAMBDA(NUMBERS,LETTERS,
LAMBDA(UNUM,ULET,
{
{"",TRANSPOSE(UNUM)};
{ULET,
MAKEARRAY(COUNTA(ULET),COUNTA(UNUM),LAMBDA(ROW,COL,
COUNTIF(FILTER(LETTERS,NUMBERS=INDEX(UNUM,COL)),INDEX(ULET,ROW))
))
}
}
)(UNIQUE(FLATTEN(NUMBERS)),UNIQUE(FLATTEN(LETTERS)))
)($A$1:$AE$1,$A$2:$AE$18)
Assume that your sample datarange is A1:AE18.
apply UNIQUE() and FLATTEN() to A1:AE1, to get the unique entries of column names.
apply UNIQUE() and FLATTEN() to A2:AE18, to get the unique entries of data.
use LAMBDA() to name the dataranges and output of step 1 & 2 as:
NUMBERS (=A1:AE1),
LETTERS (=A2:AE18),
UNUM (=UNIQUE(FLATTEN(NUMBERS))),
ULET (=UNIQUE(FLATTEN(LETTERS))).
create Arrays with {}, which...
1st column's value is a blank, followed by TRANSPOSE(UNUM) in the row,
1st row's value is a blank, followed by ULET in the column.
inside the above said range, use MAKEARRAY() to create results.
MAKEARRAY() set an array by defining the length of ROW and COL, which we uses...
COUNTA(ULET) as the number of rows and,
COUNTA(UNUM) as the number of columns.
inside MAKEARRAY(), you also need a LAMBDA() to apply what to do with each CELL of the new created array, each CELL is accessed by the ROW and COL index.
in our case, we set up the row and col number of the new array using ULET and UNUM. Therefor, the index of each CELL of the new array will be equal to the index of each value inside ULET and UNUM, we can than take that as reference and use COUNTIF() with FILTER() to calculate the number of repeats of each letter in each column name.
You can try this:
= ARRAYFORMULA(
query(
query(
SPLIT(TRANSPOSE(SPLIT(
QUERY(
TRANSPOSE(
QUERY(
TRANSPOSE(
IF(Original!A2:AE18<>"",
"😊"&Original!A1:AE1&"♥"&Original!A2:AE18, )
),,999^99)
),,999^99),
"😊")),
"♥"),
"Select Col1,Col2,count(Col2) group by Col1,Col2"),
"Select max(Col2),Col3 group by Col2,Col3 pivot Col1")
)
Note: (Got inspired by player0 useful answers)
Output:
We can read from the table that: R is appearing 40 times under the column named '1', 24 times under the colum named '2', etc...
The following is a more compact approach than the previous answers:
=arrayformula(query(split(flatten(A1:AE1&"|"&A2:AE18),"|"),"select Col2,count(Col2) group by Col2 pivot Col1"))
N.B. I'm assuming the order of the grouped values in each column is irrelevant, so the QUERY default of lexicographical ordering is fine.

VLOOKUP with 2 columns for both search_key and range

I am struggling to find a way to use a VLOOKUP where the both the search_key and range are 2 columns. In both sheets (seperate workbooks for which I am using IMPORTRANGE) I have 2 columns with First Name and Last Name. The Sheet1 also contains the Hire Date, and I would like to populate the Hire Date from Sheet1 into a column in Sheet2.
I accomplish what I want if I merge the First Name and Last Name into a single column on both sheets. Unfortunately, this cannot be a permanant solution since there are other dependancies where the names must remain seperate columns.
I have created a test worrkbook to showcase the issue.
https://docs.google.com/spreadsheets/d/1v3coBJRwJEbrrdgcflV4-dssKgknS-T2werWVjPwxEA
Put this formula in cell Sheet2!C1:
=arrayformula(
iferror(
vlookup(
A1:A & B1:B,
{ Sheet1!A1:A & Sheet1!B1:B, Sheet1!C1:C },
2, false
)
)
)
Then format the result column as Format > Number > Date.

Google Sheets COLUMN TOP ArrayFormula to calculate ROW wise which require ROW-wise ArrayFormula

Ref link below.
Essentially the aim to get a geometric progression with each term repeated X times.
The correct result on the sheet is obtained using an ArrayFormula across a row. This requires copying the formula column wise.
What I would like is a single ArrayFormula atop the column, that calcluates the results row wise (as indicated). My attempt on the sheet fails.
sheet link
New tab on your sample sheet called MK.Help. This formula is in cell E1.
It uses what I (and some others probably) call a query header smush. it takes advantage of query()'s built in ability to concatenate multiple header rows. It feeds a Transposed array into a query, then pretends like the whole thing is all header rows by setting the 3rd parameter of QUERY() equal to a very large number. It's common with this trick to use 9^9 or 9^99 which is just a very concise way of writing a very large number (9 to the 99th power).
=ARRAYFORMULA(
IF(
ROW(A:A) = 1,
"Result",
TRANSPOSE(
SUBSTITUTE(TRIM(
QUERY(TRANSPOSE(
REPT(
IF(
SEQUENCE(1,MAX(C:C),0) > C:C,,
ROUND(A:A * B:B ^ SEQUENCE(1,MAX(C:C),0)) & CHAR(10)
),
D:D
)
),, 9^9)
), CHAR(10), ",")
)
)
)
Same solution as Matt's, the only difference is that repetition is done using regex.
Try this (on sheet kishkin):
=ARRAYFORMULA(
IF(
A2:A = "",,
REGEXREPLACE(
REGEXREPLACE(
TRANSPOSE(QUERY(TRANSPOSE(
IF(
SEQUENCE(1, MAX(C2:C)) > C2:C,,
ROUND(A2:A * B2:B ^ SEQUENCE(1, MAX(C2:C),)) & ","
)
),, MAX(C2:C))),
"[^,\s]+,?",
REPT("$0", D2:D)
),
"\s+|,\s*$",
)
)
)

2 spreadsheets, IMPORTRANGE update references when adding/deleting rows

How can I get the IMPORTRANGE function to update references in Spreadsheet #2 if I've added/deleted rows to Spreadsheet #1?
Test docs:
Spreadsheet1: "S1"
Spreadsheet2: "S2"
All the answers I've found say
just duplicate/copy sheet from S1 to S2 (but I want S2 to dynamically update when I update S1. don't want to update both S1 and S2 each time)
Use this script, but I got an error saying the range was wrong
use an array (not sure how to do that...)
use address feature (but this did not work either)
use VLOOKUP array (but my spreadsheets do not have the matching column headers)
tried using absolute reference $L$48 but this didnt work either
Would appreciate some assistance figuring this out. I need L47, M47 (S1) to populate into A2, A3 (S2). My actual source spreadsheet (not linked) has tons of data (range A1:Z55) and I add/delete/move rows often.
If I add a row to S1, how can I ensure L47 will update in S2 to L48? Is the address feature the best solution or is an array better?
this can be achieved by adding an extra column far away, where it can be hidden and then populating this column by joining desired set of cells by unique separator until split will occur on the second spreadsheet. note that:
adding or deleting rows will not affect dynamicity of IMPORTRANGE
adding deleting columns will break all imported data
there is no need for an extra column if there is a unique separator per every IMPORTRANGE of data and the search is applied always to such unique separator
in this particular case, there was used column AG from which IMPORTRANGE was fed.
in Spreadsheet1 in Sheet1!AG (no matter of row number) there are formulas which JOIN content of L50 and M50 as well as the content of L51 and M51, etc... (no matter if it's done directly or indirectly as far as the output is TEXT):
=JOIN("¤"; L50; MIN(FILTER(L:L; ISNUMBER(SEARCH("*banana*"; P:P))
+ISNUMBER(SEARCH("*banana*"; Q:Q))
+ISNUMBER(SEARCH("*banana*"; R:R)))))
outputing: next banana¤30-Aug-2004
=JOIN("¤"; L51; MIN(FILTER(L:L; ISNUMBER(SEARCH("*orange*"; P:P))
+ISNUMBER(SEARCH("*orange*"; Q:Q))
+ISNUMBER(SEARCH("*orange*"; R:R)))))
outputing: next orange¤2-Oct-2003
=JOIN("♥"; L52; AVERAGE(FILTER(L:L; ISNUMBER(SEARCH("orange"; P:P))
+ISNUMBER(SEARCH("orange"; Q:Q))
+ISNUMBER(SEARCH("orange"; R:R)))))
outputing: X♥25-Sep-2013
=JOIN("♀"; L53; MIN(FILTER(L5:L48; ISNUMBER(SEARCH("*banana*"; Q5:Q48))
*ISNUMBER(SEARCH("open"; R5:R48)))))
outputing: next banana♀20-Aug-2000
=JOIN("♂"; L54; AVERAGEIFS(M5:M48; R5:R48; "open",
Q5:Q48; "*banana*"))
outputing: avg days open (banana)♂74.41
=JOIN("♪"; L55; Q50/Q51)
outputing: util♪0.370544987
=JOIN("♫"; L56; MINIFS(M5:M48; R5:R48; "open",
Q5:Q48; "*banana*"))
outputing: newest (mo)♫3.48
=JOIN("¤"; L57; M56*30.5)
outputing: newest(days)¤106.2580645
=JOIN("♤"; L58; M58)
outputing: avg LMT♤25051.35484
at this point, it doesn't matter if the format of joined cells is outputting elsehow (eg. 2nd part of the output should be formatted as $, %, mm/dd/yyyy) because in Spreadsheet2 after splitting you can format it back as you wish
in Spreadsheet2 you are free to paste following formula at any column and any row as well as you are free to:
add or delete any rows in Spreadsheet1
and add or delete any rows or columns in Spreadsheet2
=SPLIT(
ARRAY_CONSTRAIN(
QUERY(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
"select Col1 where Col1 ='"&
FILTER(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
ISNUMBER(
SEARCH("banana";
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000"))
))
&"'");
1; 1);
"¤"; 1; 0)
this basically SEARCHes for text value "banana" in Spreadsheet1 under Sheet1 from range AG1:AG1000 and feed it to the FILTER which feeds criterion of QUERY which is ARRAY_CONSTRAINed to return one entry and that entry is SPLIT after unique separator "¤" (used earlier in JOIN) into two columns at the same row. and that's it.
if the content of cell L50 is static like banana and also unique per column you can SEARCH for "banana" otherwise you need to use unique separator per column and SEARCH for such separator instead of "banana"
for a successful linkup, you need to be sure that separator in SPLIT matches separator in JOIN ("¤"). you can use any symbol you wish as the separator (http://www.i2symbol.com/symbols)
example: for formula =JOIN("♤"; L58; M58) you can use:
=SPLIT(
ARRAY_CONSTRAIN(
QUERY(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
"select Col1 where Col1 ='"&
FILTER(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
ISNUMBER(
SEARCH("lmt";
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000"))
))
&"'");
1; 1);
"♤"; 1; 0)
or
=SPLIT(
ARRAY_CONSTRAIN(
QUERY(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
"select Col1 where Col1 ='"&
FILTER(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
ISNUMBER(
SEARCH("♤";
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000"))
))
&"'");
1; 1);
"♤"; 1; 0)
or
=SPLIT(
ARRAY_CONSTRAIN(
QUERY(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
"select Col1 where Col1 ='"&
FILTER(
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000");
ISNUMBER(
SEARCH("avg LMT";
IMPORTRANGE("13evadbMLzvQVSGbYssn_0deFdcmb5l3sqpeFgcNTjOY"; "'Sheet1'!AG1:AG1000"))
))
&"'");
1; 1);
"♤"; 1; 0)

Resources