Moving range/array reference in Excel table - excel

Friends, I'm hoping you can help. I'm fairly certain I found a solution to this problem below a while ago, but silly me didn't write it down and now I can't remember how I did it. I'm drawing a blank on what to search for (Google is flooded with answers on "dynamic named ranges", which is not what I'm aiming for here). So, the question:
How can I define a range within a formula (say, RANK for example) that moves as I progress down through a table? I'm trying to avoid using INDIRECT, because it becomes a bit of a memory/processor hog when repeated throughout a large table. Pretty sure there is another way, maybe with INDEX or MATCH?
A simplified version of the data would appear as follows:
Column A has a bunch of reference numbers, each one repeats a few times.
Column B has a bunch of timestamps
Column C is where I would like to rank the timestamp in column B, as compared to all other timestamps that share the same reference number in column A.
The result set should look like this:
| A | B | C |
| abc123 | 01/01/2014 12:30 | 1 |
| abc123 | 01/02/2014 12:30 | 2 |
| abc123 | 01/02/2014 13:30 | 3 |
| abc123 | 01/03/2014 09:30 | 4 |
| def456 | 01/01/2014 12:30 | 1 |
| def456 | 01/01/2014 12:45 | 2 |
| xyz987 | 01/02/2014 12:30 | 1 |
| xyz987 | 01/02/2014 16:30 | 2 |
| xyz987 | 01/03/2014 11:30 | 3 |
Any ideas on what would be the least taxing solution for the processor in this case?

So here is the trick:
copy and paste in C1 and drag and fill down till end.
=IF(A2=A1;SUMPRODUCT(--(A$1:A$9=A1);--(B1>B$1:B$9))+1;SUMPRODUCT(--(A$1:A$9=A1);--(B1>B$1:B$9))+1)
this is an array formula, so press ctrl+shift+enter to calculate the formula
Here is the example sheet in this file downloadable from this link
P.S. remember to adjust the formula to your regional settings by replacing the ";" with "," . Have fun.

Related

Counting Time within ranges in table

