Dynamically select a column using month and year, then sumif the values based on criteria in another column - vba

Here is an image of what I'm trying to achieve:
I am not well-versed in creating my own VBA script, but can understand code written by someone else if given time to dissect it. If this objective can be resolved without VBA, that would be my preference. I've explored using INDEX and MATCH but have gotten nowhere. Any suggestions?
I'm using Excel 2013.

I would "cheat"
I have my months list was in AI1:AI12, and year list in AJ1:AJ2 (for the dropdowns in A1 and B1 respectively). Move them elsewhere for more years.
Then in A2:
=MATCH(A1,AI1:AI12,0)
In B2:
=IF(MATCH(B1,AJ1:AJ2,0)=1,0,12 *( MATCH(B1,AJ1:AJ2,0)-1))
In D1O drag across to AA10:
=SUMIF($C$3:$C$8,"Plan",D3:D8)
Note: You could remove hardcoded "Plan" and reference a cell instead.
Result in C1 with
=OFFSET(D10,,B2+A2-1,1,1)
You are basically using a formula to determine how far to offset from month 1, year1 to get the current month and year conditional sum in row 10.

Example of finding the correct column, as described in my comment (untested code):
arr = array("Jan","Feb") 'you can do the rest
x = 2018 'first year in question, to make the math easier
s = 4 'column your first month is in
y = cells(1,2).value - x
z = application.match(left(cells(1,1).value,3),arr,0)
'all that gets you to:
c = s+(y*12)+z
You can then use the final column number, c, to do your Application.Sumifs() where you specify actual/plan as one of your criteria.

Related

VBA Insert formula with offset in cell and loop

I've got hourly data. I need to have a cell that computes say the R2 for days 1 and 7 between two different variables (say column A and B) and then loop this so next time it computes the R2 for days 2-8 and then for days 3-9 etc etc.
I must say that the cell that has the R2 formula is used in Solver to solve some code/formulas for max R2, so the cell that contains the R2 needs to be a formula and not a value.. (I have been able to offset this as a value but not as a formula). Part of the current code is the following:
i = 0
ActiveSheet.Cells(24,13).Value = Application.WorksheetFunction.RSq(RangeA.offset(i,0), RangeB.offset(i,0)
i = i + 24
Many many thanks in advance for any helpful tips
Cheers
Assuming you have named ranges RangeA and RangeB, you could use:
ActiveSheet.Cells(24,13).Formula = "=RSQ(RangeA,RangeB)"
Or, you can use relative references in R1C1 notation like so:
ActiveSheet.Cells(24,13).Formula = "=RSQ(RC[-2],RC[-1])"
or, for multi-celled ranges:
ActiveSheet.Cells(24,13).Formula = "=RSQ(RC[-2]:R[2]C[-2],RC[-1]:R[2]C[-1])"

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)))

Sumproduct dates

I have a spreadsheet worksheet called “ISO Procedure Master List” where the date a procedure is requested is in column G (Format m/dd/yyyy).
In column H the date the procedure is completed is entered. Column H uses the same date format but may contain blanks (procedure not completed yet).
There are currently 67 rows of information in the spreadsheet that span from 2011 to 2015 and that number will continue to grow.
QUESTION, I would like to get the average time (in days) it took from a procedure request (column G) to the completion of procedure (column H) for all of the procedures requested in a given year.
In other words the average (in days) time it took to complete procedures in a given year.
This answer will be in a cell C34 in the same workbook but a different worksheet called “ISO Matrix”. (This information probably does not matter but I thought I would add I just in case)
I have tried several Sumproduct variations with no success.
Assumptions:
Dates in columns G and H are dates, not text string,
Data start in row 2, using row 1 for headings.
For convenience, I assume you have named the ranges you wish to average requestDate and completeDate
You wish do ommit the rows where the procedure is not finished from the average calculation.
After naming your ranges, input the following formula into C34 on "ISO Matrix" tab:
=AVERAGE(IF(completeDate<>"";completeDate-requestDate))
This is an array formula, so when normally pressing enter, remember to press CTRL+SHIFT+ENTER instead. When highlighting the cell, it will then look like this:
{=AVERAGE(IF(completeDate<>"";completeDate-requestDate))}
NOTE: My language pack uses ; as formula separator, so if you language uses , instead, change the formula to:
=AVERAGE(IF(completeDate<>"",completeDate-requestDate))
EDIT: So, I didn't catch that you needed to average by year. In line with my recent formula, it could be update to suit your request.
=AVERAGE(IF(completeDate<>"";IF(YEAR(requestDate)=A15;completeDate-requestDate)))
where A15 holds the year you are interested in. I tried it with an AND in the first IF instead of two IFs, but that did not seem to work. Mind you, you might still need to change ; to , and you also need CTRL+SHIFT+ENTER for this one.
You could also add the code below, to handle the case where you test a year that is not present in the list:
=IFERROR(AVERAGE(IF(completeDate<>"";IF(YEAR(requestDate)=A15;completeDate-requestDate)));"No such year")
...or something like that

