Comparing Date Range Excel VBA - vba

UPDATED WITH ANSWER: I found an answer to my question. I'll place a simplified version below the original question here, just to make it easy, with a more detailed version below as the accepted answer.
I'm writing a VBA function to filter a pivot table by a date range entered by the user. For some reason, it is not returning the results expected.
The dates being compared are in two different date formats. The user-entered dates are in mmmm yyyy format (October 2013). When this value is pulled into the macro for comparison, it is translated correctly as 10/1/2013. The pivot table dates are in mmm yy format (Oct 13). When I call on this date with the code PivotItem.Value it seems to be translating the date as a string "Oct 13."
I can't quite figure out what the macro is doing, as it behaves somewhat erratically. If I run it for October 2011 to October 2013, it returns all months from Jan to September for every year, 2008, 2009, 2010, etc. If I run it for June 2013 to October 2013, it returns June to September for every year. Furthermore, in each example, the macro continues to run past the maximum range of data in the pivot table and gets an error. When I debug, the macro is trying to set the visibility to 'true' for a date that doesn't even exist in the pivot table (IE for Jan 2014 when the data only goes through Oct 2013). No idea why that's happening.
Below is the code. Any insight would be greatly appreciated.
UPDATE:
So the problem is definitely the date format. If I change the field settings in the pivot table to the date format mm/dd/yyyy (10/1/2013), then the macro works exactly as expected. This would be a simple fix to the problem except that the table is feeding a chart seen in the user dashboard, which I would really like to be in the format mmm yy, since it looks much cleaner. Is there a simple way to convert the format to mm/dd/yyyy inside the macro for the comparison, then back to the desired format once complete?
And I would still like to understand why a different date format is returning such different results, when the raw data being compared is the same, and both are formatted as dates, not like date vs text or something.
Sub filterPivotDate(pt As PivotTable, strtDate As Date, endDate As Date)
Dim pf As PivotField
Dim pi As PivotItem
'Clear current date filter
Set pf = pt.PivotFields("Date")
pf.ClearAllFilters
'Set new date filter
For Each pi In pf.PivotItems
If pi.Value >= strtDate And pi.Value <= endDate Then
pi.Visible = True
Else
pi.Visible = False
End If
Next pi
end sub
ANSWER UPDATE:
I replaced the loop I was using to set the filter with the following line of code:
pf.PivotFilters.Add Type:=xlDateBetween, Value1:=strtDate, Value2:=endDate
This solved the issue I was having with the date format. More information in the accepted answer below, as well as at this website

I might be wrong, but one of your < characters looks backwards- don't you want start dates Greater than the variable?

You could try converting the string date value first:
Dim dateValue as Date
'Set new date filter on all pivot tables
For Each pt In ws.PivotTables
Set pf = pt.PivotFields("Date")
For Each pi In pf.PivotItems
If IsDate(pi.Value) Then
dateValue = CDate(pi.Value)
If dateValue < strtDate Or dateValue > endDate Then
pi.Visible = False
Else
pi.Visible = True
End If
End If
Next pi
Next pt
'call this function
Function IsDate(byval thisDateString as String) As Boolean
On Error Goto ErrorHandler
Dim d as Date
d = CDate(thisDateString)
IsDate = true
Exit Function
ErrorHandler:
IsDate = false
End Function

I found some additional information about setting pivot table filters via VBA that improves upon the original code and solves the issue I was having. I decided to post it, as I found the information extremely helpful.
There are a lot of different filters you can set with simple, one line commands, rather than complicated loops which parse all the data and set visibility manually based on a condition as I was doing before. Below is the updated code, which also solved the issue I was having with the date formatting.
There is some really useful information at this link to the globaliconnect website about different pivot table filter settings you can set using VBA.
I'm still not certain why the date was behaving weird before when doing the comparison in a loop, but dates are just kinda like that I guess...
Sub filterPivotDate(pt As PivotTable, strtDate As Date, endDate As Date)
Dim pf As PivotField
Application.ScreenUpdating = False
'Clear date filter and set new filter
Set pf = pt.PivotFields("Date")
pf.ClearAllFilters
'I REPLACED THE LOOP WITH A SINGLE LINE TO SET A FILTER BETWEEN TWO DATES
pf.PivotFilters.Add Type:=xlDateBetween, Value1:=strtDate, Value2:=endDate
Application.ScreenUpdating = True
End Sub

