Set Range based on Cell Value - excel

In the Index and Match functions, the columns are fixed (column C for the index range and Column F for the Match range). The starting row for both is on a seperate page "Input" Cell C7 and ending row for both is on the same "Input" page but Cell C10. The ranges are on a sheet "Constants". The formula is on a sheet "Summary". The starting and ending rows will change project to project and I need a way for these formulas to update based on the row values on the "Input" page.
I think the issue is that the ranges as calculated are returned with quotation marks at the beginning and end. When I hard code the current ranges, the quotation marks aren't there. I tried the Substitute function to replace the quotations with nothing but they remained. I also tried using the Address function, but it returned with quotation marks too. An example input for B2 in the formula is P102. Input!C7 = 1271, Input!C10 = 1400. So the code is trying to return the value in Column C on the constants page by matching the row 102 is in in Column F.
=IF(OR(RIGHT(B3,2)="01",RIGHT(B3,2)="64"),"REFERENCE",INDEX("Constants!C"&Input!$C$7&":"&Input!$C$10,MATCH(NUMBERVALUE(RIGHT(Summary!B3,3)),"Constants!F"&Input!$C$7&":"&"F"&Input!$C$10,0)))

Wrap your references in the INDIRECT function. From the documentation:
Use INDIRECT when you want to change the reference to a cell within a formula without changing the formula itself.
INDIRECT("Constants!C"&Input!$C$7&":C"&Input!$C$10)...
and
INDIRECT("Constants!F"&Input!$C$7&":F"&Input!$C$10)...

Related

Countifs and ranges

I'm trying to write some code that requires a cell value to be within a range of dates.
This is what I have written so far (albeit a few name changes for simplicity):
=IF(COUNTIFS('[SheetA.xlsx]TabA'!A2:AA2, "submit", '[SheetA.xlsx]TabA'!B2:AB2, '[SheetA.xlsx]TabB'!**A9:A13**) >= 1, '[SheetA.xlsx]TabA'!C2, "")
Basically, if a cell in a row contains the word "submit" AND the cell to the right of it has a date (within a specific range of five days), I'd like the function to return the third cell of that row.
The range in bold is a range of dates.
This formula doesn't work when I use a range, but returns expected values when I enter a single date. What should I change?
As for COUNTIF() not finding a date in a range, if the range is consecutive, you can get around that like so:
COUNTIFS(A2:AA2, "submit", B2:AB2,">=" & LowestDate,B2:AB2,"<=" & HighestDate)
The problem there is that you're comparing a range to a range, so the whole range has to match the whole other range. This will always return false since the ranges are not even the same shape. When instead you compare a range to a single value, Excel automatically assumes you want true if the single value exists anywhere in the range.
It sounds like your other issue is that since COUNTIFS() does not return where it found "submit" and a date, the outer IF statement cannot determine where the third cell is.
If there's only going to be one submit, you could use Match("submit",2:2,0)+2 to find the relative column of "submit" add 2 to it, and then use ADDRESS() to build the address of the third cell based on the row. Last you put that inside of an INDIRECT() to return the third cell. Something like:
=INDIRECT(ADDRESS(ROW(A2),MATCH("submit",2:2,0)+2,1,1))
Note that this will not work for multiple matches as you're returning the first value MATCH() finds.
I use ROW() because ADDRESS() may not fill the row series very well when you drag the formula down a column if you use a plain row number.

Changing countif range automatically