So I did look through a couple of existing answers, but they were all in some programing language (ie, RUBY, PHP, etc). I also managed to figure out a way to do what I want but some of my formulas felt either hard coded or verbose. So my question is, is there a cleaner way to write my formulas to achieve my goal.
What I am starting with is a simple line to calculate cost of electricity usage. It look like:
+─────────────+────────+───────+───────+─────────+──────────+───────────+───────────+────────+──────────+───────────+───────────+──────────+──────────────+─────────────+
| | | | | | KW used | | | | Rate | | | Usage | Delivery | Total Cost |
| Date | Start | Stop | KW/H | Season | On-Peak | Mid-Peak | Off-Peak | Total | On-Peak | Mid-Peak | Off-Peak | Cost | Cost | |
+─────────────+────────+───────+───────+─────────+──────────+───────────+───────────+────────+──────────+───────────+───────────+──────────+──────────────+─────────────+
| 2022/12/17 | 05:00 | 22:00 | 1.44 | Winter | 0 | 0 | 24.48 | 24.48 | 0.17 | 0.113 | 0.082 | 2.00736 | 1.141296768 | 3.15 |
+─────────────+────────+───────+───────+─────────+──────────+───────────+───────────+────────+──────────+───────────+───────────+──────────+──────────────+─────────────+
The first 4 columns are user entry fields and correspond to columns B through E. The remainder of the columns F through P are all formulas.
My seasonal time bands are contained in the following table
+─────────+──────────────+─────────────+───────────+──────────+──────────+──────────+
| Season | Start | Stop | Time | Start | Stop | Rate |
| | | | Period | (HH:mm) | (HH:mm) | ($/Kwh) |
+─────────+──────────────+─────────────+───────────+──────────+──────────+──────────+
| Summer | May 01 | October 31 | Off-Peak | 00:00 | 07:00 | 0.082 |
| | | | Mid-Peak | 07:00 | 11:00 | 0.113 |
| | | | On-Peak | 11:00 | 17:00 | 0.17 |
| | | | Mid-Peak | 17:00 | 19:00 | 0.113 |
| | | | Off-Peak | 19:00 | 24:00 | 0.082 |
+─────────+──────────────+─────────────+───────────+──────────+──────────+──────────+
| Winter | November 01 | April 30 | Off-Peak | 00:00 | 07:00 | 0.082 |
| | | | On-Peak | 07:00 | 11:00 | 0.17 |
| | | | Mid-Peak | 11:00 | 17:00 | 0.113 |
| | | | On-Peak | 17:00 | 19:00 | 0.17 |
| | | | Off-Peak | 19:00 | 24:00 | 0.082 |
+─────────+──────────────+─────────────+───────────+──────────+──────────+──────────+
Note: weekends and holidays are Off-Peak
To aid with formula reading (or so I thought) I used the following named ranges:
Season_1 =$B$75 ("Summer")
Season_1_Start =DATE(YEAR(TODAY()),5,1) ("May 01")
Season_1_End =DATE(YEAR(TODAY()),10,31) ("Oct 31")
Season_1_TimeRates =$E$75:$H$79 ("Off-Peak" to 0.82)
Season_2 =$B$80 ("Winter")
Season_2_Start =DATE(YEAR(TODAY()),11,1) ("Nov 01")
Season_2_End =DATE(YEAR(TODAY()),4,30) ("Apr 30")
Season_2_TimeRates =$E$80:$H$84 ("Off-Peak" to 0.82)
TimeRates =IF($F3="Summer",Season_1_TimeRates,Season_2_TimeRates)
Step 1
Determining the season in F4
I used the following formula in F4.
=IF(AND($B3>=DATE(YEAR($B3),MONTH(Season_1_Start),DAY(Season_1_Start)),$B3<=DATE(YEAR($B3),MONTH(Season_1_End),DAY(Season_1_End))),Season_1,Season_2)
It seamed reasonable and substituted the year of the actual entry for making date comparison. I took the approach of if its not within the range for summer, then by default it has to be winter. Part of me is thinking I should check the winter date check. If both date checks fail then toss up a check date statement or the like.
Step 2
Determine how many hours are in each category according to the table and place results in G through I. This is where things go a little ugly for me. After chasing my tail in circle for a little bit I said screw it and plunged in with some hard coding and got something that worked but looked rather ugly and lengthy to me
I started out by figuring out that each time range check had 6 possible outcomes. I boiled those outcomes down to 2 possible results: 0 or Formula.
SB = Start Before
SI = Start Inside
SA = Start After
FB = Finish Before
FI = Finish Inside
FA = Finish After
So the results were either 0 because the time range in C and D are outside of the Time range of the table. Or its some form of Finish - Start.
I couldn't figure out how to make it count the hours in the range using the title (ie On-Peak) because there were sometimes more than one entry depending on the season in F. So what I did as a working step was to create a formula that would count the hours for each of the 5 time ranges instead of the names of the time range:
To get the hours I used the following formulas for each row:
=IF(OR($D3<=INDEX(TimeRates,1,2),$C3>=INDEX(TimeRates,1,3)),0,IF($D3<=INDEX(TimeRates,1,3),$D3,INDEX(TimeRates,1,3))-IF($C3<=INDEX(TimeRates,1,2),INDEX(TimeRates,1,2),$C3))*24
=IF(OR($D3<=INDEX(TimeRates,2,2),$C3>=INDEX(TimeRates,2,3)),0,IF($D3<=INDEX(TimeRates,2,3),$D3,INDEX(TimeRates,2,3))-IF($C3<=INDEX(TimeRates,2,2),INDEX(TimeRates,2,2),$C3))*24
=IF(OR($D3<=INDEX(TimeRates,3,2),$C3>=INDEX(TimeRates,3,3)),0,IF($D3<=INDEX(TimeRates,3,3),$D3,INDEX(TimeRates,3,3))-IF($C3<=INDEX(TimeRates,3,2),INDEX(TimeRates,3,2),$C3))*24
=IF(OR($D3<=INDEX(TimeRates,4,2),$C3>=INDEX(TimeRates,4,3)),0,IF($D3<=INDEX(TimeRates,4,3),$D3,INDEX(TimeRates,4,3))-IF($C3<=INDEX(TimeRates,4,2),INDEX(TimeRates,4,2),$C3))*24
=IF(OR($D3<=INDEX(TimeRates,5,2),$C3>=INDEX(TimeRates,5,3)),0,IF($D3<=INDEX(TimeRates,5,3),$D3,INDEX(TimeRates,5,3))-IF($C3<=INDEX(TimeRates,5,2),INDEX(TimeRates,5,2),$C3))*24
I wound up hard coding the entries because ultimately these are going to wind up in the formula for G3 through I3. Otherwise I could have used the Range # column as index points.
So the next problem I had was adding ranges with the same name together. Could have used SUMIF if I was keeping the table, but in my head I could not as A) I was not keeping the table, B) This would eventually need to be in a row that could be copied down.
So I looked at what needed to be done for each season and it was not bad...IF the formula was short.
So basically need an IF statement looking for summer and follow the addition of appropriate seasonal ranges for each range type. Seems simple enough but it gave me the following formulas for G3 through I3:
=$E3*IF(OR(WEEKDAY($B3)={1,7}),0,IF($F3="Summer",IF(OR($D3<=INDEX(TimeRates,3,2),$C3>=INDEX(TimeRates,3,3)),0,IF($D3<=INDEX(TimeRates,3,3),$D3,INDEX(TimeRates,3,3))-IF($C3<=INDEX(TimeRates,3,2),INDEX(TimeRates,3,2),$C3)),IF(OR($D3<=INDEX(TimeRates,2,2),$C3>=INDEX(TimeRates,2,3)),0,IF($D3<=INDEX(TimeRates,2,3),$D3,INDEX(TimeRates,2,3))-IF($C3<=INDEX(TimeRates,2,2),INDEX(TimeRates,2,2),$C3))+IF(OR($D3<=INDEX(TimeRates,4,2),$C3>=INDEX(TimeRates,4,3)),0,IF($D3<=INDEX(TimeRates,4,3),$D3,INDEX(TimeRates,4,3))-IF($C3<=INDEX(TimeRates,4,2),INDEX(TimeRates,4,2),$C3))))*24
=$E3*IF(OR(WEEKDAY($B3)={1,7}),0,IF($F3="Summer",IF(OR($D3<=INDEX(TimeRates,2,2),$C3>=INDEX(TimeRates,2,3)),0,IF($D3<=INDEX(TimeRates,2,3),$D3,INDEX(TimeRates,2,3))-IF($C3<=INDEX(TimeRates,2,2),INDEX(TimeRates,2,2),$C3))+IF(OR($D3<=INDEX(TimeRates,4,2),$C3>=INDEX(TimeRates,4,3)),0,IF($D3<=INDEX(TimeRates,4,3),$D3,INDEX(TimeRates,4,3))-IF($C3<=INDEX(TimeRates,4,2),INDEX(TimeRates,4,2),$C3)),IF(OR($D3<=INDEX(TimeRates,3,2),$C3>=INDEX(TimeRates,3,3)),0,IF($D3<=INDEX(TimeRates,3,3),$D3,INDEX(TimeRates,3,3))-IF($C3<=INDEX(TimeRates,3,2),INDEX(TimeRates,3,2),$C3))))*24
=$E3*IF(OR(WEEKDAY($B3)={1,7}),$D3-$C3,IF(OR($D3<=INDEX(TimeRates,1,2),$C3>=INDEX(TimeRates,1,3)),0,IF($D3<=INDEX(TimeRates,1,3),$D3,INDEX(TimeRates,1,3))-IF($C3<=INDEX(TimeRates,1,2),INDEX(TimeRates,1,2),$C3))+IF(OR($D3<=INDEX(TimeRates,5,2),$C3>=INDEX(TimeRates,5,3)),0,IF($D3<=INDEX(TimeRates,5,3),$D3,INDEX(TimeRates,5,3))-IF($C3<=INDEX(TimeRates,5,2),INDEX(TimeRates,5,2),$C3)))*24
So the question is, is there way to use formulas that would allow for the tidying up of what is currently in place for cells G3 to I3 (last 3 formulas in this question) that can be copied downward?
UPDATE as requested
I am working on the table on the top, below it is my building block area for thoughts. You may recognize some of the shots above from it.
Using Excel 2013