Related

Error When Trying to Filter Pivot Table With Between Dates Using vb.net

I'm automating a number of reports using a vb.net winforms application. I have one report where I need to update the filter on a Date Field to between 2 dates (Monday & Sunday or the week in question).
I'm getting the dates by having the user select an End Date from a DateTimePicker dateStatusEnd
When the code gets to adding the filter I get the below error message:
The dates are valid because I mistakenly thought I had added them in the wrong order but this gave an error saying the end date had to be less then the start date so it's definitely reading them as errors.
Any ideas how I can resolve this? Code snippet below:
xlSht = aWorkBook.Worksheets("RBA Expiry Dates")
Dim xlPivot As PivotTable = xlSht.PivotTables("PivotTable1")
Dim xlPivotField As PivotField = xlPivot.PivotFields("RBA Expiry Date")
xlPivotField.ClearAllFilters()
If dateStatusEnd.Value.Day = 31 AndAlso dateStatusEnd.Value.Month = 12 And dateStatusEnd.Value.Date.ToString("dddd") <> "Sunday" Then
Dim aDate As Date = dateStatusEnd.Value.Date
Do Until aDate.ToString("dddd") = "Monday"
aDate = aDate.AddDays(-1)
Loop
xlPivotField.PivotFilters.Add2(Type:=XlPivotFilterType.xlDateBetween, Value1:=aDate.ToShortDateString, Value2:=dateStatusEnd.Value.Date.ToShortDateString)
Else
xlPivotField.PivotFilters.Add2(Type:=XlPivotFilterType.xlDateBetween, Value1:=dateStatusEnd.Value.Date.AddDays(-6).Date.ToShortDateString, Value2:=dateStatusEnd.Value.Date.ToShortDateString)
End If
In case anyone else comes across this in the future, it turns out that somewhere between opening the file & applying the filter the Pivot has stop recognising the date column as a date column.
Now I just need to figure out why that's happening 😢

Earliest date in VBA/Excel gives 00:00:00

