I've tried solving this problem on my own. However, I have yet to find an example or reference that fits to my particular situation.
I have the following Dataset:
However, since I cannot post more than two links, I cannot show the other sheets -- but they are equally similar.
They are single line items. (Also note, that my numbers are constantly changing in this case because I am using "=RANDBETWEEN(0,1000)". Do not focus on the numbers.
My Problem arises when I try to do my store analysis on my final page.
This is my problem:
STORE 1, JAN 16 : Electronics Cell "E4" is "Electronics!E5"
STORE 2, JAN 16 : Electronics Cell "E10" is "Electronics!E11"
When it should be "Electronics!E6"
This is just an example, my actual data has thousands of lines of data, otherwise I would just brute force this.
Any idea on what to do?
Thanks,
Calrabian
I would suggest to do a reference search with a VLOOKUP or MATCH function, instead of counting on locations alone.
For example, assuming your data is in Electronics!$C$1:$F$10, you can use an array formula in E4 and copy it to E11:
=INDEX(Electronics!$C$2:$F$10,MATCH($C4,Electronics!$A$2:$A$10,0),MATCH(E$3,Electronics!$C$1:$F$1,0))
*Use Ctrl + Shift + Enter to enter the formula as an array formula, and then copy to E11.
Explanation:
The main formula structure is INDEX(<data area>, <match Store row>, <match Date column>).
The INDEX function returns data in an array/reference according to a provided row and column indexes.
The MATCH functions find the index, horizontally or vertically.
The first MATCH($C4,Electronics!$A$2:$A$10,0) finds the Store row in the stores column A. C4 is the store name to find. You can play with this reference to suit your needs.
The second MATCH(E$3,Electronics!$C$1:$F$1,0) finds the Date column in the dates row 1.
You can make it more flexible and complex, but this is the general idea.
First off I must say your dates really bug me. Using yy-mmm for some and mmm-yy for others just throws me for a loop.
For an actual answer. Since you are not moving 1 cell at a time you will need to do some math to have a consistent formula all the way down.
First thing you need is to get a formula that returns the right row.
row 4 returns row 5
row 10 returns row 6
row 16 returns row 7 (assumption)
Use the function
=int((row()-4)/6)+4
Then insert it into an index function and you have your solution
=index(Electronics!E:E,int((row()-4)/6)+4)
Related
I need help in writing a formula in cell b7. The formula must look to the right and multiply the nonempty cells by the corresponding value in row 3, and I would like to sum up the results.
File link provided.
FILE LINK
ScreenShot
Please see my comment to your original post.
That said, I will try to explain how to approach this as I think you intend. (This solution will be a Google Sheets solution which will not work in Excel.)
The first thing you will need to do is to delete everything from Row 11 down: all of your examples and notes must be deleted for the following proposed formula to work correctly.
Once you have no superfluous data below your main chart, delete everything from B6:B (including the header "Total").
Then, place the following formula in cell B6:
={"TOTAL"; FILTER(MMULT(C7:G*1, TRANSPOSE(C$3:G$3*1)), A7:A<>"")}
This formula will return the header text "TOTAL" (which you can change within the formula itself if you like) followed by the calculation you want for each row where a name is listed in A7:A.
MMULT is a difficult function to explain, but it multiplies one matrix ("grid") or numbers by another matrix ("grid") and returns the sum of all products per row (or per column, depending on how you set it up) —— which is what you are trying to do.
MMULT must have every element of both matrices be a real number. To convert potential nulls to zeroes, you'll see *1 appended to each range (since null times 1 is zero).
This assumes that all data entered into C7:G and C3:G3 will always be either a number or null. If you enter text, you'll throw the formula into an error. If you think accidental text entries in those ranges are possible, use this version instead:
={"TOTAL"; FILTER(MMULT(IFERROR(C7:G*1, ROW(C7:G)*0), TRANSPOSE(IFERROR(C$3:G$3*1, COLUMN(C$3:G$3)*0))), A7:A<>"")}
The extra bits use IFERROR to exchange error-producing entries with zeroes, since MMULT must have every space in both matrices filled with a real number.
Currently I am using the following formula in successive rows on a sheet named Data
{=IFERROR(SMALL(IF($Q$2=DMS!$I$1:$I$99999,ROW(DMS!$I$1:$I$99999)-ROW(DMS!$I$1)+1),1),"")}
{=IFERROR(SMALL(IF($Q$2=DMS!$I$1:$I$99999,ROW(DMS!$I$1:$I$99999)-ROW(DMS!$I$1)+1),2),"")}
{=IFERROR(SMALL(IF($Q$2=DMS!$I$1:$I$99999,ROW(DMS!$I$1:$I$99999)-ROW(DMS!$I$1)+1),3),"")}
...
For a total of 30 rows to determine the first 30 rows within Sheet DMS column I that match the value in my sheet 'Data' cell Q2.
I am trying to find a way to either recreate the above arrays, or an alternate solution to using the arrays, when the searched range is no longer going to be a fixed location. Essentially what was in column I could be in column J tomorrow and H the next day and back to I for the next 3 days. I will be able to tell where it is by the column header, so I do have one static point of reference, even if it is not in a fixed column.
Try this formula. It looks for a column with the text "TheKey" in the first row of columns A to Z and will then perform the match on the values in the found column.
In Excel 365, you can just hit enter, in earlier versions, you need to use Ctrl+Shift+Enter
=IFERROR(SMALL(IF($Q$2=INDEX(dms!$A$1:$Z$9999,1,MATCH("TheKey",dms!$A$1:$Z$1,0)):INDEX(dms!$A$1:$Z$9999,9999,MATCH("TheKey",dms!$A$1:$Z$1,0)),ROW($A$1:$A$9999)),ROW(A1)),"")
In Excel 365, you can avoid the duplication of the Match function by applying the new Let() function and re-using the result. Like this:
=LET(myColumn,MATCH("TheKey",dms!$A$1:$Z$1,0),IFERROR(SMALL(IF($Q$2=INDEX(dms!$A$1:$Z$9999,1,myColumn):INDEX(dms!$A$1:$Z$9999,9999,myColumn),ROW($A$1:$A$9999)),ROW(A1)),""))
I removed the -ROW(DMS!$I$1)+1 because that does not do anything, really. Just subtracts 1 and then adds 1 again.
I also replaced the hard-coded number for subsequent rows (1, 2, 3, etc) with Row(A1), which will evaluate to 1 in the first row of the formula and when copied down will turn into 2, 3, 4, etc without having to adjust the formula for each row.
You need to combine several advanced functions. First of all, you need to locate that header, because it's your only static point.
You can locate your static header using:
=CELL("address";INDEX(DMS!$A$1:$M$1;;MATCH("STATIC HEADER";DMS!$A$1:$M$1;0)))
In this case, it will return this text: [Libro1]DMS!$I$1
It's the complete path to cell.
Now you need to combine that string, with OFFSET to get a reference to that column and get like 99999 rows of data. ISsue here is OFFSET does not work on different worksheets from active one, so you need to combine it with INDIRECT first to get a reference to range in sheet DMS:
INDIRECT function
OFFSET function
So then a formula like next one will return a reference of 1 column and 99999 cells where your static header is:
OFFSET(INDIRECT(CELL("address";INDEX(DMS!$A$1:$M$1;;MATCH("STATIC HEADER";DMS!$A$1:$M$1;0))));0;0;99999;1)
So now you can combine all of these into a really huge formula:
=IFERROR(SMALL(IF($Q$2=OFFSET(INDIRECT(CELL("address";INDEX(DMS!$A$1:$M$1;;MATCH("STATIC HEADER";DMS!$A$1:$M$1;0))));0;0;99999;1);ROW(OFFSET(INDIRECT(CELL("address";INDEX(DMS!$A$1:$M$1;;MATCH("STATIC HEADER";DMS!$A$1:$M$1;0))));0;0;99999;1)));ROW()-5);"")
Notice I've deleted the ROW(DMS!$I$1)+1 because that's always equal to 0, so not needed. I addedd in SMALL function the part ROW()-5) so I can drag down (i'm testing in row 6 and dragging down. No need of those 1, 2, 3 you input manually). Adapt this part to your needs.
Notice that if STATIC HEADER is in a different column, the formula still works.
I've uploaded a file do my Gdrive in case you want to see how it works, because copying so many functions can be crazy.
https://drive.google.com/file/d/16Y6mQ_hiu1TKLXhTUgvq8tN67eHQKtVb/view?usp=sharing
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.
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.
I have a list of numbers in a table that I would like to search for and bring back the cell reference of where that number resides. For example the data looks like:
A B C D
1 1 2 3 4
ok it doesn't come out very well as the first one is the row number and then each number below sits under each letter, so C1 would contain '3'....
If I wanted to return the reference number of C1 in a cell I am using the formula of =CELL("address",MATCH(AU14,C1:AG1)) but this just errors. I have tried to put an Index in there too, but I believe that index only works vertically so this bring back a #N/A result.
Can anyone assist as I've wasted too much time on this already! :)
You are indeed missing an INDEX. And INDEX works vertically, horizontally, or both depending on how it's called.
Here is a formula that works for the ranges in the pictures. Should be easy to modify.
Formula in C5
=CELL("address",INDEX(B2:F2,MATCH(C4,B2:F2,0)))
formula
results
To make CELL work you need a cell reference, e.g.
CELL("address",C1)
The trouble is that MATCH just gives you a number, not a cell reference.
Probably the easiest way is to use the ADDRESS function, so a first try might be
=ADDRESS(1,MATCH(AU14,C1:AG1,0)+2)
That would give you the right answer if AU14 contained 3, but isn't considered to be very good because it wouldn't update if you deleted/inserted rows or columns.
A better one would be
=ADDRESS(ROW(C1),MATCH(AU14,C1:AG1,0)+COLUMN(C1)-1)
Then you might want to put in some error handling for the case where it's not found
=IFERROR(ADDRESS(ROW(C1),MATCH(AU14,C1:AG1,0)+COLUMN(C1)-1),"Not found")