I have a spreadsheet that shows the actual dollars produced and the expected dollars produced for each employee, where each row is one day and each employee has two columns. I would like to count the number of times an employee came within 10% of their production goal without referencing specific columns. Please look at the example spreadsheet.
I want for the formulas in cells Sheet2!E4:E7 to do what the formulas in Sheet2!E10:E13 do.
I am trying to avoid using direct column references because it causes me to have to go in and update the columns in the formulas every time a new employee is added to the sheet.
I'm no stranger to using INDEX+MATCH, or to converting SUMPRODUCT formulas to INDEX+MATCH. What I can't get past are the formulas in cells Sheet2!E4:E7. If you evaluate the formula you can watch the INDEX+MATCH section on the left side of the formula work correctly, and then a nearly identical INDEX+MATCH section on the right side evaluate to 0 for no apparent reason.
The formula I'm having trouble with is in cell Sheet2!E4:
COUNTIF(INDEX(Sheet1!$A$2:$AZ$314,,MATCH($B4,Sheet1!$A$1:$AZ$1,0)),">"&(INDEX(Sheet1!$A$2:$AZ$314,,MATCH($B4,Sheet1!$A$1:$AZ$1,0)+1)))
The section to the left of the ">" will match with the correct range (Sheet1!B2:B314), however the section to the right of the ">" will evaluate to 0 instead of Sheet1!C2:C314.
This is strange to me because the only real difference between the two sections is the '+1' on the end of the MATCH function, and adding the '+1' to the section to the left of the ">" produces the expected result for the MATCH function (Sheet1!C2:C314) as seen by evaluating the formula in cell Sheet2!E5.
The formula that produces the correct result is in cell Sheet2!E10:
SUMPRODUCT(--(ISNUMBER(Sheet1!$B$2:$B$313)),--(Sheet1!$B$2:$B$313<Sheet1!$C$2:$C$313),--(Sheet1!$B$2:$B$313>=Sheet1!$C$2:$C$313*0.9))
I understand that if I exclude the '$' before the column references, any future additions/subtractions to the columns on Sheet1 will adjust the references accordingly. This solution is not ideal, because there are multiple data sheets (one for each year) where the columns are all different (Dan is column F for 2019, G for 2018, M for 2017, etc.), and the tables using these sheets are laid out in a way that would prevent me from easily being able to auto-update the formulas, so a solution that locates the correct column using the employee's name is preferred.
The correct result should be 2 for Allen and 3 for Torres, but I can only seem to get the INDEX+MATCH formulas to return 0, 12, 15, 16, or 17 (depending on what tweaks I make to the formula).
Any help with this would be greatly appreciated.
You can try this: ARRAY FORMULA CTRL + SHIFT + ENTER
=SUM(IF(ISNUMBER(INDEX($A$1:$E$30,2,MATCH(G9,$A$1:$E$1,0)):INDEX($A$1:$E$30,30,MATCH(G9,$A$1:$E$1,0))),INDEX($A$1:$E$30,2,MATCH(G9,$A$1:$E$1,0)):INDEX($A$1:$E$30,30,MATCH(G9,$A$1:$E$1,0))<INDEX($A$1:$E$30,2,MATCH(G9,$A$1:$E$1,0)+1):INDEX($A$1:$E$30,30,MATCH(G9,$A$1:$E$1,0)+1)*(INDEX($A$1:$E$30,2,MATCH(G9,$A$1:$E$1,0)):INDEX($A$1:$E$30,30,MATCH(G9,$A$1:$E$1,0))>=INDEX($A$1:$E$30,2,MATCH(G9,$A$1:$E$1,0)+1):INDEX($A$1:$E$30,30,MATCH(G9,$A$1:$E$1,0)+1)*0.9))*1)
and adapt the ranges to your needs. It is entered on the same sheet as the data.
Basically this approach uses ARRAY FORMULA CTRL + SHIFT + ENTER
INDEX($A$1:$E$30,2,MATCH(G9,$A$1:$E$1,0)):INDEX($A$1:$E$30,30,MATCH(G9,$A$1:$E$1,0)))
to get the needed ranges. MATCH looks for the right column. the row number can be set as needed, here its is from 2 to30 adapted to your provided data. My search term in this case is in G9 with Allen as content. The result of the formula is $B$2:$B$30. A +1 after Match gives the other range $C$2:$C$30. Both ranges can then be evaluated with the needed conditions
Pull it down and provide Torres in G10. Then the ranges will be adapted to $D$2:$D$30 and $E$2:$E$30.
Related
So, trying to explain what I need here is my two sheets on the same workbook, Sheet Example:
I need to make a formula for each cell that checks Sheet A "Num_Doc_Ini" and "Num_Doc_Fin" against Sheet B "CHV_CTE_REF", calculates the total after adding up the "VL_DOC" numbers on Sheet B, and finally Checks with "correct" or "Incorrect" after comparing the result to the Sheet A "VL_DOC".
So for example, the second line of Sheet A. I need to make so that check see's the NUM_DOC_INI and FIN so "101 - 102" checks those numbers on Sheet B "CHV_CTE_REF", adds up the "VL_DOC" so in this example 4,159.86 + 4,585.1 that equals = 8,744.96, and then matches it with the "VL_DOC" on Sheet A displaying in this case the text "Correct" and If it does not match displays "Incorrect".
Some lines have few docs to reach like "106 - 108" but there are some that have 10 or more to read and sum up the values, because of that I'm really breaking my mind trying to come up with something.
Is that even possible? I can think of a few ways to use VBA for this but I'm trying to do this all with Cells Formula and because of that I am kinda lost, any help would be appreciated thanks!
Edit:
I'm using excel 2016 atm.
So here is a file for the workbook: https://mega.nz/file/LgVCBbjT#xJnf2HbHd6wdRSNPY7wXSssKv2jZ1-pMsOuKcePlulQ
And the explanation with colors:
I need on the Red Cell a formula to check the numbers of the Blue ones on sheet 1, find them on Sheet 2 (blue cells), add up the VL_DOC (Green ones) on sheet 2, and check them up against the values on Sheet 1 Orange cells (VL_DOC), then print out Correct or incorrect based on the match of the values.
From what I can see in the link, you can use something like the below if you have the newest version of excel (where row ranges and column references are left to your specific case because we can't see them):
=IF(SUM(FILTER(SheetB!$VL_DOC,
(SheetB!$CHV_CTE_REF=SheetA!J2)+(SheetB!$CHV_CTE_REF=SheetA!I2)+...))=N2,
"Correct", "Incorrect")
Then add however many other conditions within the FILTER function you need. For example:
REQUESTED EDIT: If you don't have the newest version of excel, you can just repeatedly use VLOOKUP or INDEX/MATCH however many times is necessary. For example:
=IF(SUM(
VLOOKUP($I2, SheetB!$CHV_CTE_REF, 2,),
VLOOKUP($J2, SheetB!$CHV_CTE_REF, 2,),
...)=$N2,
"Correct", "Incorrect")
SUM, INDIRECT, ADDRESS, MATCH
Note that INDIRECT is a volatile function.
In cell K2 of Sheet 1 of the example workbook, you can use the following formula:
=IFERROR(IF(SUM(INDIRECT(ADDRESS(MATCH(H2,Tabela1[NUM_DOC],0)+1,COLUMN(Tabela1[VL_DOC]),1,1,"Sheet 2")&":"&ADDRESS(MATCH(I2,Tabela1[NUM_DOC],0)+1,COLUMN(Tabela1[VL_DOC]),1,1),TRUE))=J2,"Correct","Incorrect"),"")
I am trying to write a formula that checks the status and name to be ongoing and joe blogs (in this example), and once finding a match, will identify the oldest date of a ticket raised.
My formula currently includes:
=MIN(IF('Sheet2'!AA:AA="ONGOING",IF('Sheet2'!Q:Q="Joe Bloggs",'Sheet2'!B18:B49)))
I also tried:
=IF((AND(sheet2!$AA:$AA="ongoing", 'Sheet2'!$Q:$Q="Joe Bloggs")), MIN('Sheet2'!B18:B49),"No")
In Column B contains dates. Q contains names, AA contains the status.
At the moment when this runs I get the result '00/01/1990'.
I have done some checks to find the error, and appears to be around the targets name, as when the second formula is tried, the output is "no". The name is definitely in the Q column, and I have completed other formulas including countifs which have worked perfectly fine.
I have done a lot of searching to find nested ifs and min statements to have no joy , would be grateful of any advice / tips. It may be a simple error to some.
Try entering this as an array formula:
=MIN(IF(sheet2!AA:AA="ongoing",IF(sheet2!q:q="Joe Bloggs",sheet2!B:B)))
FYI I found the solution here.
You will have to apply a date format to the result.
Your first formula works well on my data (as below). If I close the formula with ENTER only, I get the result '37128' and if I close the formula with CTRL+SHIFT+ENTER I get the expected result, '25/08/2001'.
Edit: As #FocusWiz said in the comments, the only major difference (other than different column names) between my formula and yours is the the last range in your formula (B18:B49) is a different sized range to the other two, which are referring to full columns.
*This could be solved either by using the same row range for all three column references (AA18:AA49, Q18:Q49, B18:B49) or referencing the full column range for all three ranges (AA:AA,Q:Q,B:B).
This is your formula I'm talking about:
=MIN(IF('Sheet2'!AA:AA="ONGOING",IF('Sheet2'!Q:Q="Joe Bloggs",'Sheet2'!B18:B49)))
And this is the formula in my workbook F7:
=MIN(IF(B:B="ONGOING",IF(A:A="Joe Bloggs",C:C)))
As you can see in the formula editor, squiggly brackets '{}' show around the formula when it has been closed as an array formula.
If that doesn't work for you, please post some sample data with datatypes so we can help figure out what is causing the lookup value to miss the data.
While I like the technique offered by Patrick (I have frequently forgotten an "else" portion of a formula and gotten "false" as a value in a cell but never thought of a use for that...thank you!), I think this question highlights an issue we all can have with array formulas. As girlvsdata indicates, your original formula:
=MIN(IF(Sheet2!AA:AA="ONGOING",IF(Sheet2!Q:Q="Joe Bloggs",Sheet2!B:B)))
(modified above to be more generic for column B) will also work when entered as an array formula.
What likely happened is that somehow the formula got edited and was not re-entered as an array formula.
While I do not dislike array formulas, I do try to avoid them because I have fat fingers and will frequently mess them up by accidentally hitting the wrong key as I am modifying other cells.
Here is an alternative without using an array formula:
=INDEX(LARGE((Sheet2!Q:Q&Sheet2!AA:AA="Joe bloggs"&"ongoing")*(Sheet2!B:B),COUNTIFS(Sheet2!Q:Q,"Joe Bloggs",Sheet2!AA:AA,"ongoing")),1)
What it does is basically create a candidate date value for every row that has "joe bloggs" and "ongoing" which is equal to the date in column B for all such rows. All other rows get a zero candidate date value. The LARGE function takes the smallest nonzero date by counting the n valid candidates with the COUNTIFS function and taking the nth largest such candidate.
I have a Simple spreadsheet with 2 rows:
ActualJAN | BudgetJAN | ActualFEB | BudgetFEB | ActualMAR | BudgetMAR ....
100 200 300 400 500 600 ....
I'd like to sum ONLY the Budget columns up to the current month (Month(Today()).
Same for the Actual columns.
So if we're currently in February,
Budget to date would be: 600=200+400
Actual to date would be: 400=100+300
I just can't seem to get there, at least simply and elegantly.
This is a non array formula that performs array like operations. As such large range references should be avoided or you will experience a slow down or potential crash of your system. For a small defined range works great so long as the formula is not repeated too many times either.
Additionally TODAY() is a volitile function which means the formula will recalculate whenever anything in the spreadsheet changes, not just when something related to the formula changes.
This formula is generalized a bit so your data can be located anywhere on your sheet and does not require rearrangement of your data.
To get your actual sum use the following:
=SUMPRODUCT($C$4:$H$4*(COLUMN($C$4:$H$4)-COLUMN($C$4)+1<=MONTH(TODAY())*2)*(LEFT($C$3:$H$3)="A"))
To get your Budget sum use the following:
=SUMPRODUCT($C$4:$H$4*(COLUMN($C$4:$H$4)-COLUMN($C$4)+1<=MONTH(TODAY())*2)*(LEFT($C$3:$H$3)="B"))
Change C4:H4 to suit your number range. ChangeC3:H3 to suit your column title range. Change C4 to be the first cell of your number range.
Caveat: Assumes maximum 12 months starting at January
Proof of concept:
I would recommend structuring your data differently. It would be an easier task if you arrayed everything vertically and divided your data into three columns. The first would be Category, which would be populated with either "Budget" or "Actual." The next column would be Month. After that, of course, you have the Value column. Then, use a basic SUMIF, like "=SUMIF(A1:A6,"Budget",C1:C6)." A1:A6 is the range Excel will scan for the desired variable. In this case, that variable is "Budget." Then, C1:C6 is the value that corresponds to a "Budget" month. That formula will give you the answer you want as long as you expand the SUMIF formula to include the full range of values, e.g., "SUMIF(A1:A317,"Budget",C1:C317)."
So I think I understand what you're trying to do, I cannot make the entire formula without the rest of the spreadsheet but this is working currently:
For the Actual:
=IF(MONTH(TODAY())=1,A2,IF(MONTH(TODAY())=2,A2+C2,IF(MONTH(TODAY())=3,A2+C2+E2,"")))
For the Budget:
=IF(MONTH(TODAY())=1,B2,IF(MONTH(TODAY())=2,B2+D2,IF(MONTH(TODAY())=3,B2+D2+F2,"")))
Here is the spreadsheet I created to test:
If you give me the rest of the data I can complete the formula, basically all you would need to do is add more months to the formula and change the amounts it adds.
I am sure there is probably a more efficient way to accomplish this but this way works.
I suggest a hidden row to control your dates. Say, January is in column C, enter [C1] =1, [D1] =C1, [E1] =C1+1, [F1] =E1. Select E1:F1 and copy to the right until December. Hide row 1.
In row 2 use these two formulas.
[C2] ="Actual" & UPPER(TEXT("1/" & C$1,"mmm"))
[D2] ="Budget" & UPPER(TEXT("1/" & D$1,"mmm"))
Select C2:D2 and copy to the right until December. This exercise isn't required because the resulting display is exactly what you already have. But producing this result with the help of formulas ensures freedom from error, and it is faster. As an added bonus you get a visual check of what's in the hidden row.
Now you can use this formula to extract totals from row 3 where you have your values.
=SUMIFS($C3:$Z3,$C$2:$Z$2,"Budget*",$C$1:$Z$1,"<="&MONTH(TODAY()))
Change "Budget" to "Actual" and the same formula will extract the actual amounts.
I have an odd problem with some formulas in my Excel sheet for fantasy football:
In one table, I have a list of the picks and players drafted in one year. The columns are as follows: CO = Player name, CP = Year, CQ = Round, CR = Pick, CS = Owner.
Column CO is hand-entered with names, CP is hand-entered with the year 2011, and CQ is hand-entered with the draft round (the first ten are round 1, the second ten are round 2, etc).
Column CR is a formula that calculates the pick number based on the round number and the row it's in. The formula in cell CR2 looks like this: "=CQ2+MOD(ROW(CR2)-2,10)/100+0.01" and evaluates to "1.01". CR3's formula would evaluate to "1.02", CR4 would evaluate to "1.03", etc.
EDIT: Here's a picture of the top 15 rows of this sheet: picks sheet here
On another sheet, I have a 5x10 grid of VLOOKUP formulas where I try to list which owner has which picks. The VLOOKUP formula for each of the cells in this grid is as follows: "=VLOOKUP(1.01,Picks2011[[Pick]:[Owner]],2,FALSE)", where "1.01" is the name of the pick from column CR, "Picks2011" is the name of the table in the previous sheet, and "[[Pick]:[Owner]]" are the columns in the table "Picks2011". This example formula correctly outputs the name of the owner who had pick 1.01 in 2011.
EDIT: Here's a picture of the grid with the failing cells: grid showing the errors
The problem is that certain cells in this sheet are giving me an "#N/A" for no particular reason. For example, pick 2.01 outputs correctly, but pick 2.02 outputs #N/A, and pick 2.03 outputs correctly again. There doesn't seem to be any kind of a pattern to the errors. I've tried deleting both tables and recreating them from scratch, and I can't seem to figure out what's wrong with them.
Travis... I noticed that the VLOOKUP formula is pointing to a grid formatted as a table, which I love since it makes it easier than having to deal with specifying and anchoring ranges.. however, the fact that the N/A issue you are running into appears to happen every other row, makes me wonder if the formatting on those culprit rows is different than the formatting on those rows returning the values you'd expect. Maybe check that, and as a way of troubleshooting try copying data from the working rows into the failing rows to see what value your vlookup returns.. worth the shot.
Take a look at using an INDEX(MATCH) construct instead of VLOOKUP.
Unfortunately VLOOKUP behaves pretty unpredictably if you're not working with just two columns of unique strings.
I wrote an answer here ( Excel - How do programmatically convert 'number stored as Text' to Number? ) which may be just what you're looking for!
INDEX ( <return array> , MATCH ( <lookup value> , <lookup array> , 0) )
EDIT: I have revived the source data source to remove the ambiguity of my last screen shots
I am trying to transpose spreadsheet data where there are many rows where the customer name may be duplicated but each row contains a different product.
For instance
revised original data source
to
revised proposed data format
I would like to do it with formulae if possible as I struggle with VB
Thank you for any help
I realise this is a huge answer, apologies but I wanted to be clear. If you need anything from me, drop me a comment and I'll help out.
Here's the output from my formula:
EDITED ANSWER - Named ranges used for ease of understanding:
These are just an example of a few of the named ranges I have used, you can reference the ranges directly or name them yourself (simplest way is to highlight the data then put the name in the drop down next to the formula bar [top left])
Be wary that as we will be using Array formulas for AccNum and AccType, you will not want to select the entire column and instead opt for either the exact data length or overshoot it by 100 or so. Large array formulas tend to slow down calculation and will calculate every cell individually regardless of it being empty.
First formula
=IF(COUNTIF(D2:D11,">""")>0,CONCATENATE("Account Number ",LEFT((COLUMN(A:A)+1)/2,1)),"")
This formula is identical to the one in the original answer apart form the adjusted heading title.
=IF(Condition,True,False) - There are so many uses for the IF logic, it is the best formula in Excel in my opinion. I have used to IF with COUNTIF to check whether there is more than 0 cells that are more than BLANK (or ""). This is just a trick around using ISBLANK() or other blank identifiers that get confused when formula is present.
If the result is TRUE, I use CONCATENATE(Text1,Text2,etc.) to build a text string for the column header. ROW(1:1) or COLUMN(A:A) is commonly used to initiate an automatically increasing integer for formulas to use based on whether the count increase is required horizontally or vertically. I add 1 to this increasing integer and divide it by 2 so that the increase for each column is 0.5 (1 > 1.5 > 2 > 2.5) I then use LEFT formula to just take the first digit to the left of this decimal answer so the number increases only once every 2 columns.
If the result is FALSE then leave the cell blank ,""). Standard stuff here, no explanation needed.
Second Formula
=CONCATENATE(INDEX(Forename,MATCH(Sheet4!$A2,Reference,0)))
=CONCATENATE(INDEX(Surname,MATCH(Sheet4!$A2,Reference,0)))
CONCATENATE has only been used here to force blank cells to remain blank when pulled by INDEX. INDEX will read blank cells as values and therefore 0's whereas CONCATENATE will read them as text and therefore "".
INDEX(Range,Row,Column): This is a lookup formula that is much more advanced than VLOOKUP or HLOOKUP and not limited in the way that they are.
The range i have used is the expected output range - Forename or Surname
The row is then calculated using MATCH(Criteria,Range,Match Type). Match will look through a range and return the position as an integer where a match occurs. For this I have set the criteria to the unique reference number in column A for that row, the range to the named range Reference and the match type as 0 (1 Less than, 0 Exact Match, -1 Greater than).
I did not define a column number for INDEX as it defaults to the first column and I am only giving it one column of data to output from anyway.
Third Formula
Remember these need to be entered as an array (when in the formula bar hit Ctrl+Shift+Enter)
=IFERROR(INDEX(AccNum,SMALL(IF(Reference=Sheet4!$A2,ROW(Reference)-ROW(INDEX(Reference,1,1))+1),ROUNDDOWN((COLUMN(A:A)+1)/2,0))),"")
=IFERROR(INDEX(AccType,SMALL(IF(Reference=Sheet4!$A2,ROW(Reference)-ROW(INDEX(Reference,1,1))+1),ROUNDDOWN((COLUMN(B:B)+1)/2,0))),"")
As you can see, one of these is used for AccNum and the other for AccType.
IFERROR(Value): The reason that this has been used is that we are not expecting the formula to always return something. When the formula cannot return something or SMALL has run out of matches to go through then an error will occur (usually #VALUE or #NUM!) so i use ,"") to force a blank result instead (again standard stuff).
I have already explained the INDEX formula above so let's just dive in to how I have worked out the rows that match what we are looking for:
SMALL(IF(Reference=Sheet4!$A2,ROW(Reference)-ROW(INDEX(Reference,1,1))+1),ROUNDDOWN((COLUMN(B:B)+1)/2,0))
The IF statement here is fairly self explanatory but as we have used it as an array formula, it will perform =Sheet4!$A2 which is the unique reference on every cell in the named range Reference individually. In your mock data this returns a result of: {FALSE;TRUE;FALSE;FALSE;FALSE;FALSE;FALSE;FALSE;FALSE;FALSE} for the first entry (I included titles in the range, hence the initial FALSE). IF will do my row calculation* for every true but leave the FALSEs as they are.
This leaves a result of {FALSE;2;FALSE;FALSE;FALSE;FALSE;FALSE;FALSE;FALSE;FALSE} that SMALL(array,k) will use. SMALL will only work on numeric values and will display the 'k'th result. Again the column trick has been used but to cover more ground, I used another method: ROUNDDOWN(Number,digits) as opposed to using LEFT() Digits here means decimal places so I used 0 to round down to a whole integer for the same result. As this copies across the columns like so: 1, 1, 2, 2, 3, 3, SMALL will alternatively (as the formulas alternate) grab the 1st smallest AccNum then the 1st Smallest AccType before grabbing the 2nd AccNum and Acctype and so forth.
*(Row number of the match minus the first row number of the range then plus 1, again fairly common as a foolproof way to always get the correct row regardless of where the data starts; actually as your data starts on row 1 we could just do ROW(Reference) but I left it as is incase you had data in a different format)
ORIGINAL ANSWER - Same logic as above
Here's your solution in 3 parts
Part 1 being a trick for the auto completion of the titles so that they will hide when not used (in case you will just copay and paste values the whole lot to speed up use again).
=IF(COUNTIF(C2:C11,">""")>0,CONCATENATE("Product ",LEFT((COLUMN(A:A)+1)/2,1)),"") in C
=IF(COUNTIF(D2:D11,">""")>0,CONCATENATE("Prod code ",LEFT((COLUMN(B:B)+1)/2,1)),"") in D
Highlight both of the cells and drag across to stagger the outputs "Product " and "Prod code "
Part 2 would be inputting the unique IDs to the new sheet, I would suggest copying your entire column A across to a new sheet and using DATA > REMOVE DUPLICATES > Continue with current selection to trim out the multiple occurrences of unique IDs.
In column B use =INDEX(Sheet2!$B$1:$B$7,MATCH(Sheet4!$A2,Sheet2!$A$1:$A$7,0)) to get the names pulled across.
Part 3, the INDEX
Once again, we are doing a staggered input here before copying the formula across the page to cover the entirety of the data.
=IFERROR(INDEX(Sheet2!$C$1:$D$11,SMALL(IF(Sheet2!$A$1:$A$11=Sheet4!$A2,ROW(Sheet2!$A$1:$A$11)-ROW(INDEX(Sheet2!$A$1:$A$11,1,1))+1),ROUNDDOWN((COLUMN(A:A)+1)/2,0)),1),"") in C
=IFERROR(INDEX(Sheet2!$C$1:$D$11,SMALL(IF(Sheet2!$A$1:$A$11=Sheet4!$A2,ROW(Sheet2!$A$1:$A$11)-ROW(INDEX(Sheet2!$A$1:$A$11,1,1))+1),ROUNDDOWN((COLUMN(B:B)+1)/2,0)),2),"") in D
The formulas of Part 3 will need to be entered as an array (when in the formula bar hit Ctrl+Shift+Enter) . This will need to be done before copying the formulas across.
These formulas can now be dragged / copied in all directions and will feed off of the unique ID in column A.
My Answer is already rather long so I haven't gone on to break the formula down. If you have any trouble understanding how this works, let me know and I will be happy to write up a quick guide, breaking it down chunk by chunk for you.