Link to home
Start Free TrialLog in
Avatar of gfurst
gfurst

asked on

How do I fix the decimal separator in VB 6.0 different from Windows 6.setting

Can I fix in VB .0 the decimal separator to "." when the Windows Regional setting is "," ,  without changing the Windows setting?  If so, how do I do it

Thank you
Avatar of mdougan
mdougan
Flag of United States of America image

Not sure what you are asking.  Inside of VB6, when doing math calculations for example, VB6 always uses a decimal point (period) as the decimal separator.  The only time the localization/regional settings come into play is when formatting the data for display and using the "named" format options (such as Currency).  I believe that you can override the regional settings by simply using custom format strings rather than the named format options to get it to display any way you want.
You can override the locale specific formatting using GetNumericFormat API which allows you to specify your decimal and thousands separators.

http://www.ex-designz.net/apidetail.asp?api_id=213
If you mean e.g. displaying "0,5" as ",5" then format(0.5,"#.#") returns ",5"

But if you mean swapping "." with "," for displaying numbers
without changing the Windows setting (when "," is the decimal point) then:

Public Function Dbl2Str(Number As Double) As String
    Dim strNumber As String
    strNumber = CStr(Number)
    strNumber = Replace(strNumber, ".", Chr(1))
    strNumber = Replace(strNumber, ",", ".")
    Dbl2Str = Replace(strNumber, Chr(1), ",")
End Function


VK, that code does a swap of the . and , regardless of the locale or windows settings.  It would produce the reverse of what was desired if the Windows locale setting already specified US style numeric strings.

Also, CStr will never insert thousands separators.

<<when the Windows Regional setting is "," ,  without changing the Windows setting?  If so, how do I do it>>

I'm assuming:
Qfurst has a windows where the "," ist the decimal separator.
He does not intend to change that.

<<Can I fix in VB .0 the decimal separator to ".">>

This is the most confusing part of the question. I'm assuming:
Qfurst want's to "prevent" the localization/regional conversion when a string is putted out (screen, printer, ...)

<<Also, CStr will never insert thousands separators.>>

Yes, i know but that wasn't intended. Does qfurst need that?
>Qfurst has a windows where the "," ist the decimal separator.
He does not intend to change that.

Right.  But *if* the program is ever run on a different machine, where US locale is used, it will cause it to use a comma instead of a period for the decimal.  A more secure way to override the locale settings is to use the API I posted above.  I assume that the word "fix" means he doesn't want it to switch in every locale.

>Yes, i know but that wasn't intended. Does qfurst need that?

Unclear, but your code does a swap of thousands and decimal signs where no swap is possible, because no thousands character ever appears.  

GetNumberFormat returns an error because "," isn't allowed in lpValue.
(ByVal lpValue As String) requires a string as parameter

<<where no swap is possible, because no thousands character ever appears>>
the replace function does nothing when nothing to replace is found.

The code from the link with qfurst's os-setting and an example which fails:

also
GetNumberFormat ByVal 0&, 0, Str(300243.24), NF, Buffer, Len(Buffer)
would fail!
Private Type NUMBERFMT
    NumDigits As Long ' number of decimal digits
    LeadingZero As Long ' if leading zero in decimal fields
    Grouping As Long ' group size left of decimal
    lpDecimalSep As String ' ptr to decimal separator string
    lpThousandSep As String ' ptr to thousand separator string
    NegativeOrder As Long ' negative number ordering
End Type
 
Private Declare Function GetNumberFormat Lib "kernel32" Alias "GetNumberFormatA" (ByVal Locale As Long, ByVal dwFlags As Long, ByVal lpValue As String, lpFormat As NUMBERFMT, ByVal lpNumberStr As String, ByVal cchNumber As Long) As Long
 
Private Sub Form_Load()
    Dim Buffer As String, NF As NUMBERFMT
    Buffer = String(255, 0)
    With NF
        .NumDigits = 3
        .Grouping = 3
        .lpDecimalSep = ","
        .lpThousandSep = "."
        .NegativeOrder = 0
    End With
    GetNumberFormat ByVal 0&, 0, "300,243.24", NF, Buffer, Len(Buffer)
    MsgBox Buffer
End Sub

Open in new window

If a general solution converting from any locale setting to US setting is wished:
Private Enum LocaleStringConstants
    locCurrency = &H14
    locCurSymbol = &H15
    locDate = &H1D
    locDecimal = &HE
    locList = &HC
    locMoneyDecimal = &H16
    locMoneyThousands = &H17
    locNegative = &H51
    locPositive = &H50
    locThousands = &HF
    locTime = &H1E
End Enum
 
Private Declare Function GetUserDefaultLCID Lib "kernel32" () As Long
Private 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
 
Private Function LocaleString(Info As LocaleStringConstants) As String
    Dim nLocale As String
    Dim nLen As Long
    '
    nLocale = Space(10)
    nLen = GetLocaleInfo(GetUserDefaultLCID(), Info, nLocale, 10)
    LocaleString = Left(nLocale, nLen - 1)
    '
End Function
 
Public Function Dbl2USNumberStr(Number As Double) As String
    Dim strNumber As String
    '
    strNumber = CStr(Number)
    Select Case True
        Case LocaleString(locMoneyThousands) <> "."
        Case LocaleString(locMoneyDecimal) <> ","
        Case Else
            strNumber = Replace(strNumber, ".", Chr(1))
            strNumber = Replace(strNumber, ",", ".")
            strNumber = Replace(strNumber, Chr(1), ",")
    End Select
    Dbl2USNumberStr = strNumber
    '
End Function
 
Private Sub Form_Load()
    MsgBox Dbl2USNumberStr(10000 / 7)
End Sub

Open in new window

You're right that GetNumberFormat isn't a good fit because of the need to have the number as a string already.  

I think your last post is on the right track, but I'm getting commas for decimals when using a French locale.
Here is a solution from danaseaman that seems pretty complete, if more than a little complex:

http:Q_21841979.html#a16632954

May be overkill for the question author... (Would be nice to hear from the question author, but it doesn't look like that's going to happen.)
FYI, as far as dates are concerned, only the Named Formats such as Short or Long are affected by the regional settings in VB6... if you use   label1.Caption = Format(Now(), "MM-dd-yyyy") you would get 01-26-2009 even if you select French Standard Regional Setting which would have a default short date format of  dd/MM/yy

I thought the same worked for formatting decimals (ie, only named formats such as currency were affected by the regional settings, however, a quick test shows that's not the case).

I would suggest, rather than get too fancy, just write your own MyFormat() procedure that would parse a typical numeric format string and search and replace the regional characters with the desired characters... for the French standard, that would be to replace a comma with a period for the decimal separator and replace a space with a comma for the digits separator.
You are all right, and we should hear something obout the author too.
I think that it is the topic what us make so "ambitious" :-)
ASKER CERTIFIED SOLUTION
Avatar of ee_auto
ee_auto

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial