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:
wp_xxyyzz
2014-05-22 12:34:10 +00:00
parent c70b1db64f
commit ee1db37c7f
4 changed files with 86 additions and 49 deletions

View File

@ -45,6 +45,8 @@ begin
} }
// Write some number cells // 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.WriteNumber(0, 0, 1.0);
MyWorksheet.WriteUsedFormatting(0, 0, [uffBold, uffNumberFormat]); MyWorksheet.WriteUsedFormatting(0, 0, [uffBold, uffNumberFormat]);
MyWorksheet.WriteNumber(0, 1, 2.0); MyWorksheet.WriteNumber(0, 1, 2.0);
@ -378,7 +380,7 @@ begin
MyWorksheet.WriteRowInfo(5, lRow); MyWorksheet.WriteRowInfo(5, lRow);
lRow.Height := 5; lRow.Height := 5;
MyWorksheet.WriteRowInfo(6, lRow); MyWorksheet.WriteRowInfo(6, lRow);
*)
// Save the spreadsheet to a file // Save the spreadsheet to a file
MyWorkbook.WriteToFile(MyDir + 'test' + STR_EXCEL_EXTENSION, sfExcel2, true); MyWorkbook.WriteToFile(MyDir + 'test' + STR_EXCEL_EXTENSION, sfExcel2, true);
MyWorkbook.Free; MyWorkbook.Free;

View File

@ -86,9 +86,14 @@ function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
ACurrencySymbol: String = '?'): String; ACurrencySymbol: String = '?'): String;
function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat; function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
const AFormatSettings: TFormatSettings; AFormatString: String = ''): String; const AFormatSettings: TFormatSettings; AFormatString: String = ''): String;
function AddAMPM(const ATimeFormatString: String;
const AFormatSettings: TFormatSettings): String;
function StripAMPM(const ATimeFormatString: String): String; function StripAMPM(const ATimeFormatString: String): String;
function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte; function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte;
function AddIntervalBrackets(AFormatString: String): String; function AddIntervalBrackets(AFormatString: String): String;
function SpecialDateTimeFormat(ACode: String;
const AFormatSettings: TFormatSettings; ForWriting: Boolean): String;
function SciFloat(AValue: Double; ADecimals: Byte): String; function SciFloat(AValue: Double; ADecimals: Byte): String;
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String; //function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
@ -784,20 +789,12 @@ function BuildDateTimeFormatString(ANumberFormat: TsNumberFormat;
const AFormatSettings: TFormatSettings; AFormatString: String = '') : string; const AFormatSettings: TFormatSettings; AFormatString: String = '') : string;
var var
fmt: String; fmt: String;
am, pm: String;
begin begin
case ANumberFormat of case ANumberFormat of
nfFmtDateTime: nfFmtDateTime:
begin Result := SpecialDateTimeFormat(lowercase(AFormatString), AFormatSettings, false);
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;
nfShortDateTime: nfShortDateTime:
Result := AFormatSettings.ShortDateFormat + ' ' + FormatSettings.ShortTimeFormat; Result := AFormatSettings.ShortDateFormat + ' ' + AFormatSettings.ShortTimeFormat;
// In the DefaultFormatSettings this is: d/m/y hh:nn // In the DefaultFormatSettings this is: d/m/y hh:nn
nfShortDate: nfShortDate:
Result := AFormatSettings.ShortDateFormat; // --> d/m/y Result := AFormatSettings.ShortDateFormat; // --> d/m/y
@ -810,20 +807,14 @@ begin
nfShortTimeAM: nfShortTimeAM:
begin // --> hh:nn AM/PM begin // --> hh:nn AM/PM
Result := AFormatSettings.ShortTimeFormat; Result := AFormatSettings.ShortTimeFormat;
if (pos('a', lowercase(AFormatSettings.ShortTimeFormat)) = 0) then begin if (pos('a', lowercase(AFormatSettings.ShortTimeFormat)) = 0) then
am := IfThen(AFormatSettings.TimeAMString = '', 'AM', AFormatSettings.TimeAMString); Result := AddAMPM(Result, AFormatSettings);
pm := IfThen(AFormatSettings.TimePMString = '', 'PM', AFormatSettings.TimePMString);
Result := Format('%s %s/%s', [Result, am, pm]);
end;
end; end;
nfLongTimeAM: // --> hh:nn:ss AM/PM nfLongTimeAM: // --> hh:nn:ss AM/PM
begin begin
Result := AFormatSettings.LongTimeFormat; Result := AFormatSettings.LongTimeFormat;
if pos('a', lowercase(AFormatSettings.LongTimeFormat)) = 0 then begin if pos('a', lowercase(AFormatSettings.LongTimeFormat)) = 0 then
am := IfThen(AFormatSettings.TimeAMString = '', 'AM', AFormatSettings.TimeAMString); Result := AddAMPM(Result, AFormatSettings);
pm := IfThen(AFormatSettings.TimePMString = '', 'PM', AFormatSettings.TimePMString);
Result := Format('%s %s/%s', [Result, am, pm]);
end;
end; end;
nfTimeInterval: // --> [h]:nn:ss nfTimeInterval: // --> [h]:nn:ss
if AFormatString = '' then if AFormatString = '' then
@ -904,19 +895,22 @@ begin
end; end;
if ANumberFormat in [nfCurrency, nfCurrencyRed] then if ANumberFormat in [nfCurrency, nfCurrencyRed] then
Result := Result +';' + Format(POS_FMT[cf], ['0' + decs, ACurrencySymbol]) 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 else
Result := Result + ';-'; Result := Result + ';-';
end; end;
end; 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; function StripAMPM(const ATimeFormatString: String): String;
var var
i: Integer; i: Integer;
@ -968,6 +962,42 @@ begin
end; end;
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 { Formats the number AValue in "scientific" format with the given number of
decimals. "Scientific" is the same as "exponential", but with exponents rounded decimals. "Scientific" is the same as "exponential", but with exponents rounded
to multiples of 3 (like for "kilo" - "Mega" - "Giga" etc.). } to multiples of 3 (like for "kilo" - "Mega" - "Giga" etc.). }

