I reproduced the behavior and suspect the cause is that x and y are declared as Variant. The Format documentation never states that the input is passed ByVal, so the argument is likely passed ByRef. During execution, Format implicitly casts the value, and because of ByRef, x gets changed.
A simple helper function that takes the argument ByVal avoids this issue and works as expected.
Public Function SafeFormat(ByVal v As Variant, Optional ByVal fmt As String = vbNullString) As String
SafeFormat = Format$(v, fmt)
End Function
And if you declare the variable as a basic data type (e.g., Integer, Double, String or even date), the issue does not occur.
Dim x As Date, y As Date
x = Empty ' Be aware: Implict conversion in this line now
Debug.Print TypeName(x), TypeName(y), IsEmpty(x)
y = Format(x, "0")
Debug.Print TypeName(x), TypeName(y), IsNull(x)
This works fine as well.
Dim x , y
x = Empty
Debug.Print TypeName(x), TypeName(y), IsEmpty(x)
y = SafeFormat(x, "0")
Debug.Print TypeName(x), TypeName(y), IsNull(x)
PS If you want to force a copy or an explicit conversion without a helper function, use Format(CVar(x), "0") instead which documents the intent more clearly.
PPS I am not saying that one can really assign Empty to a basic data type. The basic variable types all have a default value and VBA does a lot of implcit conversions. The conversions might be misleading.
Further reading
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/format-function-visual-basic-for-applications
https://learn.microsoft.com/en-us/office/vba/language/reference/keywords-visual-basic-for-applications (Description Empty)
Empty Used as a Variant subtype that indicates an uninitialized variable value.
Debug.Print xnow returnsNull(on my end (Win10 MS365 both 64bit)). So you're asking: "How on earth did x become Null when I didn't do anything to it, or did I?"?Variantwhere a lot of implicit conversions are ongoing.