Dynamic calculation in Excel based on a cell value - vba

I've got a challenge in Excel i hope you guys can solve for me.
I have a drop down list (weeks) where i select the week 2015-18 to 2016-17. (nr 1 in picture)
In the cell called LY (nr 2 in picture) I want that to type the result of a dynamic sum range, based on the weeks input.
Picture of setup of the text above
The calculation logic is:
If i select week 2015-20, the VBA or formula should sum(F5:F7)/(G5:G7).
So in other words, I want a dynamic calculation that starts from week 2015-18 (F5/G5) and then sums the values down to the value that i have selected in "Weeks"
Picture of the setup of the logic values
The value of this calculation should be shown in LY (first picture, nr 2).
I really hope you can solve this for me. I've got more rows to calculate, so if you could come up with a "global" code that works for that, it would be great

ok, so you do not need VBA for this.....
for the sake of easier updates; mark the weekrange, right click them and give them a name, with Define name
I called it yearlyweeks
The two drop downs lists, will contain the value corresponding to the text indicating that week.
So we can use this to get a cells address by value (if that text is unique in the range named yearlyweeks):
=ADDRESS(MATCH(H8,yearlyweeks, 0), 2)
where H8 is the cell address of a dropdownlist cell. 2 is the column index of the "B" column
this will result in something like:
$B$2
where the 2 indicates the relative row index, in the range, not the absolute row number.
we are really not interested in the column, or relative row, only the absolute row, but so far we can live with relative..:
=ROW(INDIRECT(ADDRESS(MATCH(H8,yearlyweeks, 0), 2)))
this will give you the relative row of the cell coresponding to what you selected on the drop downlist for one of the lists. So I would do this in two calculation cells, just to avoid the next piece getting too long..
lets let the calculation cells be in I10, and J10..
I10 hold the relative row for the beginning week
J10 for the ending week
below create a new set of cells with:
="F"&(I10 + 7)
and
="G"&(J10 + 7)
where 7 is the row offset of yearlyweeks
in yet one more cell J12 we make the range string:
=CONCATENATE(I11;":";J11)
and then does the calculation in the final cell:
=SUM(INDIRECT(J12))
Now I can do this as a one liner, but you really would hate that

Related

Extracting "hidden" data from expanding/collapsing pivot table - Excel

I'm not sure if this is possible but as you can see I have a pivot table with multiple dependent and expandable fields. I am trying to concatenate the data from columns A:D into one cell which works fine in row 2 but doesn't work with blank parent cells, as you can see in column F.
Any ideas for how to achieve this?
Pivot table
This answer assumes that you don't want to just Repeat All Item Labels in the PivotTable from the "Report Layout" drop-down on the Pivt Table Tools "Design" tab.
A formula to get the first non-blank value on or above the same row as the current cell from Column B can be constructed with a combination of AGGREGATE, SUMPRODUCT and OFFSET, like so:
=OFFSET($B2,SUMPRODUCT(AGGREGATE(14,6,ROW($B$1:$B$100)*--(ROW($B$1:$B$100)<=ROW())*--(LEN($B$1:$B$100)>0),1))-ROW(),0)
How does it work?
Starting with the outermost part, OFFSET($B2, VALUE, 0) - this will start in cell B2, then look up or down by VALUE rows to get the value.
Next we need to know how many rows we will need to look up-or-down. Now, if we can work out the bottom-most row with data, we can subtract the current ROW() from that, giving us OFFSET($B2, NON_BLANK-ROW(),0)
So, to finish up we need to work out which rows are not blank, AND which rows are on-or-above our current row, then take the largest of those. This is going to take an ArrayFormula, but we can use SUMPRODUCT to make that calculate properly. To find the largest number we could use MAX or LARGE - but we get less errors if we pick AGGREGATE(14,6,..,1). (The 14 means "we want the kth largest number", the 6 means "ignore error values", and the 1 is k - so "we want the largest number, ignoring errors")
But, what list of numbers are we going to look at, I don't hear you ask. Well, we want the ROW for output from our range (I'm using $B$1:$B$100, because using the whole column B would take far to long to calculate repeatedly), a comparison against the current ROW(), and check that the LENgth is > 0. Those last two are comparisons, so let's write them out first:
ROW($B$1:$B100)<=ROW()
and
LEN($B$1:$B$100)>0
We want to use -- to convert TRUE and FALSE to 1 and 0 - this means that any "bad" values become 0, and any "good" values are larger than 0:
ROW($B$1:$B$100)*--(ROW($B$1:$B$100)<=ROW())*--(LEN($B$1:$B$100)>0)
This gives us the Row number when the Row is on-or-before the current row AND Column B is not blank - if either of those are False, then we get 0 instead. Stick that in the AGGREGATE to find the largest number:
AGGREGATE(14, 6, ROW($B$1:$B$100)*--(ROW($B$1:$B$100)<=ROW())*--(LEN($B$1:$B$100)>0), 1)
Then put it in a SUMPRODUCT to force Excel to treat it as an ArrayFormula, and that's your NON_BLANK. This then gives you that first formula right at the top of the post

