I have a database with the relevant data in the same rows across several sheets, with data in every other column. I have been trying to use 3D ranges with AVERAGE/SUM and OFFSET but I can't seem to figure it out. I am getting a #VALUE error during the OFFSET part. Here is the setup I have been using.
=AVERAGE(OFFSET('Sheet 1:Sheet 4'!A1,0,COLUMN(A1)*2-1))
The sheet names do have spaces in them so the space in my above formula between the word Sheet and the number is intentional. I have tried the 3D range with just the average/sum functions and it works fine. Are the 3D ranges not compatible with the OFFSET function?
Try...
=AVERAGE(N(OFFSET(INDIRECT("'"&{"Sheet1","Sheet2"}&"'!A1"),0,COLUMN(A1)*2-1)))
or
=AVERAGE(N(OFFSET(INDIRECT("'"&$G$2:$G$3&"'!A1"),0,COLUMN(A1)*2-1)))
...where G2:G3 contains the sheet names. Note that the second formula needs to be confirmed with CONTROL+SHIFT+ENTER, not just ENTER.
Hope this helps!
FIRST EDIT
While an array formula is still required, you can avoid having to confirm the formula with CONTROL+SHIFT+ENTER, and you can avoid having to list your sheet names in a range of cells.
1) First define the name SheetNames as follows...
Refers to: ={"Instrument Partners","Supply Partners","Repair Partners","Wholesale Partners"}
2) Then try...
=AVERAGE(INDEX(N(OFFSET(INDIRECT("'"&SheetNames&"'!A1"),0,COLUMN(A1)*2-2)),0))
...which only needs to be confirmed with ENTER.
SECOND EDIT
"'"&SheetNames&"'!A1" returns the following array of text values...
"'Instrument Partners'!A1"
"'Supply Partners'!A1"
etc...
This array of text values is passed to INDIRECT, which returns the following array of references...
'Instrument Partners'!A1
'Supply Partners'!A1
etc...
In turn, this array of references is passed to OFFSET, which also returns an array of references based on the row and column offsets...
OFFSET('Instrument Partners'!A1,0,COLUMN(A1)*2-2) --> 'Instrument Partners'!A1
OFFSET('Supply Partners'!A1,0,COLUMN(A1)*2-2) --> 'Supply Partners'!A1
etc...
Then we retrieve the values by passing this array of references to the N() function...
N('Instrument Partners'!A1) --> returns actual value from the cell reference
N('Supply Partners'!A1) --> returns actual value from the cell reference
etc...
Then we pass this array of values to the INDEX function, which returns an array of values and allows the formula to be confirmed with just ENTER, instead of CONTROL+SHIFT+ENTER.
Lastly, the array of values is passed to the AVERAGE function, which returns the actual average.
Related
If you have a CSE array constant as follows in cell A1:
{={2,4,6,8}}
How can you get a specific element from the array constant? I tried the following formulas but they all return the first value of the array constant (2).
=INDEX(A1, 0)
=INDEX(A1, 1)
However, it does work if the array is not a reference. The following formula returns the 3rd element (6).
=INDEX({2,4,6,8},3)
Thank you
You could put the array constant in a Name instead of a cell.
Then INDEX will work with it properly with no implicit intersection.
Or you could parse the formula using the FORMULATEXT function, but that sounds tedious.
Try =INDEX(A1#,1). The # tells excel that A1 is a spill formula (more than 1 cell long). The array index starts at 1, not 0 in this case.
As a side note, Index knows you are referring to an index, not a row, when you give it a 1D array. In your example =INDEX(A1#,4) and =INDEX(A1#,1,4) return the Fourth item in your array (8 in this case), but =INDEX(A1#,4,1) will give you the error #REF!. If you define your array vertically {={2;4;6;8}}, =INDEX(A1#,4) and =INDEX(A1#,4,1) both work.
Edit: It looks like this does not always work in Excel 365 when a an array formula is created using Ctrl+Shift+Enter. I think this is due to the changes in 365. Array formulas have pretty much been replaced with spill formulas. Entering ={2,4,6,8} is mostly equivalent to a pre-365 array formula, but creating an array formula with Ctrl+Shift+Enter confines the output to as many cells as selected. In Dan's case, he selected only one cell and the formula doesn't automatically spill, so the formula is confined only to that cell. Excel seems to treat that cell as if it only contains that array element. If you select 2 cells and enter an array formula then =INDEX(A1#,2) will work but =INDEX(A1#,3) returns #REF!.
Edit2: It is possible with the FORMULATEXT Function as #DickKusleika suggested. Here is a function adapted from ExcelJet that does the job.
=LET(
DesiredIndex, 1,
ArrayFormulaRef, A1,
Formula, FORMULATEXT(ArrayFormulaRef),
FormulaLen, LEN(Formula),
CSVStart, FIND("{",Formula,2),
CSV, MID(LEFT(Formula,FormulaLen-1),CSVStart+1,FormulaLen),
TRIM(MID(SUBSTITUTE(CSV,",",REPT(" ",LEN(CSV))),(DesiredIndex-1)*LEN(CSV)+1,LEN(CSV)))
)
The situation
In the sheet "Planning" I have an area that contains pairs of sessions (strings) and hours (numbers) in adjacent cells (e.g. D11 and E11, I12 and J12 etc.) One session can occur multiple times.
D11:E11 is | Foo | 8 |
I12:J12 is | Foo | 4 |
In another sheet, I want to find a session in the Planning sheet and return an array with all the hours booked on that session (to calculate a total)
I use an array formula with a conditional and intend to use the SMALL function to retrieve the results from the array
The problem
The following formula returns all the correct references to hours booked on "Foo", so far so good.
=IF(Planning!$D$11:$CV$18="Foo";ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning"))
{"Planning!$E$11"\FALSE\FALSE\FALSE\FALSE\"Planning!$J$12"}
However, if I use the INDIRECT function to retrieve the values of those references, they always return the value of the first reference in the array ("Planning!$E$11")
=IF(Planning!$D$11:$CV$18="Foo";INDIRECT(ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning")))
{8\FALSE\FALSE\FALSE\FALSE\8}
How do I retrieve the correct values? Or should I tackle the problem in a whole different way?
Screenshots
The planning sheet
The overview I want
Since I was mainly interested in the total of planned hours, I eventually used the following formula:
=SUM(SUM(INDIRECT(IF(Planning!$D$11:$CV$18="Foo";(ADDRESS(ROW(Planning!$D$11:$CV$18);COLUMN(Planning!$D$11:$CV$18)+1;;;"Planning"));"$U$19"))))
IF: Create the array with references to the Planning sheet if the string is found. If it's not found, add the reference $U$19.
Using INDIRECT, replace all references with the values in the Planning sheet. $U$19 contains the value 0.
Then use SUM twice to sum up all the values. I don't know why, but see
Is it possible to have array as an argument to INDIRECT(), so INDIRECT() returns array?
https://superuser.com/questions/1196243/simplify-a-sum-of-indirect-cell-values
Indirect doest work in most array formulas. If you give it a string that refers to an array, like "A1:A10" it it returns those cells as expected but thats about it. You can use that array as the input to another function but you cant send an array output from another function to INDIRECT(). (Or at least i have not figured out a way)
Try using the INDEX function with the ROW function.
INDIRECT("A1:A10") is similar to
INDEX(A:A,ROW(A1:A10))
However the former is less flexible.
Comsider:
INDEX(A:A,FILTER(ROW(A1:A10),NOT(ISBLANK(A1:A10))*ISNUMBER(A1:A10)))
This returns an array containing the numerical values in the range but does not treat an empty cell as zero. Watch your order of operations and parenthesis.
The product NOT(ISBLANK(A1:A10)*ISNUMBER(A1:A10) is the inner product of two vectors of boolean values.
ROW(A1:A10) creates a vector of row values of the of the elements in that range. Then filter throws out any where the corespinsing element of the boolean vector is 0. Index then returns an array of values of the cells in its range coresponding to those rows. The range given to INDEX could be any row in fact. Not just the one your selecting on. Using the entire column (for example A:A) allows excel to automatically update the references if you move the source data, for instance if you insert a header row. If you use a specific range you will need to add an offset to the row value and it will not automatically update refernces. (Without a far more complex formula)
I have an Excel file with 2 sheets - one sheet contains my items, prices, codes, etc. and the other sheet is for cross-matching with competitors.
I've included an Excel file and image below.
I want to be able to generate my code automatically when manually entering any of my competitor's codes. I was able to do INDEX/MATCH but I was only able to match with one column (I'm assuming they're all in one sheet to make it easier). Here is my formula:
=INDEX(C:C,MATCH(K2,E:E,0)
So this is looking only in E:E, when I tried to enter a different column such as C:C or D:D it returns an error.
I tried to do the MATCH as C:G but it gave an error right away.
The reason why match gave you error is because it's looking for an array and you put in multiple columns.
There is definitely a more elegant way to do this but this is the first one that I came up with.
=IFERROR(INDEX(B:B,MATCH(K2,C:C,0)),IFERROR(INDEX(B:B,MATCH(K2,D:D,0)),IFERROR(INDEX(B:B,MATCH(K2,E:E,0)),IFERROR(INDEX(B:B,MATCH(K2,F:F,0)),IFERROR(INDEX(B:B,MATCH(K2,G:G,0)),"")))))
Index/Match Combination
Please try this formula:
{=INDEX($B$2:$B$5,MATCH(1,(K2=$C$2:$C$5)+(K2=$D$2:$D$5)+(K2=$E$2:$E$5)+(K2=$F$2:$F$5)+(K2=$G$2:$G$5),0))}
Instruction: Paste the formula {without the curly brackets} to the formula bar and hit CTRL+SHIFT+ENTER while the cell is still active. This will create an array formula. Hence, the curly brackets. Please take note though that manually entering the curly brackets will not work.
Description:
The INDEX function returns a value or the reference to a value from within a table or range.1
The MATCH function searches for a specified item in a range of cells, and then returns the relative position of that item in the range.2
Syntax:
The INDEX function has two forms—Array and Reference form. We're going use the Reference form in this case.
INDEX(reference, row_num, [column_num], [area_num])1
MATCH(lookup_value, lookup_array, [match_type])2
Explanation:
To simplify, we're going to use this form:
INDEX(reference, MATCH(lookup_value, lookup_array, [match_type]))
The INDEX function returns a value from the reference My code column (B1:B5) based on the row_num argument, which serves as an index number to point to the right cell, and we're going to do that by substituting row_num with MATCH function.
MATCH function, on the other hand, returns the relative position of a value in competitorn column that matches the value in individual cells of the competitor code column.
To make it work with multiple lookup range, we're going to create arrays of boolean values (TRUE/FALSE, aka logical values) by comparing values from individual cells in competitor code column with values in individual competitorn columns. Now, we convert these boolean values into numerical values by performing a mathematical operation that does not alter its implied value (i.e. TRUE=1, FALSE=0). We're going to add these values directly to make it simple. The resulting array have four index with two possible values: 1 or 0. Since each item in MATCH's lookup_array is unique, then there can be only one TRUE or 1. The rest are FALSE or 0's. So, with that knowledge, we're going to use it as our lookup_value.
Let's dissect the formula:
=INDEX(B2:B5,MATCH(1,(K2=C2:C5)+(K2=D2:D5)+(K2=E2:E5)+(K2=F2:F5)+(K2=G2:G5),0))
My code 2 = INDEX({"My code 1";"My code 2";"My code 3";"My code 4"},MATCH)
My code 2 = INDEX({"My code 1";"My code 2";"My code 3";"My code 4"},(2))
2 = MATCH(1,(K2=C2:C5)+(K2=D2:D5)+(K2=E2:E5)+(K2=F2:F5)+(K2=G2:G5),0)
2 =MATCH(1,
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;FALSE;FALSE;FALSE}+
{FALSE;TRUE;FALSE;FALSE},0))
OR
=MATCH(1,
{0;0;0;0}+
{0;0;0;0}+
{0;0;0;0}+
{0;0;0;0}+
{0;1;0;0},0))
=========
{0;1;0;0},0))
2 = MATCH(1,{0;1;0;0},0))
I hope this answer is helpful.
References and links:
INDEX function
MATCH function
Create an array formula
I have write below array formula:
=INDEX(Table1[Column2],SMALL(IF(Sheet1!G6=Table1[Column1],ROW(Table1[Column1])-ROW(Table1[[#Headers],[Column1]])),ROW($A:$A)))
According this picture1:
Note that selected range contains above array formula.
I need define that array formula returned values in the list form of data validation for Column2 of right table.
What I had tried:
I defined a Name, because responsively Sheet1!G6 reference part of above formula have change in Column2 cells for its appropriated Column1 cell. (in right table), according to below picture2:
Then set Column2 of right table's data validation, (picture3 below):
The problem is
But in result, validation list only contains first result of array formula! as picture4 below:
Question
How can define an array formula valued results set to a Name (Picture 2 above) and use in List Data Validation (picture 3 above) for a Column of table ? (Picture 4 above)
My concepts are:
There where a array form formula as shown above. (On the paper and
not in a worksheets range, yet)
This array formula is corresponding to a set -collection- of (potentially returned) results.
I want use above set in the Data-Validaton List for a special Table column.
Not using helper things (as Sheet, Column, Pivot-table and Etc...)
Using (1)- Name (Ctrl + F3), (2)- the array formula (for generating valid results collection), and (3)- Data-Validation List (to check is entered value in above special Table column is valid or not valid; and let entering only valid data in that special column))
I know you said you don't want to use a helper column or sheet. But saying:
A Table and an array formula can't coexist.
Data validation source can't be a complex formula of any kind, but you can use Indirect to a named range or address (but only if its a continuous region, not multiple areas) on the source formula if you want.
An array is never returned as a whole result in array formula, each cell used on as target destiny of the calculation is an item of the returned array.
So what I would do, return the array formula in a region let's Say A1, and a counter to the number of items in your array result that are valid using another cell B1. Use a cell C1 to determine the address of the list that you want to use. Then use =INDIRECT(C1) in the source of your validation.
You can hide other sheet so another use can't see it, and if you hide it by macro you can set it to very hidden and it's not possible to make it visible from the workbook directly. You might also create a named range to the C1 cell in my example so the end user can't see where this source on validation is from.
I have some named ranges some are single cell NamedRanges others are multicelled.
When I use "=AnyNameofSingleCellNamedRange" in any cell of the workbook.It returns it's value.
But When I use "=AnyNameofMultiCellNamedRange" It returns #VALUE error saying it's of the wrong data type.
If you enter =MultiCellNamedRange into a cell on the same row as the range it refers to Excel does an implicit intersection and gives you the value that is the intersection of the named range and the row. if there is no intersection then you get #Value.
If you enter =MultiCellNamedRange as a multicell array formula using Control-shift-Enter then Excel does not do implicit intersection and will return an array of values from the multicell named range.
Simplest method of accessing data from a multi-celled named range is the INDEX function. For example:
=INDEX(AnyNameofMultiCellNamedRange,2)
This gives the 2nd value of a multi-celled named range.
=INDEX(AnyNameofMultiCellNamedRange,2, 3)
In a 2D array, this shows value of the cell on the 2nd row and 3rd column.
In VBA, it is even simpler - you reference it as you would any other array. For example:
x = AnyNameofMultiCellNamedRange (2,3)
Note that without the (x,y) or (x) reference in brackets after the named range, you're essentially saying "make x = to the entire array".
=AnyNameofMultiCellNamedRange is actually returning an array of values. Depending on the physical location of the formula, you may see one of the values, or the #VALUE! error.
To see the individual values, you can either enter it as an array formula over a range of the same dimensions, or you can use the Index function to see individual values. It will work as required in functions that take array arguments.