Excel - Advanced Sorting Function - function

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)),"")}

Related

Can I show the results of COUNTIF in one column only if there is data in another column?

I have a spreadsheet with multiple sheets.
Sheet A is generated from a template, and it is where users will enter in data to be formatted into a report; it will be deleted after that report is submitted.
As people enter info into Column A of Sheet A, they don't have to enter client information if we already have them entered in this spreadsheet, but otherwise they need to go over to Sheet B and enter it in.
To make it easier for them (so they don't have to check every time, or go back and enter info later after getting an error generating the report), I have used conditional formatting. The way it works is, column Z is set up as a helper column, and uses a "COUNTIF" function to check if the client ID in Sheet A, Column A is found in Sheet B, Column C. Sheet A Column Z returns 0 or 1 (or, theoretically, more than one if we had duplicates), and then Sheet A column A has conditional formatting based on Column Z's value-- if the client is already in, the cell for client ID turns green after they type it; if not, it turns red.
It works great! However, I am adding scripts to these sheets, and looping through them. This helper column is filled from Z1 to Z1000, which means I can't use sheet.maxRow() to get the last row.
I see plenty of workarounds on the script side, but I was wondering if anyone has a clever way to input a value into the helper column Z ONLY IF the corresponding cell (same row) in column A has a value using spreadsheet formulas.
I suspect that an array formula with a filter might do it, but I have little experience with either and can't get anything to work out.
Thanks for your help!
You can use this expression with INDEX, MAX and ROW to make an ARRAYFORMULA only expandable until the last cell with value in column:
A2:INDEX(A2:A,MAX(ROW(A2:A)*(A2:A<>"")))
It will go from A2 to the maximum number of row in A in which A is different than null (that's why both conditions are multiplied).
Then you can set a formula like this in Z2 (check the ranges in case something is not right from reading your text, and delete all other formulas in Z too in case you weren't using an arrayformula already):
=BYROW(A2:INDEX(A2:A,MAX(ROW(A2:A)*(A2:A<>""))),LAMBDA(each,IF(each="","",COUNTIF('Sheet B'!C:C,each))))

Google script custom function for different column [duplicate]

I'm trying to do a couple of different things with a spreadsheet in Google and running into some problems with the formulas I am using. I'm hoping someone might be able to direct me to a better solution or be able to correct the current issue I'm having.
First off all, here is a view of the data on Sheet 1 that I am pulling from:
Example Spreadsheet
The first task I'm trying to accomplish is to create a sheet that lists all of these shift days with the date in one column and the subject ("P: Ben" or S: Nicole") in another column. This sheet would be used to import the data via a CSV into our calendar system each month. I tried doing an Index-Match where it used the date to pull the associated values however I found that I had to keep adjusting the formula offsets in order to capture new information. It doesn't seem like Index-Match works when multiple rows/columns are involved. Is there a better way to pull this information?
The second task I am trying to accomplish is to create a new tab which lists all the dates a specific person is assigned too (that way this tab will update in real time and everyone can just look at their own sheet to see what days they are on-call). However, I run into the same problem here because for each new row I have to change the formula to reflect the correct information otherwise it doesn't pull the correct cell when it finds a match.
I would appreciate any and all information/advice on how to accomplish these tasks with the formula combination I mentioned or suggestions on other formulas to use that I have not been able to find.
Thanks in advance!
Brandon. There are a few ways to attack your tasks, but looking at the structure of your data, I would use curly brackets {} to create arrays. Here is an excerpt of how Google explains arrays in Sheets:
You can also create your own arrays in a formula in your spreadsheet
by using brackets { }. The brackets allow you to group together
values, while you use the following punctuation to determine which
order the values are displayed in:
Commas: Separate columns to help you write a row of data in an array.
For example, ={1, 2} would place the number 1 in the first cell and
the number 2 in the cell to the right in a new column.
Semicolons: Separate rows to help you write a column of data in an array. For
example, ={1; 2} would place the number 1 in the first cell and the
number 2 in the cell below in a new row.
Note: For countries that use
commas as decimal separators (for example €1,00), commas would be
replaced by backslashes () when creating arrays.
You can join multiple ranges into one continuous range using this same
punctuation. For example, to combine values from A1-A10 with the
values from D1-D10, you can use the following formula to create a
range in a continuous column: ={A1:A10; D1:D10}
Knowing that, here's a sample sheet of your data.
First Task:
create a sheet that lists all of these shift days with the date in one
column and the subject ("P: Ben" or S: Nicole") in another column.
To organize dates and subjects into discrete arrays, we'll collect them using curly brackets...
Dates: {A3:G3,A7:G7,A11:G11,A15:G15}
Subjects: {A4:G4,A5:G5,A8:G8,A9:G9,A12:G12,A13:G13,A16:G16,A17:G17}
This actually produces two rows rather than columns, but we'll deal with that in a minute. You'll note that, because there are two subjects per every one date, we need to effectively double each date captured.
Dates: {A3:G3,A3:G3,A7:G7,A7:G7,A11:G11,A11:G11,A15:G15,A15:G15}
Subjects: {A4:G4,A5:G5,A8:G8,A9:G9,A12:G12,A13:G13,A16:G16,A17:G17}
Still with me? If so, all that's left is to (a) turn these two rows into two columns using the TRANSPOSE function, (b) combine our two columns using another pair of curly brackets and a semicolon and (c) add a SORT function to list the dates in chronological order...
=SORT(TRANSPOSE({{A3:G3,A3:G3,A7:G7,A7:G7,A11:G11,A11:G11,A15:G15,A15:G15};{A4:G4,A5:G5,A8:G8,A9:G9,A12:G12,A13:G13,A16:G16,A17:G17}}),1,TRUE)
Second Task:
create a new tab which lists all the dates a specific person is
assigned too (that way this tab will update in real time and everyone
can just look at their own sheet to see what days they are on-call).
Assuming the two-column array we just created lives in A2:B53 on a new sheet called "Shifts," then we can use the FILTER function and SEARCH based on each name. The formula at the top of Ben's sheet would look like this:
=FILTER(Shifts!A2:B53,SEARCH("Ben",Shifts!B2:B53))
Hopefully this helps, but please let me know if I've misinterpreted anything. Cheers.

Setting array formula until last column in Google Sheets

I have a formula as follows in google sheets:
=ARRAYFORMULA(IF(LEN(F2:F),IFERROR(SPLIT(REPT("PAID ",F2:F)&REPT("- ",(24-F2:F))," ")),))
This formula will show paid according to number of paid in the cell and show "-" to the cells in the rest column. For now, this formula is only applicable for columns. I dont want like that, I want this formula to be used until the last column because the number of columns will be increased every year. I dont know whether this should be done in Google App Script or what. Anything should be fine to solve my problems. I have attached some images to explain myself clearly. Thanks in advance.
https://docs.google.com/spreadsheets/d/1bM8l6JefFsPrlJnTWf56wOhnuSjdIwg3hMbY1tN1Zp8/edit#gid=1775459006 - Link to google sheets
I will use the sheet "JALAN SANGGUL 4" as an example. Then you will need to apply to all of the other sheets that have the same structure.
Replace your current G1 formula with this:
=TRANSPOSE(FILTER(Configuration!P2:P,Configuration!P2:P<>""))
Replace your current G2 formula with this:
=ARRAYFORMULA(IF(LEN(F2:F),IFERROR(SPLIT(REPT("PAID ",F2:F)&REPT("- ",(COUNTA(FILTER(G1:1,G1:1<>""))-F2:F))," ",1,1)),))
The added FILTER in each constrains things to only areas where data exists. By counting where only data exists instead of using a set "24" in the second REPT clause, you'll always get dashes going only as far as there are months in Row 1.

How to exclude cells with specific values from a partial match search criterion?

My Question
I will leave a much more detailed explanation below, but here is my problem in short. I need to know how to check a string for a specific character, in my case "/". If the cell has a "/", I then want to split it into two separate strings, one containing everything before the slash, and one containing everything afterwards. Then, as long neither string equals either of two different values, do something. I would appreciate any help!
Detailed Explanation of Problem
I have a spreadsheet I use to schedule many different classes at different times of the day, and in different locations. The first sheet has the time in 15 minute increments running along the left side of my sheet. The header row has every location in my facility. I then manually write the name of a class in the time/location grid. Also, when a class size is sufficiently large, we will oftentimes split it into two or three groups and assign every group to a different location. In order to account for this, I will write "B" and "C" versions of the class. For example: if "Level 1" is a class name, and I need to split it into 3 separate groups at 8:30, I would enter "Level 1", "Level 1 B", and "Level 1 C" under different locations, all in the 8:30 row. See the image below.
After planning my classes according to time and location, I have a second sheet that will organize all of the information so that the time runs along the left side of the second sheet, the class names (followed by the "B" and "C" variants) are in the header row, and the locations then fall under the class name. Every cell in the second sheet contains a formula that carries out this process. By default, if a "B" or "C" variant does not find a match, it will retrieve the value from the original class name. This is what the information from the first image looks like in my second sheet.
After using the spreadsheet for a few months, I've encountered the problem where every now and then, I need to schedule 2 classes at the same time and in the same location. If I try to write both class names into a cell (i.e. "Level 1/Level 3"), the formulas on the second sheet can no longer find the class names on the first sheet since the formulas are matching a cell's entire value. I know I can use wildcards, such as "*" before and after the class name in order to partial match the cell, and the formulas will then work, but I have another difficulty. If I use a * wildcard in a formula searching for any class name that is not followed by a B or C, the formula can also pull data from any cell that contains a B or C variant. For example: if I am searching for any cell that partially contains "Level 3", the formula could be satisfied with cells that contain "Level 1/Level 3", "level 3 C", or "Level 3 B/Level 2 C". I only want to retrieve information from the cells that partially match the exact value "Level 3". This is what it looks like currently.
And this is what I want it to look like.
As I stated before, I have been using formulas to organize the data the way I want. I believe my problem can be solved much more simply with apps script. I know how to use createTextFinder() to find all the cells that contain a partial match with my class names. I do not however know how to limit the search to cells that do not contain the B and C variants of the class. My current idea would be to use textFinder to find all cells that contain a partial or complete match. I could then check to see if the cell contains a "/"; if it does, I could somehow split the string into two separate strings - 1 for everything before the slash, and one for everything after. Then, as long as neither string equals the "B" or "C" variant of the class, get the location name and write under the class name at the correct time. I know how to do just about everything in my idea, except for splitting the string and comparing both halves to the class name. Again, I would appreciate any help anyone can give me!
Please try the following and see if any meets your needs as starting points to "...do something"
Split in 2 columns
=ArrayFormula(IF(REGEXMATCH(A2:A,"Level 3$|Level 3/"),SPLIT(A2:A,"/"),""))
1 column
=ArrayFormula(IFERROR(SUBSTITUTE(REGEXEXTRACT(A2:A11,"Level 3$|Level 3/"),"/","")))
1 column + the rest
=ArrayFormula(IFERROR(SUBSTITUTE(REGEXEXTRACT(A2:A11,"Level 3$|Level 3/"),"/",""),A2:A11))
(Please adjust ranges to your needs.
If in further need, please share a test sheet so as you can be easier helped.)
Functions used:
ArrayFormula
IFERROR
IF
REGEXMATCH
SUBSTITUTE
REGEXEXTRACT
SPLIT

Find answer for data in A in predefined list of answers - VLOOKUP - Google Spreadsheets

I've got a google spreadsheet with a main sheet tab. column A contains a bunch of company names, some of which repeat, and are included multiple times. In column B i want to have a predefined unique code for each company. For instance if I had a company name Nike in a10, a14, a21 I would have the same code each time in b10, b14, b21.
I was initially looking at if / else blocks and switch statements (not sure if google spreadsheet can even do them) to accomplish this, but they would become massive and unmanageable as single line pieces of code will involve several hundred company names.
Instead I've setup another tab called Codes Data with a predefined list of all of the company names in column A and the code in column B. This list will be added to over time.
What I'm trying to do is have a formula in the main sheet column B that will check the value of the corresponding column A cell, find the unique code for that company in the Codes Data tab and place that code in column B.
I started using VLOOKUP for this and at first it seemed to work, but now I'm getting inconsistent results (i.e. its outputting Addidas | am-1121 and ACMECO RESTAUR | am-1121 where according to the Codes Data sheet it should output Addidas | ad-5426).
I've provided an example spreadsheet here : https://docs.google.com/spreadsheets/d/156Lla5IyLjB-hp7s50jpotC1qcaov9RdFkpUzATe710/edit#gid=458436476
Is VLOOKUP the correct function to be doing this? If so, how can I use it more properly, and if not what would be a better approach?
You must add FALSE to your lookup formula, or it won't work:
=VLOOKUP(A5, 'Codes Data'!$A:$B, 2, FALSE)
Use the Help menu, and choose "Sheets Help", and then type in "vlookup". You'll get the documentation:
is_sorted - [OPTIONAL - TRUE by default] - Indicates whether the column to be searched (the first column of the specified range) is sorted.
If is_sorted is TRUE or omitted, the nearest match (less than or equal to the search key) is returned. If all values in the search column are greater than the search key, #N/A is returned.
If is_sorted is set to TRUE or omitted, and the first column of the range is not in sorted order, an incorrect value might be returned.
If is_sorted is FALSE, only an exact match is returned. If there are multiple matching values, the content of the cell corresponding to the first value found is returned, and #N/A is returned if no such value is found.