You've already forked lazarus-ccr
fpspreadsheet: Some simplification of number format token analysis. Add number format unit tests for the new formats (fraction, split-off thousands)
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4131 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -89,13 +89,14 @@ type
|
||||
// Format string
|
||||
function BuildFormatString: String; virtual;
|
||||
// Token analysis
|
||||
{
|
||||
function GetTokenIntValueAt(AToken: TsNumFormatToken;
|
||||
ASection,AIndex: Integer): Integer;
|
||||
function IsNumberAt(ASection,AIndex: Integer; out ANumFormat: TsNumberFormat;
|
||||
out ADecimals: Byte; out ANextIndex: Integer): Boolean;
|
||||
function IsTextAt(AText: string; ASection, AIndex: Integer): Boolean;
|
||||
function IsTokenAt(AToken: TsNumFormatToken; ASection,AIndex: Integer): Boolean;
|
||||
|
||||
}
|
||||
public
|
||||
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String);
|
||||
destructor Destroy; override;
|
||||
@ -292,13 +293,11 @@ end;
|
||||
|
||||
procedure TsNumFormatParser.CheckSection(ASection: Integer);
|
||||
var
|
||||
el, next, i: Integer;
|
||||
el, i: Integer;
|
||||
section: PsNumFormatSection;
|
||||
nfs, nfsTest: String;
|
||||
nf: TsNumberFormat;
|
||||
datetimeFormats: set of TsNumberformat;
|
||||
f1,f2: Integer;
|
||||
decs: Byte;
|
||||
formats: set of TsNumberFormat;
|
||||
begin
|
||||
if FStatus <> psOK then
|
||||
exit;
|
||||
@ -308,6 +307,12 @@ begin
|
||||
|
||||
for el := 0 to High(section^.Elements) do
|
||||
case section^.Elements[el].Token of
|
||||
nftZeroDecs:
|
||||
section^.Decimals := section^.Elements[el].IntValue;
|
||||
nftFracNumSpaceDigit, nftFracNumZeroDigit:
|
||||
section^.FracNumerator := section^.Elements[el].IntValue;
|
||||
nftFracDenomSpaceDigit, nftFracDenomZeroDigit:
|
||||
section^.FracDenominator := section^.Elements[el].IntValue;
|
||||
nftPercent:
|
||||
section^.Kind := section^.Kind + [nfkPercent];
|
||||
nftExpChar:
|
||||
@ -370,13 +375,18 @@ begin
|
||||
section^.NumFormat := nfTimeInterval
|
||||
else
|
||||
begin
|
||||
datetimeFormats := [nfShortDateTime, nfLongDate, nfShortDate, nfLongTime,
|
||||
formats := [nfShortDateTime, nfLongDate, nfShortDate, nfLongTime,
|
||||
nfShortTime, nfLongTimeAM, nfShortTimeAM, nfDayMonth, nfMonthYear];
|
||||
for nf in datetimeFormats do
|
||||
for nf in formats do
|
||||
begin
|
||||
nfsTest := BuildDateTimeFormatString(nf, FWorkbook.FormatSettings);
|
||||
if Length(nfsTest) = Length(nfs) then
|
||||
begin
|
||||
if SameText(nfs, nfsTest) then
|
||||
begin
|
||||
section^.NumFormat := nf;
|
||||
break;
|
||||
end;
|
||||
for i := 1 to Length(nfsTest) do
|
||||
case nfsTest[i] of
|
||||
'/': if not (nf in [nfLongTimeAM, nfShortTimeAM]) then
|
||||
@ -390,17 +400,28 @@ begin
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
{
|
||||
if SameText(nfs, BuildDateTimeFormatString(nf, FWorkbook.FormatSettings)) then
|
||||
begin
|
||||
section^.NumFormat := nf;
|
||||
break;
|
||||
end;
|
||||
}
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
nfs := GetFormatString;
|
||||
formats := [nfFixed, nfFixedTh, nfPercentage, nfExp, nfFraction];
|
||||
for nf in formats do begin
|
||||
nfsTest := BuildNumberFormatString(nf, FWorkbook.FormatSettings, section^.Decimals);
|
||||
if SameText(nfs, nfsTest) then
|
||||
begin
|
||||
section^.NumFormat := nf;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if (section^.NumFormat = nfCustom) and (nfkCurrency in section^.Kind) then
|
||||
begin
|
||||
section^.NumFormat := nfCurrency;
|
||||
if section^.Color = scRed then
|
||||
section^.NumFormat := nfCurrencyRed;
|
||||
end;
|
||||
|
||||
{
|
||||
el := 0;
|
||||
while el < Length(section^.Elements) do
|
||||
begin
|
||||
@ -470,6 +491,7 @@ begin
|
||||
end;
|
||||
if (section^.NumFormat = nfCurrency) and (section^.Color = scRed) then
|
||||
section^.NumFormat := nfCurrencyRed;
|
||||
}
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -743,7 +765,7 @@ function TsNumFormatParser.GetParsedSections(AIndex: Integer): TsNumFormatSectio
|
||||
begin
|
||||
Result := FSections[AIndex];
|
||||
end;
|
||||
|
||||
{
|
||||
function TsNumFormatParser.GetTokenIntValueAt(AToken: TsNumFormatToken;
|
||||
ASection, AIndex: Integer): Integer;
|
||||
begin
|
||||
@ -752,7 +774,7 @@ begin
|
||||
else
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
}
|
||||
{ Returns true if the format elements contain at least one date/time token }
|
||||
function TsNumFormatParser.IsDateTimeFormat: Boolean;
|
||||
var
|
||||
@ -766,7 +788,7 @@ begin
|
||||
end;
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
{
|
||||
function TsNumFormatParser.IsNumberAt(ASection, AIndex: Integer;
|
||||
out ANumFormat: TsNumberFormat; out ADecimals: Byte;
|
||||
out ANextIndex: Integer): Boolean;
|
||||
@ -837,7 +859,7 @@ begin
|
||||
Result := IsTokenAt(nftText, ASection, AIndex) and
|
||||
(FSections[ASection].Elements[AIndex].TextValue = AText);
|
||||
end;
|
||||
|
||||
}
|
||||
{ Returns true if the format elements contain only time, no date tokens. }
|
||||
function TsNumFormatParser.IsTimeFormat: Boolean;
|
||||
var
|
||||
@ -851,7 +873,7 @@ begin
|
||||
end;
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
{
|
||||
function TsNumFormatParser.IsTokenAt(AToken: TsNumFormatToken;
|
||||
ASection, AIndex: Integer): Boolean;
|
||||
begin
|
||||
@ -859,7 +881,7 @@ begin
|
||||
(AIndex < Length(FSections[ASection].Elements)) and
|
||||
(FSections[ASection].Elements[AIndex].Token = AToken);
|
||||
end;
|
||||
|
||||
}
|
||||
{ Limits the decimals to 0 or 2, as required by Excel2. }
|
||||
procedure TsNumFormatParser.LimitDecimals;
|
||||
var
|
||||
|
@ -19,11 +19,14 @@ type
|
||||
SollNumFormat: TsNumberFormat;
|
||||
SollSectionCount: Integer;
|
||||
SollDecimals: Byte;
|
||||
SollFactor: Double;
|
||||
SollNumeratorDigits: Integer;
|
||||
SollDenominatorDigits: Integer;
|
||||
SollCurrencySymbol: String;
|
||||
end;
|
||||
|
||||
var
|
||||
ParserTestData: Array[0..8] of TParserTestData;
|
||||
ParserTestData: Array[0..10] of TParserTestData;
|
||||
|
||||
procedure InitParserTestData;
|
||||
|
||||
@ -56,6 +59,9 @@ begin
|
||||
SollNumFormat := nfFixed;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 0;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[1] do begin
|
||||
@ -64,6 +70,9 @@ begin
|
||||
SollNumFormat := nfFixed;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 3;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[2] do begin
|
||||
@ -72,6 +81,9 @@ begin
|
||||
SollNumFormat := nfFixedTh;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 3;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[3] do begin
|
||||
@ -80,6 +92,9 @@ begin
|
||||
SollNumFormat := nfPercentage;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 3;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[4] do begin
|
||||
@ -88,6 +103,9 @@ begin
|
||||
SollNumFormat := nfLongTime;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 0;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[5] do begin
|
||||
@ -96,32 +114,66 @@ begin
|
||||
SollNumFormat := nfLongTimeAM;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 0;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[6] do begin
|
||||
FormatString := '[$-409]hh:mm:ss\ AM/PM;@';
|
||||
SollFormatString := 'hh:mm:ss AM/PM';
|
||||
SollNumFormat := nfLongTimeAM;
|
||||
SollFormatString := 'hh:mm:ss\ AM/PM;@';
|
||||
SollNumFormat := nfCustom;
|
||||
SollSectionCount := 2;
|
||||
SollDecimals := 0;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[7] do begin
|
||||
FormatString := '[$-F400]dd.mm.yy\ hh:mm';
|
||||
SollFormatString := 'dd.mm.yy hh:mm';
|
||||
SollNumFormat := nfShortDateTime;
|
||||
SollFormatString := 'DD.MM.YY\ hh:mm';
|
||||
SollNumFormat := nfCustom;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 0;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[8] do begin
|
||||
FormatString := '[$€] #,##0.00;-[$€] #,##0.00;{$€} 0.00';
|
||||
SollFormatString := '"€" #,##0.00;-"€" #,##0.00;"€" 0.00';
|
||||
FormatString := '[$€] #,##0.00;-[$€] #,##0.00;[$€] 0.00';
|
||||
SollFormatString := '[$€] #,##0.00;-[$€] #,##0.00;[$€] 0.00';
|
||||
SollNumFormat := nfCurrency;
|
||||
SollSectionCount := 3;
|
||||
SollDecimals := 2;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '€';
|
||||
end;
|
||||
with ParserTestData[9] do begin
|
||||
FormatString := '0.00,,';
|
||||
SollFormatString := '0.00,,';
|
||||
SollNumFormat := nfCustom;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 2;
|
||||
SollFactor := 1e-6;
|
||||
SollNumeratorDigits := 0;
|
||||
SollDenominatorDigits := 0;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
with ParserTestData[10] do begin
|
||||
FormatString := '# ??/??';
|
||||
SollFormatString := '# ??/??';
|
||||
SollNumFormat := nfFraction;
|
||||
SollSectionCount := 1;
|
||||
SollDecimals := 0;
|
||||
SollFactor := 0;
|
||||
SollNumeratorDigits := 2;
|
||||
SollDenominatorDigits := 2;
|
||||
SollCurrencySymbol := '';
|
||||
end;
|
||||
{
|
||||
with ParserTestData[5] do begin
|
||||
FormatString := '#,##0.00 "$";-#,##0.00 "$";-';
|
||||
@ -167,21 +219,28 @@ var
|
||||
begin
|
||||
MyWorkbook := TsWorkbook.Create; // needed to provide the FormatSettings for the parser
|
||||
try
|
||||
for i:=0 to 5 do begin
|
||||
for i:=0 to High(ParserTestData) do begin
|
||||
parser := TsNumFormatParser.Create(MyWorkbook, ParserTestData[i].FormatString);
|
||||
try
|
||||
actual := parser.FormatString;
|
||||
CheckEquals(ParserTestData[i].SollFormatString, actual,
|
||||
'Test format string ' + ParserTestData[i].SollFormatString + ' construction mismatch');
|
||||
CheckEquals(ord(ParserTestData[i].SollNumFormat), ord(parser.ParsedSections[0].NumFormat),
|
||||
'Test format (' + GetEnumName(TypeInfo(TsNumberFormat), integer(ParserTestData[i].SollNumFormat)) +
|
||||
') detection mismatch');
|
||||
CheckEquals(
|
||||
GetEnumName(TypeInfo(TsNumberFormat), ord(ParserTestData[i].SollNumFormat)),
|
||||
GetEnumName(TypeInfo(TsNumberformat), ord(parser.ParsedSections[0].NumFormat)),
|
||||
'Test format (' + ParserTestData[i].FormatString + ') detection mismatch');
|
||||
CheckEquals(ParserTestData[i].SollDecimals, parser.ParsedSections[0].Decimals,
|
||||
'Test format (' + ParserTestData[i].FormatString + ') decimal detection mismatch');
|
||||
CheckEquals(ParserTestData[i].SollCurrencySymbol, parser.ParsedSections[0].CurrencySymbol,
|
||||
'Test format (' + ParserTestData[i].FormatString + ') currency symbol detection mismatch');
|
||||
CheckEquals(ParserTestData[i].SollSectionCount, parser.ParsedSectionCount,
|
||||
'Test format (' + ParserTestData[i].FormatString + ') section count mismatch');
|
||||
CheckEquals(ParserTestData[i].SollFactor, parser.ParsedSections[0].Factor,
|
||||
'Test format (' + ParserTestData[i].FormatString + ') factor mismatch');
|
||||
CheckEquals(ParserTestData[i].SollNumeratorDigits, parser.ParsedSections[0].FracNumerator,
|
||||
'Test format (' + ParserTestData[i].FormatString + ') numerator digits mismatch');
|
||||
CheckEquals(ParserTestData[i].SollDenominatorDigits, parser.ParsedSections[0].FracDenominator,
|
||||
'Test format (' + ParserTestData[i].FormatString + ') denominator digits mismatch');
|
||||
finally
|
||||
parser.Free;
|
||||
end;
|
||||
|
Reference in New Issue
Block a user