Excel formul to count Table Range using month from date text

I have an excel workbook where I am trying to count the number of apples in a named table. The workbook has multle sheets each named Jan, Feb, Mar, etc. with a corresponding table range of the same name.
My main worksheet has a list of months as columns and fruit as rows, I want to use a countif or suitable function to count the number of each fruit per month using the column heading as the worksheet portion of the formula.
This is what I have tried, this works, but has to be manually coded for each month, i would prefer it be more dynamic.
=COUNTIF(JAN[Labels],$A2)
Note: A2 contains the word apple
I have tried to get the month from the column date but it doesnt work
=COUNTIF(TEXT(E25,"mmm")[Labels],$A2)
This is roughly what the "master" table should look like (for clarity)
| | Jan-20 | Feb-20 | Mar-20 | .... |
| Apple | 4 | 3 | 5 | ... |
| Pear | 5 | 4 | 9 | ... |
EDIT:
Just to assist with anyone trying to help, this is roughly what a table on another sheet will look like:
| invoice | labels|
| 12535 | Apple |
| 12536 | Pear |
| 12537 | Apple |
This table would be a named table of Jan or Feb, etc.
Please try this:-
=COUNTIF(INDIRECT(TEXT(G2,"mmm")),"A")
G2 contains a proper date.
Here is a variation of the above where column 2 of the table is specified as the range to count in.
=COUNTIF(INDEX(INDIRECT(TEXT(G2,"mmm")),0,2),"B")
If you must use column captions to identify the column I would suggest MATCH to find it.
OK, so I found an answer, combining the above answer by Variatus with an additional new row.
| A | B | C | D |
1| | Jan-20 | Feb-20 | Mar-20 |
2| |JAN[Labels]|FEB[Labels]|MAR[Labels]| <- =UPPER(TEXT(B1,"MMM"))&"[Labels]"
3|Apple | 5 | 7 | 3 | <- =COUNTIF(INDIRECT(B$2),$A3)
4|Pear | 7 | 2 | 9 |
5|Orange| 1 | 3 | 3 |
So formula in B2 makes an uppercase text value of the month from B1 plus the column name Labels.
The formula in B3 (and down) counts the number of instances of the fruit from the named table & column shown in B2.

