2016-08-07 12 views
1

У меня есть аналогичный случай as in this question.Есть ли функция StrToCurr, которая может работать с тысячами разделителей?

procedure TForm2.FormCreate(Sender: TObject); 
var 
    S: string; 
    C: Currency; 
    FormatSettings: TFormatSettings; 
begin 
    S := '1.000.000,00'; 
    FormatSettings := TFormatSettings.Create; 
    FormatSettings.ThousandSeparator := '.'; 
    FormatSettings.DecimalSeparator := ','; 
    // raises an Exception which is "as designed" as per the documentation 
    C := StrToCurr(S, FormatSettings); 
    ShowMessage(FormatCurr(',0.00', C)); 
end; 

Цитирую Давида:

Так это ошибка передать строку, содержащую разделитель тысяч этой функции.

Итак, есть ли в Delphi встроенная функция, которая будет анализировать валютные строки, содержащие тысячи разделителей?

+0

Газа тысячи SEPS –

+0

ThousandSeparator & DecimalSeparator с использованием только для отображения валюты в надлежащем формате – Zam

+0

@Zam, только 'ThousandSeparator' является чисто декоративным,' DecimalSeparator' является значительным. Вот мои 2 доллара. –

ответ

5

Решение этой конструкции (изъяна) прост: определите свою собственную функцию.

unit MyFixForSysUtils; 

interface 

function StrToCurr(const Str: string): Currency; overload; 
function StrToCurr(Str: string; const FormatSettings : TFormatSettings): Currency; overload; 

implementation 

uses SysUtils; 

function StrToCurr(Str: string; const FormatSettings : TFormatSettings): Currency; 
begin 
    Str:= StringReplace(Str, FormatSettings.ThousandSeparator, '', [rfReplaceAll]); 
    Result:= SysUtils.StrToCurr(Str, FormatSettings); 
end; 

function StrToCurr(const Str: string): Currency; 
begin 
    Result:= StrToCurr(Str, FormatSettings); 
end; 

Если вы убедитесь, что ваш собственный вариант ближе по объему, чем sysutils, то вам не нужно менять код:

uses 
    SysUtils, 
    MyFixForSysUtils, <-- contains the above function 
    .... other units. 

Теперь Delphi будет выбрать фиксированную функцию вместо сломанной один.

Для получения дополнительной информации об этой концепции см: Delphi interposer

+1

Не дизайн дефекта. Совершенно разумный дизайн и один из многих других библиотек. –

+0

Я решил присвоить функции новое имя, потому что я считаю, что проще реорганизовать вызовы функций, а не полагаться на то, что порядок использования остается неизменным. Я также хотел бы избежать глобального загрязнения пространства имен, поэтому я сделал его методом статического класса класса утилиты. –

+0

Большинство компонентов программы используют компоненты базы данных (например, «TDBEdit') в любом случае, и это просто вопрос назначения« DisplayFormat: = », 0,00 ';'.Иногда вам действительно нужна оригинальная функция с фиксированными форматами FormatSettings (то есть текстовыми файловыми интерфейсами). –

4

Вы можете использовать VarCyFromStr из «varutils.pas», который по умолчанию указывает на COM-хелперов VarCyFromStr импортируемого из «oleaut32» в «activex.pas» (который Вам может напрямую использовать).

Если вы знаете, что строка локализована с языковыми настройками системы по умолчанию, вы можете использовать:

var 
    S: string; 
    C: Currency; 
begin 
    S := '1.000.000,00'; 
    if varutils.VarCyFromStr(S, 0, LOCALE_NOUSEROVERRIDE, C) = VAR_OK then 
    ShowMessage(FormatCurr(',0.00', C)) 
    else 

или передать GetThreadLocale для LCID использовать параметры текущего потока.

Если строка локализована по умолчанию, вы можете сделать RTL ее для вас, которая использует эту функцию для преобразования вариантов.

var 
    V: Variant; 
    C: Currency; 
begin 
    V := '1.000.000,00'; 
    C := V; 
    ShowMessage(FormatCurr(',0.00', C)); 

В противном случае вы должны знать, в каком языке строка представляет собой валюту. Пример:

var 
    S: string; 
    C: Currency; 
begin 
    S := '1,000,000.00'; 
    if varutils.VarCyFromStr(S, MAKELCID(LANG_ENGLISH, SORT_DEFAULT), 0, C) = VAR_OK then 
    ShowMessage(FormatCurr(',0.00', C)) 
    else 
    // handle error 
+0

Это хороший кандидат, но для этого требуется использовать WideString и LCID, поэтому я буду придерживаться решения 'Replace()'. –

+1

@Jens - AFAICS, что делает эта функция, так или иначе разделит разделитель тысяч. Assign '1.0.0.0.000,00' для варианта и у вас есть 1.000.000,00 денег. –

+1

@Sertac: Я пробовал, но мой банковский счет не изменился.