I have a data in Excel as shown in attached image where in I've used named ranges.
Spends. Apr18. May18. Jun18
Category A. 120. 120. 120
Category B. 135. 125. 129
Category C. 110. 111. 112
Name Range: Spends
Range: =Sheet1!$A$1:$D$4
The average quarterly spends are calculated using named references as:
=AVERAGE(INDEX(Spends,2,2):INDEX(Spends,2,4))
This returns 119 in Cell E2
How can I drag this formula to subsequent cells so that it is applied automatically.
If you use the INDEX function with constants, of course these constants will not change when you drag the formula down and/or across.
You will need to learn about absolute and relative references and use something like Row(A1) and/or Column(A1) instead of the constants 2 and 2.
But maybe it does not have to be that complicated.
You could just add a column in the data table that calculates the Average and refer to that cell.
Or, in cell E2, use the formula =average(B2:D2).
I don't see the need for the named range at all in this scenario. It only complicates things.
It seems that you are struggling with appropriate data architecture concepts rather than with using formulas.
If in doubt, keep it simple. I don't see an application for copying the formula across, since you only have three months of data and you want to average these three months.
If your real scenario has more columns, then, please!!, update your question and post more relevant context. Then post a comment, so I can see you made a change.
Again, since you are new here: do not post updates into comments. Edit your question and then post a comment.
Use the ROW() function to return the relative position
E.g. in E2 and drag down
=AVERAGE(INDEX(Spends,ROW(),2):INDEX(Spends,ROW(),4))
Maybe you want to dynamically find the quarter start and end columns then you can use Match function to find the dates and return the position (column) where found. Then feed these into your formula:
Getting the columns by searching for qtr start and end:
Referencing those found positions as column arguments in your formula:
Related
I am new to excel formulas and vba etc. thats why i have no idea how to solve this problem.
Problem:
I want to create a dynamic chart using the offset function. Basically i want to show in my chart
the last 7 entries from the newest entry and insert all the data from the columns in it.
The current code that i used is this:
Bereich.verschieben is german for offset btw.
=BEREICH.VERSCHIEBEN(Historie!$C$307:$C$312;0,0;1;Charts!$B$58-1)
I want something like:
=BEREICH.VERSCHIEBEN(Historie!$C$307:$C$312;**0:5**;0;1;Charts!$B$58-1)
to show the data in the whole range. And i would like to add the part where i only show the last 5 entries from the current filled cell. In the picture below for example, from Col L to Col H all the data should be shown.
What i current got is this:
The Data in the chart is further on the back with the current date. Thats why the numbers dont match up exactly.
I recreated a data table similar to yours (the exact length and values are not important for the formulas):
I understand that you want to create a dynamic array similar to the one shown here:
The one shown here has been created using 3 formulas in the highlighted cells.
There are 2 ways to write these formulas that immediately come to mind. a) using INDEX() functions or b) using OFFSET() functions.
Starting with the INDEX() based formulas:
the formula for the machines is =TRANSPOSE(Historie!$B$307:$B$312)
for the last 5 dates =LET(Dates,Historie!$306:$306,INDEX(Dates,1,SEQUENCE(5,1,MATCH(MAX(Dates),Dates,0)-4)))
and for the values you can then use =LET(Data,Historie!$307:$312,Dates,Historie!$306:$306,INDEX(Data,SEQUENCE(1,COLUMNS(C3#)),MATCH(B4#,Dates,0)))
where the direct cell references correspond to the arrays as shown in the screenshot further below.
And the OFFSET() based formulas:
the formula for the machines is the same =TRANSPOSE(Historie!$B$307:$B$312)
for the last 5 dates you can use =LET(Dates,Historie!$306:$306,TRANSPOSE(OFFSET(Dates,0,MATCH(MAX(Dates),Dates,0)-5,1,5)))
and for the values =LET(Data,Historie!$307:$312,Dates,Historie!$306:$306,TRANSPOSE(OFFSET(Data,0,MATCH(MAX(Dates),Dates,0)-5,6,5)))
Both alternatives generate the same table as shown here below:
Note: In both alternatives, I hard wrote some numbers into the formulas that imply that you want to extract the values for exactly 5 dates and exactly 6 machines. If either one or both of those numbers shall be variable, adjustments have to be made accordingly.
Edit 1: Avoiding LET() function
When the LET() function is not available for your purposes, the above formulas can be rewritten. I will leave out the 1st of the 3 formulas since it doesn't use LET()
INDEX() based formulas:
the dates formula is =INDEX(Historie!$306:$306,1,SEQUENCE(5,1,MATCH(MAX(Historie!$306:$306),Historie!$306:$306,0)-4))
the formula for the values is =INDEX(Historie!$307:$312,SEQUENCE(1,COLUMNS(C3#)),MATCH(B4#,Historie!$306:$306,0))
OFFSET() based formulas:
the dates formula is =TRANSPOSE(OFFSET(Historie!$306:$306,0,MATCH(MAX(Historie!$306:$306),Historie!$306:$306,0)-5,1,5))
the formula for the values is =TRANSPOSE(OFFSET(Historie!$307:$312,0,MATCH(MAX(Historie!$306:$306),Historie!$306:$306,0)-5,6,5))
These adjusted formulas generate the exact same table as the LET-formulas above. See Screenshot
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.
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.
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 working on data from a population of people with allergies. Each person has a unique ExceptionID, and each allergen has a unique AllergenID (451 in total).
I have a data table with 2 columns (ExceptionID and AllergenID), where each person's allergies are listed row by row. This means that the ExceptionID column has repeated values for people with multiple allergies, and the AllergenID column has repeated values for the different people who have that allergy.
I am trying to count how many times each pair of allergies is present in this population (e.g. Allergen#107 & Allergen#108, Allergen#107 & Allergen#109,etc). To keep it simple I've created a matrix of 451 rows X 451 columns, representing every pair (twice actually because A/B and B/A are equivalent).
I somehow need to use the row name (allergenID) to lookup the ExceptionID in my data table, and count the cases where that matches the ExceptionIDs from the column name (also AllergenID). I have no problem using Vlookup or Index/Match, but I'm struggling with the correct combination of a lookup and Sumproduct or Countif formula.
Any help is greatly appreciated!
Mike
PS I'm using Excel 2016 if that changes anything.
-=UPDATE=-
So the methods suggested by Dirk and MacroMarc both worked, though I couldn't apply the latter to my full data set (17,000+ rows) because it was taking a long time.
I've since decided to turn this into a VBA macro because we now want to see the counts of triplets instead of pairs.
With the 2 columns you start with, it is as good as impossible... You would need to check every ExceptionID to have 2 different specific AllergenID. Better use a helper-table with ExceptionID as rows and AllergenID as columns (or the opposite... whatever you like). The helper table needs a formula like:
=COUNTIFS($A:$A,$D2,$B:$B,E$1)
Which then can be auto-filled. (The ranges are from my example, you need to change them to your needs).
With this helper-matrix you can easily go for your bigger matrix like this:
=COUNTIFS(E:E,1,INDEX($E:$G,,MATCH($I2,$E$1:$G$1,0)),1)
Again, you can auto-fill with this formula, but you need to change it, so it fits your needs.
Because the columns have the same ID2 (would be your AllergenID), there is no need to lookup them because E:E changes automatically with the auto-fill.
Most important part of the formulas are the $ which should not be messed up, or you can not auto-fill it.
Picture of my self-made example (formulas are from the upper left cell in each table):
If you still have any questions, just ask :)
It can be done straight from your original set-up with array formulas:
Please note that array formulas MUST be entered with Ctrl-Shift-Enter, before copying across and down:
In the example pic, I have NAMED the data ranges $A$2:$A$21 as 'People' and $B$2:$B$21 as 'Allergens' to make it a nicer set-up. You can see in the formula bar how that looks as a formula. However you could use the standard references like this in your first matrix cell:
EDIT: silly me, N function is not needed to turn the booleans into 1's and 0's, since multiplying booleans will do the trick. Below formula works...
SUM(IF(MATCH($A$2:$A$21,$A$2:$A$21,0)=ROW($A$2:$A$21)-1, NOT(ISERROR(MATCH($A$2:$A$21&$E2,$A$2:$A$21&$B$2:$B$21,0)))*NOT(ISERROR(MATCH($A$2:$A$21&F$1, $A$2:$A$21&$B$2:$B$21,0))), 0))
Then copy from F2 across and down. It can be perhaps improved in technique with sumproduct or whatever, but it's just a rough example of the technique....