Return values from other workbook

Have a question about formula which will resolve my issue.
In my main workbook I need to compare data from two sources.
One of the columns must retrieve data(amounts) from other workbook.
I want formula which will search for all amounts in column G and will skip all blank cells. Tried to use VLOOKUP, INDEX and SMALL functions but no effect.
Each day amounts are different and I need to match them in main file and find exeptions.
Any ideas?
How about an array formula such as the following?
=INDEX($G$2:$G$20,SMALL(IF(($G$2:$G$20)=0,"",ROW($G$2:$G$20)),ROW()-1)-ROW($G$2:$G$20)+1)
The formula would have to be placed into cell I2 as an array formula (which must be entered pressing Strg + Shift + Enter). Then you can drag down the formula to get all the other values.
It doesn't have to be in column I but it has to be in row 2 because this formula get's the n-th Number from the list which is not = 0. The n-th place is (in this formula) row()-1. So for row 2 it will be 2-1=1 and thus the 1st number. By dragging down the formula you get the 2nd, 3rd, etc. number. If you start with the formula in cell I5 instead then it would have to be adjusted to be as follows:
=INDEX($G$2:$G$20,SMALL(IF(($G$2:$G$20)=0,"",ROW($G$2:$G$20)),ROW()-4)-ROW($G$2:$G$20)+1)
You could loop through the column and store each value >0 in an array and then compare or you loop through the column and compare directly...
something like:
Dim i as Integer = 0
Foreach value in Maintable
Do
If otherworkbook.cells(i,7) = value Then '7 for G
do your stuff
End If
i = i + 1
While i < otherworkbook.rows.count
Next
I think that could be the right approach

Dynamic reference in excel formula

I have the following array formula which works for what I want to do but I'm trying to change the formula when a user selects a value.
=INDEX($A$2:$B$70,SMALL(IF($A$2:$B$70=$A$121,ROW($A$2:$B$70)),ROW(1:1))-1,1)
It's used for a monthly report and the user will choose from a drop down the day of the month, e.g 1,2,3 - 31.
So if the user selects 1 from the drop down menu I want the formula to use the above formula.
If they select 2 for example I want the formula to move over a column so it would change to
=INDEX($A$2:$C$70,SMALL(IF($A$2:$C$70=$A$121,ROW($A$2:$C$70)),ROW(1:1))-1,1)
and so on moving over a column at a time.
It this possible at all or can it even be done without VBA?
I have an example of what I want done on the following link
https://docs.google.com/spreadsheets/d/1MDOzoQxYLgW-UOyljZsMwSu8zyAB7O2k1V-bTNP5_F0/edit?usp=sharing
All the data is on the first tab called staff. Each employee has a row and the duty assigned under the corresponding day column.
On the Roster tab it summarises each day. So what I am trying to get to happen is when you choose the day of the month (or preferably the actual date) the sheet changes to reflect the data.
At the moment the code I have working does for just Day 1 because the column references are coded into the formula. I was hoping to somehow choose 6 for example from the drop down and then the formula will map chosen day to the corresponding range in the raw data and update the formula and change the formula from Staff!$A$2:$B$68 to Staff!$A$2:$G$68.
If the formula finds no more entries if shows #NUM! but I intended to use the function ISERROR() to replace #NUM! with "".
This is what I'm trying to achieve it if makes sense?
There are a few issues here/ You are returning the value from column A so the first range can be $A$2:$A$70 and that means you don't need the 1 to specify the column_num. The IF statement was covering A2:C70 when you really only want either B2:70 or C2:C70 depending on the 1 or 2.
Assuming that A122 has either a 1 or 2 in it then,
=INDEX($A$2:$A$70, SMALL(IF(INDEX($B$2:$C$70, 0, $A$122) = $A$121, ROW($1:$69)), ROW(1:1)))
Standard non-array alternative,
=INDEX($A$2:$A$70, SMALL(INDEX(ROW($1:$69)+(INDEX($B$2:$C$70, 0, $A$122) <> $A$121)*1E+99,, ), ROW(1:1)))

