Delphi - сбориник статей


Формат чисел. Разделители. (DecimalSeparator, ThousendSeparator)


Почитайте "диалог" на Круглом столе - вроде бы все понятно ("а все и делов то в запятой")! А нет, не все! В "International" (в русском "Язык и стандарты") можно установить любые DecimalSeparator и ThousandsSeparator, отличные от принятых по-умолчанию фирмой Microsoft для русской версии Windows. Я, например, всегда меняю принятые по-умолчанию десятичную точку "," на "." и разделитель тысяч с " " (пробел) на "'" (апостроф, как в калькуляторе). Так формат "# ##0,00" у меня работать не будет...

И это еще не все! Заходим в настройки Excel'я "Сервис/Параметры" переходим на закладку "Международные" и видим опять "Разделитель целой и дробной части", "Разделитель разрядов" и чекбокс "Использовать системные разделители". Т.е. использование системных разделителей не может гарантировать правильного применения при форматировании чисел в Excel'е. Решение: использовать свойство ExcelApplication.International (о нем дальше). Причем, даже при установленном свойстве ExcelApplication.UseSystemSeparators = False и отличных от системных ExcelApplication.DecimalSeparator и ExcelApplication.ThousandsSeparator, ExcelApplication.International отработает корректно.

Далее рассмотрим примеры работы (или не работы), приняв "стандартные" настройки для русских Windows:

Код на VBA (эталон):

Sub Test2() Dim R As Range Set R = Range("a1") R.Clear R.Value = 1234567.89 R.NumberFormat = "#,##0.00" ' работает R.NumberFormatLocal = "# ##0,00" '
работает для стандартных настроек R.NumberFormat = "# ##0,00" ' не работает R.NumberFormatLocal = "#,##0.00" ' не работает Set R = Nothing End Sub

Код на Delphi:

R := ASheet.Range['A1', EmptyParam]; R.Value2 := 1234567.89; R.NumberFormat := '#,##0.00'; // не работает R.NumberFormatLocal := '# ##0,00'; //
работает для стандартных настроек

R.NumberFormat := '# ##0,00'; //
работает для стандартных настроек

Примечание:
в примерах значения записываются в Value2 для предотвращения форматирования "на лету" самим Excel'ем. Так число 123.45, записанное в Value будет автоматически отформатировано Excel'ем в формат валюты, а присвоение Value = Date будет автоматически переведено в формат даты. Запись в Value2 "воспринимает" значение как Double. Подробнее смотрите в справке VBA для Excel'я.

Решения (с использованием ExcelApplication.International):

Для получения формата даты можно написать функцию:

function XL_GetShortDateFormat(XLApp: ExcelApplication): String; var d, m, y: Integer; begin if XLApp.International[xlDayLeadingZero, lcid] then d := 2 else d := 1; if XLApp.International[xlMonthLeadingZero, lcid] then m := 2 else m := 1; if XLApp.International[xl4DigitYears, lcid] then y := 4 else y := 2; Result := Format('%1:s%0:s%2:s%0:s%3:s', [ DateSeparator, StringOfChar(VarToStr(XLApp.International
[xlDayCode, lcid])[1], d), StringOfChar(VarToStr(XLApp.International
[xlMonthCode, lcid])[1], m), StringOfChar(VarToStr(XLApp.International
[xlYearCode, lcid])[1], y) ]); end;

Для формата чисел:

function XL_GetNumberFormat
(XLApp: ExcelApplication): String; begin Result := Format('#%s##0%s%s', [ XLApp.International[xlThousandsSeparator, lcid], XLApp.International[xlDecimalSeparator, lcid], StringOfChar('0', Integer
(XLApp.International[xlCurrencyDigits, lcid])) ]); end;

Для формата валюты:

function XL_GetCurrencyFormat(XLApp: ExcelApplication): String; begin Result := Format('%s "%s"', [ XL_GetNumberFormat(XLApp), XLApp.International[xlCurrencyCode, lcid] ]); end;

Тот же принцип можно применить к времени и другим типам. Также смотрите другие индексы для свойства International (их там много) в справке VBA. Например, получить "основной" (general) формат можно так:

GenFmt := XL.International[xlGeneralFormatName, lcid];

Примечание:

установить основной формат еще можно установить, записав в NumberFormat "пустую" строку, т.е. указать, что нет форматирования для чисел (даты):

Range.NumberFormat := '';

Содержание раздела