Final solution for filtering dates

YasserKhalil
PlatinumLounger
Posts: 4931
Joined: 31 Aug 2016, 09:02

Final solution for filtering dates

Post by YasserKhalil »

Hello everyone
I have a problem that faces me many times and each time is solved in different way .. I have no fixed way to solve it
It the problem of DATES with FILTER ...
I think this is related to the regional settings but I need a final solution for it
Here's an example (taken from another thread here)

Code: Select all

Sub Test()
    Dim dFrom As Date
    Dim dTo As Date

    With WorksheetFunction
        dFrom = .EoMonth(Date, 1) - Day(.EoMonth(Date, 1)) + 1
        dTo = .EoMonth(Date, 1)
    End With

    With Sheets("Sheet1").Cells(1).CurrentRegion
        .Parent.AutoFilterMode = False

        dFrom = DateSerial(Year(dFrom), Month(dFrom), Day(dFrom))
        dTo = DateSerial(Year(dTo), Month(dTo), Day(dTo))

        .AutoFilter 3, ">=" & dFrom, xlAnd, "<=" & dTo
    End With
End Sub
using dateserial doesn't work well .. I don't know why?
When running the code I got empty rows although there are dates ....

Thanks advanced for help
You do not have the required permissions to view the files attached to this post.

User avatar
HansV
Administrator
Posts: 78620
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Final solution for filtering dates

Post by HansV »

The lines

Code: Select all

        dFrom = DateSerial(Year(dFrom), Month(dFrom), Day(dFrom))
        dTo = DateSerial(Year(dTo), Month(dTo), Day(dTo))
don't change the values of dFrom and dTo. They simply assign the same value they already had. So there is no point at all to use these lines.
Best wishes,
Hans

User avatar
HansV
Administrator
Posts: 78620
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Final solution for filtering dates

Post by HansV »

You can try

Code: Select all

        .AutoFilter 3, ">=" & CLng(dFrom), xlAnd, "<=" & CLng(dTo)
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4931
Joined: 31 Aug 2016, 09:02

Re: Final solution for filtering dates

Post by YasserKhalil »

Thanks a lot Mr. Hans
The idea of this thread is that I need final solution

In some cases just using CDate solve the problem.. Sometimes using Clng solve it
Sometime using Dateserial solve it .. sometimes using .Value2 as for dates in ranges solve it
Sometimes nothing solve this problem
How can I control and solve such a problem completely?

YasserKhalil
PlatinumLounger
Posts: 4931
Joined: 31 Aug 2016, 09:02

Re: Final solution for filtering dates

Post by YasserKhalil »

And why when using Clng like that

Code: Select all

        dFrom = CLng(DateSerial(Year(dFrom), Month(dFrom), Day(dFrom)))
        dTo = CLng(DateSerial(Year(dTo), Month(dTo), Day(dTo)))
it doesn't work in that way .. but it is working if I used Clng in the line of filter away from the variable (that's too weird for me)

User avatar
HansV
Administrator
Posts: 78620
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Final solution for filtering dates

Post by HansV »

In the first place, DateSerial(Year(dFrom), Month(dFrom), Day(dFrom)) returns exactly and precisely the same as dFrom, so there is no point whatsoever in using DateSerial(Year(dFrom), Month(dFrom), Day(dFrom)). The only thing is does is slow down your code slightly by performing a senseless calculation.

In the second place, dFrom is a variable of type Date. Even though you use CLng to assign it a value, the result is a date. So you still use a date in the AutoFilter line.
The code that I proposed uses number values in the AutoFilter line. This is similar to Rory's suggestion to use Value2 in this thread. If a cell contains a date, Value2 returns the numeric equivalent of that date, just as if you use CLng.
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4931
Joined: 31 Aug 2016, 09:02

Re: Final solution for filtering dates

Post by YasserKhalil »

Thank you very much for this great explanation .. so in summary the best way is to deal with the numeric value of the dates not with the dates directly
And this would be done by using Value2 if a date was in range and by using CLng if the date was stored in a variable

Thanks a lot Mr. Hans
Best Regards

User avatar
Doc.AElstein
BronzeLounger
Posts: 1499
Joined: 28 Feb 2015, 13:11
Location: Hof, Bayern, Germany

dates.. .Value .Value2 and My Hip HooArrays() :-)

Post by Doc.AElstein »

Hi
I think Excel VBA taking a .Value or a .Value2 in different situations is one of those problems like Excel changing numbers into dates or getting confused in different systems with decimal separators and thousand separators.
You will never get a full solution.
There will always be situations when you have to fiddle / adjust your results to get back to the format you want.

There are a few unsolved oddities in Excel and VBA when it comes to .Value and .Value2, such as:
http://www.eileenslounge.com/viewtopic. ... 87#p196639" onclick="window.open(this.href);return false;

In this case you find that if you use a range object, Rng, as first argument in an Index function to return a range of values as output, then Excel VBA decides to give you .Value2 values for the case of what it sees as dates in the second argument range object.
If you convert that first argument range object, Rng, to an Array of values first via _..
Arr() = Rng.Value
_.. and then use that instead in the Index function, then any range of output returned retains the date string format.

