Override VBA's Now() function - excel

Is there a way to override Now() in VBA for testing purposes? Something like this here - What's a good way to overwrite DateTime.Now during testing?, but for VBA.
Thus, I would need Now() to return a predefined value and not the current PC time.
What I do not want is something like this:
Option Explicit
Public Function NowDefined() As Date
'NowDefined = Now()
NowDefined = Format("2016-01-15 15:01:01", "yyyy-MM-dd hh:mm:ss")
End Function
and simply changing in the whole code Now() to NowDefined().

Rather than creating a String variable and then making Excel try to cast it to a Date, you would be better off generating the actual date to start with:
Function Now() As Date
Now = DateSerial(2016, 1, 15) + TimeSerial(15, 1, 2)
End Function

Vityata's answer works, but it is a bit fragile and can get cumbersome: you must remember to remove or comment out the entire function declaration when you're done testing; and put it back in whenever you need to do more testing... and then remember to remove it again when you release... etc.
I'd do something like this:
Const IN_TESTING_MODE As Boolean = True ' Set this to false when done testing
Function Now() As Date
If IN_TESTING_MODE Then
Now = ... 'whatever date you want
Else
Now = VBA.Now() ' back to default behavior
End If
End Function
Here you only have to change one thing to go in and out of testing mode: the value of the constant IN_TESTING_MODE. You can reuse this constant in other functions as well for which you want a different behavior while testing.

Actually this works:
Option Explicit
Public Function Now() As Date
Now = Format("2016-01-15 15:01:01", "yyyy-MM-dd hh:mm:ss")
End Function

Related

Iterating numbers within a string (Matlab)

In Matlab I am trying to achieve the following:
I need to provide an end date, which I would like to iterate forward by quarter in the format:
'1970q1'
For this I have made a loop.
for yy=1970:1971
for jj=1:4
fprintf('''%dq%d''',(yy),(jj))
end
end
However, when I set enddate=fprintf
for yy=1970:1971
for jj=1:4
enddate=fprintf('''%dq%d''',(yy),(jj))
end
end
within the loop, it does not store the end date as what the fprintf output is, but something else. The way the end date should be stored is:
enddate='1970q1'
You should use sprintf function for creating strings instead of fprintf that writes text to file.
In your case, if you want to save all the enddate values you should save it in a vector:
enddate = [];
for yy=1970:1971
for jj=1:4
enddate=[enddate sprintf('''%dq%d''',(yy),(jj))];
end
end

Excel vba : Convert Unix Timestamp to Date Time

I know this has been asked quite a bit, but for some reason none of the solutions seem to work for me.
I have a unix time stamp (for example purposes use 1637402076084)
On my excel sheet I can convert that fine using
= (C2/ 86400000) + DATE(1970,1,1)
However I want to do this in my VBA code as there's a lot of data and I prefer doing it all in an array then applying my array to the sheet (for performance purposes)
However in my code I'm trying to use dateAdd
DateAdd("s", 1637402076084#, "1/1/1970 00:00:00")
but I get an overflow error
I'm assuming this is because the unix timestamp is too big? But it's one that gets returned from an api call and is a geniune one (as demonstrated by the formula) but I'm not sure why my code isn't working.
There are two types of UNIX timestamps. 10 digits and 13 digits. The function you try using is for 10 digits type. To convert the 13 digits type, you should create another function, exactly as you use in the cell:
Function fromUNIX13Digits(uT) As Date
fromUNIX13Digits = CDbl(uT) / 86400000 + DateSerial(1970, 1, 1)
End Function
And test it as:
Sub testFromUNIX13()
Debug.Print fromUNIX13Digits("1637402076084")
End Sub
For 10 digits type, you can use:
Public Function fromUnix10(ts) As Date
fromUnix10 = DateAdd("s", CDbl(ts), "1/1/1970")
End Function
And test it using:
Sub testFromUnix10()
Debug.Print fromUnix10("1651680385")
Debug.Print Format(fromUnix10("1651680385"), "yyyy/mm/dd hh:nn:ss")
End Sub
Or build a function able to deal with both types:
Function FromUNIX(uT) As Date
If Len(uT) = 10 Then
FromUNIX = DateAdd("s", CDbl(uT), "1/1/1970")
ElseIf Len(uT) = 13 Then
FromUNIX = CDbl(uT) / 86400000 + DateSerial(1970, 1, 1)
Else
MsgBox "No UNIX timestamp passed to be converted..."
End If
End Function
And test it using:
Sub testFromUnix_()
Dim x As String, y As String
x = "1637402076084"
y = "1651680385"
Debug.Print FromUNIX(x)
Debug.Print FromUNIX(y)
End Sub

chanaging an IF and Weekday formula into a vba

I need help to change the following function into VBA code. This will be part of a larger code.
IF((WEEKDAY($B12)=7),$I12,"")
There are probably more than 5 ways to do what you want, depending on what exactly do you need. One of these ways is to build a simple custom formula like this:
Public Function changingIfAndWeekday() As Variant
Application.Volatile
If Weekday(Range("B12")) = 7 Then
changingIfAndWeekday = Range("I12")
Else
changingIfAndWeekday = ""
End If
End Function
You could also do it like so (if you want the result on cell C12):
Sheet1.range("C12").value = "=IF(Weekday(Sheet1.range("B12").value = 7),Sheet1.range("I12").value,"")
You could also do it like so (if you want the result on a variable):
Variable = "=IF(Weekday(Sheet1.range("B12").value = 7),Sheet1.range("I12").value,"")

Now() is giving an error

I am getting an error in the below code.
Dim CurrentTime As Date
CurrentTime = Format(Now(), "hh:mm AM/PM")
If CurrentTime = ActiveSheet.Range("I1") Then
Call SendEMail
End If
When the time is right, then the macro is debugging and Now is highlighted.
Could anyone solve this problem?
You are not getting an actual error are you? It is just not working as expected.
Matt Cremeens has identified your issue I believe, you have declared CurrentTime as a date data type. A date data type stores a number representing a time/date, however you are asking for it to store string information (AM/PM) too which is can't so it is getting stripped out.
The results is cell one may hold a value like '10:30 AM' but the Format(Now(), "hh:mm AM/PM") code going into the Date variable is resulting in '10:30:00', so the two are never matching as strings. Copy as Matt has suggested and this should work (Dim CurrentTime As String).
Better yet, use the date comparison function DateDiff:-
If DateDiff("s",ActiveSheet.Range("I1"),Time()) > 0 then
SendEmail
End If
This is saying if the time now is greater than the value in I1 (to the second) then run SendEmail.
I don't have the environment to test the solution right now but from what I remember you don't need the brackets in 2007 and also you don't need the format.
Try the following code and see if that fits your need:
If Hour(Now) = ActiveSheet.Range("I1") Then
(...)
End If

Excel VBA's Date() function acting up

VBA is complaining about something but I don't know what that is.
My code:
Sub datesnstuff()
Const today = Now()
Const yesterday = Date(Year(today),Month(today),Day(today) - 1)
End Sub
And it gives me the following error:
Compile error:
Expected: )
I think it is clear what I want it to do, but Excel is being a pain. It won't even let me use Date(2015,1,1).
Any help would be appreciated.
Date is a property and does not accept parameters.
You want DateSerial().
The Date() function does not take any parameters, and returns the current system date. Try:
yesterday = DateAdd("d", -1, today)
Also, you cannot declare a Const with a function on the right hand side of the = sign. It must be a constant value.

Resources