I have the following formula:
=SUM(INDEX($M50:$N72,COLUMN(B:B),))
When I drag the formula down, it becomes:
=SUM(INDEX($M51:$N73,COLUMN(B:B),))
As you can see the cell increment is by 1.
Question
How can I change increment by other number like, 24, for instance? So that when I drag down the formula should become:
=SUM(INDEX($M74:$N96,COLUMN(B:B),))
This appears what you are asking for (it takes the current row of a formula, multiplies one row less by 24 [assuming you start on row 1 and copy down], and adds in the starting row numbers), although I doubt it does what you want. Are you sure you want the row number of the index function to be "COLUMN(B:B)"?
=SUM(INDEX(INDIRECT("$M"&(ROW()-1)*24+50&":$N"&(ROW()-1)*24+72),COLUMN(B:B)))
It's preferable to avoid the volatile INDIRECT in such situations, if possible. What's more, ROWS is a much better choice than ROW (especially in its unqualified form, i.e. ROW()) here, viz:
=SUM(INDEX($M:$N,50+24*(ROWS($1:1)-1)+1,))
which is equivalent to:
=SUM($M51:$N51)
and, when copied down, to:
=SUM($M75:$N75)
=SUM($M99:$N99)
etc., etc.
I confess I have no idea why you are using a construction such as COLUMN(B:B) for INDEX's row_num parameter.
If you're interested in an explanation as to my statement regarding ROW vs ROWS:
http://excelxor.com/2014/08/25/row-vs-rows-for-consecutive-integer-generation/
Regards
Related
It's probably a simple problem, but I did not even know the keywords to google it ;/. Let's say I have this data :
Now I also have this litle formula:
If I know drag the C cell to the right, Excel will attempt the following caluclation:
=2+B1
What I want him to do is to attempt this calculation
=2+A2
Of course the easiest solution would be to store my initial data in one row instead of 1 column, but it is really inconvenient for me. Thanks for any help
You can use the indirect() method to reference a cell by it's "String identifier", i.e. "A3". When filling out to the right, use CONCATENATE() and COLUMN() to create your String identifiers {A1,A2,A3,A4,A5...} as required:
=2+INDIRECT(CONCATENATE("A";COLUMN()-2))
This will result in the following:
Side-Node: If you want this for some x/y-Grid-Generation, you can also be lazy,
and just insert =COLUMN() for every cell from "A1 - Z1" and ROW() for every cell from "A2 - A24".
(Or even avoid these at all and directly perform your actual calculation by using column() and row() as replacement for your x/y.
You may try using a combination of the INDIRECT and COLUMN functions:
=2+INDIRECT("A"&(COLUMN()-2))
You would paste the above formula into cell C1, and then drag across to the right however many columns/rows you wanted to cover.
This would result in the following:
This works because COLUMN()-2 returns 1 for the C column, 2 for the D column, and so on. Therefore, the formula will be calling INDIRECT on A1, A2, etc. for column C, D, and so on.
In general, if you want relative references to move down as cells are dragged to the right, you can use this:
Instead of:
= 2+A1
Do:
= 2+INDEX($A:$A,COLUMN()+<offset>)
Where <offset> is whatever offset you need. The offset will change depending on which column the starting formula is located in.
INDEX should be preferred over INDIRECT because INDIRECT is volatile (must recalculate after any change to the workbook) but INDEX is not (only recalculated when one of the inputs the formula, in this case $A:$A, changes).
I am making a spreadsheet which has multiple sheets and one of the sheets has an equation that looks to see if there is anything written in a certain cell on all the other sheets. Right now I just use this equation to find out whether or not it has anything written in that cell.
=IF(LEN('A'!N18)>1,CONCATENATE('A'!C18," "),)
This is just checking to see if anything is in the cell. The problem is that I want this to keep working if I add a new row on A, but right now it bumps row 18 to 19 and I am left with no row 18 so it won't even check that new row!
If you want to add a row between row 1 and row 18 on worksheet A but keep your formula references to A!N18 and A!C18 then you need to use INDIRECT or INDEX. Of these two, INDEX is the better choice as it is not volatile. A volatile function like INDIRECT will recalculate whenever anything in the workbook chanmges. A non-volatile function like INDEX will only recalculate when something that affects its outcome is changed.
'INDIRECT method; works but not optimal
=IF(LEN(INDIRECT("'A'!N18"))>1,CONCATENATE(INDIRECT("'A'!C18"," "),)
'INDEX method; works and is non-volatile
=IF(LEN(INDEX('A'!N:N, 18))>1,CONCATENATE(INDEX('A'!C:C, 18)," "),)
The link that Slai posted in the comments to your question should be what you're looking for. If you don't want a reference to change when you add/delete rows/columns you need to use absolute references. As currently written "N18" and "C18" are relative references. If you change the columns/rows on sheet 'A', these references will automatically change with them. That's why it's moving to row 19 on you.
You can turn these into absolute references by adding "$" like this: "$C$18" and "$N$18". The first "$" sets the absolute reference for the column and the second sets the absolute reference for the row. You can mix and match these for various results.
Mixing relative and absolute values really comes in handy when you are reusing a formula with slight differences. For instance, if you want to multiply a number in column b (starting with row 4) by the number in A1 and show the result in column C (also starting with row 4). You'll always be using A1 so we can set this as an absolute value and in C4 enter the formula =$A$1*B4. Copy this down column C and it will automatically update the B value to the new column but will always use "$A$1" for the other part.
You can split the relative reference by only using the "$" on the column or row reference of the reference. Whichever one you use it on will be locked and the other can still adjust based on changes to the sheet or copying. Learning how to use absolute references can be a great time-saver.
I'm curious about part of your formula though. Why are you concatenating C18 with just a blank space? If you are using the info somewhere else, it may make sense to add the space in that concatenate but it's a personal choice.
I have a file that doesn't have a fixed number of columns.
I was wondering if there is a way to tell excel to put the sum of this row in a specific cell, in a way that each time a column is added to the file I don't have to update the formula and increase the range of the sum.
p.s.
I know I can make it a bit easier by just updating the formula like once in 10 times or so. But I was wondering if it's possible to do it once in a lifetime.
Yes sum(1:1) will sum up all values within the first row.
Keep in mind this does not work if the sum needs to be stored in the same row. As you would create a circularity problem.
If your formula will be in b1, and you want to sum from C1 to the end, then simply:
B1: =SUM(C1:XFD1)
Replace XFD with whatever column you think will be far enough to the right that you'll never have to adjust the formula; or leave it as is.
You could make the range dynamic, with something like:
B1: =SUM(OFFSET($A1,0,2,1,LOOKUP(2,1/ISNUMBER(1:1),COLUMN(1:1))-2))
but since that formula is volatile, it may add excessive time to the calculations.
First: Take note of your first cell (Assumed A1)
Second: Take note of your farthest cell (Assumed AZ1)
Then:
=sum(A1:AZ1)
In the screenshot provided, I am trying to extract all of the flow data into one column by itself. I got started using the INDEX function, but I believe I am missing something. In the screenshot, cell G2 should contain the value "998", which it does. Starting from cell C8, flow values occur every 14 rows in that column, so I want to write a function that when I copy and paste starts looking at cell C8 and returns the value every 14 rows. What I have so far is this:
=INDEX(C8:C354528, ROW(C1)+14)
This is close, because it does return me the value "998", but going forward, it basically moves my array selection down by one and the counts 14 rows...not what I want.
As an example, the next two values after "1000" should be, 998 and 992.
What am I missing here?
If you can use a second helper column, you can use this Array formula to find such rows. Note that this has a benefit in that your rows can be in any order - you aren't relying on the fact that "Flow" data is exactly X rows apart.
In Column I, let's say, in I1, you can put this:
=IFERROR(SEARCH(" Flow ",$B1),"").
Then, where you want to keep your Flow numbers, you can use this array formula:
=INDEX($C$1:$C$100,SMALL(IF($I$1:$I$100<>"",ROW($C$1:$C$100)-ROW($C$1)+1),ROWS($C$1:C1)))
(enter using CTRL+SHIFT+ENTER)
Use this:
=INDEX(C:C,8+(ROW(1:1)-1)*14)
And copy/drag down.
As stated in the comments OFFSET is volatile and should be avoided when possible. INDEX() is not volatile.
I have many columns all labeled with many many values underneath, which can be words or numbers
Here is the current equation =INDEX(AK6:AK94,MODE(MATCH(AK6:AK94,AK6:AK94,0))) I have this on the in cell 5 of each column.
The number of values in each column may increase or decrease. If i reference the entire column (until the end of the worksheet) the blank spaces interfere with an accurate output.
How do I reference cell A6 to Last Non-Blank
There are much more efficient - and non-volatile - set-ups available for determining the last non-blank cell in a range than, for example, the SUMPRODUCT/MAX one given by sancho.s, though only if the blank cells within that range are all "genuine" blanks, and not the null string "" e.g. as a result of formulas in those cells.
If this can be guaranteed, then, for a range containing mixed datatypes (some text, some numerics) you can use:
=MAX(MATCH(REPT("z",255),A:A),MATCH(9.9E+307,A:A))
which will be far more efficient than any solution (such as the SUMPRODUCT/MAX set-up) which tests each individual cell within the specified range as to whether it is blank or not.
What's more, the above construction can reference the entirety of column A with no detriment to calculation speed, thus eliminating the need to select a limited range. (Note that using the same range, i.e. A:A, within SUMPRODUCT (or any other array formula) would not at all be a good idea, since this would be forcing Excel to calculate more than a million cells individually, leading to noticeably slower workbook performance).
As for forming a dynamic range, I'm constantly surprised that so many sources around the internet continue to advocate set-ups involving volatile functions such as OFFSET and INDIRECT (I've even seen several sites using ADDRESS for this purpose), especially when there is a perfectly good non-volatile (actually, not fully non-volatile, but near enough) INDEX set-up available, viz:
AK6:INDEX(A:A,LastRow)
where LastRow is a Defined Name given the formula I posted above.
Regards
You need to determine the row of last non-blank cell in the column. The method for this would depend on whether there are blank cells in the middle, for instance.
Two alternatives are (taken from here*):
=SUMPRODUCT(MAX(($AK6:$AK94<>"")*(ROW(AK6:AK94))))
=INDEX(MAX(($AK6:$AK94<>"")*(ROW(AK6:AK94))),0)
Then you can use this value with OFFSET to get a reference to the target cell. So your range will be (using the second form)
A6:OFFSET(AK1,INDEX(MAX(($AK6:$AK94<>"")*(ROW(AK6:AK94))),0)-1,0)
This expression will be embedded in a formula.
Notes:
You may have to change absolute/relative references.
Depending on the formula you embed the expression in, I foresee you might need to enter your formula as an array formula, with Ctrl+Shift+Enter.
*This aims at getting the last non-blank value instead of a reference to the cell, but some of the results posted are useful.
Would counting the non blank cells work, then use offset to move that number of rows.
Have a look at this:
MATCH(1,A6:OFFSET(A6,COUNTIF(A6:A600,">0"),))
the offset & count resolve to complete A6:A14 on my simple test sheet.
One option is to increase the number of rows in the formula to be as high as you might need, and add an extra IF function in the formula to handle blanks, e.g. this version will allow you up to 995 rows of data
=INDEX(AK6:AK1000,MODE(IF(AK6:AK1000<>"",MATCH(AK6:AK1000,AK6:AK1000,0))))
.....but will still work if you have fewer rows and blanks in that range
confirm with CTRL+SHIFT+ENTER