Excel - Using COUNTIFS to count dates within a certain range across multiple sheets - vba

I am trying to "COUNT" the number of dates that fall between a certain date range over multiple sheets excluding the first 'Summary' sheet. Following other examples I have used:
=COUNTIFS('CWP-A1-Inst'!S7:S51,">=2015-09-13" _
,'CWP-A1-Inst'!S7:S51,"<=2015-09-19") _
+ COUNTIFS('CWP-A2-Inst'!V7:V51,">=2015-09-13" _
,'CWP-A2-Inst'!V7:V51,"<=2015-09-19") _
+ COUNTIFS('CWP-A3-Inst'!T7:T50,">=2015-09-13" _
,'CWP-A3-Inst'!T7:T50,"<=2015-09-19")
This method works but I have 28 sheets, 75 date ranges (each week starting with Sunday ending with Saturday for over a year) and 7 cost codes to fill this out for. It would take forever to change these all manually.
I have also tried the UDF suggested in another example - Excel - Using COUNTIF/COUNTIFS across multiple sheets/same column - but I am unable to figure out how to add the second set of criteria in the example as I am by no means a VB expert.
Thanks in advance for any recommendations.

It is easier to get summary information about data when it is in a good structure.
If you had one big long list you would benefit from being able to use pivot tables For examples see here
If you were to take you data and put it in one long list this would be a good start (if the existing tables have the same structure).
Harvey

Try this mod to the posted UDF link.
Edit: code has been fixed so now it works. I also added the "<=" into the function, so all you need to provide is the input dates as they are and nothing else.
Function myCountIf(rng As Range, startDate as Variant, endDate as Variant) As Long
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
myCountIf = myCountIf + WorksheetFunction.CountIf(ws.Range(rng.Address), "<=" & endDate) - WorksheetFunction.CountIf(ws.Range(rng.Address), "<=" & startDate)
Next ws
End Function
And for startDate and endDate enter your criteria eg =myCountIf(A:A,">=2015-09-13","<=2015-09-19").

Related

Filtering values from OLAP Cube Pivot Table

I have a pivot table with a lots of date that I can choose in the filter (more than 1000 differents values).
What I need is to filter these values which are Dates from a user input.
example: Start date is 01-03-2018 to End date 20-03-2018
I need to do this through VBA code.
I'm not sure if actually the date values shown in the PT are really declared as date variable.
These values come from the Time dimension of the cube.
Here are some screenshots.
Image 1
Image 2
I made a try by using Wroksheet_Change but that works fine when I enter one date only (for example 2018-03-20) and the PT updates correctly, but i don´t know how to do it for a range of dates. Here is the code I used for one date only
Private Sub Worksheet_Change(ByVal Target As Range)
Dim newDate As String
newDate = Worksheets("KPICuboSIGP").Range("M4").Value
If Target.Address = "$M$4" Then
ActiveSheet.PivotTables("KPI-BPOP").PivotFields("[Time].[Date].[Date]"). _
VisibleItemsList = Array("[Time].[Date].&[" & newDate & "T00:00:00]")
End If
End Sub
I turned on the macro recorder too, and this is what it recorded.
ActiveSheet.PivotTables("KPI-BPOP").PivotFields("[Time].[Date].[Date]"). _
VisibleItemsList = Array("[Time].[Date].&[2018-01-21T00:00:00]", _
"[Time].[Date].&[2018-01-22T00:00:00]", "[Time].[Date].&[2018-01-23T00:00:00]", _
"[Time].[Date].&[2018-01-24T00:00:00]", "[Time].[Date].&[2018-01-25T00:00:00]", _
"[Time].[Date].&[2018-01-26T00:00:00]")
Those dates recorded should be selected automatically once I have the range from the user. Maybe I need to cycle through the options in the filter with For cycle, but I don´t know how to do it.
I'm pretty much a rookie in VBA
Can anyone help me with this.
Thanks for any advice
You can use the Labels filter to accomplish this. The problem is that the Labels filter isn't available to fields in the Filters part of a PivotTable. So you need to whip up a second PivotTable with nothing but the Dates field in it as a row field, then connect that PivotTable to the original PivotTable with a Slicer, and then programatically set a Label filter on the second PivotTable as I outline at Use VBA to select and deselect multiple slicer items (OLAP data)

