Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Day() return 30 on invalid input?

Tags:

vba

This is a problem I discovered, then solved, myself and since I couldn't find a SO question on the topic, I figured I'd create one for future reference.

I accidentally wrote

debug.Print day(ow)

Instead of

debug.Print day(now)

To my surprise, rather than throwing an error, I instead got the following result:

debug.Print day(ow)
 30 

Why doesn't it throw an error when given an un-initialised variable as input?

like image 767
Kaz Avatar asked Jun 06 '16 15:06

Kaz


2 Answers

Unless you write Option Explicit at the top of your module, VBA allows you to create variables spontaneously (as Variant types) at the first point of use.

Such variables are effectively zero-initialised.

So day(ow) is equivalent to day(0) which evaluates to 30. (Corresponding to 30-Dec-1899).

like image 99
Bathsheba Avatar answered Nov 20 '22 01:11

Bathsheba


The simple answer is default values.

The following result is illustrative:

debug.Print day(0)
 30 

Why? Because Day(0) in the VBA Calendar is the date 30/12/1899. Demonstrated by the following:

debug.Print format(Cdate(0), "dd/mm/yyyy")
30/12/1899

Unless you write Option Explicit at the top of your module, VBA allows you to create variables spontaneously (as Variant types) at the first point of use.

When a variable is created (but not set) it is set to its' default value. Sample Default Values:

Long --- 0 (Same for other numerics, including Date, Integer, Byte, Double etc.)
Boolean --- False (which, in VBA's permissive type system, can be coerced to 0)
Variant --- Empty (which can also be coerced to 0)
String --- Zero-Length-String ("") (which, actually, can't be coerced to 0, and will throw an error if you try to print Day(""))
Any Object --- Nothing

So, if you write Debug.Print Day(Var) and Var is any numeric data type, or a Boolean, or a Variant (or never declared in the first place) then this will be coerced to Day(0) which gives the output of 30 as seen above.


In the specific situation in the question:

VBA recognises ow as an undeclared variable, so it creates it (and initialises it to a Variant data type) and passes it to Day(). Since it is a Variant, it has the initial value Empty which is then coerced to 0, resulting in Day(0) which returns 30.

like image 37
Kaz Avatar answered Nov 20 '22 01:11

Kaz