Excel Formula to calculate number of user hits in a system everyday

This is the continuation of my previous questions and I have included my global aim with project.
Excel Link:
https://drive.google.com/file/d/0B5W4CgZKsARFSmhqV0ZSM1lBSkE/view?usp=sharing
Task:
The task is to collect the "number hits" of a user in an application "on each day". I can collect a log from the system which will give me the name of the users and their last hit date and total number of hits.(This total number of hits in not on daily basis, but sum of all days). and I need to make a formula to segregate these on daily basis
Screenshot:
To understand in better way I have created few screenshot, which I am looking to implement.
The excel has two tabs raw_data and value_capture. I will use raw_data to paste my raw data collecting from system log and value_capture to generate day by day hit statistics
Raw_data tab:
It has three details, 1. date. 2. name and 3 totals hits(This total hits are overall hits of that user on all days)
value_capture:
This has all user names and all dates to mark each day and a column to display all hits.
Now, considering an example of date 20141120, all users hits are 0.
raw_data shows 0 against all users
so value_capture are has to be updated with same
Now on next day 20141121, there is some hits against some users. (Note : if there is no hit against a user, it will only the previous date ie,date will update only if there is a hit on that day)
value_capture updated with that details
On 20141122, there are some more hits against the users
value_capture updated with the details. since the raw_data will show total number of hits against a user, the way of calculating on a particular will be total hits- previous date hit
I am stuck at a way to develop the excel formula here.Looking for an idea to implement this.
Note :
Users name will be fixed on both tabs, but that may come in different order in raw_data tab.
UPDATE
My raw_data sheet will be updated everyday and I want my formula results be fixed in the value_capture sheet after the values are updated (removed) from sheet raw_data
So as i mentioned in my answer to your previous question, the only way to save the results of a formula after deleting/removing its reference cells, is to use a macro.
First of all
you need a proper formula to pull the data from the raw_data sheet and then calculate the difference between that particular cell where the formula resides and the sum of previous cells in that row.
we need two formulas:one for the column B of your value_capture sheet. and the second one for the rest of your table. why? because in the first column you don't calculate the difference between itself and the previous cells, because there aren't any. So there is a little difference in the formula.
FORMULA ONE:(paste in B3 and drag and fill down)
=SUMIFS(raw_data!$C:$C;raw_data!$B:$B;$A3;raw_data!$A:$A;B$2)
FORMULA TWO:(paste in C3 and drag and fill down and to the right)
=IF(SUMIFS(raw_data!$C:$C;raw_data!$B:$B;$A3;raw_data!$A:$A;C$2)-IF(ISNUMBER(B3);SUM($B3:B3);0)>0;SUMIFS(raw_data!$C:$C;raw_data!$B:$B;$A3;raw_data!$A:$A;C$2)-IF(ISNUMBER(B3);SUM($B3:B3);0);0)
As you see in my screenshot for user in cell A3, we have value of 4 for the date 20141120 and the next day the value is 14 but the cell gets the difference, that is 10, and then then next day, the value increases to 16, so the cell value for D3 becomes 2 which is the different of 16 for that day and the sum of previous ones. This continues until today's value which is 24 so the cell gets 7 because the sum of previous ones is 17.
Now that you have your values captured correctly, with respect to the difference with the sum of previous days, it is time to make them fixed and eternal.
For this you need a macro:
Sub saveMyData()
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Range("B3:L18").Copy
ws.Range("B3").PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
End Sub
So obviously you need to update this range "B3:L18" this is what I have in the example sheet only.
Now this macro, copies and pastes all the values from that range onto itself, so you lose your formulas.So each day, you need to go to *line 21** of the same sheet and get the formula from C21 and paste it on somewhere on row 3 from where you want to continue capturing the new day's data. (you won't need the first formula, because it is only used once in the first column, the first day.)
This was the only way to capture the values using formulas and then save the results of the formulas in their place and go and fetch new data. I couldn't think of any other strategy to make it more automatic, except for writing mova VBA and letting excel go and find where you left the day before and paste the formulas in their right place and repeat the task.
all these formulas are array formulas, so press ctrl+shift+enter to calculate the formulas.
Remember to adjust the formulas to your regional settings, i suppose, by replacing the ";" with ",".
here is the example sheet downloadable from this link
Tell me if you have problems anywhere and don't forget to answer my question in the comments about the way you update your dates in row 2 of value_capture.
The formula that you are looking for is SUMIFS
=SUMIFS([SUM RANGE],[RANGE 1],[VALUE 1],[RANGE 2],[VALUE 2])
SUM RANGE is the column of values that you want to SUM so that is your column C. For Range 1 you want to select the range of IDs. The VALUE 1 will be equal to the value in Column A Row X. For RANGE 2 it will be the Date column. For VALUE 2 it will be the value in the column header.
Put this together and you have something akin to:
=SUMIFS(raw_data!$C:$C,raw_data!$B:$B,$A3,raw_data!$A:$A,B$2)
This would be in cell B3 and you could fill the other cells from there.
If total hits for a day is a rolling count of ALL hits ever then at the end of your equation you need to subtract the sum of the prior days.
For example:
=SUM(B3:B4)
This would only need to be added to subsequent columns (not the first).
So the equation in C3 would be
=SUMIFS(raw_data!$C:$C,raw_data!$B:$B,$A3,raw_data!$A:$A,C$2)-SUM(B$3:C3)
Then in D3 it becomes
=SUMIFS(raw_data!$C:$C,raw_data!$B:$B,$A3,raw_data!$A:$A,D$2)-SUM(B$3:D3)
Try Sumifs formula
=SUMIFS(raw_data!$C:$C,raw_data!$B:$B,$A3,raw_data!$A:$A,B$2)-IF(ISNUMBER(A3),A3,0)

Sum of unfixed number of cells if corresponding cell has given value

I am strugling how to make this happen. I have a worksheet where the data is going to be read in. The size of the data will vary from time to time. I have programmed a generated summation column after the data is read in. I want each cell to sum all values in the row, with the index value in the first row equal to the value in the first row in the summation column. The picture might give you a less abstract visualization of the case. I included the manual formulas for row 3 in row 12 as text. I want to do this in VBA. There might be up to 50 sets ([2010,2011,avvik] or [2010,avvik] or [2011,avvik]). There are two variables with a saved number (column number) for both the start and the end of the data area.
In other words; The money column under "SUM 2010" (which in my program actually is only 2010) should sum every cell in the given row, which has the value 2010 in row 1 in the same column. The same goes for 2011.
(You might want to save/open the picture for details)
You can do this with the formula SUMIF. For Q3, you would write:
=SUMIF(A1:P1, "2010", A3:P:3)
In layman's terms, you are saying, look at all the cells in the range A1 - P1 and for each one, if the value happens to be "2010", I want you to add the value in the range A3 - P3 to the sum.
BTW, you can also use this formula in cell Q11 to get the totals instead of the current formula you have. The fact that the year dates and numbers are in the same column make this really easy.