I currently have generation data over half-hourly time intervals. However there are about 70 entries for each half hour. What I want to do is make a column that aggregates all the generation for each time interval.
Currently my approach is this =SUM(D2:D71) and then in the next cell SUM(D72:D144) etc. Surely there must be a more efficient way of doing this?
Thanks
Hi you can create a pivot table
Ctrl + a your data - Insert - create pivot table
put the interval number in the [Rows] field and put the Energy generated in [Values]
SUMIFS would seem to be useful.
=sumifs(d:d, c:c, ">="&a2+time(8, 0, 0), c:c, "<"&a2+time(8, 30, 0)
=sumifs(d:d, c:c, ">="&a2+time(8, 30, 0), c:c, "<"&a2+time(9, 0, 0)
=sumifs(d:d, c:c, ">="&a2+time(9, 0, 0), c:c, "<"&a2+time(9, 30, 0)
=sumifs(d:d, c:c, ">="&a2+time(9, 30, 0), c:c, "<"&a2+time(10, 0, 0)
'etc ...
The time sequence could likely be resolved with a ROW() function that advances when filled down.
If you copied column C to a new unused column (e.g. column H) and removed duplicates then this should suffice.
=sumifs(d:d, h:h, ">="h2, h:h, "<"&h2+time(0, 30, 0)
Related
I'm having trouble with an excel formula where i'm trying to get the sum of all numbers in the row which are at 1 column offset with the criteria.
Eg. A1 = Price | B1 = $1000| C1 = Price| D1 = $1500 and so on....
Answer should be 1000+1500= $2500
I tried =SUMIF(1:1,"Price",OFFSET(1:1,0,1)) but gives me error!
I am guessing you have the cell with your formula in the same row, so it is a cyclic reference that gives you the error.
You can cut 1:1 before the cell with the SUMIF:
=SUMIF(OFFSET(1:1, 0, 0, 1, COLUMN() - 2), "Price", OFFSET(1:1, 0, 1, 1, COLUMN() - 2))
a possible solution is to offset your reference ranges. This means you will not be able to do an entire row reference. In your limited example your formula would wind up looking like this:
=SUMIF(A1:Q1,"price",B1:R1)
so you sum range will be limited to one less column than what is available to the sheet to allow for the second range (equal in size range) to be shifted one column to the right.
SIDE NOTE
Idealy you would want to arrange your data in a table. I understand this may not always be possible when dealing with 3rd party data dumps, limited VBA knowledge, and large amounts of data.
SUMIF(A20:ZZ20, "Price", OFFSET(20:20, 0, 1, 1, COLUMN() - 2))
I have an excel table for raw material offloads. All get tested, but some don't get offloaded right away. I'm trying to create a formula that looks at the future 20 entries for the same railcar and see if it changed from "N" to "Y" for offload.
Here's what my data looks like:
CAR # Offloaded?
CTCX733450 N
CTCX733450 Y
GATX207935 N
CTCX733472 Y
GATX207923 N
GATX207935 Y
GATX207923 Y
I've tried COUNTIF functions and IF functions. I can detect the duplicate railcars, but can't correspond the Y and N with the railcar.
Any help is appreciated.
You can use COUNTIFS to check multiple columns at once. For example
=COUNTIFS(A3:A22, A2, B3:B22, "Y")
This will take the value in cell A2 (CTCX733450), then look at the following 20 rows (Rows 3-22) to see how many time Column A is that value and Column B is "Y". If it is greater than 0, then one of the next 20 instances of that Railcar has been Offloaded.
Notably, this "the next 20 rows", and not "the next 20 entries for the same railcar". For that, we would need to use AGGREGATE and INDEX to find the 20th time that railcar next appears, which will be the final row we check.
For the time being, we will substitute for this row value with ROW_VALUE. This then lets us rewrite our formula using INDEX, as follows:
=COUNTIFS(A3:INDEX(A:A, ROW_VALUE), A2, B3:INDEX(B:B, ROW_VALUE), "Y")
Simple enough! The tricky bit, though, is now working out what value we should have for ROW_VALUE. This is where the AGGREGATE comes in.
You see, we can use AGGREGATE to get the kth (fourth parameter) smallest (First parameter = 15) non-error value (Second parameter = 6) from a list of values (third parameter). We can also make a list of Rows where column A is the same as the value in A2, by using #DIV0! (divide by zero) errors, and the fact that TRUE/FALSE can be treated as 1/0
AGGREGATE(15, 6, Row(A:A)/(A:A=A2), k)
In your case, we want k to be 20 + how many copies of railcar we already have. We can count how many copies of the railcar have passed us by using COUNTIF, so long as we lock one end to the first row:
AGGREGATE(15, 6, Row(A:A)/(A:A=A2), 20+COUNTIF(A$1:A2, A2))
Now, in theory we could shove that in as our ROW_VALUE. In practice, I can immediately see 2 big problems with it. The first, working on Whole Columns is slow. Second, and more important: What happens if there are less than 20 copies of the railcar remaining? You get a #NUM! error, that's what.
We can fix both of these issues with COUNTA (assuming that there are no rows without railcar numbers). For the first one, we will use INDEX again:
AGGREGATE(15, 6, Row(A$1:INDEX(A:A, COUNTA(A:A)))/(A$1:INDEX(A:A, COUNTA(A:A))=A2), 20+COUNTIF(A$1:A2, A2))
Alternatively, you can rearrange this to get rid of the COUNTIF at the end, by starting your Range on the next row, and just looking for the 20th number:
AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20)
For the second issue, we'll use IFERROR. This is a simple function - it just says "Return this value, unless it is an error - then, use this other value instead". Our "other value" will be the COUNTA of Column A, which should give us the last row in your list of Railcars:
IFERROR(AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20),COUNTA(A:A))
This then gives us our ROW_VALUE, which we can plug into our other earlier COUNTIFS:
=COUNTIFS(A3:INDEX(A:A, IFERROR(AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20),COUNTA(A:A))), A2, B3:INDEX(B:B, IFERROR(AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20),COUNTA(A:A))), "Y")
Finally, and optionally: we can make a slight boost in calculation time by working out if the AGGREGATE will error before it does so, by checking if there are at least 20 more entries for the Railcar. This also replaces the IFERROR with an IF statement, but makes the whole equation longer:
=COUNTIFS(A3:INDEX(A:A, IF(COUNTIF(A3:INDEX(A:A, COUNTA(A:A)),A2)<20, COUNTA(A:A), AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20))), A2, B3:INDEX(B:B, IF(COUNTIF(A3:INDEX(A:A, COUNTA(A:A)),A2)<20, COUNTA(A:A), AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20))), "Y")
We have replaced this ROW_VALUE
IFERROR(AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20),COUNTA(A:A))
with this one instead
IF(COUNTIF(A3:INDEX(A:A, COUNTA(A:A)),A2)<20, COUNTA(A:A), AGGREGATE(15, 6, Row(A3:INDEX(A:A, COUNTA(A:A)))/(A3:INDEX(A:A, COUNTA(A:A))=A2), 20))
I want to use a specific range reference programmatically to sum (next 25 cells), for which I'm using OFFSET(), which requires a cell reference. However, most lookup functions return indexes, or values, not cell references, so I have to use INDEX().
I find it a bit ridiculous that I have to do this just to find the cell reference of a cell programatically:
INDEX(A:A, MATCH(C2, A:A, 0), 1)
Is there a better way to get a cell reference programmatically?
The whole thing looks like:
=SUM(OFFSET(INDEX(A:A, MATCH(C2, A:A, 0), 1), 0, 1, 25, 1))
You will want to utilize multiple Match() and their offsets... see:
=SUM(OFFSET(A1,MATCH(C2,A:A,0)-1,0):OFFSET(A1,MATCH(C2,A:A,0)+24,0))
Broken down:
First cell in your range to sum in column 1 (A), have to subtract 1 from it so you're using your actual match reference:
OFFSET(A1,MATCH(C2,A:A,0)-1,0)
Final cell in your range to sum in column 1 (A), have to subtract 1 from the desired offset (25) similar to the first cell:
OFFSET(A1,MATCH(C2,A:A,0)+24,0)
You can then sum between the offsets
It may seem ridiculous to you but the best non-volatile option is a pair of INDEX/MATCH functions that define the start and stop of your sum range in column B and dispense of OFFSET altogether.
=sum(INDEX(B:B, MATCH(C2, A:A, 0)):INDEX(B:B, MATCH(C2, A:A, 0)+24))
I have data like below. I am calculating third column (next higher date. For each unique values of created date for data, I need to know what is next higher date available for data. There are duplicates. Also if there is no next higher date then I use generic date of 1/1/2017.
Last date = 1/1/2017
Now my question here is how can I achieve this using INDEX/MATCH or LARGE functions or do I need to use VBA scripting to get my results?
Per the sample image, put one if these in this in C2 and drag down.
'xl2003-xl2007
=MIN(MIN(INDEX(B$2:B$99+((A$2:A$99<>A2)+(B$2:B$99<=B2))*1E+99, , )), DATE(2017, 1, 1))
'xl2010-xl2013
=IFERROR(AGGREGATE(15, 7, B$2:B$99/((A$2:A$99=A2)*(B$2:B$99>B2)), 1), DATE(2017, 1, 1))
'xl2016/Office 365
=IFERROR(MINIFS(B:B, A:A, A2, B:B, ">"&B2), DATE(2017, 1, 1))
I am looking for a formula that gives me the closest value in a specific row in a table and another formula that gives me the column number where the value was found.
Thank you,
Debby
Fill these two array formulas into b16:b17 finishing each with ctr+shift+enter.
=AGGREGATE(15, 6, (INDEX(B4:I11, MATCH(B14, A4:A11, 0), 0))/(ABS(INDEX(B4:I11, MATCH(B14, A4:A11, 0), 0)-B15)=MIN(ABS(INDEX(B4:I11, MATCH(B14, A4:A11, 0), 0)-B15))), 1)
=AGGREGATE(15, 6, COLUMN(A:H)/(ABS(INDEX(B4:I11, MATCH(B14, A4:A11, 0), 0)-B15)=MIN(ABS(INDEX(B4:I11, MATCH(B14, A4:A11, 0), 0)-B15))), 1)