For Next loop with two statements - Copy & Paste

I have a workbook with 2 worksheets, the 1st having a large range of data and formulas and the 2nd containing two empty tables to be populated with specific date from sheet1. Sheet1 has a column of dates Range("DK7:DK39") that range from 5/1/1986 to 5/1/2018. Any time the first date is changed in this column ("DK7"), all of the other dates in the following years will auto-update to the same day in the given year. With these changes, two separate columns will be repopulated with new data that is determined based on date-specific data.
I am trying to run a code that will loop through a range of days for which I need data (5/1 through 8/28), changing the value of cell("DK7") to each date in that range. However, I need the loop to also copy and paste data from the two data columns ("DS7:DS38") & ("DT7:DT38") into the two tables on sheet2 which have the years 1986-2017 as the y-axis column and 5/1 through 8/28 as the x-axis row. I have figured out how to loop the date through the Cell("DK7") but can't figure out the copy & pasting into the 2nd worksheet in respective year / date columns. Any help greatly appreciated, thanks.
Private Sub CommandButton1_Click()
Dim i As Date
For i = ("5/1/1986") To ("8/28/1986")
Range("DK7").Value = i
Worksheets(1).Range("DS7:DS38").Copy
Worksheets(2).Range("D4:E36").PasteSpecial
Next i
End Sub
This is a good way to loop through the dates:
Public Sub TestMe()
Dim i As Date
For i = DateSerial(1986, 5, 1) To DateSerial(1986, 8, 28)
Debug.Print i
Next i
End Sub
Make sure you are using DateSerial() function as there is a big difference between date formats around the world.

How to select column and display its current format using VBA Macro?

Please find my requirement below for which I am unable to find any solution:
1. Iterate over workSheet from workbook
2. Find all the columns containing date values using current format/type of column (Here is a trick. Worksheet is not static, it can contain any number of columns containing date values. Columns containing date values may have any name. And such worksheets can be more than one in number)
3. Apply macro on date columns for date formatting (below macro) if "Flag" value is "y"
<code>
Sub FormatDate()
If wksSecDist.Range("Flag").value = "y" Then
LastRowColA = Range("X" & Rows.Count).End(xlUp).Row
' Here I am finding total number of rows in column X
wksSecDist.Range("X2", "X" & LastRowColA).NumberFormat = "dd/mmm/yyyy"
' Here applying specified date format to Range("X2", "X10") [if last row index for column X is 10]
End If
End Sub
</code>
I am just a beginner to VBA.
Thanks in advance.
I suspect you didn't find a solution on the internet because you looked simply for a solution and not the parts needed to build your own solution.
You mention you are a VBA beginner, please take the below answer to be of educational use and begin you in getting you where you need your tool to be. Note, if it doesn't answer your question because of information that was not included, it has still answered your question and the missing information should form part of a new question. That said, lets get this function up and running.
From what you have written I have interpreted the requirement to be: -
Look over all worksheets in a workbook ('worksheets can be more than one in number')
Check every column to see if it holds a date value
If it does, set the whole column to a specific format
What is needed to accomplish this is iteration(loops), one to loop through all worksheet, and another to loop through all columns: -
The is pseudo code of the target: -
.For each Worksheet in the Workbook
..For each Column in the Worksheet
...If the Column contains dates then format it as required
..Process next column
.Process next Worksheet
We achieve this using a variable to reference a Worksheet and using a loop (For Each) to change the reference. The same goes for the columns.
Public Sub Sample()
Dim WkSht As Excel.Worksheet
Dim LngCols As Long
Dim LngCol As Long
'This loop will process the code inside it against every worksheet in this Workbook
For Each WkSht In ThisWorkbook.Worksheets
'Go to the top right of the worksheet and then come in, this finds the last used column
LngCols = WkSht.Range(WkSht.Cells(1, WkSht.Columns.Count).Address).End(xlToLeft).Column
'This loop will process the code inside it against every column in the worksheet
For LngCol = 1 To LngCols
'If the first cell contains a date then we should format the column
If IsDate(WkSht.Cells(2, LngCol)) Then
'Set right to the bottom of the sheet
WkSht.Range(WkSht.Cells(2, LngCol), WkSht.Cells(WkSht.Rows.Count, LngCol)).NumberFormat = "dd/mmm/yyyy"
End If
Next
Next
End Sub
Hopefully that has all made sense, this does work on the premise that the header row is always row 1 and there are no gaps in the columns, but these are separate issues you can approach when you're ready to.

