Converting
precision values with strings
by Pascal “2BallzOnFire” vd Heiden.
Applies to:
Visual Basic 5
and Visual Basic 6
Converting
a String to and from Single or Double is
used in most applications. Or you may
want to use it to round/format a value
in combination with the Format function.
Converting Strings to/from precision
values is not easy if you want to do it
the right way.
The
CSng function can convert String into a
Single and the CDbl function from String
to Double. However, these functions come
with a bug in relation to the Regional
Settings of the system. This
documentation will describe the problems
with CSng and CDbl and how to solve
them.
Note:
You can also use Val to solve the
problems that come with CSng and CDbl
but if you need to convert, for example
100 strings, Val is extremely slow !!!
Regional
Settings or what?
Regional
Settings are used by Visual Basic when
converting from and to precision values.
Regional Settings are different on each
system over the world, and so is the
conversion of precision values with
Strings. This can be usefull when
creating an application which has to
show the user a value using the Regional
Settings, but it can be a pain in the
ass if you are transferring precision
values (through internet, with files,
etc.) from one computer to another.
Creating
a String from a precision value is not
such a problem, at least, if you like to
make use of the Regional Settings…
Dim
MyStr
as
String
Dim
MyVal
as
Single
MyVal
=
12.345
MyStr
=
MyVal |
|
|
|
That
will do the job (you might want to use
CStr for explicit conversion). The
String MyStr will now contain a
“string-version” of MyVal, but
formatted with the Regional Settings’
Currency Symbol. The Currency Symbol is
usually a dot for systems configured as
English (default), but other countries
have other Currency Symbols (comma, for
example).
When
converting the String back to Single or
Double, the use of the Currency Symbol
differs in VB5 and VB6. In VB5, the
Curreny Sumbol is used, and so your
Strings that you want to convert to
Single or Double must use that Currency
Symbol. Lets take a look what would
happen with different Currency
Symbols…
DotString
=
“34.567”
CommaString
=
“34,567”
DotSingle
=
CSng(DotString)
CommaSingle
=
CSng(CommaString) |
|
|
|
For
Visual Basic 5:
When
we use a dot as Currency Symbol,
DotSingle will be 34.567 and CommaSingle
will be 34567. When we use a comma as
Currency Symbol, DotSingle will be 34567
and CommaSingle will be 34.567. This
shows that VB5 uses the Regional
Settings correctly on the conversions.
Lets see what VB6 thinks about this…
For
Visual Basic 6:
When
we use a dot as Currency Symbol,
DotSingle will be 34.567 and CommaSingle
will be 34567, just like with VB5. When
we use a comma as Currency Sumbol, both
DotSingle and CommaSingle will be 34567
! Visual Basic 6 ignores the Regional
Settings and does not use decimals at
all, unless the Currency Symbol is a dot
!!!
What
are you going to do about that?
Nothing.
We’ll have to use a “workaround”
here. Now you have to choose if you want
to make use of the Currency Symbol or
not.
When
you like to use the Currency Symbol, you
can write a DLL in VB5 to do the
conversion for your VB6 application, or
build your entire application in VB5.
If
you don’t like to use the Currency
Symbol, or your application doesn’t
need it, you can use a small piece of
code to change the Currency Symbol
temporarely and do your conversion. For
fullscreen applications, like games, you
can change the Currency Symbol at
startup and restore the old symbol at
shutdown. For desktop applications, you
will have to consider yourself when to
change/restore the symbol. (keep in mind
that applications in background may not
like the Currency Symbol to change while
they are doing their conversions using
the Currency Symbol !)
Here
is some code to receive and/or change
the Currency Symbol.
'//
API
functions
needed
to
get/change
the
Currency
Symbol
'//
(note
that
they
each
API
should
be on
one
line!)
Declare
Function
GetLocaleInfo
Lib
"kernel32"
Alias
"GetLocaleInfoA"
(ByVal
Locale
As
Long,
ByVal
LCType
As
Long,
ByVal
lpLCData
As
String,
ByVal
cchData
As
Long)
As
Long
Declare
Function
SetLocaleInfo
Lib
"kernel32"
Alias
"SetLocaleInfoA"
(ByVal
Locale
As
Long,
ByVal
LCType
As
Long,
ByVal
lpLCData
As
String)
As
Long
Declare
Function
GetUserDefaultLCID%
Lib
"kernel32"
()
'//
Constants
used
Private
Const
LOCALE_SDECIMAL
=
&HE
'//
Function
to get
the
Currency
Symbol
from
the
Regional
Settings
Public
Function
GetCurrencySymbol()
As
String
Dim
Symbol
As
String
Dim
iRet1
As
Long
Dim
iRet2
As
Long
Dim
lpLCDataVar
As
String
Dim
Pos As
Integer
Dim
Locale
As
Long
'//
Get
the
Local
ID
Locale
=
GetUserDefaultLCID()
'//
Get
the
Local
info
iRet1
=
GetLocaleInfo(Locale,
LOCALE_SDECIMAL,
lpLCDataVar,
0)
'//
Get
the
symbol
from
the
Local
info
Symbol
=
String$(iRet1,
0)
iRet2
=
GetLocaleInfo(Locale,
LOCALE_SDECIMAL,
Symbol,
iRet1)
Pos
=
InStr(Symbol,
Chr$(0))
If
Pos
> 0
Then
Symbol
=
left$(Symbol,
Pos -
1)
'//
Return
the
symbol
GetCurrencySymbol
=
Symbol
End
Function
'//
Procedure
to
change
the
Currency
Symbol
Public
Sub
SetCurrencySymbol(Symbol
As
String)
Dim
Locale
As
Long
Dim
iRet1
As
Long
'//
Get
the
Local
ID
Locale
=
GetUserDefaultLCID()
'//
Change
the
symbol
iRet1
=
SetLocaleInfo(Locale,
LOCALE_SDECIMAL,
Symbol)
End
Sub |
|
|
|
Place
this code in a Module and you can use
GetCurrencySymbol and SetCurrencySymbol
to receive/change the Currency Symbol.
Documentation
by Pascal “2BallzOnFire” vd Heiden,
owner and programmer of XODE Multimedia.
XODE Multimedia, www.xodemm.com
Pascal vd Heiden, xodemm@hotmail.com
References:
MSDN article Q198098 - PRB: CSng/CDbl
Not Using Regional Settings…
See
also:
MSDN article Q145695 - PRB: Error
Converting String to… When Using
"%"
MSDN article - Writing International
Code in Visual Basic
|