I'm using this formula to count the word red in the last 30 days but the range is not changing when a new row is added at the bottom.
How can I change the formula so when a new row is added at the bottom the range is adjusted automatically? The quantity of rows to check is always 30.
=COUNTIF(D2433:D2463, "Red")
Another technique is using a dynamic named range:
Formula > Name Manager > New: Give a Name first and then insert the following formula into Referes to field. Also see the picture.
=INDEX(Sheet1!A:A,1):INDEX(Sheet1!A:A,INDEX(MAX((Sheet1!$A:$A<>"")*(ROW(Sheet1!A:A))),0))
This should give you a range like $A$1:$A$300 depends where the last non-empty cell is.
Now in the cell that you want to evaluate, add this formula:
=COUNTIF(rng,"red")
Please note rng is the named range that you should change to the name you want to use.
This will find the last cell and even work for blank cells. Try and let me know if you have any question.
Use the following:
=COUNTIF(OFFSET($D$2433,0,0,30,1),"Red")
The references you are using $D$2433 till $D$2463 count 31 if you need 31 change in the above formula 30 to 31
Offset will start in $D$2433 and count the rows down in the same column
Countif will count if Red
Update
If in column D you insert only Data to be counted, you can use :
=COUNTIF(OFFSET(INDIRECT("$D$"&MAX(IF($D:$D<>"",ROW($D:$D),0))),0,0,-30,1),"Red")
This is an array formula press Ctrl+Shift+Enter instead of just Enter
The new formula will find the last non empty row in column D and Indirect will correct the formula automatically
You need a relative cell reference. You can do this with the
=OFFSET()
function.
=COUNTIF(INDEX(D:D,AGGREGATE(14,6,ROW(D:D)/--((D:D)<>""),1)-30):INDEX(D:D,AGGREGATE(14,6,ROW(D:D)/--((D:D)<>""),1)),"Red")
Conditions:
There all rows beneath the last row must be blank
There cannot be any blank row within the last 30 row or your count may be off.
This is an array like function. If you use full range references it checks 1048576 cells each time the aggregate function references the full column range. As such if you use the formula a lot you can bog down your computer, if you are only using it a couple of time you will probably be ok.

use ADDRESS function to define range in COLUMN

I have to use
=COLUMN($L$1:$CA$1)
as part of my original formula that CA, is the last column for a table named MyTable.
Because the last column is always changing (add columns every month),
i want to use
=COLUMN($L$1:ADDRESS(1,COLUMNS(MyTable)))
but this is not work.
My question is: how can i add last column of a table to a part of specific range?
ADDRESS returns a string. But the range reference in COLUMN($L$1:...) needs a cell reference after the :. INDEX will return a cell reference.
So try within your formula:
...COLUMN($L$1:INDEX(MyTable,1,COLUMNS(MyTable)))...

Autofill by next column over with indirect formula

I was wondering why the formula I did won't go to the next column over. I did place the $ sign to stay in the same row, but not on the column, thinking it will go to the next column over. Is there any suggestions as to why this is doing this?
The following is the formula I inputted into the spreadsheet:
=(INDIRECT("BHR8732A2!P$16"))*$S283
Because you have " " around the sheet and cell reference BHR8732A2!P$16, it's going to be treated as a text string, not a cell reference. It's not going to change when you copy across.
If you want to just multiply the value in column S by the value in row 16, you'd write it as ='BHR8732A2'!P$16*$S283.
If you want to multiply the value in column S by the value in another cell whose address is in row 16, you'd write it as =INDIRECT('BHR8732A2'!P$16)*$S283.
Using a text string inside the Indirect is kind of the 'worst of both worlds', where you're just feeding the cell reference directly into the Indirect, which is unnecessary.
I'm not sure why the whole BHR8732A2!P$16 has quotes. Excel does not seem to recognise the P$16 part as a cell reference for me.
Try this: =(INDIRECT('BHR8732A2'!P$16))*$S283

Is there a 2 Value Look up function in MS Excel that can perform the following?