Excel to CountIF in filtered data

I am trying to count the number of occurrences of a specific string in filtered data. I can do it using a formula in a cell but when I combine that with the other macros in my workbook the whole thing freezes.
So I would like to move the calculation to VBA so that it only calculates when the macro is run. Here is the formula that works in the cell:
=SUMPRODUCT(SUBTOTAL(3,OFFSET('2015 Master'!H:H,ROW('2015 Master'!H:H)-MIN(ROW('2015 Master'!H:H)),,1)),ISNUMBER(SEARCH("*Temp*",'2015 Master'!H:H))+0)
Basically I want to count the number of times "Temp" occurs in column H but only in the filtered data.
Thank you for your help!
ADDITION:
Here is the code I've written for the macro so far. It filters the data on a different sheet then updates the pivot table with the date range. I would like to add the count calculations to the end of this code and return the count to a cell on the 'Reporting' sheet.
Sub Button1_Click()
'Refresh the pivot table and all calculations in the active sheet
ActiveWorkbook.RefreshAll
'Gather the start and end times from the active sheet
dStart = Cells(2, 5).Value
dEnd = Cells(3, 5).Value
'Change the active sheet to the alarms database, clear all filters and then filter for the defined date range and filter for only GMP alarms
Sheets("2015 Master").Select
If ActiveWorkbook.ActiveSheet.FilterMode Or ActiveWorkbook.ActiveSheet.AutoFilterMode Then
ActiveWorkbook.ActiveSheet.ShowAllData
End If
ActiveSheet.ListObjects("Table44").Range.AutoFilter Field _
:=3, Criteria1:=">=" & dStart, Operator:=xlAnd, Criteria2:= _
"<=" & dEnd
Range("Table44[[#Headers],[GMP or non-GMP]]").Select
ActiveSheet.ListObjects("Table44").Range.AutoFilter Field:=2, Criteria1:= _
"GMP"
'Change the active sheet to the Reporting sheet
Sheets("Reporting").Select
'Within the alarms pivot table clear the label filters then filter for the date range and GMP alarms
ActiveSheet.PivotTables("PivotTable1").PivotFields("Active Time"). _
ClearLabelFilters
ActiveSheet.PivotTables("PivotTable1").PivotFields("Active Time").PivotFilters. _
Add Type:=xlDateBetween, Value1:=dStart, Value2:=dEnd
ActiveSheet.PivotTables("PivotTable1").PivotFields("GMP or non-GMP"). _
CurrentPage = "GMP"
End Sub
Pertinent to clarified question topic (i.e. " Basically I want to count the number of times "Temp" occurs in column H..."), the VBA solution can be as shown in the following code snippet. Assuming sample data entered in Column "H":
H
Temp Directory on C: Drive
Temp Directory
Project Directory
Output Temp Directory
Start Directory
Temp obj
apply the VBA Macro:
Sub CountTempDemo()
Dim i As Integer
Dim count As Integer
Dim startRow As Integer
Dim lastRow As Integer
Dim s As String
startRow = 2 'or use your "filtered range"
lastRow = Cells(Rows.count, "H").End(xlUp).Row 'or use your "filtered range"
count = 0
For i = 2 To lastRow
If InStr(Cells(i, 8).Value, "Temp") > 0 Then
count = count + 1
End If
Next
End Sub
where count value of 4 is a number of "Temp" occurrences in specified "H" range.
Hope this may help. Best regards,
To iterate over a column and find only visible (unfiltered) cells, one way is this:
Set h = ... Columns ("H");
Set r = h.SpecialCells(xlCellTypeVisible)
' now r is a composite range of potentially discontiguous cells
' -- it is composed of zero or more areas
'but only the visible cells; all hidden cells are skipped
Set ar = r.Areas
for ac = 1 to ar.Count
Set rSub = ar(ac)
'rSub is a contiguous range
'you can use a standard formula, e.g. Application.WorksheetFunction.CountIf(...)
'or loop over individual elements
'and count what you like
next
caveats: if any rows (or the column) are hidden manually (not from filtering) the count using this method will consider them as filtered (i.e. hidden/not visible).
Update: answer to comment
A Range is really a very general purpose notion of an aggregation of cells into a grouping or collecting object (the Range). Even though we usually think of a Range as being a box or rectangle of cells (i.e. contiguous cells), a Range can actually assemble discontiguous cells.
One example is when the user selects several discontiguous cells, rows, and/or columns. Then, for example, ActiveSheet.Selection will be a single Range reflecting these discontiguous cells. The same can happen with the return value from SpecialCells.
So, the Excel object model says that in general, a Range can be composed of Areas, where each Area itself is also represented by a Range, but this time, it is understood to be a contiguous Range. The only way you can tell if the Range is contiguous or not is if you created it as a box/rectangle, or, if Areas.Count = 1.
One way to investigate a bit more might be to select some discontiguous cells, then enter a macro and use the debugger to observe Selection.

