I currently have this formula but it returns the non-zero values in the opposite order I want.
Here's the formula:
=INDEX($R275:$BE275,LARGE(IF($R275:$BE275<>0,COLUMN($R275:$BE275)- MIN(COLUMN($R275:$BE275))+1),COLUMNS($A:A)))
This returns the first non-zero value from column BE looking back towards R, when I want it to work the other way, the first instance from right to left. When I draft the formula to the right, I want it to pick up the next non-zero value, right to left.
If I could get this figured out, as well as how to return the column header as well, that would be great.
Screenshot/here refer.
The formula you provided returns the last non-zero value which is also what you state you're trying to find:
"I want...the first instance from right to left."
To avoid ambiguity, I provide solutions for the first such occurrence (and corresponding heading), and a revised method to determine the last occurrence (or first occurrence "from right to left").
First occurrence
(working from left to right)
Function can be simplified significantly to the following:
=INDEX(A2:H2,0,MATCH(1,--(A2:H2<>0),0))
Corresponding heading:
=INDEX($A$1:$H$1,0,MATCH(1,--(A2:H2<>0),0))
Per #ScottCraner, this also works (albeit uses the same unnecessarily long function):
=INDEX($R275:$BE275,SMALL(IF($R275:$BE275<>0,COLUMN($R275:$BE275)- MIN(COLUMN($R275:$BE275))+1),COLUMNS($A:A)))
Last occurrence
Revised function to consider (requires Office 365 compatible version of Excel, and customisation to return corresponding heading)..
=LET(reverse,INDEX(A2:H2,0,SEQUENCE(1,COUNTA(A2:H2),COUNTA(A2:H2),-1)),INDEX(reverse,MATCH(1,--(reverse<>0),0)))
Related
I'm trying to make my monthly transaction spreadsheet less work-intensive but I'm running up against problems outputting my category lookups as an array. Right now I have a table with all my monthly transactions and I want to create another table with monthly running totals. What I've been doing is manually summing each entry from each category, but I'd love to automate the process. Here's what I have:
=SUM(INDEX(Transactions[Out], N(IF(1,MATCH(I12,Transactions[Category],FALSE)))))
I've also tried using AGGREGATE in place of SUM but it still only returns the first value in the category. The N(IF()) was supposed to force INDEX to return all the matches as an array, but it's not working. I found that trick online, with no explanation of why it works, so I really don't know how to fix it. Any ideas?
Just in case anyone ever looks at this thread in the future, I was able to find a simpler solution to my problem once I implemented the Transactions[Category]=I12 method. SUM, itself will take an array as an argument, so all I had to do was form an array of the values I wanted to keep from Transactions[Out] range. I did this by adjusting the method Ron described above, but instead of using 1/(Transactions[Category]=I12 I used 1/IF(Transactions[Category]=I12, 1,1000) and surrounded that by a FLOOR(*resulting array*, .01) which rounded all the thousandth's down to zero and didn't yield any #DIV/0! errors.
Then! I realized that the simplest way to get the actual numbers I wanted, rather than messing with INDEX or AGGREGATE, was to multiply the range Transactions[Out] by the binary array from the IF test. Since the range is a table, I know they will always be the same size. And SUM automatically multiplies element by element and then adds for operations like this.
(The result is a "CSE" formula, which I guess isn't everyone's favorite. I'm still not 100% clear on what it means: just that it outputs data in a single cell, rather than over multiple cells. But in this context, SUM should only output a single number, so I'm not sure why I need CSE... A problem for another day!)
In your IF, the value_if_true clause needs to return an array of the desired row numbers from the array.
MATCH does not return an array of values; it only returns a single value which, with the FALSE parameter, will be the first value. That's why INDEX is only returning the first value.
One way to return an array of values:
Transactions[Category]=I12
will return an array of {TRUE,FALSE,FALSE,TRUE,...} depending on if it matches.
You can then multiply that by the Row number to get the relevant row on the worksheet.
Since you are using a table, to obtain the row number in the data body array, you have to subtract the row number of the Header row.
But now we are going to have an array which includes 0's for the non-matching entries, which is not good for us as a row number argument for the INDEX function.
So we get rid of that by using the AGGREGATE function with the ignore errors argument set after we do change the equality test to 1/(Transactions[Category]=I12) which will create DIV/0 errors for the non-matchers.
Putting it all together
=SUM(INDEX(Transactions[Out],AGGREGATE(15,6,1/(Transactions[Category]=I12)*ROW(Transactions)-ROW(Transactions[#Headers]),ROW(INDIRECT("1:"&COUNTIF(Transactions[Category],$I$12))))))
You may need to enter this with CSE depending on your version of Excel.
Also, if you have a lot of these formulas, you may want to change the k argument for AGGREGATE to use the INDEX function (non-volatile) instead of the volatile INDIRECT function.
=SUM(INDEX(Transactions[Out],AGGREGATE(15,6,1/(Transactions[Category]=I12)*ROW(Transactions)-ROW(Transactions[#Headers]),ROW(INDEX($A:$A,1,1):INDEX($A:$A,COUNTIF(Transactions[Category],$I$12),1)))))
Edit
If you have Excel/O365 with dynamic arrays and the FILTER function, you can greatly simplify the above to the normally entered:
=SUM(FILTER(Transactions[Out],Transactions[Category]=I12))
I had an excel test that I didn't do particularly well on, but this one question had me stumped. I need an equation that takes the name in this list and outputs the agent name in 'first.initial' or "COPY" or "NOT FOUND"
Sheet 1:
Agent
Adam.m
Agent
David.e
Agent
Joe.A
Agent
Ben.B
Agent
Kat.C
Agent
Training.22
Agent
Admin
Convert these names: Correct output:
David Everit David.e
Joe a. Joe.A
Ben Ben.B
Sam p. NOT FOUND
Training 22 Training.22
David E. COPY
Kat Cathy Kat.C
David D. NOT FOUND
Adam.S NOT FOUND
The equation I submitted that my teacher said was wrong was:
=IFNA(IF(COUNTIF(Sheet1!A:A, A3)>1, "COPY", INDEX(Sheet1!A:A,MATCH(A3&"*",Sheet1!A:A,0))),"Not Found")
Well here's the thing.
You are checking the original data source for the name, pre-conversion. I must admit, the COPY was a bit misleading at first but I caught on later.
You are also wrapping the whole thing in a single logical... ISNA()... Your formula can only return TRUE, FALSE or an error from this.
Putting the wrapped ISNA() aside, this means that for your formula the majority of these entries are Not Found. True, if you instead had a list of data that had already been manipulated this would almost succeed. But you are checking for the "COPY" in the wrong data...
Your first task here would be to manipulate the data to the desired format of '[Firstname].[initial]' // So assuming that the first set of characters in the cell is always going to be the forename you can use a combination of something like:
=LEFT(A2,SEARCH(" ",A2)-1) - Gets the forname by returning the left-most characters to a length of the first space position minus 1.
=RIGHT(A2,LEN(A2)-SEARCH(" ",A2)) - Gets all characters to the right of space by determining the legth from the right as the total cell length minus the position of space.
You will need to perform a logical on the second scenario though as you want a single letter is it is a word or the entire thing if it is a number:
=IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))
So what i have done here is attempt to remove 0 from the string, if it is a number, this will succeed and return that number to us. If it fails it will produce an error and progress on to the second clause, giving us the single character.
You can combine these using simple string building or a concatenate clause:
=LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))
or
=CONCATENATE(=LEFT(A2,SEARCH(" ",A2)-1),".",IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))
So now we are almost there, except that Ben and Adam are producing errors as there isn't a space character that can be found. We'll handle that error now so that we can move on to our search:
=IF(ISERROR(SEARCH(" ",A2)),A2,LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))) - if you cannot find a space character then we will have the whole cell, otherwise, we will use the space to build the search term.
Now that we have the text formatted in the way that we want it, we can move forward to do the search, the order is important as we will need to first check our results from above for duplicates and print "COPY" where found, then look for the match and return it if it's there and lastly return "NOT FOUND" if we cannot find it.
We are going to need the use of the wildcard in order to satisfy the entry Ben. So let's show the logic first then throw the whole formula together:
=IF(COUNTIF($B$1:B1,[SearchTermFormula]),"COPY", - This part of the formula uses countif to check whether the search term already exists above it, returns "COPY" if so and will continue to the next part, the absolute referencing ($$) is important so that the range updates as you copy the formula down but keeps the first cell locked.
IF(ISNUMBER(MATCH([SearchTermFormula]&"*",Sheet1!$A$1:$A$14,0)),[SearchTermFormula],"NOT FOUND") - So this works to show the basic logical, again we use IF() to determine whether a match can be made as a number would be returned if so. We can then return the search term itself or "NOT FOUND".
A more elegent version of this part though would be:
IFERROR(INDEX(Sheet1!$A$1:$A$14,MATCH([SearchTermFormula]&"*",Sheet1!$A$1:$A$14,0)),"NOT FOUND"))
As it actually returns the result from sheet1 as well as making us use the [SearchTermFormula] 1 less time, using less resources.
INDEX() essentially maps the range as a 1 based array. What that means is the first cell in the range is considered an address of 1,1. You can think of it adding X and Y axis but 0,0 is outside the top left and the Y axis is inverted.
So we get it to index column A and MATCH returns the relative position, as the row's are equally sized, the relative position will be the row number we are after so we get the result returned or an error value, so IFERROR() leads us on to produce "NOT FOUND".
Putting all that together we have:
=IF(COUNTIF($B$1:B1,IF(ISERROR(SEARCH(" ",A2)),A2,LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1))))>0,"COPY",IFERROR(INDEX(Sheet1!$A$1:$A$14,MATCH(IF(ISERROR(SEARCH(" ",A2)),A2,LEFT(A2,SEARCH(" ",A2)-1)&"."&IFERROR(RIGHT(A2,LEN(A2)-SEARCH(" ",A2))-0,MID(A2,SEARCH(" ",A2)+1,1)))&"*",Sheet1!$A$1:$A$14,0)),"NOT FOUND"))
Sorry for the essay but I hope it helps you understand the scope
What is the best way to find the right column for the travelled miles using visual basic coding or some excel function and return the price from that column? HLOOKUP can't be used here because the lookup value isn't exact and the ranges in the table are also not with specific intervals (If they were, I could use e.g. FLOOR(travelled miles/100)*100 and find the price with HLOOKUP). Obviously, it's easy to find the price manually with a small table but with a big table computer will be faster.
Note that, if x is between a and b, then MEDIAN(x,a,b)=x. Combine this with some nested IFs:
=IF(MEDIAN(B5,B1,C1-1)=B5,B2,IF(MEDIAN(B5,C1,D1-1)=B5,C2,IF(MEDIAN(B5,D1,E1-1)=B5,D2)))
I'm on my phone, so just done the first three cases, but hopefully you can see how it continues.
(should note you need to remove the dashes for this to work)
Edit:
I also want to answer your question in the comments above. You can use the following to keep the dash, but get a number to work with.
Assume cell A1 has got the value 10-. We can use the FIND function to work out where the - occurs and then use the LEFT function to only return the characters from before the dash:
=LEFT(A1,FIND("-",A1)-1)
This will return the value 10, but it will return it as a string, not a number - basically Excel will think it is text. To force Excel to consider it as a number, we can simply multiply the value by one. Our formula above therefore becomes:
=(LEFT(A1,FIND("-",A1)-1))*1
You may also see people use a double minus sign, like this:
=--LEFT(A1,FIND("-",A1)-1)
I don't recommend this because it's a bit complex, but combining with the formula above would give:
=IF(MEDIAN(B5,--LEFT(B1,FIND("-",B1)-1),--LEFT(C1,FIND("-",C1)-1)-1)=B5,B2,IF(MEDIAN(B5,--LEFT(C1,FIND("-",C1)-1,--LEFT(D1,FIND("-",D1)-1-1)=B5,C2,IF(MEDIAN(B5,--LEFT(D1,FIND("-",D1)-1,--LEFT(E1,FIND("-",E1)-1-1)=B5,D2)))
I wrote an IF formula as follows...
=IF(AB2>=500000,"Platinum",IF(AB2>100000,"Gold",IF(AB2>0,"Silver","")))
This works perfectly fine, however I've been given a new caveat and I haven't been able to figure it out.
If Column labeled Sponsor (see below image) has a value, then it should become a "Platinum" tier.
So pretty much, I'm seeing if it's possible add this additional condition to my existing formula. Any help would be greatly appreciated!
You can just add an OR() to the IF statement that you already have.
=IF(OR(AB2>=500000,AA2<>""),"Platinum",IF(AB2>100000,"Gold",IF(AB2>0,"Silver","")))
=If(LEN(AA2)<> 0,"Platinum",if(AB2>50000,"Platinum .... etc.
However, your logic is going to get a bit twisted with the many nested IFs. You might instead consider using a CHOOSE > MATCH structure, thus:
=IF(LEN(AA2)<> 0,"Platinum",CHOOSE(MATCH(AB2,{0,100000,500000},1),"Silver","Gold","Platinum"))
This formula first checks to see if there's a sponsor, and if there is sets it to "Platinum"; if there isn't it proceeds to the CHOOSE(MATCH.
The MATCH looks for the largest number in the array (i.e., {0, 100000, 500000}) that is less than or equal to the value in AB2, and returns an index number for where it finds the match. The CHOOSE then selects that entry from the list and returns it.
I have a column A3:A71 I wish to populate with values
=COUNTIF(B3:B71,B3)
Where the second argument is incremented with every cell.
Obviously I don't want to copy this function every time, so I was hoping that fill handle would help me. However although it correctly increments the second argument of COUNTIF, it also increments the first one. Even if I correctly populate the first two or three cells in the column A3:A71 with the values
=COUNTIF(B3:B71,B3)
=COUNTIF(B3:B71,B4)
=COUNTIF(B3:B71,B5)
when I drag down from the bottom right corner, I get the function:
=COUNTIF(B6:B74,B6)
=COUNTIF(B6:B74,B7)
=COUNTIF(B6:B74,B8)
=COUNTIF(B9:B77,B9)
=COUNTIF(B9:B77,B10)
=COUNTIF(B9:B77,B11)
Can anybody please tell me how can I force the first argument to stay the same while the second one is increased correctly?
I am using MS Office 2011 for MacOS, but a Windows solution would be just as helpful.
Please try:
=COUNTIF(B$3:B$71,B3)
There are further details at OwenBloggers.com including a table:
and mention that other terms are “absolute cell reference” and “locking”.