INDEX/MATCH Multiple Criteria Between Dates

Hope you can help me
My expected result is in column I,
where if the activity of this specific ID falls into the date range from columns C-D, i will get the minimum date and get the name column
however, in the formula i created, it always get the minimum date for that specific ID and its corresponding name
Not sure how to update the formula, to get the outcome that i need
Appreciate any help!
Thanks
excel sample
Put the dates in a single ordered column if you can:
| A | B
1 | 2016-01-01 | able
2 | 2016-04-01 | baker
3 | 2016-07-01 | charlie
4 | 2016-10-01 | dog
5 | 2017-01-01 | easy
Then if you can use Index-Match like this:
| IN | =Match(IN1, A:A) | =Index(B:B, Match(IN1, A:A))
1 | 2016-01-01 | 1 | able
2 | 2016-02-01 | 1 | able
3 | 2016-04-01 | 2 | baker
If your date ranges have to be in two columns - there's probably a much more complicated way to do this using array formulas.
Use this Array formula:
=INDEX($E$2:$E$7,MATCH(MIN(IF(($C$2:$C$7=G2)*($D$2:$D$7<=H2),H2-$D$2:$D$7)),IF(($C$2:$C$7=G2)*($D$2:$D$7<=H2),H2-$D$2:$D$7),0))
We need to find where the date is closest but less than the criteria.
Being an Array formula it must be confirmed with Ctrl-Shift-Enter when exiting Edit mode. If done correctly Excel will put {} around the formula.

Counting the frequency of combinations of numbers (in excel using VBA)

