Lock sumif to specific cell range - excel

I have a spreadsheet that contains data in columns A:D. Each block of data A1:D11, A12:D22, etc. represents a single days worth of data. It has configuration items that I do a sumif function on to pull for the grand total since the report began(=SUMIF(A:A,L2,B:B). I have now been asked to sum only the last weeks worth of data. My current formula is (=SUMIF(A1:A55,L13,B:B)-very simple. However, I need it to lock so that we only checks data between A1:A55. If I add in a new days block of data it changes the reference to (=SUMIF(A12:A66,L13,B:B). If I use the $ refernce it does the same thing...how do I lock the formula so that it will always look between A1:A55?
Regards

When you do some deletions or insertions, excel will shift the reference used in the formula automatically. e.g. If the original formula in B1 is =SUM(A1:A20), after inserting cell A5 with shifting cells down , the formula will be =SUM(A1:A21).
To avoid this situation, you can use the formula INDIRECT, it will return the reference decided by the argument with string type. Since it is a string, excel will not change its value, therefore the range will always be the same no matter you inserted or deleted something.
So give it a try =)
=SUMIF(INDIRECT("A1:A55"),L13,B:B)

As an alternative suggestion, I would create another column in your table that calculates the weeknumber from the date using weeknum() and then use sumif to lookup a specific week.
That way you don't need to worry about row inserts at all.
By using the Indirect() method (which is a good solution and may be be all you need to solve your problem), you still have the problem of data being inserted into the range that your sumif() covers that might not be part of the week that you're monitoring (for example, if a row containing data from a different week were to be entered into A55).

Related

How to remove a row in excel without affecting a formula based on integer values?

I have a use-case with a formula based on integers. It basically takes one value and subtracts an unknown range of numbers from it.
The range of numbers to subtract change every day, but do not exceed 999.
Hence, the formula that I have used looks like this: =B1-(SUM(C1:C999))
Now my problem is, that I need to be able to delete cells in column C without affecting the formula.
I have tried locking the cells like this: =B1-(SUM($C$1:$C$999)), but the formula still changes when I delete cells.
INDIRECT won't work either, cause I'm not working with text strings.
Any ideas?
If you cannot use #RichardHansell suggestion, because you may have data below c999:
=B1-SUM(C:C)
you could use one of these:
=B1-SUM(INDIRECT("c1:c999"))
=B1-SUM(OFFSET($C$1,0,0,999))
Those are both volatile functions so will recalculated when anything changes. For a non-volatile function:
=$B$1-SUM(INDEX($C:$C,1,1):INDEX($C:$C,999,1))

Counting the Amount with Multiplication Condition

I have an Excel List That Looks Like This:
And i need to Count the Amount of Rows that have the Value Finished in Row C. But if T Value in Column B Contains a Semikolon it hase to Count double, if it Contains 2 Semikolons it hase to count 3 and so on...
Her is a Picture to show how the Counting should work.
I will not be able to Add Another Column to the Sheet, so i'm Locking for a Matrix Fomula or something like this.
Till now i tried it with the Countif and Countifs Formula but that didn't work.
Can someone give me a hint how to do thsi or waht Fomula would be the best to use?
For your "Finished" total, use this formula (adjust ranges as necessary to fit your actual data):
=SUMPRODUCT((LEN($B$5:$B$28)-LEN(SUBSTITUTE($B$5:$B$28,";",""))+1)*($C$5:$C$28="Finished"))
For your "Pending" total, if it needs the same treatment, use this formula:
=SUMPRODUCT((LEN($B$5:$B$28)-LEN(SUBSTITUTE($B$5:$B$28,";",""))+1)*($C$5:$C$28="Pending"))
Are you allowed to use/create a new worksheet (other than the one containing the data)? If yes, you can always compute the values you need for this to work in a separate worksheet, then use cell referencing to pull the value back into your original workbook. So, in a Sheet2 (for example), I would have two columns:
PENDING: =IF(Sheet1!$C4="Pending",1+LEN(Sheet1!$B4)-LEN(SUBSTITUTE(Sheet1!$B4,";","")),0)
FINISHED: =IF(Sheet1!$C4="Finished",1+LEN(Sheet1!$B4)-LEN(SUBSTITUTE(Sheet1!$B4,";","")),0)
Fill that formula as far down as needed.
Then, on your original sheet where you would like to enter the sums (I called it Sheet1 in the formulae above, you would do a =SUM(Sheet2!$B$1:$B$25) to populate the Amount Pending cell and =SUM(Sheet2!$A$1:$A$25) for the Amount Finished.
**
If you are not allowed to use a new worksheet, I would say a VB script would be the only other choice.
EDITED
Best solution is the SUMPRODUCT formula offered previously.

How do I use an array formula over a whole column or varying range?

I have a spreadsheet that I'm importing data into. I need to find the value within a column that is closest to zero. The column contains both positive and negative values, and the value closest to zero will be used in another formula. I've found an answer using an array formula, but it will only work for a fixed range (e.g. K2:K10), and the number of records imported into my sheet will vary each time I use it.
Here's what I have so far:
=INDEX(K:K,MATCH(MIN(ABS(K:K)),ABS(K:K),0))
Is there a way to apply an array formula over an entire column and just include non-zero cells other than the column title? Or possibly just cells with numerical values? Or is it possible to control the range that it applies to?
We can dynamically find the last cell in the range by using another INDEX/MATCH formula that is not an array:
=INDEX(K:K,MATCH(1E+99,K:K))
This will find the last cell that has a number in column K.
So we now use this as the last cell in the range:
=INDEX($K$2:INDEX(K:K,MATCH(1E+99,K:K)),MATCH(MIN(ABS($K$2:INDEX(K:K,MATCH(1E+99,K:K)))),ABS($K$2:INDEX(K:K,MATCH(1E+99,K:K))),0))
And now the formula is dynamic.
This formula is still an array formula and must be confirmed with Ctrl-Shift-Enter when exiting edit mode. If done correctly then Excel will put{} around the formula.
If as you pointed out there is a chance of deleting row 2 then all the K2 references will also be deleted.
In place of K2 we can use INDEX(K:K,2) It will now always look at the second row and will not error when row 2 is erased. So use this instead:
=INDEX(INDEX(K:K,2):INDEX(K:K,MATCH(1E+99,K:K)),MATCH(MIN(ABS(INDEX(K:K,2):INDE‌​X(K:K,MATCH(1E+99,K:K)))),ABS(INDEX(K:K,2):INDEX(K:K,MATCH(1E+99,K:K))),0))
There is nothing wrong with the Offset() function in small amounts, but it is a volatile function. Which means that it will calculate EVERY TIME excel calculate whether the data to which it is dependent has changed or not.
For the benefit of anyone reading this post, I ran into another issue and found a way around it. Scott Craner's answer above worked well until I ran a macro that I had for that sheet, which would delete certain rows. If row 2 got deleted, the formula would give a #REF error, because it was trying to call $K$2.
My solution was to replace $K$2 with
OFFSET(K1,1,0)
Therefore, the complete formula would be:
=INDEX(OFFSET(K1,1,0):INDEX(K:K,MATCH(1E+99,K:K)),MATCH(MIN(ABS(OFFSET(K1,1,0):INDEX(K:K,MATCH(1E+99,K:K)))),ABS(OFFSET(K1,1,0):INDEX(K:K,MATCH(1E+99,K:K))),0))
And as Scott mentioned, remember to hit Ctrl-Shift-Enter to execute the array formula.

Reference a range of cells and keep the order when adding new rows

I am referencing a range of cells in a first sheet, to build a second sheet. Often I add rows in the middle of the first sheet. In the second sheet that is referencing the first, there is a skip in the cell number where I have added a row.
SHEET 1: Contains my main list, that is updated
A new row is added (A3) to SHEET 1:
SHEET 2: references Sheet 1 and pulls through the rows
However, you can see that where row 3 should contain the added row 'Rachael', it instead has shifted down to Sheet1!A4 and missed A3 out all together.
How can I fix this?
Try using this formula in sheet2:
(add it to Sheet2, A2, then copy it around.)
=offset(sheet1!$A$1,row(a2)-1,column(a2)-1,1,1)
Try to avoid formula volatilty, which means a formula recalculates on a change to the sheet even if its precedents have not changed.
Having numerous volatile formulas in a worksheet can cause performance issues.
Any formulas that utilize the OFFSET() function or the INDIRECT() function automatically become volatile. But of these two functions, INDIRECT is much worse than OFFSET. Both are volatile, but OFFSET is extremely fast, while INDIRECT is extremely slow.
DO NOT USE INDIRECT().
The best alternative is without question the INDEX() function. It is even faster than the OFFSET function and INDEX is not volatile.
So use the following formula in cell A2 of the 2nd sheet:
=INDEX(Sheet1!$1:$1048576,ROW(),COLUMN())
...and then copy as needed.
To directly answer your question - you can achieve this with the INDIRECT function. INDIRECT allows you to dynamically reference a cell through a formula, which doesn't necessarily follow Excel's "tracking" rules. Keep in mind that normally, Excel gives each cell a 'unique id', and when you initially reference any cell, the internal logic points to that specific 'unique id', and the visible reference points to the 'A1' style reference to that cell. This is done so you can insert rows and columns without unintentionally losing all of your references.
It is generally not a good idea to do what I'm about to show, because you lose the inherent benefit that direct references provide (in general: easier to maintain). However, to show you how it would work, see below [this assumes you want one header row, and that the column on your results sheet should match the column on your raw data sheet]:
=INDIRECT("Sheet1!R"&ROW()+1&"C"&COLUMN())

Excel Performance - INDEX-MATCH combination

I am using excel to create data sets that are used in a vba application later. I am using this formula:
=INDEX(BaseData!$L$2:$L$10000;MATCH(DataSet!D5&DataSet!E5&DataSet!K5;INDEX(B‌​aseData!$B$2:$B$10000&BaseData!$C$2:$C$10000&BaseData!$D$2:$D$10000;0);0))
usually with a range from f.ex.: A2 - A10000, because my data can be differently long and often vary in data selection.
However, this slows my excel extremely down. I switched to manual calculations, but then, when activating automatic again, my excel instance takes extremely long and often crashes.
I also tried to past some data, but when creating a new dataset, I have to pull the formula down again and sometimes through this errors occur in my data set.
Any suggestions what I can do to make the INDEX-MATCH formulas more performant?
I appreciate your replies!
UPDATE
I guess a lot of performance goes away because index-match does not select the exact range, but also counts in blank rows. How to get the exactl range with index match automatically?
As I mention in my comment above, as long as this is a 'regular' formula and not an Array Formula, you may find success simply replacing "A1:A10000" with "A:A". However barring that, you can create a cell which will calculate reference the number of rows of data which you have, and then use that cell to indirectly reference the complete column with data in it.
CALCULATING YOUR DESIRED RANGE
For the following example to work, I assume that: Column A includes an index key in the form of numbers only; Column A includes no numbers in the header and above; and that the index rows are continuous, with no breaks. Start with the following formula:
=COUNT(A:A)
If my assumptions above hold, then this will return the number of data elements in your table. Once we know where this data starts, we can use this COUNT to determine where it ends. Assume your header is in row 2. (I like to include the header so that if you insert a row beneath the header, Excel picks up that you want to include the new row in your formulas).With that in mind, this formula will create the Excel-style reference which finds the last cell in column A which has data in it:
=ADDRESS(ROW(A2)+1+COUNT(A:A),COLUMN(A2),1,1)
Assuming 50 rows of data [which start at row 3, below the header], and all other assumptions above, this formula will return the text result "$A$53".
If you wanted to do the same thing, but instead return the full range in Column A where data exists (from the header to row 53), you could do as follows:
=ADDRESS(ROW(A2),COLUMN(A2),1,1)&":"&ADDRESS(ROW(A2)+1+COUNT(A:A),COLUMN(A2),1,1)
This returns the text string result "$A$2:$A$53", which is a reference to the full index of unique ID values. It will automatically move around as you would generally expect if you insert any rows or columns. Now assume for your INDEX that you want to pull the same data, but for column B, instead. The formula will be exactly the same, except that where I have "COLUMN(A2)" above, replace with "COLUMN(B2)".
REFERENCING YOUR CALCULATED RANGE
So now you have the address of your proper, limited columns - but how do you actually reference those areas in a formula? By using the INDIRECT function. INDIRECT says "Evaluate some specific criteria. It will create a cell reference. Now look at that cell reference." In its simplest form, this could look like this:
=INDIRECT(A1)
Assume that A1 holds the value "B5". Indirect will pick up the value "B5", and instead of displaying "B5", it will go to B5, and pick up the value there. So to use this with the above, wrap the whole thing in the INDIRECT function. Instead of picking up the text string "$A$1:$A$53", it will actually now reference that range properly. Like so:
=INDIRECT(ADDRESS(ROW(A2),COLUMN(A2),1,1)&":"&ADDRESS(ROW(A2)+1+COUNT(A:A),COLUMN(A2),1,1))
USING A NAMED RANGE
But that is a very long formula to have, and you won't want to use it within a specific cell for a simple INDEX/MATCH. Instead of entering these formulas in cells (although you could), I recommend you go to the Formula Ribbon -> Name Manager -> New Name. Call the name for the index of A "ID_COLUMN". Call the name for the index of "B_COLUMN" (or something more specific).
FINAL FORMULA
Now, if you wanted to make an INDEX/MATCH of your table, which automatically grows/shrinks as you change the data, your formula would look like this [this would, for example, pick the row from column B where column A has the number 100]:
=INDEX(ID_COLUMN,MATCH(100, B_COLUMN, 0))

Resources