Why is my for next loop not working properly?

I'm new to this site as well as to VBA. I've been working on a project and have run into a wall. I hope someone can help me out. What I'm trying to do is create a loop that will go through the specified sheet and pull data that matches my criteria, copy and paste it to another sheet, where I will be calculating it and then showing the results of the calculations in another sheet.
so, I have the following code (excel VBA) that is suppose to go through the sheet and pull all records that match the current week (I'm also trying to add the current year, no luck so far) and paste all matching records to the sheet named Archieve:
Sub DataByWeek()
Dim cw As Integer ' current week
Dim cy As Integer ' current year
Dim lr As Long 'last row of data
Dim i As Long ' row counter
'Get week number of today's date
cw = Format(Date, "ww")
cy = Format(Date, "yyyy")
ActiveWorkbook.Worksheets("Daily DB").Activate
' Find last row of data plus one down
lr = Sheet7.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
For i = 2 To lr
If Cells(i, 6) = cw Then
Range(Cells(i, 1), Cells(i, 5)).Copy
ActiveWorkbook.Worksheets("Archieve").Activate
Range("A2").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
End If
Next i
End Sub
This code does everything I want it to do except return beyond the first matching iteration. The code does go through all data on the sheet named Daily DB, but only returns the first matching record. I've tried looking online (many site including this one) to see if I missed something or did something wrong, but I can't find where I went wrong.
I would also like to know how I can add a second criteria to the If statement condition. I'd like to add the year so that the condition reads something like
If Cells(i, 6 & 7) = cw & cy Then
...
Where i, 6 contains the week number and i, 7 contains the year. In other words, I'd like to 'say' find all records that contain the x week of x year.
Sorry if this was too long and thank you in advanced for any and all help.
If you add ActiveWorkbook.Worksheets("Daily DB").Activate before the End If statement, I believe it would fix your problem. I'm not sure it's the most efficient way though.