Search code examples
vbawinapivba7

How can I provide Nothing (Null-Pointer) to a user defined type in VBA for using it as Windows API function argument?


In VBA, I declared a Windows API function that requires a pointer to a struct argument. For representing this struct I created a Public Type and declared the function parameter as ByRef.

Now, this struct pointer may be null, so I tried to assign Nothing to a variable of my UDT, but that doesn't work.

How can I make this work?

Here are the basic excerpts from my code:

Private Declare PtrSafe Function GetNumberFormatEx& Lib "Kernel32" ( _
  ByVal lpLocaleName As LongPtr, _
  ByVal dwFlags&, _
  ByVal lpValue As LongPtr, _
  ByRef lpFormat As NumberFormat, _
  ByVal lpNumberStr As LongPtr, _
  ByVal cchNumber& _
)


Public Type NumberFormat
  NumDigits As Integer
  LeadingZero As Integer
  Grouping As Integer
  lpDecimalSep As LongPtr
  lpThousandSep As LongPtr
  NegativeOrder As Integer
End Type


Public Function FormatNumberLocale$(srcValue As Double, lcid$, Optional flags& = 0, Optional customFormat$ = vbNullString)
  Dim buffer$
  Dim charCount&
  Dim numFormat As NumberFormat

  buffer = String(100, 0)
  'numFormat = Nothing    ' THIS DOESN'T WORK !!!
  charCount = GetNumberFormatEx(StrPtr(lcid), flags, StrPtr(Str$(srcValue)), numFormat, StrPtr(buffer), 100)
  
  If charCount > 0 Then FormatNumberLocale = Left$(buffer, charCount)
End Function

Edit

I changed the declaration to:

Private Declare PtrSafe Function GetNumberFormatEx& Lib "Kernel32" ( _
  ByVal lpLocaleName As LongPtr, _
  ByVal dwFlags&, _
  ByVal lpValue As LongPtr, _
  ByVal lpFormat As LongPtr, _
  ByVal lpNumberStr As LongPtr, _
  ByVal cchNumber& _
)

and called the function like this:

...
Dim value$

buffer = String(100, 0)
value = Str$(srcValue)
charCount = GetNumberFormatEx(StrPtr(lcid), flags, StrPtr(value), CLngPtr(0&), StrPtr(buffer), 100)

But even when calling it with basic parameters, like ?FormatNumberLocale(123,"en"), charCount is always 0, and Err.LastDllError always returns 87 (0x57): ERROR_INVALID_PARAMETER.

Any ideas?


Solution

  • The idiomatic VBA way of passing NULL for a struct pointer is declaring the argument as ByRef As Any:

    Private Declare PtrSafe Function GetNumberFormatEx Lib "Kernel32" ( _
      ByVal lpLocaleName As LongPtr, _
      ByVal dwFlags As Long, _
      ByVal lpValue As LongPtr, _
      ByRef lpFormat As Any, _
      ByVal lpNumberStr As LongPtr, _
      ByVal cchNumber As Long _
    ) As Long
    

    and then passing either a struct variable (numFormat in your example) or ByVal 0& for null.