Excel VBA creating a new column with formula

I have an excel file with a column which has date data. I want the user to input a date of their choosing and then I want to create a new column that lists the difference in days between the two dates. The Macro that I have is working but I have a few questions and I would like to make it better. Link to MWE small data file is here.
The user input date was 9/30/2013, which I stored in H20
Macro:
Sub Date_play()
Dim x As Date
Dim x2 As Date
Dim y As Variant
x = InputBox(Prompt:="Please enter the Folder Report Date. The following formats are acceptable: 4 1 2013 or April 1 2013 or 4/1/2013")
x2 = Range("E2")
y = DateDiff("D", x2, x)
MsgBox y
'Used DateDiff above and it works but I don't know how to use it to fill a column or indeed a cell.
Range("H20").FormulaR1C1 = x
Range("H1").FormulaR1C1 = "Diff"
Range("H2").Formula = "=DATEDIF(E2,$H$20,""D"")"
Range("H2").AutoFill Destination:=Range("H2:H17")
Range("H2:H17").Select
End Sub
Now, could I have done this without storing the user input date in a particular cell? I would've preferred to use the variable "x" in the formula but it wasn't working for me. I had to store the user input in H20 and then use $H$20.
What's the difference between the function Datedif and the procedure DateDiff? I am able to use the procedure DateDiff in my macro but I don't know how to use it to fill out my column. Is one method better than the other?
Is there a better way to add columns to the existing sheet, where the columns include some calculations involving existing data on the sheet and some user inputs? There are tons of more complicated calculations I want to do next.
Thanks
Q1. Now, could I have done this without storing the user input date in a particular cell? I would've preferred to use the variable "x" in the formula but it wasn't working for me. I had to store the user input in H20 and then use $H$20.
Try this (UNTESTED)
Replace
Range("H20").FormulaR1C1 = x
Range("H1").FormulaR1C1 = "Diff"
Range("H2").Formula = "=DATEDIF(E2,$H$20,""D"")"
Range("H2").AutoFill Destination:=Range("H2:H17")
Range("H2:H17").Select
by
Range("H2:H17").Formula = "=DATEDIF(E2," & datevalue(x) & ",""D"")"
The above will fill all the cells with the formula in one go. You do not need the Autofill to do the job. Also Inputbox is the worst choice to accept dates. You might want to see THIS
Q2. What's the difference between the function Datedif and the procedure DateDiff? I am able to use the procedure DateDiff in my macro but I don't know how to use it to fill out my column. Is one method better than the other?
DATEDIF is a worksheet function and DateDiff is a VBA Function.

Counting multiple criteria

I'm trying to count multiple criteria and got the code to work somehow with SUMPRODUCT.
Range("i2") = [SUMPRODUCT(($CZ$2:$CZ$61410="condition 1")*($DD$2:$DD$61410="condition 2")*($CU$2:$CU$61410=$A$2 <-/date/)*($CY$2:$CY$61410="condition 3"))]
There's around 40 colums with different conditions. So I have to code for each condition. But that's not really working for me, because I have to do the same thing for the whole month.
Explanation
Cells A2 to A32 hold dates, let's say from 1st of August 'til 31 of August.
Raw data table (on the same sheet) has dates on the CU column (might be 60000+ lines).
Column CZ, DD, CY, etc. have conditions that have to be met to be counted.
Question
What I want to do is if the date in column CU = the date in A2 then it will be counted to row 2, if the date in column CU = the date in A3 then it will be counted to row 3.
That way I can write one code for the whole month, not each day separately.
I offer first a solution of a formula (WorksheetFunction if preferred) of this type:
=COUNTIFS(CZ:CZ,"=1",DD:DD,"=2",CY:CY,"=3", ... CU:CU,"="&A2)
and an image showing what this results in (the yellow cell) depending upon the date chosen:
This counts the number of instances, on the date chosen in A2, that match the hard-coded criteria displayed in Row1 for illustrative purposes.
Without the hard-coding of criteria but with possibly a slightly better 'match' to the OP and with more examples:
Apart from the highlighting, the contents of C6 were entered via the following macro:
Sub Macro1()
Range("C6").Select
ActiveCell.FormulaR1C1 = "=COUNTIFS(C[101],R1C[101],C[105],R1C[105],C[100],R1C[100],C[96],""=""&RC[-2])"
End Sub