Формат чисел. Разделители. (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 := '';