Divide rows and then transfer divided values in new worksheet (values: time periods & amounts) - vba

Hope you can help with this:
In worksheet "TOTALS" and Range "M11:N251" there are "from:to" time periods inserted by user ("From" is in "M11:M" and "To" is in "N11:N"). Number of rows (and inserted time periods) may vary. Time periods are quadrimester (4months) but not always 120 days (could be 119, 122 or sth like that - if less than 100 then user must not be allowed to divide). Range "W11:W251" hosts amounts of money. So, for example, "M11:N11" can be 1/1/13-1/5/13 (dd/mm/yy) and W11 just a number (i.e. 98,45).
I want to be able to divide each time period almost by 2 (first part can be 60 days, second part rest of days) and amounts accordingly (depending on the number of days of its divided period) and transfer the divided periods and amounts to a new worksheet (TOTALS2) to -let's say- range "A11:B251" & "G11:G251").
So, in the above example, in "TOTALS2" we'll have 1/1/13-1/3/13 in "A11:B11" and 1/3/13-1/5/13 in "A12:B12", and the divided amounts accordingly to the counted days of "A11:B11" & "A12:B12" in "G11" and "G12".
And so on until there are no more time periods & amounts in TOTALS to divide and transfer to TOTALS2.
How can this be done? Ideas?
Thanks in advance!
If you want to check out the file, then download it:
http://www.sendspace.com/file/5kudcy

Based on the file you give in your link where the values in TOTALS start at row 10 (rather than 11 as stated), the prices are in column S (rather than W as stated) and the values in TOTALS2 are to appear in row 10 onwards (rather than row 11 onwards as stated) the following approach works:
Add 5 columns to worksheet TOTALS. These 5 columns have a header in row 9 and formulae in rows 10, 11, 12, etc. Using columns X, Y, Z and AA the header values in X9:AB9 are
Period, Int.To, Int.From, Proportion1, Proportion2
(where Int. is an abbrevation for intermediate.)
The formulae to use in cells X10 to AB10 are:
X10: =N10-M10+1 Calculates number of days from date M10 to date N10, inclusive.
Y10: =M10+59 Calculates end date of the 60 day period starting on date M10 (i.e calculates last date of first "half period")
Z10: =1+Y10 Calculates day after date in Y10 (start date of second "half period")
AA10: =60/X10 Proportion of whole period that is accounted for by first half-period
AB10: =1-AA10 Proportion of whole period that is accounted for by second half period
The formulae in X10:AB10 can be copied down for as many rows as contain data in worksheet TOTALS, to get something like...
The additional columns in TOTALS now provide the information that you need to split each quadrimester into two "halves". Cols M, N, Y and Z provide the date information and S, AA and AB the values for splitting each quadrimester's costs. To get it to display as desired in TOTALS2 you will also need to add a couple of columns to TOTALS2. I've used columns L and M with the following headers in L9 and M9:
Source, Part
In both L10 and L11 insert the value 1, whilst in M10 and M11 insert the values 1 and 2, respectively. Now add the following formulae to L12 and M12
L12: =1+L10
M12: =M10
Copy the formulae in L12 and M12 down so that columns L and M contain values in at least twice the number of rows (in TOTALS) that you wish to split into first half and second half periods. You should end up with the sequence 1,1,2,2,3,3,4,4 etc in column L and 1,2,1,2,1,2,1,2 etc in M.
The Source column (L) indicates which data row in TOTALS (1=first, 2=second, 3=third, etc) acts as the source of the values to be split in "half" and the Part column (M) indicates which "half" it is (1=first, 2=second).
All that remains is to put it all together using appropriate formulae in columns A, B and G of TOTALS2. The formulae to insert into A10, B10 and M10 are:
A10: =OFFSET(IF(M10=1,TOTALS!M$9,TOTALS!Z$9),L10,0)
B10: =OFFSET(IF(M10=1,TOTALS!Y$9,TOTALS!N$9),L10,0)
G10: =OFFSET(TOTALS!S$9,L10,0)*OFFSET(TOTALS!Z$9,TOTALS2!L10,M10)
Copy these formulae down the rows in TOTALS2 and it should be looking like...
The formulae in col A pick the start dates of the "half" periods using either col M or col Z from the correct Source row in TOTALS, according to whether the Part value is 1 or 2. Similarly, the formulae in col B pick the end dates using cols Y and N of TOTALS. The formulae in G multiply the cost value (col S of TOTALS) by the correct proportion from either col AA or col AB in TOTALS, again according to whether Part is 1 or 2.
I haven't included refinements such as:
preventing periods which are too short (or long) in TOTALS from being split (hint: you can detect this using the Length column in worksheet TOTALS) or
controlling the number of displayed rows in TOTALS2 so that it is exactly twice the number of data rows entered in TOTALS (not too difficult and several ways it can be approached) or
rounding the calculated costs for the two "halves" to 2 decimal places AND making sure that they add back to the original quadrimester cost (it is formatting in the worksheet that is causing only 2 decimals to be displayed and it is not guaranteed that the displayed values will sum precisely to their original source cost - the examples chosen just happen to have this property. Again not too difficult to solve.)
However, the above is a basic solution on which you can build.

