This sample provides a drop-in ready class module, which you can use in
either Classic VB or VBA to determine the regional settings currently in use.
You have the option to override the user's preferred settings, as well, to
determine what the default regional settings for this machine should be. Also,
you may (hopefully with the user's permission!) change the current user's
preference for regional settings.
The CLocaleInfo class will use Unicode functions by default, when they're
available, and ANSI functions when it finds itself operating under older (Win9x)
platforms. Using this class is extremely simple. For example:
Dim li As CLocaleInfo
Set li = New CLocaleInfo
li.AllowUserOverride = True
Debug.Print Format$(Now, li.LocaleInfo(LOCALE_SLONGDATE))
Note however that there isn't always a direct 1:1 correspondence between VB's
custom formatting strings and those used by Windows. For example, Windows uses
"t" or "tt" to represent "A/P" or "AM/PM", so you can't directly pass
LOCALE_STIMEFORMAT to the native Format function without some massaging of the
results. In order to avoid these messy situations, I added two more functions to
the class which show how to call the API functions GetTimeFormat and
GetDateFormat. These are as simple to use as this:
Debug.Print li.LocaleDate(, , DATE_LONGDATE); " at ";
Debug.Print li.LocaleTime()
All the constants used with the Locale functions are conveniently exposed as
public enumerations. These are available for your inspection:
 |
Public Enum LocaleInfoTypes
LOCALE_ILANGUAGE = &H1 ' language id
LOCALE_SLANGUAGE = &H2 ' localized name of language
LOCALE_SENGLANGUAGE = &H1001 ' English name of language
LOCALE_SABBREVLANGNAME = &H3 ' abbreviated language name
LOCALE_SNATIVELANGNAME = &H4 ' native name of language
LOCALE_ICOUNTRY = &H5 ' country code
LOCALE_SCOUNTRY = &H6 ' localized name of country
LOCALE_SENGCOUNTRY = &H1002 ' English name of country
LOCALE_SABBREVCTRYNAME = &H7 ' abbreviated country name
LOCALE_SNATIVECTRYNAME = &H8 ' native name of country
LOCALE_IDEFAULTLANGUAGE = &H9 ' default language id
LOCALE_IDEFAULTCOUNTRY = &HA ' default country code
LOCALE_IDEFAULTCODEPAGE = &HB ' default code page
LOCALE_SLIST = &HC ' list item separator
LOCALE_IMEASURE = &HD ' 0 = metric, 1 = US
LOCALE_SDECIMAL = &HE ' decimal separator
LOCALE_STHOUSAND = &HF ' thousand separator
LOCALE_SGROUPING = &H10 ' digit grouping
LOCALE_IDIGITS = &H11 ' number of fractional digits
LOCALE_ILZERO = &H12 ' leading zeros for decimal
LOCALE_SNATIVEDIGITS = &H13 ' native ascii 0-9
LOCALE_SCURRENCY = &H14 ' local monetary symbol
LOCALE_SINTLSYMBOL = &H15 ' intl monetary symbol
LOCALE_SMONDECIMALSEP = &H16 ' monetary decimal separator
LOCALE_SMONTHOUSANDSEP = &H17 ' monetary thousand separator
LOCALE_SMONGROUPING = &H18 ' monetary grouping
LOCALE_ICURRDIGITS = &H19 ' # local monetary digits
LOCALE_IINTLCURRDIGITS = &H1A ' # intl monetary digits
LOCALE_ICURRENCY = &H1B ' positive currency mode
LOCALE_INEGCURR = &H1C ' negative currency mode
LOCALE_SDATE = &H1D ' date separator
LOCALE_STIME = &H1E ' time separator
LOCALE_SSHORTDATE = &H1F ' short date format string
LOCALE_SLONGDATE = &H20 ' long date format string
LOCALE_STIMEFORMAT = &H1003 ' time format string
LOCALE_IDATE = &H21 ' short date format ordering
LOCALE_ILDATE = &H22 ' long date format ordering
LOCALE_ITIME = &H23 ' time format specifier
LOCALE_ICENTURY = &H24 ' century format specifier
LOCALE_ITLZERO = &H25 ' leading zeros in time field
LOCALE_IDAYLZERO = &H26 ' leading zeros in day field
LOCALE_IMONLZERO = &H27 ' leading zeros in month field
LOCALE_S1159 = &H28 ' AM designator
LOCALE_S2359 = &H29 ' PM designator
LOCALE_SDAYNAME1 = &H2A ' long name for Monday
LOCALE_SDAYNAME2 = &H2B ' long name for Tuesday
LOCALE_SDAYNAME3 = &H2C ' long name for Wednesday
LOCALE_SDAYNAME4 = &H2D ' long name for Thursday
LOCALE_SDAYNAME5 = &H2E ' long name for Friday
LOCALE_SDAYNAME6 = &H2F ' long name for Saturday
LOCALE_SDAYNAME7 = &H30 ' long name for Sunday
LOCALE_SABBREVDAYNAME1 = &H31 ' abbreviated name for Monday
LOCALE_SABBREVDAYNAME2 = &H32 ' abbreviated name for Tuesday
LOCALE_SABBREVDAYNAME3 = &H33 ' abbreviated name for Wednesday
LOCALE_SABBREVDAYNAME4 = &H34 ' abbreviated name for Thursday
LOCALE_SABBREVDAYNAME5 = &H35 ' abbreviated name for Friday
LOCALE_SABBREVDAYNAME6 = &H36 ' abbreviated name for Saturday
LOCALE_SABBREVDAYNAME7 = &H37 ' abbreviated name for Sunday
LOCALE_SMONTHNAME1 = &H38 ' long name for January
LOCALE_SMONTHNAME2 = &H39 ' long name for February
LOCALE_SMONTHNAME3 = &H3A ' long name for March
LOCALE_SMONTHNAME4 = &H3B ' long name for April
LOCALE_SMONTHNAME5 = &H3C ' long name for May
LOCALE_SMONTHNAME6 = &H3D ' long name for June
LOCALE_SMONTHNAME7 = &H3E ' long name for July
LOCALE_SMONTHNAME8 = &H3F ' long name for August
LOCALE_SMONTHNAME9 = &H40 ' long name for September
LOCALE_SMONTHNAME10 = &H41 ' long name for October
LOCALE_SMONTHNAME11 = &H42 ' long name for November
LOCALE_SMONTHNAME12 = &H43 ' long name for December
LOCALE_SMONTHNAME13 = &H100E ' long name for 13th month (if exists)
LOCALE_SABBREVMONTHNAME1 = &H44 ' abbreviated name for January
LOCALE_SABBREVMONTHNAME2 = &H45 ' abbreviated name for February
LOCALE_SABBREVMONTHNAME3 = &H46 ' abbreviated name for March
LOCALE_SABBREVMONTHNAME4 = &H47 ' abbreviated name for April
LOCALE_SABBREVMONTHNAME5 = &H48 ' abbreviated name for May
LOCALE_SABBREVMONTHNAME6 = &H49 ' abbreviated name for June
LOCALE_SABBREVMONTHNAME7 = &H4A ' abbreviated name for July
LOCALE_SABBREVMONTHNAME8 = &H4B ' abbreviated name for August
LOCALE_SABBREVMONTHNAME9 = &H4C ' abbreviated name for September
LOCALE_SABBREVMONTHNAME10 = &H4D ' abbreviated name for October
LOCALE_SABBREVMONTHNAME11 = &H4E ' abbreviated name for November
LOCALE_SABBREVMONTHNAME12 = &H4F ' abbreviated name for December
LOCALE_SABBREVMONTHNAME13 = &H100F ' abbreviated name for 13th month (if exists)
LOCALE_SPOSITIVESIGN = &H50 ' positive sign
LOCALE_SNEGATIVESIGN = &H51 ' negative sign
LOCALE_IPOSSIGNPOSN = &H52 ' positive sign position
LOCALE_INEGSIGNPOSN = &H53 ' negative sign position
LOCALE_IPOSSYMPRECEDES = &H54 ' mon sym precedes pos amt
LOCALE_IPOSSEPBYSPACE = &H55 ' mon sym sep by space from pos amt
LOCALE_INEGSYMPRECEDES = &H56 ' mon sym precedes neg amt
LOCALE_INEGSEPBYSPACE = &H57 ' mon sym sep by space from neg amt
'#if(WINVER >= 0x0400)
LOCALE_FONTSIGNATURE = &H58 ' font signature
LOCALE_SISO639LANGNAME = &H59 ' ISO abbreviated language name
LOCALE_SISO3166CTRYNAME = &H5A ' ISO abbreviated country name
'#endif /* WINVER >= 0x0400 */
'#if(WINVER >= 0x0500)
LOCALE_IDEFAULTEBCDICCODEPAGE = &H1012 ' default ebcdic code page
LOCALE_IPAPERSIZE = &H100A ' 0 = letter, 1 = a4, 2 = legal, 3 = a3
LOCALE_SENGCURRNAME = &H1007 ' english name of currency
LOCALE_SNATIVECURRNAME = &H1008 ' native name of currency
LOCALE_SYEARMONTH = &H1006 ' year month format string
LOCALE_SSORTNAME = &H1013 ' sort name
LOCALE_IDIGITSUBSTITUTION = &H1014 ' 0 = none, 1 = context, 2 = native digit
'#endif /* WINVER >= 0x0500 */
End Enum
' Time Flags for GetTimeFormatW.
Public Enum LocaleTimeFlags
TIME_NOMINUTESORSECONDS = &H1 ' do not use minutes or seconds
TIME_NOSECONDS = &H2 ' do not use seconds
TIME_NOTIMEMARKER = &H4 ' do not use time marker
TIME_FORCE24HOURFORMAT = &H8 ' always use 24 hour format
End Enum
' Date Flags for GetDateFormatW.
Public Enum LocaleDateFlags
DATE_SHORTDATE = &H1 ' use short date picture
DATE_LONGDATE = &H2 ' use long date picture
End Enum
You may notice an odd addition near the end of the module, in the private
ForceEnumCase routine. All of these enumerated constants are defined within a
conditional compilation block. And, odder still, the test is written such that
the block is never compiled! Why? Doing this forces the VB IDE to maintain
proper-casing on all these constants. Were they only enumerated, if you typed
one manually (rather than choose it from the Intellisense dropdown) and used a
different casing, it would change globally throughout your project. I "can't
imagine what they were smoking" when they made this design decision in Redmond,
can you? Anyway, this trick overrides that idiotic behavior, and doesn't bloat
your final EXE at all. VBA users may want to remove the superfluous routine if
the added bulk hinders their distribution size.