I am looking to create a formula that enables me to search a set of data for an 8 digit number. I have attached my testing sheet.
In column B is the stock numbers I need to find within a set of data.
In column E is the full list to be checked against, however, within any one cell, you can have several different 8 digit stock numbers.
In my test sheet, I have found that a vlookup only searches for the first stock number and not all the stock numbers within that cell. I have attempted an index match formula combined with a transpose split however none of these has enabled me to properly search my data set.
=ARRAYFORMULA(VLOOKUP(B2:B,$E$2:$E,1,0))
then
=INDEX($E$2:$E$1139,(MATCH(B2,TRANSPOSE(SPLIT($E$2:$E,";, ")))))
The data can be separated within the cell with either spaces or "," or ";"
You should be able to make a copy of my test sheet using this link:
https://docs.google.com/spreadsheets/d/1UckPZw6tWBw0H13p79N94IqV2EFyfhYNyEhmLecr3XM/copy#gid=55962883
Hope you can help.
try:
=FILTER(E:E, REGEXMATCH(E:E&"", TEXTJOIN("|", 1, B2:B)))
update:
to get true/false use:
=INDEX(REGEXMATCH(E2:E&"", TEXTJOIN("|", 1, B2:B)))
or if you want to return match or N/A use:
=INDEX(IF(REGEXMATCH(E2:E&"", TEXTJOIN("|", 1, B2:B)), E2:E, ISNA()))
Related
I am working with a large (but simple) formula In Google Sheets that re-uses the same blocks of formulas repeatedly. To get a bunch of data from a bunch of different tabs I have to use 708 characters in that block of formulas. But then I need to repeatedly reference that data over and over within just the 1 cell which multiplies the length of the formula to the point where I can't even tell what is going on any more.
For example I have a cell with the final code (with 2216 characters) of:
=iferror(IF(ISNUMBER(SEARCH("a",concatenate(TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Brown!$C$3:$C$68&Brown!$D$3:$D$68,Brown!H$3:H$68,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Godoy!$C$3:$C$76&Godoy!$D$3:$D$76,Godoy!H$3:H$76,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Sindel!$C$7:$C$60&Sindel!$D$7:$D$60,Sindel!H$7:H$60,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Taylor!$C$3:$C$82&Taylor!$D$3:$D$82,Taylor!H$3:H$82,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Wanner!$C$3:$C$55&Wanner!$D$3:$D$55,Wanner!H$3:H$55,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Gehrman!$C$3:$C$16&Gehrman!$D$3:$D$16,Gehrman!H$3:H$16,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Francois!$C$3:$C$17&Francois!$D$3:$D$17,Francois!H$3:H$17,"")))))),"A",average(ArrayFormula(mid(concatenate(TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Brown!$C$3:$C$68&Brown!$D$3:$D$68,Brown!H$3:H$68,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Godoy!$C$3:$C$76&Godoy!$D$3:$D$76,Godoy!H$3:H$76,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Sindel!$C$7:$C$60&Sindel!$D$7:$D$60,Sindel!H$7:H$60,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Taylor!$C$3:$C$82&Taylor!$D$3:$D$82,Taylor!H$3:H$82,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Wanner!$C$3:$C$55&Wanner!$D$3:$D$55,Wanner!H$3:H$55,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Gehrman!$C$3:$C$16&Gehrman!$D$3:$D$16,Gehrman!H$3:H$16,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Francois!$C$3:$C$17&Francois!$D$3:$D$17,Francois!H$3:H$17,"")))),sequence(len(concatenate(TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Brown!$C$3:$C$68&Brown!$D$3:$D$68,Brown!H$3:H$68,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Godoy!$C$3:$C$76&Godoy!$D$3:$D$76,Godoy!H$3:H$76,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Sindel!$C$7:$C$60&Sindel!$D$7:$D$60,Sindel!H$7:H$60,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Taylor!$C$3:$C$82&Taylor!$D$3:$D$82,Taylor!H$3:H$82,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Wanner!$C$3:$C$55&Wanner!$D$3:$D$55,Wanner!H$3:H$55,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Gehrman!$C$3:$C$16&Gehrman!$D$3:$D$16,Gehrman!H$3:H$16,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Francois!$C$3:$C$17&Francois!$D$3:$D$17,Francois!H$3:H$17,"")))))),1)*1))),"")
This looks crazy long, but it is only because I am using this one formula (with 708 characters):
concatenate(TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Brown!$C$3:$C$68&Brown!$D$3:$D$68,Brown!H$3:H$68,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Godoy!$C$3:$C$76&Godoy!$D$3:$D$76,Godoy!H$3:H$76,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Sindel!$C$7:$C$60&Sindel!$D$7:$D$60,Sindel!H$7:H$60,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Taylor!$C$3:$C$82&Taylor!$D$3:$D$82,Taylor!H$3:H$82,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Wanner!$C$3:$C$55&Wanner!$D$3:$D$55,Wanner!H$3:H$55,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Gehrman!$C$3:$C$16&Gehrman!$D$3:$D$16,Gehrman!H$3:H$16,""))),TEXTJOIN("",TRUE,arrayformula(if($B3&$C3=Francois!$C$3:$C$17&Francois!$D$3:$D$17,Francois!H$3:H$17,""))))
3 times within the cell.
Is it possible to have one cell just contain the block of functions that I want to use (as a string) and then somehow convert the string to code to reuse it without making a monster function?
For example, could I assign A1 to hold the long code that I want to have multiple times and then have a formula like:
=IFERROR(IF(ISNUMBER(SEARCH("a",textToFormula(A1))),"A",AVERAGE(ArrayFormula(mid(textToFormula(A1),sequence(len(textToFormula(A1))),1)*1)).
I should also mention that there is no room in my sheet to just put the string of data I am looking for in a separate cell, because I have to apply this formula roughly 50 rows and 180 columns.
Ouch! That is a long formula! Sadly, there's no eval() like in JavaScript, but we can at least make you a simpler formula.
How about this one? It's still a bit long, but far less complex. It only Queries each sheet once. This one works in cell F3, but can be dragged.
=IF(
JOIN("",{Teacher1!G$7:G;Teacher2!G$7:G;Teacher3!G$7:G;Teacher4!G$7:G;Teacher5!G$7:G})<>"",
IFERROR(Average(ArrayFormula(--{
QUERY(ArrayFormula(TO_TEXT(Teacher1!$A$7:$GX)),"select Col"&COLUMN()+1&" where Col3='"&$B3&"' and Col4='"&$C3&"'");
QUERY(ArrayFormula(TO_TEXT(Teacher2!$A$7:$GX)),"select Col"&COLUMN()+1&" where Col3='"&$B3&"' and Col4='"&$C3&"'");
QUERY(ArrayFormula(TO_TEXT(Teacher3!$A$7:$GX)),"select Col"&COLUMN()+1&" where Col3='"&$B3&"' and Col4='"&$C3&"'");
QUERY(ArrayFormula(TO_TEXT(Teacher4!$A$7:$GX)),"select Col"&COLUMN()+1&" where Col3='"&$B3&"' and Col4='"&$C3&"'");
QUERY(ArrayFormula(TO_TEXT(Teacher5!$A$7:$GX)),"select Col"&COLUMN()+1&" where Col3='"&$B3&"' and Col4='"&$C3&"'")}
)),"A"),
""
)
The Query Statement:
Each cell queries each sheet as a table where the name is matched in the sheet as a row.
The COLUMN()+1 is to get the corresponding columns to line up. I.e. If we're in column F (6), we want to look in column G (7).
The TO_TEXT allows us to look for non-numbers ("A").
After that, convert each query result to a number with --, then take the Average. If any of the numbers cannot be converted to a number, Average gives us an error, and we assume the value was "A".
In the case that all cells in a column for a date are blank (the blank JOIN), bypass the queries altogether and output a blank cell.
In this sheet, I've the below input data:
As seen, the courses are separated by /
I want to display the same in the format below, where each line shows one course only, with the data of the student repeated:
I know using =split(C3," / ",true,true) can split the courses into 2 columns at the same row, but I need them in the same column, so I tried =TRANSPOSE(split(C3," / ",true,true)) that is working fine for the first line only, but it fail with using ARRAYFORMULA.
Any thought? I'm opened for any potential solution, formula or script or any other.
UPDATE
I tried this trick, creating a new column showing number of courses for each student as =ArrayFormula(LEN(REGEXREPLACE(C11:C13, "[^/]", ""))+1)
Then using Rep to repeat each row based on the number of courses =arrayformula({transpose(split(concatenate(rept(B11:B13 & ",",D11:D13)),",",false,true)),transpose(split(concatenate(REPT(C11:C13 & ",",D11:D13)),",",false,true))}) then ended up with:
But here, I've the courses still joint together, how can i split them!
I've added two sheets to your sample spreadsheet. "Sheet2" is a cleanup of your testing sheet, "Sheet1." The other sheet ("Erik Help") references Sheet2, not Sheet1, and contains the following formula in cell A1:
=ArrayFormula({"Student ID","Student Name","Course";SUBSTITUTE(SPLIT(QUERY(FLATTEN(SPLIT(FILTER(SUBSTITUTE("/ "&Sheet2!C3:C,"/","/ "&Sheet2!A3:A&"zzz~"&Sheet2!B3:B&"~"),Sheet2!A3:A<>""),"/")),"Select * WHERE Col1 Is Not Null"),"~"),"zzz","")})
This one array formula produces all headers and results.
A virtual array is formed between the curly brackets { }. Headers are introduced first followed by a semicolon, which means "bump down one row to continue." The header titles can be changed as you like.
How It Works:
An addition "/ " is concatenated to the front of every non-blank entry in Sheet2!C2:C. Then SUBSTITUTE replaces every one of these forward slashes with Col A data, "zzz~", Col B data and "~". The tildes (~) will be used later by the outer SPLIT. The "zzz" is added to make sure that ID numbers are converted to text so that they hold formatting throughout the processing and don't turn into real numbers; later, the outer SUBSTITUTE will replace those with null (i.e., get rid of the 'zzz').
Once the initial concatenations are complete, they are SPLIT at the forward slash and then FLATTENed into one column. QUERY removes any blank rows in this virtual array so far. The remaining results are again SPLIT at the tilde. Finally, that outer SUBSTITUTE removes the temporary instances of 'zzz'.
I also added a custom CF formula for the alternating color banding on alternate rows.
You can try this one:
Formula:
=ARRAYFORMULA(TRIM(QUERY(SPLIT(FLATTEN(IF(IFERROR(SPLIT(C3:C5, "/"))="",,
A3:A5&"×"&B3:B5&"×"&SPLIT(C3:C5, "/"))), "×"),
"where Col3 is not null")))
Output:
Reference:
How to transpose & split multiple columns and repeat specific cells in a column
I'm trying to run a formula to identify in which row a total sum is reached.
I've been able to do that calculation when I have an entire range of cells to work with, however, I'm doing a filter / join calculation because I need to do this from an individual row with all the data instead of an entire range of cells.
Here is an example google sheet (EDITABLE - feel free) where you can see the range and working formula (both below). Help getting this from the single-cell versions on the top would be very helpful. The error I get with both row() & index() formulas is that the "argument must be a range".
If there's another way to do this besides the single-cell I had that doesn't require referencing the range (e.g. using FILTER) then I'm open to it.
My desired result is to be able to pull the get the second column (date) at the point when the sum is reached (can be via the INDEX & MATCH formula I used or an alternative). This will tell me the earliest date that feeds into the desired sum.
Yes unfortunately you can't do that trick with SUMIFS to get a running total unless the column being totalled is an actual range.
The only approach I know is to multiply successive values by a triangular array like this:
1 0 0 ...
1 1 0 ...
1 1 1 ...
so you get just the sum of the first value, the first 2 values, then 3 values up to n.
This is the formula in F5:
=ArrayFormula(match(E14,mmult(IF(ROW(A1:INDEX(A1:ALL1000,COUNT(split(A5,",")),COUNT(split(A5,","))))>=
COLUMN(A1:INDEX(A1:ALL1000,COUNT(split(A5,",")),COUNT(split(A5,",")))),1,0),TRANSPOSE(SPLIT(A5,",")))))
And the formula in F6 is just
=to_date(INDEX(TRANSPOSE(SPLIT(B5,",")),F5,1))
EDIT
You might have guessed that the above formula was adapted from Excel, where you try to avoid volatile functions like Offset and Indirect.
I have realised since posting this answer that it could be improved in two ways:
(1) By using Offset or Indirect, thus avoiding the need to define a range of arbitrary size like A1:ALL1000
(2) By implying a 2D array by comparing a row and column vector, rather than actually defining a 2D array. This would give you something like this in F5:
=ArrayFormula(match(E14,mmult(IF(ROW(indirect("A1:"&address(COUNT(split(A5,",")),1)))>=
COLUMN(indirect("A1:"&address(1,COUNT(split(A5,","))))),1,0),TRANSPOSE(SPLIT(A5,",")))))
which could be further simplified to:
=ArrayFormula(match(E14,mmult(IF(ROW(indirect("A1:A"&COUNT(split(A5,","))))>=
COLUMN(indirect("A1:"&address(1,COUNT(split(A5,","))))),1,0),TRANSPOSE(SPLIT(A5,",")))))
Motive: I am trying to compare 2 cells with comma separated values within each and find out the number of common occurrences. Also based on the number of common occurrences and Experience Input Values, i want to print a certain keyword.
Attaching The Screenshot:
GOAL: The mentioned text in Deep Red are my goals:
1. Count the number of common words between B2 & B6
2. Print B1 IF certain conditions are true.
B11:
=SUMPRODUCT(TRIM(SPLIT(B2,","))=UNIQUE(TRANSPOSE(TRIM(SPLIT(B6,",")))))
B12:
=IF(AND(B11>50,B7>=B3,B7<=B4),B1,"👎")
I have a tournament spreadsheet that has a list of names in column "D" (between 20 and 150 entries) and the table number that each person is assigned to (column "E").
In column "I", I have a ridiculous formula that creates a list of the number of seats available at each table (this information changes from one event to another).
Column "G" is my problem. I want to run through the contents of column "E" and anytime there is a value in column "E" that matches the contents of column "I", to give the the contents of column "D".
Here is my formula as it currently stands in cell G3:
{=IFERROR(INDEX(D$3:D$150,SMALL(IF(E$3:E$150=I3,ROW(E$3:E$150)-ROW(E$3)+1),ROWS(E$3:E3))),"")}
The formula works perfectly for all values in column "E" as long as the value in column "E" is 1. This formula works beautifully in Google Sheets but Excel seems to process the ranges differently. I've tried with both a standard formula and an array formula without success.
Any advice would be greatly appreciated.
One additional note, I can use VBA if needed but I would prefer to stick with functions.
for this example I used the following formula:
=INDEX($C$14:$C$25,AGGREGATE(15,6,(ROW($D$14:$D$25)-ROW($D$14)+1)/($D$14:$D$25=H16),COUNTIF($H$16:H16,H16)),1)
You will need to adjust the ranges to suit your needs.
From my testing, the problem appears to be with the ROWS(E$3:E3) as the second argument for the SMALL function. Basically, when you get down to your first 2 in row 12, you are asking the small function for the 10th smallest value in D that has 2 in column E. Since it looks like you are only expecting eight players, this will never find anything.
Try changing ROWS(E$3:E3) to COUNTIF(I$3:I3, I3).
That will count how many 1's or 2's you've already passed in column I, so when you get to the 2's, it should reset and ask for the first smallest.
#Forward Ed. Thanks for your input. That helped get me on the path that I needed.
Here is the formula that ended up working for me:
{=IFERROR(INDEX(D$3:D$150,SMALL(IF(E$3:E$150=I3,ROW(E$3:E$150)-MIN(ROW(E$3:E$150))+1),J3)),"")}