Related

Excel VBA - Looping to count cell values larger than / smaller than specific value

I'm currently working with a large amount of contract lists. Each list is in a separate worksheet for each year's quarter and it needs to stay that way. E.g.: 2007_Quarter1, 2007_Quarter2, etc. I have 10 years of data, so 40 quarter report worksheets.
Now I need to code a vba routine that would do the following, in the specified order:
In each quarter report worksheet, run through the column containing contract values; then
Count all values between 0 and 10,000; then
Count all values between 10,001 and 25,000; and so on
Then, when there are no more contract values in the range (which will vary from sheet to sheet), go to the next worksheet and repeat the procedure.
All results should be returned in a worksheet (let's call it Worksheets("Report")) in a table where rows are for value intervals (e.g. 0 to $10,000) and columns are for quarters (e.g. 2007 Q1, 2007 Q2, etc.).
One particular aspect of my problem is that, for practical reasons, I'd prefer to set the control intervals' min and max values in a table contained in another worksheet ("Variables"), where, for example, I'd have all minimum values in range C4 down and all maximum values in range D4 down.
For each contract value, an "If" condition should look like:
If ContractVal > Worksheets("Variables").Range("C4").Value And
If ContractVal < Worksheets("Variables").Range("D4").Value Then ...
So far I'm having no success at coding this efficiently. I suspect some loop would work but I can't find a way to make it happen. A loop would do:
In 2007_Quarter1 ws:
For each cell from A4 down to the end, count values included between Range("C4").Value and Range("D4").Value
Then for each cell from A4 down to the end, count values included between Range("C5").Value and Range("D5").Value
... and so on, then repeat for 2007_Quarter2, 2007_Quarter3, and so on.
I need rescue! Thanks in advance!
If it is ok to you to prepare the resulting matrix manually (intervals in rows and quarters in columns) you could write a macro that read the right file and count the contracts in the right range for every cell in the matrix.
If you want to build the matrix automatically you should tell the macro the year range. Then you can write a loop that read the ranges and for every range you write a loop to read every file in the right order.

Complex conditional

I have the following sheet called DailyReport:
I am currently calculating Column M with:
=SUMPRODUCT(A2:A200=A2, G2:G200)
Then on a secondary sheet I have the following second sheet WeeklyReport:
Now what I want to do is, if WeeklyReport Column A2 == DailyReport Column A, then take the date in DailyReport Column B and test it to fall in the date range in WeeklyReport Column B and Column C with:
=IF(AND(DailyReport.B2>=B2,DailyReport.B2<=C2),1, 0)
and if that is true add the Total Daily Hours to the total in WeeklyReports Column D from DailyReports Column M.
I think summing values from column M, which is itself a sum, would not meet the goal. Summing sums would make too big a value, and column M is not filtered by date, so numbers from the wrong dates would be included.
I like better the idea of extending the way you used SUMPRODUCT to get the column M numbers. Instead of just checking for a matching name, add two more parameters to check for a date later or equal to the "Week Start Date" and earlier or equal to the "Week End Date".
So three true/false or 1/0 parameters (where multiplying by 1 for true keeps the value and multiplying by 0 for false removes the value) and the fourth parameter of the hour values to be summed:
=SUMPRODUCT(DailyReport.A$2:A$200=A2, DailyReport.B$2:B$200>=B2, DailyReport.B$2:‌​B$200<=C2, DailyReport.G$2:G$200)
The poster also came very close to a solution using SUMIFS (in the comments). The default condition test is =, but for the date comparisons we want to use greater than and less than operators. The LibreOffice/OpenOffice syntax for this is to put the relational operators in double quotes, then use & to connect them to the cell address that contains the test value:
=SUMIFS(DailyReport.G$2:G$200, DailyReport.A$2:A$200, A2, DailyReport.B$2:B$200, ">=" & B2, DailyReport.B$2:B$200, "<=" & C2)
In both these cases I have included $ signs to make the row numbers absolute. Absolute cell addresses will not change if the formula is copy-pasted; in this case the copy-paste might be over multiple rows on the WeeklyReport sheet to get hour totals for multiple people.

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)

