My current spreadsheet has integers that I'd like to average in every 9th cell in the K Column, starting from K10. So right now my current formula reads,
=AVERAGE(K9,K18,K27)
I'd like the EQ to consider [K36, K45, K54] even though those cells aren't filled in yet.
I believe I can use something like;
*pseudocode*
Find the average of K1+(K1+9)
*Attempt*
\\
=AVERAGE(OFFSET(K10,9,,,)
\\
I think I'm missing the complete knowledge of OFFSET, or I'm thinking maybe an AverageIF() may be in order? I've spent probably an hour on it so far
This array formula will return every 9nth cell starting with K10 and expand to include new data as it is put in:
=AVERAGE(INDEX(K:K,N(IF({1},(ROW(A1:INDEX(A:A,(MATCH(1E+99,K:K)-9)/9))-1)*9+10))))
The -9 is the number of rows to get the starting row to row 1 10-9=1
The /9 and the *9 are the spacing
The +10 is the starting row.
Confirm with Ctrl-Shift-Enter instead of Enter when exiting edit mode
If you can add a column as a flag, you could us the MOD function to check the row number like this:
=MOD(ROW(K10)+1,9) - this returns 0 for every 9th cell starting at K10
Then you could use the AVERAGEIF function to average if the MOD function returns 0.
If you can't add a flag, you may need to look into using an array formula like this:
=AVERAGE(IF(MOD(ROW(K10:K30)-1,9)=0,K10:K30))
You can activate the array formula by hitting Ctrl+Shift+Enter. If done correctly, braces ({}) will be put around the formula in the formula bar.
EDIT:
**both of the following methods counts empty cells as 0
This array formula will work for column K if there is a value in every row of column K:
=AVERAGE(IF(MOD(ROW(INDIRECT("K10:K" & COUNTA(K:K)+10))-1,9)=0,INDIRECT("K10:K" & COUNTA(K:K)+10)))
Or if you don't have continuous data in column K, this method gets the last filled cell.
=AVERAGE(IF(MOD(ROW(INDIRECT("K10:K" & MAX((K:K<>"")*(ROW(K:K)))))-1,9)=0,INDIRECT("K10:K" & MAX((K:K<>"")*(ROW(K:K))))))
Related
I have a small data set of 2 columns and several rows (columns A and B)
I want to return each instance of codeblk 3 in a formula that is elsewhere in my sheet, (so a vlookup is out as it only shows the first instance) if it does not appear then a message to say its not there should come up.
I have the formula partially working but i cant see the reason why its not displaying the values.
My formula is as below:
This is an array
{=IF(ISERROR(INDEX($A$55:$B$70,SMALL(IF($B$55:$B$70=3,ROW($B$55:$B$70)),ROW(1:1))-1,1)),"No value's produced",INDEX($A$2:$C$7,SMALL(IF($B$55:$B$70=3,ROW($B$55:$B$70)),ROW(1:1))-1,1))}
The result that shows up is only "No values produced" but it should reflect statement B, C and D in 3 separate cells (when changing ROW(1:1), ROW(2:2) etc)
{=SMALL(IF($B$56:$B$69=4,ROW($B$56:$B$69)),ROW(1:1))} - This produces the result 68 which is the correct row.
Any ideas?
Thanks,
This is an array formula - Validate the formula with Ctrl+Shift+Enter while still in the formula bar
=IFERROR(INDEX($A$55:$B$70,SMALL(IF($B$55:$B$70=3,ROW($B$55:$B$70)-54),ROW(1:1)),1),"No value's produced")
The issue you are facing is that your index starts it's first row on $B$55, you need to offset the row numbers in the array to reflect this. For example, the INDEX contains 16 rows but if you had a match on the first row you are asking for the 55th row from that INDEX(), it just can't fulfil that.
EDIT
The offset was out of sync as your original formula included another -1 outside of the IF(), I also left an additional bracket in play (the formula above has now been edited)
The ROW() function will essentially translate $B$55:$B$70 into ROW(55:70) which will produce the array {55;56;57;58;59;60;61;62;63;64;65;66;67;68;69;70} so the offset is needed to translate those row numbers in to the position they represent in the indexed data of INDEX().
The other IF() statement then produces and array of {FALSE;2;3;4;FALSE etc.
You can see these results by highlighting parts of the formula in the formula bar and hitting F9 to calculate.
I am trying to get the max value of a column based on the Left function
What I am doing is the following :
These are the results I get when i write this into column C :
=MAX(LEFT(A:A, 2))
But what I truly want is to get in column C the max value of all column A not for each cell.
So the result should be in this case 90 for all rows.
What should be the formula here?
Just another option that gets entered normally:
=AGGREGATE(14,6,--LEFT($A$1:INDEX(A:A,MATCH("ZZZ",A:A)),2),1)
Array formulas will calculate the enitre referenced array. So care should be taken to limit the number of iterations to only the data set.
The $A$1:INDEX(A:A,MATCH("ZZZ",A:A)) part of the formula does that. It finds the last cell in column A with data in it and sets that as the upper bound. So in this instance the reference range is A1:A3. But, it will grow dynamically as data in Column A is added, so no need to change the formula each time data is added.
Update 2
Here is another solution which I think is better than my original (below)
=INT(SUMPRODUCT(MAX(SUBSTITUTE(A:A,"-",".")*1)))
it can be entered as normal (just Enter)
Orignal Answer
You need numbers and arrays
=MAX(IFERROR(LEFT(A:A,2)*1,0))
Let's break this down. Multiplying by turns your strings into numbers - since Left only returns a string
LEFT(A:A,2)*1
Unfortunately this method returns #Value if you multiply an empty string by 1. You will definitely have some empty strings in the range A:A so we wrap the whole thing with an IFERROR function.
IFERROR(LEFT(A:A,2)*1,0)
Now we still need excel to treat this as an array (i.e. a whole column of numbers, rather than just one number). So we put the MAX formula in and enter it with Ctrl+Shift+Enter rather than just Enter. The result is that the formula looks like this in the formula bar
{=MAX(IFERROR(LEFT(A:A,2)*1,0))}
which would return 90 in your example, as required
Update 1
If you are using Excel 2013 or later, you can also use the NUMBERVALUE function
=MAX(NUMBERVALUE(LEFT(A:A,2)))
again, enter it with Ctrl+Shift+Enter
TABLE + DESIRED RESULT
This is what I got but not sure why it doesn't work:
Formula entered in Sheet2!A2=
index($A$2:$A$100, match(0,if(OR(AND(now()-Sheet1!O2<1,D2="closed"),D2="Pending",""),0))
Show me the list of cells in Sheet1! when Condition 1: Now - Time in O2 < 1 Day & D2 = "closed"
Or Condition 2: D2 = "Pending"
Thanks for the help guys
Ok I think I got it, this is an array formula so you want to copy it into cell G2 and press CTRL+SHIFT+ENTER, then drag the formula down far enough to hold all the results. I changed the condition from "Open, waiting, pending or closed within the last 24 hours" to "not closed more than 24 hours ago" to make it easier to read
formula for G2 is:
=IFERROR(INDEX(A$2:A$11, SMALL(IF(NOT((C$2:C$11="Closed")*(NOW()-D$2:D$11>1)), ROW(A$2:A$11)-ROW(A$2)+1), ROWS(A$2:A2))), "")
The SMALL function looks like this =SMALL(array, n) and returns the nth smallest element of the array. In our case n is given by ROWS(A$2:A2) which will give the row number of the current row in the result output. i.e. the first row of your results will contain the 1st smallest number, the 2nd row will contain the 2nd smallest number etc, the trick is that its not giving the smallest number in the id list but its giving the smallest number in the array defined by this line:
IF(NOT((C$2:C$11="Closed")*(NOW()-D$2:D$11>1)), ROW(A$2:A$11)-ROW(A$2)+1
This part is a little complicated as its all array formulas/logic. Please note the * in this context represents a logical AND. If you want to understand it better you can highlight just this part of the formula in the formula bar in Excel and press F9, this will show the values of the array. Clicking in cell G2 and highlighting the line above gives this:
{1;FALSE;3;4;5;FALSE;FALSE;8;9;10}
You can see that the resulting array contains the row number for rows that meet the condition and FALSE for those who don't. The INDEX and SMALL functions then display the id of the row with the 1st smallest value then the second etc with the FALSE's used to ignore the rows that don't meet the condition.
syntax error
you have:
AND(now()-Sheet1!O2<1, D2="closed")
which is fine, problem is in your OR statement:
OR(AND(now()-Sheet1!O2<1,D2="closed"),D2="Pending","")
the last parentheses should be before the last comma I believe. Currently you have an OR statement with 3 arguments the last of which is "" which isn't going to give you what you want. I think you intended the "" to be the result of the IF statement not a condition for the OR statement, try this:
if(OR(AND(now()-Sheet1!O2<1, D2="closed"), D2="Pending"),"",0)
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.
I am trying to use COUNTBLANK to count the number of blank cells in a column, but the function returns an extremely high value because (I think) it's counting all the way to the end of the worksheet.
I want it to stop counting at the first blank cell in the A column. Here is the formula I started with:
=COUNTBLANK(DbT!BZ:BZ)
I want to know how many rows have a blank BZ column AND a value in the A column. I also tried this function:
=COUNTIFS(DbT!BZ:BZ," ",A:A,"")
This formula works:
=COUNTIFS(DbT!BZ:BZ, "",DbT!S:S, "<>")
Assuming your column A is empty after that first blank, you could do the following:
Get the length of the needed range
COUNTA(A:A)
Get the range in the B column that's just as long
OFFSET(B1,0,0,COUNTA(A:A))
Use this as range for your COUNTBLANK
=COUNTBLANK(OFFSET(B1,0,0,COUNTA(A:A)))
If the first assumption is incorrect, you could use the row number of the first blank in column A instead of the COUNTA but I'll have to look around a bit longer for that one...
I am still not entirely clear on what you mean by "I want it to stop counting at the first blank cell in the A column," but if, alternatively, you're looking for the number of rows that have both a blank cell in column BZ and a non-blank cell in column A, as you also say above, then this formula should help:
=COUNTIFS(A:A,"<>",BZ:BZ,"")
EDIT:
OK I think I have it now. It's an array formula, so you'll need to press CTRL + SHIFT + ENTER instead of just ENTER after typing it in the cell:
=SUMPRODUCT(IF(NOT(ISBLANK(A:A)),1,0),IF(TRIM(BZ:BZ)="",1,0))
EDIT 2:
If you prefer a slightly simpler formula, this works too:
=SUMPRODUCT(INT(NOT(ISBLANK(A1:A8))),INT(TRIM(B1:B8)=""))
It's still an array formula, so you'll need to press CTRL + SHIFT + ENTER