I want excel to count the FREQUENCY that certain number-letter combinations appear down a column in excel (using vba). All my data goes down one column like this:
Column A (only 1,2,3,4,5,s,f appear)
1
2
s
4
3
s
4
2
f
2
s
2
s
I want to count the number of occasions combinations of (1-s, 2-s, 3-s, 4-s, 5-s) occur, strictly when the number occurs first (is in the higher row). I do not want to count occasions when the s comes before the number (e.g. s-2). I know how to count the number of individual letters/numbers using the countIf function.
I might later want to expand my analysis to look at the occasions that three letter-number combinations (e.g. 2-s-3, 2-s-5)
I am very much a VBA noob.
Try inserting a new column to the right of Column A. Use this formula =A1&A2 and fill it down the column. The values will look like this:
+----------+----------+
| Column A | Column B |
+----------+----------+
| 1 | 12 |
| 2 | 2s |
| s | s4 |
| 4 | 43 |
| 3 | 3s |
| s | s4 |
| 4 | 42 |
| 2 | 2f |
| f | f2 |
| 2 | 2s |
| s | s2 |
| 2 | 2s |
| s | s |
+----------+----------+
Now you can count occurences like you were doing before! :D
Of course, you can expand to three character frequency analysis by making the formula =A1&A2&A3.
Seems possible with COUNTIFS, with 1 to 5 inclusive in C1:G1 and in C2:
=COUNTIFS($A1:$A12,C1,$A2:$A13,"s")
copied across to suit.
You can use the VBA equivalent of this formula
=SUMPRODUCT(--(ISNUMBER(A1:A12)),--(A2:A13="s"))
which looks for number, followed by s in the row below (4 for your sample)
code
MsgBox Evaluate("SUMPRODUCT(--(ISNUMBER(A1:A12)),--(A2:A13=""s""))")

Average of multiple survey responses (columns)

I feel a bit embarrassed for asking this but here goes:
I'm using Excel 2010 and I have a worksheet containing 700+ customer satisfaction survey responses. Each row is a survey with a 1-5 or NA response to 5 questions. It looks like the following:
+-Agent--+--Q1--+--Q2--+--Q3--+
| | | | |
| Jeff | 5 | 5 | 5 |
+--------+------+------+------+
| James | 1 | 1 | 1 |
+--------+------+------+------+
| Jack | 5 | 5 | 5 |
+--------+------+------+------+
| Jeff | 3 | NA | 5 |
+--------+------+------+------+
| Jeff | NA | NA | 3 |
+--------+------+------+------+
| James | 5 | 5 | 5 |
+--------+------+------+------+
| ... | ... | ... | ... |
+--------+------+------+------+
I want to create a worksheet listing each agent in column A and the average of all of questions answered regarding them. I tried a formula like AVERAGEIF(SurveyResponses!A2:A7,A2,SurveyResponses!B2:D7) where A2 contains the agent's name, but it doesn't appear to work properly.
For example, I get a 5.00 average for some agents when it should be a 4.61. When I look in the Function Arguments screen for my AVERAGEIF on this person, it looks like it recognizes the values properly. The Average_rage shows {"NA","NA","NA","NA",1;5,5,5,5,5;5,... but the returned value below that says = 5 which is not right since there is a 1.
Can anyone guide me in the right direction?
AVERAGEIF works like SUMIF, the second range used is actually the same size and shape as the first range, starting with the top left cell, so when you use this
=AVERAGEIF(SurveyResponses!A2:A7,A2,SurveyResponses!B2:D7)
because the first range is a single column then the second range used must be too (there's a 1 to 1 relationship between the cells) so because the top left cell in SurveyResponses!B2:D7 is SurveyResponses!B2 the range begins there and is the same size and shape as SurveyResponses!A2:A7
....so you are actually getting this....
=AVERAGEIF(SurveyResponses!A2:A7,A2,SurveyResponses!B2:B7)
AVERAGEIF help does tell you that but it isn't very clear
If you want the ranges to be different sizes you need an "array formula" like this
=AVERAGE(IF(SurveyResponses!A2:A7=A2,SurveyResponses!B2:D7))
You need to confirm that with CTRL+SHIFT+ENTER so that curly braces appear around the formula in the formula bar. That formula will count any blanks as zeroes but ignore text values like NA
Easiest way to do this would be a pivot table. They look scary, but they're fairly easy to use. Rows = names, Columns = Q, Average for the answers.

Resources