Trailing Average Using AverageIf in Excel

I am trying to find the average for the last 3 instances only. I am using the AVERAGEIF statement and it will calculate the average for the entire range but I need it to only calculate for that last 3 instances it finds (or less if there is less than 3 available). I need the entire column for G and H to have the average for the last 3 games that the Team played.
This is what I have:
=AVERAGEIF(B3:C17,B17,D3:E17)
You can do this with array formulas (They have to be entered using the keys Ctrl+Shift+Enter)...
Basic steps are:
Find the row (including and above current) that is the third highest row number containing the team name (or use row 1 otherwise)
Use the INDIRECT ranges in your AVERAGEIF from B-that_row to C-current_row and D_that_row to E-current_row
So in cell F17 you would have the formula
{=AVERAGEIF(INDIRECT("B"&LARGE(IF(--($B$3:B17=B17)+($C$3:C17=B17),ROW($B$3:B17),1),3)&":"&CELL("address",C17)),B17,INDIRECT("D"&LARGE(IF(--($B$3:B17=B17)+($C$3:C17=B17),ROW($B$3:B17),1),3)&":"&CELL("address",E17)))}
We repeat some of the logic, because we have two ranges (criteria range and average range).
IF(--($B$3:B17=B17)+($C$3:C17=B17),ROW($B$3:B17),1) means that if column B or (using +) column C has the value of in B17, give me the row number, otherwise 1 (our <3 case... we could make this 3, the first row of team names)
LARGE(...,3) will give us the third highest of this array --> the third highest row number having our team name
INDIRECT("B"&...&":"&CELL("address",C17)) is going to give us the range using our third highest row number to the current row, columns B and C
then we do exactly the same thing as you were doing in AVERAGEIF but using this INDIRECT range and the equivalent for columns D and E
Fun question! Good luck. And remember to use Ctrl+Shift+Enter to enter it!
EDIT The above was giving an #NUM! error for the first two rows - that was because the LARGE function was trying to get the third largest in an array of 2! Also noticed that there were some cases where the column letter needed to be absolute (i.e. $) for copying to the Away column. So the updated formula:
{=AVERAGEIF(INDIRECT("B"&LARGE(IF(--($B$3:$B17=B17)+($C$3:$C17=B17),ROW($B$3:$B17),1),MIN(3,ROW()-2))&":"&CELL("address",$C17)),B17,INDIRECT("D"&LARGE(IF(--($B$3:$B17=B17)+($C$3:$C17=B17),ROW($B$3:$B17),1),MIN(3,ROW()-2))&":"&CELL("address",$E17)))}
Replaced the 3 with MIN(3,ROW()-2) so that we get 3 if there are, but 1 or 2 if we are in one of the first two data rows
OK I posted this prematurely and attempted to delete it when I realised it wouldn't work. It should work now.... providing you add another condition which is the game dates in column A. Remember that this is an array formula so hit ctrl+shift+enter. Dates in column A; teams in column B; stats in column D. This formula can reside somewhere permanent on the sheet so you can enter the team name (shown as F13 here) to get the three most recent stats.
=AVERAGE(VLOOKUP(LARGE(IF(B3:B24=F13,A3:A24),1),A3:D24,4),VLOOKUP(LARGE(IF(B3:B24=F13,A3:A24),2),A3:D24,4),VLOOKUP(LARGE(IF(B3:B24=F13,A3:A24),3),A3:D24,4))

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.