I am going crazy over this. It seems so simple yet I can't figure this out. I have two worksheets. First worksheet is my data. Second is like an answer key. Upon checking checking, A1:B1 in Sheet 1 is a match with the conditions in Row 52 in SHEET 2, therefore, the value in Column C is "MGC". What is the formula that will perform this function? It's really hard to explain without the data so I pasted a link of the sample spreadsheet. Thank you so much in advance.
sample spreadsheet here. https://docs.google.com/spreadsheets/d/1_AjuNfCdGfEM-XkqPa6W4hSIxQg4NM2Vg4c2C1pQ_vQ/edit?usp=sharing
screenshot here. (wont let me post i have no reputation)
In Sheet2, insert a column in front of Column A and put the formula in A2 =C2&D2.
Then in Sheet1, Cell C2 the formula =vlookup(A2&B2,Sheet2!A:B,2,0).
the first make a concatenated key to lookup, then the second looks up that key.
How about a index(match())? If I've understood correctly you need to match across both the A and B column in sheet one, checking for the relevant values in B and C on sheet 2 to retrun worksheet 2 column a to worksheet 1 column c.
third version try:
=INDEX(Sheet2!$C$1:$C$360,MATCH(Sheet1!A1&Sheet1!B1,Sheet2!$B$1:$B$360&Sheet2!$C$1:$C$360,0))
Basically what this does is use concatenation, the & operator, to specify you are looking for "Criteria A" & "Criteria B" in sheet 1, which makes the string "Criteria A Criteria B", which is supplied in the first part of the match function.
In the second it then says match this against all of my variables in sheet 2 in the same way with concantenation.
The final part of match function (0) specifies you want an 'exact' match
It then supplied this as a reference to the index function, which then finds the row intersecting with the value you want, and returns that.
As noted here https://support.microsoft.com/en-us/kb/59482 this is an array formula, so it behaves differently, and must be input differently. https://support.office.com/en-za/article/Guidelines-and-examples-of-array-formulas-7d94a64e-3ff3-4686-9372-ecfd5caa57c7
There are (at least) 2 ways you could do this without VBA.
USING A SORTED LIST
The first relies on the assumption that your data can be re-sorted, so that everything "Unreported" is in the top, and everything "reported" is together below that (or vice versa). Assuming that this is the case (and it appears to already be sorted like this),we will use the function OFFSET to create a new range which shows only the values that align with either being "Unreported" or "Reported".
Offset takes a given reference to a point on a sheet, and then moves down/up & left/right to see what reference you want to return. Then, it returns a range of cells of a given height, and a given width. Here, we will want to start on Sheet2 at the top left, moving down until we find the term "Unreported" or "Reported". Once that term is found, we will want to move one column to the right (to pull column B from sheet 2), and then have a 'height' of as many rows as there are "unreported" or "reported" cells. This will look as follows in A1 on sheet 1, copied down:
=OFFSET(Sheet2!$A$1,MATCH(A1,Sheet2!A:A,0)-1,1,COUNTIF(Sheet2!A:A,A1),1)
This says: First, start at cell A1 on sheet2. Then find the term in A1 (either "unreported" or "reported", on sheet2!A:A (we subtract 1 because OFFSET starts at A1 - so if your data starts at A1 we need to actually stay at "0". If you have headers on sheet2, you will not need this -1). Then, move 1 column to the right. Go down the rows for as many times as Sheet2 column A has the term found in Sheet1 A1. Stay 1 column wide. Together, this will leave you with a single range on sheet2, showing column B for the entire length that column A matches your term in sheet1 A1.
Now we need to take that OFFSET, and use it to find out when the term in Sheet1 B1 is matched in Sheet2 column B. This will work as follows:
=MATCH(B1,[FORMULA ABOVE],0)
This shows the number of rows down, starting at the special OFFSET array created above, that the term from B1 is matched in column B from sheet2. To use this information to pull the result from column C on sheet 2, we can use the INDEX function, like so:
=INDEX([FORMULA ABOVE],MATCH(B1,[FORMULA ABOVE],0))
Because this would be fairly convoluted to have in a single cell, we can simplify this by using VLOOKUP, which will only require the OFFSET function to be entered a single time. This will work as follows:
=VLOOKUP(B1,[FORMULA ABOVE],2,0)
This takes the OFFSET formula above, finds the matching term in B1, and moves to the 2nd column to get the value from column C in sheet2. Because we are going to use VLOOKUP, the offset formula above will need to be adjusted to provide 2 columns of data instead of 1. Together, this will look as follows:
FINAL FORMULA FOR SHEET1, C1 & COPIED DOWN
=VLOOKUP(B1,OFFSET(Sheet2!$A$1,MATCH(A1,Sheet2!A:A,0)-1,1,COUNTIF(Sheet2!A:A,A1),2),2,0)
OPTION USING ARRAY FORMULAS
The above method will only work if your data is sorted so that the REPORTED and UNREPORTED rows are grouped together. If they cannot be sorted, you can use an ARRAY FORMULA, which essentially takes a formula which would normal apply to a single cell, and runs it over an entire range of cells. It returns an array of results, which must be reduced down to a single value. A basic array formula looks like this [assume for this example that A1 = 1, A2 = 2...A5 = 5]:
=IF(A1:A5>3,A1:A5,"")
Confirm this (and all array functions) by pressing CTRL + SHIFT + ENTER, instead of just ENTER. This looks at each cell from A1:A5, and if the value is bigger than 3, it gives the number from that cell - otherwise, it returns "". In this case, the result would be the array {"";"";"";4;5}. To get the single total of 9, wrap that in a SUM function:
=SUM(IF(A1:A5>3,A1:A5,""))
In your case, we will want to use an array formula to see what row in Sheet2 matches A1 from Sheet1, and B1 from Sheet1. This will look like this:
=IF(Sheet2!$A$1:A$100=A1,IF(Sheet2!$B$1:$B$100,ROW($B$1:$B$100),""),"")
This checks which rows in column A from sheet 2 match A1. For those that do, it then checks which rows in column B from sheet 2 match B1. For those, it pulls the row number from that match. Everything else returns "". Assuming no duplicates, there should only 1 row number which gets returned. To pull that number from the array of results, wrap the whole thing in a MATCH function. Now that you have the row number, you can use an INDEX function to pull the result in Column C with that row, like this:
FINAL ARRAY FORMULA METHOD
=INDEX($C$1:$C$100,MAX(IF(Sheet2!$A$1:A$100=A1,IF(Sheet2!$B$1:$B$100,ROW(Sheet2!$B$1:$B$100),""),"")))
Remember to confirm with CTRL + SHIFT + ENTER instead of just ENTER, when you type this formula. Note that I didn't refer to all of Sheet2!A:A, because array formulas run very slowly over large ranges.
The following formula should work without making any changes to the datasheets.
=INDEX(Sheet2!$A$1:$A$360,MATCH(Sheet1!A1,IF(Sheet2!$C$1:$C$360=Sheet1!B1,Sheet2!$B$1:$B$360),0))
Remember to save this formula as an array with CTRL+SHIFT+ENTER
Documentation on how to use INDEX and MATCH against multiple criteria can be found on Microsoft Support.
It's not clear what you want to do with the multiples that do not have corresponding matches. txed is listed as Unreported twice in Sheet1; kntyctap is listed as Unreported three times. There are only one corresponding match on Sheet2 for each of these.
Non-array Standard Formulas for multiple criteria matches
For Excel 2010 and above use this standard formula in Sheet1!C1:
=IFERROR(INDEX(Sheet2!$A$1:$A$999,AGGREGATE(15,6,ROW(1:999)/((Sheet2!$B$1:$B$999=A2)*(Sheet2!$C$1:$C$999=B1)), COUNTIFS(A$1:A1, A1, B$1:B1, B1))), "")
For version of Excel prior to 2010 use this standard formula in Sheet1!C1:
=IFERROR(INDEX(Sheet2!$A$1:$A$999, SMALL(INDEX(ROW($1:$999)+((Sheet2!$B$1:$B$999<>A1)+(Sheet2!$C$1:$C$999<>B1))*1E+99, , ), COUNTIFS(A$1:A1, A1, B$1:B1, B1))), "")
I've handled error with the IFERROR function in that latter formula. Excel 2003 and previous may have to use an IF(ISERROR(..., ...)) combination.

Resources