View File

@ -127,9 +127,12 @@ const
procedure InitSollFmtData; procedure InitSollFmtData;
var var
i: Integer; i: Integer;
fs: TFormatSettings;
begin begin
// Set up norm - MUST match spreadsheet cells exactly // Set up norm - MUST match spreadsheet cells exactly
fs := DefaultFormatSettings;
// Numbers // Numbers
SollNumbers[0] := 0.0; SollNumbers[0] := 0.0;
SollNumbers[1] := 1.0; SollNumbers[1] := 1.0;
@ -182,13 +185,13 @@ begin
for i:=Low(SollDateTimes) to High(SollDateTimes) do begin for i:=Low(SollDateTimes) to High(SollDateTimes) do begin
SollDateTimeStrings[i, 0] := DateToStr(SollDateTimes[i]) + ' ' + FormatDateTime('t', SollDateTimes[i]); SollDateTimeStrings[i, 0] := DateToStr(SollDateTimes[i]) + ' ' + FormatDateTime('t', SollDateTimes[i]);
SollDateTimeStrings[i, 1] := DateToStr(SollDateTimes[i]); SollDateTimeStrings[i, 1] := DateToStr(SollDateTimes[i]);
SollDateTimeStrings[i, 2] := FormatDateTime('hh:nn', SollDateTimes[i]); SollDateTimeStrings[i, 2] := FormatDateTime(fs.ShortTimeFormat, SollDateTimes[i]);
SolLDateTimeStrings[i, 3] := FormatDateTime('hh:nn:ss', SollDateTimes[i]); SolLDateTimeStrings[i, 3] := FormatDateTime(fs.LongTimeFormat, SollDateTimes[i]);
SollDateTimeStrings[i, 4] := FormatDateTime('hh:nn am/pm', SollDateTimes[i]); // dont't use "t" - it does the hours wrong SollDateTimeStrings[i, 4] := FormatDateTime(fs.ShortTimeFormat + ' 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, 5] := FormatDateTime(fs.LongTimeFormat + ' am/pm', SollDateTimes[i]);
SollDateTimeStrings[i, 6] := FormatDateTime('dd/mmm', SollDateTimes[i]); SollDateTimeStrings[i, 6] := FormatDateTime(SpecialDateTimeFormat('dm', fs, false), SollDateTimes[i]);
SollDateTimeStrings[i, 7] := FormatDateTime('mmm/yy', SollDateTimes[i]); SollDateTimeStrings[i, 7] := FormatDateTime(SpecialDateTimeFormat('my', fs, false), SollDateTimes[i]);
SollDateTimeStrings[i, 8] := FormatDateTime('nn:ss', SollDateTimes[i]); SollDateTimeStrings[i, 8] := FormatDateTime(SpecialDateTimeFormat('ms', fs, false), SollDateTimes[i]);
SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], [fdoInterval]); SollDateTimeStrings[i, 9] := FormatDateTime('[h]:mm:ss', SollDateTimes[i], [fdoInterval]);
end; end;

