VB6 - VConvert, A Class for Locale-Specific Data Conversions
There are times when you need another option for wading through the localization minefield.
There are many things in VB6 that are locale-aware, such as CStr, CSng, CDate, Print #, etc. When you need to bypass this and use "universal" (invariant) locale conversion there are always the Str$() and Val() functions but these come with some baggage such as forcing numbers through a specific type which can result in loss of precision.
There is another option, and this one lets you use the invariant locale or even a specific locale for a wide range of data types.
While there is some overhead because it uses Variants, most of the time the benefits outweigh this cost. And it can still be faster (and less prone to bugs) than a lot of alternative logic people whang together to try to do the same thing.
I have wrapped it as a class here, but it is just an API call that you could inline just as well with care. I find the class convenient because usually I just set the locale I want once and then I can do a number of conversions without the need to respecify it every time.
Code:
Option Explicit
'
'VConvert
'--------
'
'A VB6 class used to convert between Variant types using a specific
'locale instead of the current program locale.
'
'This is most useful with LOCALE_INVARIANT for non-String typed data
'that is perisisted or communicated as String data. This avoids
'cross-cultural factors related to language, the decimal point
'character, etc.
'
'It can also be used with conversions of data between a user
'interface and data where your code assumes a fixed locale and you
'want to insist users work in that locale even when the user locale
'is an entirely different one. Note that this is not a recommended
'practice for most software!
'
'Example:
'
' Program always expects dates to be entered in U.S. format,
' i.e. mm/dd/yyyy but some users have U.K. settings which make
' locale-aware conversions such as CDate() expect strings in
' dd/mm/yyyy format.
'
Private Const S_OK As Long = 0
Private Const VARIANT_ALPHABOOL As Long = &H2&
Private Const VARIANT_LOCALBOOL As Long = &H10&
Public Enum LCIDs
'Add more as you need them here:
LOCALE_INVARIANT = 127&
End Enum
Private Declare Function VariantChangeTypeEx Lib "oleaut32" ( _
ByRef vargDest As Variant, _
ByRef varSrc As Variant, _
ByVal desiredlcid As Long, _
ByVal wFlags As Integer, _
ByVal vt As VbVarType) As Long
Public LCID As Long
'Default property:
Public Property Get Convert(ByVal Value As Variant, ByVal ToType As VbVarType) As Variant
If VariantChangeTypeEx(Convert, _
Value, _
LCID, _
VARIANT_ALPHABOOL _
Or VARIANT_LOCALBOOL, _
ToType) <> S_OK Then
Err.Raise 5, TypeName(Me), "Conversion failed"
End If
End Property
Private Sub Class_Initialize()
LCID = LOCALE_INVARIANT
End Sub
The LCIDs Enum is really just there for the LOCALE_INVARIANT constant, but you can add specific locales to the list as well if you frequently require them.