You've already forked lazarus-ccr
fpspreadsheet: In the unit tests, use the same methods for creating "soll" date/times and test format strings. --> No more biff-related regressions.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3078 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -45,6 +45,8 @@ begin
|
||||
}
|
||||
|
||||
// Write some number cells
|
||||
MyWorksheet.WriteDateTime(0, 0, EncodeDate(2012,1,12)+EncodeTime(13,14,15,0), nfShortTimeAM);
|
||||
(*
|
||||
MyWorksheet.WriteNumber(0, 0, 1.0);
|
||||
MyWorksheet.WriteUsedFormatting(0, 0, [uffBold, uffNumberFormat]);
|
||||
MyWorksheet.WriteNumber(0, 1, 2.0);
|
||||
@ -378,7 +380,7 @@ begin
|
||||
MyWorksheet.WriteRowInfo(5, lRow);
|
||||
lRow.Height := 5;
|
||||
MyWorksheet.WriteRowInfo(6, lRow);
|
||||
|
||||
*)
|
||||
// Save the spreadsheet to a file
|
||||
MyWorkbook.WriteToFile(MyDir + 'test' + STR_EXCEL_EXTENSION, sfExcel2, true);
|
||||
MyWorkbook.Free;
|
||||
|
@ -86,9 +86,14 @@ function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
||||
ACurrencySymbol: String = '?'): String;
|
||||
function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
|
||||
const AFormatSettings: TFormatSettings; AFormatString: String = ''): String;
|
||||
|
||||
function AddAMPM(const ATimeFormatString: String;
|
||||
const AFormatSettings: TFormatSettings): String;
|
||||
function StripAMPM(const ATimeFormatString: String): String;
|
||||
function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte;
|
||||
function AddIntervalBrackets(AFormatString: String): String;
|
||||
function SpecialDateTimeFormat(ACode: String;
|
||||
const AFormatSettings: TFormatSettings; ForWriting: Boolean): String;
|
||||
|
||||
function SciFloat(AValue: Double; ADecimals: Byte): String;
|
||||
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
|
||||
@ -784,20 +789,12 @@ function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
|
||||
const AFormatSettings: TFormatSettings; AFormatString: String = '') : string;
|
||||
var
|
||||
fmt: String;
|
||||
am, pm: String;
|
||||
begin
|
||||
case ANumberFormat of
|
||||
nfFmtDateTime:
|
||||
begin
|
||||
fmt := lowercase(AFormatString);
|
||||
if (fmt = 'dm') then Result := 'd/mmm'
|
||||
else if (fmt = 'my') then Result := 'mmm/yy'
|
||||
else if (fmt = 'ms') then Result := 'nn:ss'
|
||||
else if (fmt = 'msz') then Result := 'nn:ss.z'
|
||||
else Result := AFormatString;
|
||||
end;
|
||||
Result := SpecialDateTimeFormat(lowercase(AFormatString), AFormatSettings, false);
|
||||
nfShortDateTime:
|
||||
Result := AFormatSettings.ShortDateFormat + ' ' + FormatSettings.ShortTimeFormat;
|
||||
Result := AFormatSettings.ShortDateFormat + ' ' + AFormatSettings.ShortTimeFormat;
|
||||
// In the DefaultFormatSettings this is: d/m/y hh:nn
|
||||
nfShortDate:
|
||||
Result := AFormatSettings.ShortDateFormat; // --> d/m/y
|
||||
@ -810,20 +807,14 @@ begin
|
||||
nfShortTimeAM:
|
||||
begin // --> hh:nn AM/PM
|
||||
Result := AFormatSettings.ShortTimeFormat;
|
||||
if (pos('a', lowercase(AFormatSettings.ShortTimeFormat)) = 0) then begin
|
||||
am := IfThen(AFormatSettings.TimeAMString = '', 'AM', AFormatSettings.TimeAMString);
|
||||
pm := IfThen(AFormatSettings.TimePMString = '', 'PM', AFormatSettings.TimePMString);
|
||||
Result := Format('%s %s/%s', [Result, am, pm]);
|
||||
end;
|
||||
if (pos('a', lowercase(AFormatSettings.ShortTimeFormat)) = 0) then
|
||||
Result := AddAMPM(Result, AFormatSettings);
|
||||
end;
|
||||
nfLongTimeAM: // --> hh:nn:ss AM/PM
|
||||
begin
|
||||
Result := AFormatSettings.LongTimeFormat;
|
||||
if pos('a', lowercase(AFormatSettings.LongTimeFormat)) = 0 then begin
|
||||
am := IfThen(AFormatSettings.TimeAMString = '', 'AM', AFormatSettings.TimeAMString);
|
||||
pm := IfThen(AFormatSettings.TimePMString = '', 'PM', AFormatSettings.TimePMString);
|
||||
Result := Format('%s %s/%s', [Result, am, pm]);
|
||||
end;
|
||||
if pos('a', lowercase(AFormatSettings.LongTimeFormat)) = 0 then
|
||||
Result := AddAMPM(Result, AFormatSettings);
|
||||
end;
|
||||
nfTimeInterval: // --> [h]:nn:ss
|
||||
if AFormatString = '' then
|
||||
@ -904,19 +895,22 @@ begin
|
||||
end;
|
||||
if ANumberFormat in [nfCurrency, nfCurrencyRed] then
|
||||
Result := Result +';' + Format(POS_FMT[cf], ['0' + decs, ACurrencySymbol])
|
||||
{
|
||||
Result := Result + ';0' + decs;
|
||||
if cf in [2,3] then
|
||||
Result := Format('%s "%s"', [Result, ACurrencySymbol])
|
||||
else
|
||||
Result := Format('%s"%s"', [Result, ACurrencySymbol]);
|
||||
}
|
||||
else
|
||||
Result := Result + ';-';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function AddAMPM(const ATimeFormatString: String;
|
||||
const AFormatSettings: TFormatSettings): String;
|
||||
var
|
||||
am, pm: String;
|
||||
begin
|
||||
am := IfThen(AFormatSettings.TimeAMString <> '', AFormatSettings.TimeAMString, 'AM');
|
||||
pm := IfThen(AFormatSettings.TimePMString <> '', AFormatSettings.TimePMString, 'PM');
|
||||
Result := Format('%s %s/%s', [StripAMPM(ATimeFormatString), am, pm]);
|
||||
end;
|
||||
|
||||
function StripAMPM(const ATimeFormatString: String): String;
|
||||
var
|
||||
i: Integer;
|
||||
@ -968,6 +962,42 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Creates the formatstrings for the date/time codes "dm", "my", "ms" and "msz"
|
||||
out of the formatsettings. }
|
||||
function SpecialDateTimeFormat(ACode: String;
|
||||
const AFormatSettings: TFormatSettings; ForWriting: Boolean): String;
|
||||
var
|
||||
pd, pm, py: Integer;
|
||||
sdf: String;
|
||||
MonthChar, MinuteChar, MillisecChar: Char;
|
||||
begin
|
||||
if ForWriting then begin
|
||||
MonthChar := 'M'; MinuteChar := 'm'; MillisecChar := '0';
|
||||
end else begin
|
||||
MonthChar := 'm'; MinuteChar := 'n'; MillisecChar := 'z';
|
||||
end;
|
||||
ACode := lowercase(ACode);
|
||||
sdf := lowercase(AFormatSettings.ShortDateFormat);
|
||||
pd := pos('d', sdf);
|
||||
pm := pos('m', sdf);
|
||||
py := pos('y', sdf);
|
||||
if ACode = 'dm' then begin
|
||||
Result := DupeString(MonthChar, 3);
|
||||
Result := IfThen(pd < py, 'd/'+Result, Result+'/d'); // d/mmm
|
||||
end else
|
||||
if ACode = 'my' then begin
|
||||
Result := DupeString(MonthChar, 3);
|
||||
Result := IfThen(pm < py, Result+'/yy', 'yy/'+Result); // mmm/yy
|
||||
end else
|
||||
if ACode = 'ms' then begin
|
||||
Result := DupeString(MinuteChar, 2) + ':ss'; // mm:ss
|
||||
end
|
||||
else if ACode = 'msz' then
|
||||
Result := DupeString(MinuteChar, 2) + ':ss.' + MillisecChar // mm:ss.z
|
||||
else
|
||||
Result := ACode;
|
||||
end;
|
||||
|
||||
{ Formats the number AValue in "scientific" format with the given number of
|
||||
decimals. "Scientific" is the same as "exponential", but with exponents rounded
|
||||
to multiples of 3 (like for "kilo" - "Mega" - "Giga" etc.). }
|
||||
|
@ -127,9 +127,12 @@ const
|
||||
procedure InitSollFmtData;
|
||||
var
|
||||
i: Integer;
|
||||
fs: TFormatSettings;
|
||||
begin
|
||||
// Set up norm - MUST match spreadsheet cells exactly
|
||||
|
||||
fs := DefaultFormatSettings;
|
||||
|
||||
// Numbers
|
||||
SollNumbers[0] := 0.0;
|
||||
SollNumbers[1] := 1.0;
|
||||
@ -182,13 +185,13 @@ begin
|
||||
for i:=Low(SollDateTimes) to High(SollDateTimes) do begin
|
||||
SollDateTimeStrings[i, 0] := DateToStr(SollDateTimes[i]) + ' ' + FormatDateTime('t', SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 1] := DateToStr(SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 2] := FormatDateTime('hh:nn', SollDateTimes[i]);
|
||||
SolLDateTimeStrings[i, 3] := FormatDateTime('hh:nn:ss', SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 4] := FormatDateTime('hh:nn am/pm', SollDateTimes[i]); // dont't use "t" - it does the hours wrong
|
||||
SollDateTimeStrings[i, 5] := FormatDateTime('hh:nn:ss am/pm', SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 6] := FormatDateTime('dd/mmm', SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 7] := FormatDateTime('mmm/yy', SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 8] := FormatDateTime('nn:ss', SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 2] := FormatDateTime(fs.ShortTimeFormat, SollDateTimes[i]);
|
||||
SolLDateTimeStrings[i, 3] := FormatDateTime(fs.LongTimeFormat, SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 4] := FormatDateTime(fs.ShortTimeFormat + ' am/pm', SollDateTimes[i]); // dont't use "t" - it does the hours wrong
|
||||
SollDateTimeStrings[i, 5] := FormatDateTime(fs.LongTimeFormat + ' am/pm', SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 6] := FormatDateTime(SpecialDateTimeFormat('dm', fs, false), SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 7] := FormatDateTime(SpecialDateTimeFormat('my', fs, false), SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 8] := FormatDateTime(SpecialDateTimeFormat('ms', fs, false), SollDateTimes[i]);
|
||||
SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], [fdoInterval]);
|
||||
end;
|
||||
|
||||
|
@ -176,11 +176,13 @@ end;
|
||||
|
||||
procedure TsBIFF2NumFormatList.AddBuiltinFormats;
|
||||
var
|
||||
fs: TFormatSettings;
|
||||
ds, ts, cs: string;
|
||||
begin
|
||||
ds := DefaultFormatSettings.DecimalSeparator;
|
||||
ts := DefaultFormatSettings.ThousandSeparator;
|
||||
cs := DefaultFormatSettings.CurrencyString;
|
||||
fs := Workbook.FormatSettings;
|
||||
ds := fs.DecimalSeparator;
|
||||
ts := fs.ThousandSeparator;
|
||||
cs := fs.CurrencyString;
|
||||
AddFormat( 0, '', nfGeneral);
|
||||
AddFormat( 1, '0', nfFixed, 0);
|
||||
AddFormat( 2, '0'+ds+'00', nfFixed, 2); // 0.00
|
||||
@ -193,15 +195,15 @@ begin
|
||||
AddFormat( 9, '0%', nfPercentage, 0);
|
||||
AddFormat(10, '0'+ds+'00%', nfPercentage, 2);
|
||||
AddFormat(11, '0'+ds+'00E+00', nfExp, 2);
|
||||
AddFormat(12, 'M/D/YY', nfShortDate);
|
||||
AddFormat(13, 'D-MMM-YY', nfLongDate);
|
||||
AddFormat(14, 'D-MMM', nfFmtDateTime);
|
||||
AddFormat(15, 'MMM-YY', nfFmtDateTime);
|
||||
AddFormat(16, 'h:mm AM/PM', nfShortTimeAM);
|
||||
AddFormat(17, 'h:mm:ss AM/PM', nfLongTimeAM);
|
||||
AddFormat(18, 'h:mm', nfShortTime);
|
||||
AddFormat(19, 'h:mm:ss', nfLongTime);
|
||||
AddFormat(20, 'M/D/YY h:mm', nfShortDateTime);
|
||||
AddFormat(12, fs.ShortDateFormat, nfShortDate);
|
||||
AddFormat(13, fs.LongDateFormat, nfLongDate);
|
||||
AddFormat(14, SpecialDateTimeFormat('dm', fs, true), nfFmtDateTime);
|
||||
AddFormat(15, SpecialDateTimeFormat('my', fs, true), nfFmtDateTime);
|
||||
AddFormat(16, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM);
|
||||
AddFormat(17, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM);
|
||||
AddFormat(18, fs.ShortTimeFormat, nfShortTime);
|
||||
AddFormat(19, fs.LongTimeFormat, nfLongTime);
|
||||
AddFormat(20, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime);
|
||||
|
||||
FFirstFormatIndexInFile := 0; // BIFF2 stores built-in formats to file.
|
||||
FNextFormatIndex := 21; // not needed - there are not user-defined formats
|
||||
@ -231,7 +233,7 @@ begin
|
||||
(fmt = 'dd-mm') or (fmt = 'dd/mm') or
|
||||
(fmt = 'dd-mmm') or (fmt = 'dd/mmm')
|
||||
then
|
||||
AFormatString := 'D-MMM'
|
||||
AFormatString := SpecialDateTimeFormat('dm', Workbook.FormatSettings, true)
|
||||
else
|
||||
if (fmt = 'm-yy') or (fmt = 'm/yy') or
|
||||
(fmt = 'mm-yy') or (fmt = 'mm/yy') or
|
||||
@ -240,7 +242,7 @@ begin
|
||||
(fmt = 'mm-yyyy') or (fmt = 'mm/yyyy') or
|
||||
(fmt = 'mmm-yyyy') or (fmt = 'mmm-yyyy')
|
||||
then
|
||||
AFormatString := 'MMM-YY'
|
||||
AFormatString := SpecialDateTimeFormat('my', Workbook.FormatSettings, true)
|
||||
else
|
||||
if (copy(fmt, 1, 5) = 'nn:ss') or (copy(fmt, 1, 5) = 'mm:ss') or
|
||||
(copy(fmt, 1, 4) = 'n:ss') or (copy(fmt, 1, 4) = 'm:ss')
|
||||
|
Reference in New Issue
Block a user