When one assigns a Variant containing a string value to a floating point variable Delphi calls VarToDoubleAsString to do the conversion, which in turn uses the OS settings for decimal and thousand separator (via VarR8FromStr). This is problematic if one has to change SysUtils.DecimalSeparator
and SysUtils.ThousandSeparator
. For example run the following program:
program VarStrToFloat;
{$APPTYPE CONSOLE}
uses
SysUtils,
Math;
function FormatFloatUsingDelphiSettings(Value: Extended): string;
begin
Result := FormatFloat('#,##0.00', Value);
end;
procedure Test(const AMsg: string);
var
r1, r2: Extended;
s1, s2: string;
v: Variant;
begin
r1 := 5432.1;
s1 := FormatFloatUsingDelphiSettings(r1);
v := s1; // <== conversion uses OS settings
r2 := v;
s2 := FormatFloatUsingDelphiSettings(r2);
Write(AMsg: 8, s1: 10, s2: 10, ' ');
if SameValue(r1, r2) then
Writeln('OK')
else
Writeln('FAIL');
end;
procedure SwapEm;
var
tmp: Char;
begin
tmp := DecimalSeparator;
DecimalSeparator := ThousandSeparator;
ThousandSeparator := tmp;
end;
begin
Test('Default');
SwapEm;
Test('Changed');
Readln;
end.
The first test works fine, the second one fails.
Is there a way to make the Variant conversion use SysUtils.DecimalSeparator
and SysUtils.ThousandSeparator
?
SetVariantManager
), but this was removed in recent releases. Well, it's still there, it just does nothing. I need to replace_VarFromCurr
for reasons which are too complex to explain in this comment (QC#87786). You could achieve what you need by replacing_VarToDouble
which would be possible but rather more difficult (involves some hooking). Of course, there may be an official way to do this that I'm not aware of..... – Taddeusz