In the codes I was using VBA did not get mixed up with other things, such as Strings, Emptys, number etc. It was able to recognise and preserve that formats in all situations using the Rng or Rng.Value. Just the dates it decided to change to .Value2 in the use of a range.

Excel can be a Bitch sometimes with things like that. :(

I am not too clued up on your specific problem, Yasser, and I have no experience at all with advanced filters ( or even unadvanced ones ) but just to demo what I am talking about, as anything to do with filtering ranges might mess up in the same way as VBA Excel did with me..
Run this simple code on a test range as shown in the screenshot:

Code: Select all

Sub ExcelsABitch()
Dim Rng As Range
 Set Rng = Range("A34:C35")
Dim WotEverIGet As Variant
 Let WotEverIGet = Application.Index(Rng, 1, Array(1, 2, 3))
End Sub
RngAsFirstArgument.JPG : https://imgur.com/WcKn4JM" onclick="window.open(this.href);return false;
RngAsFirstArgument.JPG
Run Code like This To see contants of Array:
(From Excel Alt+F11 to get VB Editor: paste code in Code window)
Put stop at End Sub by clicking in left Margin to get Brown circle.
Run Code. ( click in code and Hit F5 for full run or F8 for step mode )
Highlight WotEverIGet.
Hit Shift+F9 to get Watch Window.
Click on + to reveal contents of Array
PutStopInLeftMargin RunCode Highlight WotEverIGet HitShift+F9.JPG : https://imgur.com/zAVfZhB" onclick="window.open(this.href);return false;




Now the same again with an Array as the first argument:

Code: Select all

Sub ExcelsFunk()
Dim Rng As Range
 Set Rng = Range("A34:C35")
Dim WotEverIGet As Variant
 Let WotEverIGet = Application.Index(Rng.Value, 1, Array(1, 2, 3))
End Sub
RngDotValueArrayAsFirstArgument.JPG : https://imgur.com/CSRc1cz" onclick="window.open(this.href);return false;
RngDotValueArrayAsFirstArgument.JPG
The problem I had back then was that for other reasons I wanted to use a range object rather than an array as the first argument. The problem with Excel VBA returning the .Value2 for the case of a date in the Rng case was a bit of a Bitch.
The problem only occurred with dates
I don’t remember the exact workaround I had at the time, but I think it usually was a bit different in different situations.


Alan

P.s. If you do this code then you get the same results as the first code, so that is suggesting that VBA takes the .Value2

Code: Select all

Sub ExcelsAWierdo()
Dim Rng As Range
 Set Rng = Range("A34:C35")
Dim WotEverIGet As Variant
 Let WotEverIGet = Application.Index(Rng.value2, 1, Array(1, 2, 3))
End Sub
In a simple case of just wanting a single row as output then this was a workaround, (as you can get a returned range in such a case), but that was not of so much use as I was picking a 2 dimensional array for my output

Code: Select all

Sub WorkaroundSingleRowOutput()
Dim Rng As Range
 Set Rng = Range("A34:C35")
Dim WotEverIGet As Variant
 Let WotEverIGet = Application.Index(Rng, 1, 0).Value
End Sub
' or
Sub IndexReturnsALongRowForMyHipHooArray()
Dim Rng As Range
 Set Rng = Range("A34:C35")
Dim RangeIGet As Range
 Set RangeIGet = Application.Index(Rng, 1, 0)
Dim myArray() As Variant
 Let myArray() = RangeIGet.Value ' myHipHooArray.JPG : https://imgur.com/G4TbRps
End Sub
InterceptionImplicitIntersection.JPG : https://imgur.com/oX5pjxa" onclick="window.open(this.href);return false;
InterceptionImplicitIntersection.JPG
_.___________-
Edit:
P.s. 2: I expect it might never make any difference in your case, but the date as .Value2 is actually held in a Double I think, not a Long. I guess there are two reasons for that
_ Longs end up converted to Doubles I think somewhere along the line anyway
_ I think dates and dates and time are all held somewhere as part of the same thing, so you need Double to get the fraction of the day which is time. You might want to bear that in mind and possibly consider using CDbl rather than CLng, just in case it might make any difference.
You may sometimes get a problem that a date is not recognised as a date and then CDbl or CLng will not work. I have occasionally had this problem. A workaround to that which has sometimes worked has been to do this
Dim dte As Double
dte = CDbl(CDate(SomethingThatLooksToMeLikeADate))

For example in my second code above, Sub ExcelsFunk() , you would need to do
dte = CDbl(CDate(WotEverIGet(1)))
( and note another Excel quirk… That Array , WotEverIGet() , comes from a spreadsheet range( starts at 1 and not 0 )… but unusually is 1 Dimension in this case.…. )
You do not have the required permissions to view the files attached to this post.
Last edited by Doc.AElstein on 15 Mar 2018, 22:38, edited 5 times in total.
I am having difficulty logging in with this account just now.
You can find me at DocAElstein also

YasserKhalil
PlatinumLounger
Posts: 4931
Joined: 31 Aug 2016, 09:02

Re: Final solution for filtering dates

Post by YasserKhalil »

Thanks a lot for your time spent to illustrate and explain all these details. I appreciate that alot
Kind Regards