View File

@ -176,11 +176,13 @@ end;
procedure TsBIFF2NumFormatList.AddBuiltinFormats; procedure TsBIFF2NumFormatList.AddBuiltinFormats;
var var
fs: TFormatSettings;
ds, ts, cs: string; ds, ts, cs: string;
begin begin
ds := DefaultFormatSettings.DecimalSeparator; fs := Workbook.FormatSettings;
ts := DefaultFormatSettings.ThousandSeparator; ds := fs.DecimalSeparator;
cs := DefaultFormatSettings.CurrencyString; ts := fs.ThousandSeparator;
cs := fs.CurrencyString;
AddFormat( 0, '', nfGeneral); AddFormat( 0, '', nfGeneral);
AddFormat( 1, '0', nfFixed, 0); AddFormat( 1, '0', nfFixed, 0);
AddFormat( 2, '0'+ds+'00', nfFixed, 2); // 0.00 AddFormat( 2, '0'+ds+'00', nfFixed, 2); // 0.00
@ -193,15 +195,15 @@ begin
AddFormat( 9, '0%', nfPercentage, 0); AddFormat( 9, '0%', nfPercentage, 0);
AddFormat(10, '0'+ds+'00%', nfPercentage, 2); AddFormat(10, '0'+ds+'00%', nfPercentage, 2);
AddFormat(11, '0'+ds+'00E+00', nfExp, 2); AddFormat(11, '0'+ds+'00E+00', nfExp, 2);
AddFormat(12, 'M/D/YY', nfShortDate); AddFormat(12, fs.ShortDateFormat, nfShortDate);
AddFormat(13, 'D-MMM-YY', nfLongDate); AddFormat(13, fs.LongDateFormat, nfLongDate);
AddFormat(14, 'D-MMM', nfFmtDateTime); AddFormat(14, SpecialDateTimeFormat('dm', fs, true), nfFmtDateTime);
AddFormat(15, 'MMM-YY', nfFmtDateTime); AddFormat(15, SpecialDateTimeFormat('my', fs, true), nfFmtDateTime);
AddFormat(16, 'h:mm AM/PM', nfShortTimeAM); AddFormat(16, AddAMPM(fs.ShortTimeFormat, fs), nfShortTimeAM);
AddFormat(17, 'h:mm:ss AM/PM', nfLongTimeAM); AddFormat(17, AddAMPM(fs.LongTimeFormat, fs), nfLongTimeAM);
AddFormat(18, 'h:mm', nfShortTime); AddFormat(18, fs.ShortTimeFormat, nfShortTime);
AddFormat(19, 'h:mm:ss', nfLongTime); AddFormat(19, fs.LongTimeFormat, nfLongTime);
AddFormat(20, 'M/D/YY h:mm', nfShortDateTime); AddFormat(20, fs.ShortDateFormat + ' ' + fs.ShortTimeFormat, nfShortDateTime);
FFirstFormatIndexInFile := 0; // BIFF2 stores built-in formats to file. FFirstFormatIndexInFile := 0; // BIFF2 stores built-in formats to file.
FNextFormatIndex := 21; // not needed - there are not user-defined formats 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-mm') or (fmt = 'dd/mm') or
(fmt = 'dd-mmm') or (fmt = 'dd/mmm') (fmt = 'dd-mmm') or (fmt = 'dd/mmm')
then then
AFormatString := 'D-MMM' AFormatString := SpecialDateTimeFormat('dm', Workbook.FormatSettings, true)
else else
if (fmt = 'm-yy') or (fmt = 'm/yy') or if (fmt = 'm-yy') or (fmt = 'm/yy') or
(fmt = 'mm-yy') or (fmt = 'mm/yy') or (fmt = 'mm-yy') or (fmt = 'mm/yy') or
@ -240,7 +242,7 @@ begin
(fmt = 'mm-yyyy') or (fmt = 'mm/yyyy') or (fmt = 'mm-yyyy') or (fmt = 'mm/yyyy') or
(fmt = 'mmm-yyyy') or (fmt = 'mmm-yyyy') (fmt = 'mmm-yyyy') or (fmt = 'mmm-yyyy')
then then
AFormatString := 'MMM-YY' AFormatString := SpecialDateTimeFormat('my', Workbook.FormatSettings, true)
else else
if (copy(fmt, 1, 5) = 'nn:ss') or (copy(fmt, 1, 5) = 'mm:ss') or 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') (copy(fmt, 1, 4) = 'n:ss') or (copy(fmt, 1, 4) = 'm:ss')