I have a set of dates pulled from a PivotTable (which can either be accessed straight from the PT or I can copy it into a new sheet - I'm not fussed either way) and I need both the earliest and latest date e.g.
Scheduled date
01/01/17
05/08/17
08/11/16
03/12/16
...
So all I want is for VBA to tell me that the earliest date is 08/11/16 and the latest is 05/08/17 (This is part of a macro that cycles through different versions of different assessments, so a manual fix won't suffice and the model is so large that an array formula in the sheet is going to make it ridiculously slow).
So far I have tried the following for the earliest date:
Dim AllDates As Variant
Dim NumberDates As Integer
Dim Earliest As Date, Latest As Date
Set AllDates = ThisWorkbook.Sheets("Pivot Table 5 - To Use").Range("A4:A203")
'Attempt 1
Earliest = WorksheetFunction.Min(AllDates)
'Attempt 2
Earliest = Format(Application.Min(AllDates), "dd/mm/yyyy")
'Attempt 3
Earliest = Format(WorksheetFunction.Min(AllDates), "dd/mm/yyyy")
'Attempt 4
Debug.Print CDate(Application.Max(AllDates))
Every attempt results in "00:00:00" so I'm assuming I am actually working with Date values (I doubled checked and ensured that the worksheets were formatted to the correct date format) but beyond that I am COMPLETELY stumped.
This worked for me:
Sub test()
Dim Earliest As Date
Dim Latest As Date
AllDates = "$A$2:$A$204"
Earliest = Application.WorksheetFunction.Min(ActiveSheet.Range(AllDates))
Latest = Application.WorksheetFunction.Max(ActiveSheet.Range(AllDates))
MsgBox Earliest & Chr(13) & Latest
End Sub

VBA - Selecting cells that contain dates for the past 5 years

I currently have a spreadsheet that has the dates (excluding weekends and holidays) for the past 10 years in column A. For example, A1 contains "7/19/2007" and A2520 contains "7/19/2017"
Column E contains the closing price for the stock SPY on those corresponding dates.
I am trying to figure out the standard deviation for the past 5 years. In order to do so, my idea was to write a VBA code that would select today's date and the previous five years, and then use that to calculate the standard deviation.
This list is updated everyday, meaning tomorrow, it will contain 7/20/2017 and the closing price for that day. My issue is that I cannot figure out how to make it so it will select today's date and the past five years, so then I can calculate the standard deviation.
Thank you guys for all your help! Sorry if this seems simple, I have just started learning VBA last week!
How's this? I make a few assumptions, like your dates are contiguous, and there's no empty cell in your Date column. I also assume your dates are in order, ascending. (So your day 10 years ago is in say row 10, and today is in row 1000).
Sub get_difference()
Dim dateRng As Range, cel As Range, priceRng As Range
Dim dateCol As Long, stockCol As Long, lastDate As Range
Dim tdyDate As Date, decadeAgo As Date
dateCol = 1 ' column A has your dates
stockCol = 5
tdyDate = WorksheetFunction.Text(Now(), "mm/dd/yyyy")
decadeAgo = get_Previous_Date(tdyDate)
Debug.Print decadeAgo
With Sheets("Stock Prices") ' change name as necessary
With .Columns(dateCol)
Set lastDate = .Find(what:=tdyDate) ' Assuming no break in data from A1
'lastDate.Select
Set cel = .Find(what:=decadeAgo)
'cel.Select
End With
Set rng = .Range(.Cells(cel.Row, dateCol), .Cells(lastDate.Row, dateCol))
'rng.Select
Set priceRng = rng.Offset(0, stockCol - dateCol)
'priceRng.Select
'priceRng.Offset(0, 1).Select
priceRng.Offset(0, 1).FormulaR1C1 = "=IFERROR((RC[-1]/R[-1]C[-1])-1,"""")"
End With
End Sub
Function get_Previous_Date(Dt As Date) As Date
' https://www.mrexcel.com/forum/excel-questions/37667-how-subtract-year-date-2.html
Dim numYearsBefore as Long, numDaysBefore as Long, numMonthsBefore as Long
numYearsBefore = 10 ' Change this to any amount of years
numDaysBefore = 0
numMonthsBefore = 0
get_Previous_Date = DateSerial(Year(Dt) - numYearsBefore, Month(Dt) - numMonthsBefore, Day(Dt) - numDaysBefore)
End Function
Make changes as needed, i.e. sheet name (I called mine "Stock Prices"), and the columns. It's also a little verbose, and could be made more compact, but I figured it'd help you learn to keep it like that. I suggest stepping through with F8 to see what happens, and uncommenting the .select lines so you can visually see what it's doing.

What exactly happens if I add two dates in VBA

Please help me what happend here- I know it is stupid but I want to know.
The output of the below code is April-18-2105. How did it pop up?
Private Sub CommandButton1_Click()
Dim firstDate As Date, secondDate As Date
firstDate = DateValue("Jun 19, 2010")
secondDate = DateValue("oct 29,1994")
MsgBox (firstDate + secondDate)
End Sub
Thanks in advance!
Dates are actually stored as numbers, so if we look at the numeric value for these dates:
CLng(datevalue("Jun 19, 2010")) '// 40348
CLng(datevalue("oct 29, 1994")) '// 34636
and add them together:
40348 + 34636 = 74984
and convert that number back to a date:
CDate(74984) '// 18/04/2105
Because it's 74,984 days after 00/01/1900
dates are numbers, formatted as dd/mm/yyyy, I think its the days from 31/12/1899, so that's what's happening. The result is 40348+34636=74984, which is 18/04/2105.
Excel stores the date as the number days after a specified date. As such the integer representing the date of 2010/06/19 is 40348 and the integer representing 1994/10/29 is 34636. When you add those integers together you get 74984 which is the integer that represents 2105/04/18.
The reference date does vary from mac to windows. I am running on windows and I did not change my reference date settings, That is where those integers came from. Mac uses January 2nd 1904 as day 1 and Windows uses January 1 1900 as day 1.

Date comparison is incorrect

This is just part of a vba code I am writing and simple date comparison is not working. I have one sheet with tons of data and the vba code creates a pivot table. The code runs fine and does filter out all the past dates but it does not filter out (Feb 3 and Feb 4) for some reason (today is Feb 29). It filters out all the other Feb dates properly but its just those two dates. Anyone know what is wrong?
With ActiveSheet.PivotTables("pivottable1").PivotFields("issuedate")
For Each pi In .PivotItems
If pi < Date Then
pi.Visible = False
End If
Next pi
End With
Have you checked that the column type is a date and not a string? Maybe try CDate(pi)?
If that doesn't work please post the dates that aren't working - maybe by doing a Debug.print(pi).