I have a 12x18 Excel range which draws data from a 823x20 sheet (Results!$A:$T) according to the 12x18 range's page, row and column headers (criterion1, criterion2 and criterion3, respectively)
={INDEX(Results!$A:$T,
MATCH(1, (criterion1 = Results!$A:$A) * (criterion2 = Results!$B:$B), 0),
MATCH(criterion3, Results!$A$1:$T$1, 0))}
As you can see, it's not that much data, but still, when I change the page header, my computer (2 GHz Intel Xeon with 24 GB of RAM) takes about a minute to update the 216 (12x18) index searches and I'm not even half way done with creating searches.
Earlier on my project, these searches only had one criterion, so I used VLOOKUP() and the results came very quickly. However, now I need to find values according to three criteria, and the function above is the best way I've managed to accomplish this. However, it seems to be the responsible for the long computation times I'm getting. So my question is: how can I optimize a VLOOKUP() of multiple criteria? Should I tweak INDEX(1, MATCH()*MATCH(), MATCH()) or is there a faster way to do this?
Here's a sample of the 12x18 index searches (branch name is the only variable that the end-user will be able to change):
And of the 823x20 sheet it searches (column A has no merges, actually):
For a summary and options for Lookup with multiple criteria you may check this.
I use a lot Method 2 here (it is non-array formula) and method here.
I guess you should try them to check their speed.
First of all, can't this be accomplished simply by filtering on column A in sheet 'Results'? I think that is the most straightforward solution.
However, I have created an example workbook based on the criteria you described. It can be found here
First I created a list of the unique branches by using Advanced Filter for unique values on sheet 'Results' column A and put them on sheet 'Lists' where I created a named range listUnqBranches. I used that named range to create a data validation drop-down list on sheet 'Sheet1' cell A1 so that users can select which branch they'd like to see. I named that cell Branch.
Next I created two named ranges. rngDate is defined with this dynamic named range formula:
=INDEX(Results!$B:$B,MATCH(Branch,Results!$A:$A,0)):INDEX(Results!$B:$B,MATCH(Branch,Results!$A:$A,0)+COUNTIF(Results!$A:$A,Branch)-1)
rngLookup is defined with this dynamic named range formula:
=INDEX(Results!$C:$C,MATCH(Branch,Results!$A:$A,0)):INDEX(Results!$T:$T,MATCH(Branch,Results!$A:$A,0)+COUNTIF(Results!$A:$A,Branch)-1)
Lastly, in sheet 'Sheet1' cell B2 and copied over and down is this formula:
=IF(Branch="","",INDEX(rngLookup,MATCH($A2,rngDate,0),MATCH(B$1,Results!$C$1:$T$1,0)))
Note that the formula solution with named ranges is dependent on the data in sheet 'Results' being sorted by Branch. Does that work for you?
Related
My current formula is: =XLOOKUP(R2&S3,X1:EA1&X2:EA2,X1:EA150) with the source data being in the same sheet (X1:EA150). However, the source data is not usually within the same sheet (I only copied it over to see if the formula works). How do I nest(?) another =xlookup within my current formula to find the source data in Sheet1. I don't really want to use helper cells as then I'll have 2 dynamic ranges unless it can be automated.
(my previous question)
Thanks
Screenshot(s) refer:
The issue doesn't concern ranges from what I can tell - it's the missing final parameter assoc. with xlookup (like match: exact match: 0 etc.).
Of course, this assumes that your lookup ranges (K1:N1, K2:N2) correspond with respective lookup values that you have combined as (H2 & I3).
=XLOOKUP(H2&I3,K1:N1&K2:N2,K2:N11,"not found",0)
It's a trivial matter to then cut the appropriate range (i.e. contiguous range, 1:1 correspondence with resp[. (sub/) function ranges etc)
But what about duplicate match results?
The above will only return the first instance of a match. If you're looking to return every instance where there is a match, then I far prefer the filter function for this job:
=FILTER(K2:N11,--ISNUMBER(MATCH(K1:N1,H2,0)*MATCH(K2:N2,I3,0)))
And now we have this:
(assumes Office 365 compatibility RE: Excel)... ta
So I'm not a fan of VBA and I recently learned that OFFSET can be used with COUNTA to flashfill a range as far at it is as long as you aim for a longer range than you have data. Now I want to be able to achieve this both for columns and rows at the same time, where the rows are averaged. Could this be done? I am banging my head against the wall to find some logic to do it, but can only manage to combine it in a way that multiplies the rows with the number of the column.. which is not desired, of course.
I have posted a Minimal Reproducible Example in Excel Online:
https://onedrive.live.com/view.aspx?resid=63EC0594BD919535!1491&ithint=file%2cxlsx&authkey=!ALmV0VtFb7QZCvI
If you see Cell J9 and J11 you will see what I want to combine. The three rows in J11 and down, I want to average in J10, and spill/flashfill (like J9 and 11 does automatically because of the formula already) them from to the right, for as many columns as there data in the range A1-G4..
So I have raw data of numbers with titles in A1-G4, and by writing =OFFSET($A$1:$A$1,0,0,1,COUNTA($A$1:$EV$1)-1) in J9 I get all the titles of the columns filled from left to right, and by writing =OFFSET($A$1,1,0,COUNTA($A:$A)-1) in J11 I get the rows of the first column filled from top to bottom. They can also be combined, by writing OFFSET(Days,1,0,COUNTA($A:$A)-1,COUNTA(Days)), where "Days" is =OFFSET($A$1:$A$1,0,0,1,COUNTA($A$1:$EV$1)-1) (in a named range for readability) or OFFSET($A$1:$A$1,0,0,1,COUNTA($A$1:$EV$1)-1) without using a named range
As a thought, though I'm not sure how to implement it, maybe this could somehow be used in some form to get the column reference for the horizontal part in combination with =AVERAGE(OFFSET($A$1,1,0,COUNTA($A:$A)-1))
=MID(ADDRESS(ROW(),COLUMN()),2,SEARCH("$",ADDRESS(ROW(),COLUMN()),2)-2)
..found at https://superuser.com/questions/1259506/formula-to-return-just-the-column-letter-in-excel/1259507
Now, based on your explanation, here is the screenshot of my test:
Section A1:Exxx
I have converted that section into a Table, called «TblData», having numerous avantages:
It expands automatically without any additional efforts/formula
We can identify Data by its Columns attributed automatically by the Table [#1], [#2],[#3], [#4], [#5]
Section J9:N9
As a replica of the table name, I have used the following formula to retrieve it:
=INDEX(TblData[#Headers],1,COLUMN(A1)) '<--- This is for J9
=INDEX(TblData[#Headers],1,COLUMN(E1)) '<--- This is for N9
Section J11:Nxx
As a replica of the Table Content, I have used the following formula to populate the content:
=INDEX(TblData,ROW($A1),MATCH(J$9,TblData[#Headers],0)) '<--- This is on J11
=INDEX(TblData,ROW($A3),MATCH(N$9,TblData[#Headers],0)) '<--- This is on N13
Section J10:N10
Now this is the interesting part of the Average, so here is the formula I used for it:
=AVERAGE(TblData[1]) '<--- This is on J10
=AVERAGE(TblData[5]) '<--- This is on N10
NB: (1) Instead of using the Content below J10:N10, I prefer to reuse the Table as it expands automatically as more rows are added.
(2) Unless it is really necessary, I feel it is a double work as well to replicate again A1:Exxx from J9:Nxxx, because you can use the Table for whatever you need, with less maintenance.
Kindly find attached the file as well after I updated those items:
File Link: https://drive.google.com/open?id=1wRbpUxg0XLpfGqdvMF4fNKXDrL7xPPWs
We can correspond more below for further info. Hoping you to strech more your compentence :)
Sorry, mate, I can't figure out what you want to calculate. If it makes sense to add J9+J11 then you could just concatenate the two formulas in J9 and J11 with a plus sign. After much deliberation I decided to assume that your question is not one of formula but of formula-writing - "referencing" for short. Therefore I prepared this answer for you, hoping that it will prove helpful.
Building on your named range Days I suggest you create a dynamic named range Data with this formula.
[Data] =OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),COUNTA(Sheet1!$1:$1))
The range thus defined is dynamic in both directions. However, bearing in mind that OFFSET is volatile (slows down your worksheet) you may like to keep its use limited to this one formula and perhaps start the range at A2, but I shall tempt you to break the rule. Now you can use the INDEX function to refer to the Data range.
= INDEX(Data, [Row number], [Column number])
defines a single cell. But by setting either column or row to zero you can define an entire column or row. =INDEX(Data,0,1) defines column 1 of the Data range, =INDEX(Data,1,0) defines its first row.
=INDEX(OFFSET(Data,1,0),0,1) defines the first column of a range moved down by one row from its original position. I recommend the alternative and start the Data range from A2 and perhaps declare another range for the first row if needed.
=AVERAGE(INDEX(Data,0,1)) would draw the same average you already have in your sheet, provided that Data was defined starting at A2. For fun's sake, =AVERAGE(INDEX(OFFSET(Data,1,0),0,1)) would do the same without the change in the range's definition.
=COLUMN() returns the number of the column this formula resides in. So, you could enter =COLUMN()-6 in column G, copy to the right and get a count starting from 1. (You can do the same vertically with the ROW() function.) Applied to your formula, =AVERAGE(INDEX(Data,0,COLUMN()-6)) would return the average from column 1 if entered in column G, and from columns 2, 3 4, etc as copied to the right.
As I said, I don't understand enough of your request to bring this idea to a conclusion but I think that using the method described above will provide you with a tool to copy formulas into the table your sample has at its right. If you would elaborate on your requirement I might be able to assist more.
How do you create formulas that will return the totals, averages, counts, min, max, etc from different worksheets? The columns (that exist) are consistent in their header information, but may or may not be different from one sheet to the next, column number wise. Let's say I have 7 tabs of data, some or all of them may contain a column heading of beans, for example, but the column numbers may or may not be consistent across all tabs, where present. Their actual locations within the worksheet are completely dynamic.
My spreadsheet has several tabs of raw data that I want to compare against in a summary/report sheet. I'm sure this can be done but I am afraid it is a little too far beyond the capability of this old brain.
I've thought about and toyed with a bunch of formulas using indirect, index, match and just can't figure it out. Your help would be most appreciated. Thanks
Here's a possible function only solution. The final result will look like:
We will use four(4) primary functions:
ADDRESS
INDIRECT
MATCH
LEFT
Note: Just follow the link if you have question on how to use these functions
The formula: This is in cell C4 Above
=AVERAGE(
INDIRECT(
"'"& C$3 & "'!" &
LEFT(ADDRESS(1,MATCH($E$2,INDIRECT("'"&C$3&"'!1:1"),0),4,1),1)
& ":" &
LEFT(ADDRESS(1,MATCH($E$2,INDIRECT("'"&C$3&"'!1:1"),0),4,1),1)
)
)
Edit1: To handle the comment below for headers beyond 26, change this
LEFT(ADDRESS(1,MATCH($E$2,INDIRECT("'"&C$3&"'!1:1"),0),4,1),1)
to this:
SUBSTITUTE(ADDRESS(1,MATCH($E$2,INDIRECT("'"&C$3&"'!1:1"),0),4,1),"1","")
Basically what is does is:
Find where the header Bean is located using MATCH function. To do that, you will have to incorporate the use of INDIRECT since your sheet name is dynamic (in this example, your sheet name is in C3 - Data1). (I assumed all your headers are in 1st row, I use 1:1 in there). Note: In this example, Bean is in column H of Data1 sheet
MATCH($E$2,INDIRECT("'"&C$3&"'!1:1"),0) <~~ returns 8
After finding where it is, we need to get the entire column address so we can apply counting and summing functions (e.g. SUM,COUNT,AVERAGE etc...). To do that we use the ADDRESS function combined with LEFT to get the column letter.
LEFT(ADDRESS(1,MATCH($E$2,INDIRECT("'"&C$3&"'!1:1"),0),4,1),1) <~~ returns H
Then we just repeat that formula and connect it with : to get H:H
Now that we have the column address, we simply connect it again with the sheet name and apply the final INDIRECT function plus the counting and/or summing function of your choice.
Sample formula of Total in C5:
Sample formula of Max in C6:
Finally, all you have to do is copy the formula across all columns with sheet name. Just add sheet names beside the last one and copy formula. That's it. I hope this is close to what you want and I hope that all the functions I used are available in Excel 2000.
I'm stuck on an Excel problem and am hoping someone can assist. I read through 10-15 topics that are similar, but I wasn't able to get anything to work. Here is where I'm at...
I have a large data set containing columns for Year, Name, Total 1, Total 2 (and 20+ other columns). The same names appear in multiple rows based on the yearly totals. On a separate sheet, I have another data set containing Name and would like to pull the data from sheet one into columns as shown below.
I have done this in the past using only one year as the initial data set with the following formula:
=INDEX(DATARANGE,MATCH([#Name],DATARANGE[Name],0),MATCH("Total 1",DATARANGE[#Headers],0))
The problem I am having is the result of adding multiple years of data to my 1st data set. Is there a way to match the row based on name and year and then return the results of the appropriate column?
=SUM(($A$2:$A$9=B$16)*($B$2:$B$9=$A17)*($C$2:$C$9))
Enter above in cell B14 as an array formula or below as standard
=SUMPRODUCT(($A$2:$A$9=B$16)*($B$2:$B$9=$A17)*($C$2:$C$9))
You can do the same for total 2 just replace Cs with Ds
And then drag right and down.
Change the first MATCH function to something like this:
=MATCH(1,INDEX(([#Name]=DATARANGE[Name])*([#Year]=DATARANGE[Year]),0),0)
so as part of your whole formula that would be this
=INDEX(DATARANGE,MATCH(1,INDEX(([#Name]=DATARANGE[Name])*([#Year]=DATARANGE[Year]),0),0)
,MATCH("Total 1",DATARANGE[#Headers],0))
Another way you can use for returning numbers only (as here) is like this: (with cell refs for simplicity).
=SUMPRODUCT((A2:A9=2013)*(B2:B9="name x")*(C1:D1="Total 1"),C2:D9)
If the presented data to be indexed is a table then
This
=MATCH(1,INDEX(([#Name]=DATARANGE[Name])*([#Year]=DATARANGE[Year]),0),0)
should be corrected to a proper structured reference of
#[Name]
Also since this is an array formula it may not work with structured references at all. You'd be better served with regular cell references. Also if it is not a table only cell references will work.
I am trying to compare two different Excel (2010/xlsx) tables with related data to find matches. They would be on different sheets but in the same workbook (not that it should affect the problem).
I think the best route is some combination of sumproduct, match, and index... but I haven't been able to get them to work so far. I see the main question (cell G17) being solved by creating a subset of rows from Table 2 to compare against their corresponding data in Table 1 (index/match), then using arrays to do a multiple criteria selection to count how many match the criteria I chose (sumproduct).
I have played around with vlookup, countif(s), and sumif(s) but haven't seen a good way to apply them to this problem.
You can use SUMIF as a "quasi-lookup" like this
=SUMPRODUCT((file="doc")*(modified < SUMIF(user,creator,create)))
I'm not sure how to do it in a single cell as you've asked, but I would create an extra column in the second table which uses vlookup to find the created date, and another column containing whether or not the created date is greater than the modified date. Finally, you could use countif to combine them.
To be more concrete, in your example, I would put =vlookup(F3,A$3:D$5,2,FALSE) in cell I3, and =I3>H3 into cell J3, and expand both of these down. Then cell G17 could be given by =countif(J3:J5,TRUE).