fpspreadsheet: Improved fraction format parser

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4079 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-04-08 22:43:57 +00:00
parent bb76adab15
commit 389c4646f5
2 changed files with 235 additions and 164 deletions

View File

@ -31,8 +31,11 @@ type
nftSign, nftSignBracket, nftSign, nftSignBracket,
nftDigit, nftOptDigit, nftOptSpaceDigit, nftDecs, nftOptDec, nftDigit, nftOptDigit, nftOptSpaceDigit, nftDecs, nftOptDec,
nftExpChar, nftExpSign, nftExpDigits, nftExpChar, nftExpSign, nftExpDigits,
nftPercent, nftPercent, // '%'
nftFraction, nftFracSymbol, // '/'
nftFracIntDigit, nftFracIntSpaceDigit, nftFracIntZeroDigit, // '#', '?', '0'
nftFracNumDigit, nftFracNumSpaceDigit, nftFracNumZeroDigit,
nftFracDenomDigit, nftFracDenomSpaceDigit, nftFracDenomZeroDigit,
nftCurrSymbol, nftCountry, nftCurrSymbol, nftCountry,
nftColor, nftCompareOp, nftCompareValue, nftColor, nftCompareOp, nftCompareValue,
nftSpace, nftEscaped, nftSpace, nftEscaped,
@ -119,16 +122,21 @@ type
// General // General
procedure CheckSections; procedure CheckSections;
procedure CheckSection(ASection: Integer); procedure CheckSection(ASection: Integer);
procedure FixMonthMinuteToken(ASection: Integer);
// Format string // Format string
function BuildFormatString(ADialect: TsNumFormatDialect): String; virtual; function BuildFormatString(ADialect: TsNumFormatDialect): String; virtual;
function BuildFormatStringFromSection(ASection: Integer; function BuildFormatStringFromSection(ASection: Integer;
ADialect: TsNumFormatDialect): String; virtual; ADialect: TsNumFormatDialect): String; virtual;
// NumberFormat // NumberFormat
procedure EvalNumFormatOfSection(ASection: Integer); procedure EvalNumFormatOfSection(ASection: Integer);
function GetTokenIntValueAt(AToken: TsNumFormatToken;
ASection,AIndex: Integer): Integer;
function IsCurrencyAt(ASection: Integer; out ANumFormat: TsNumberFormat; function IsCurrencyAt(ASection: Integer; out ANumFormat: TsNumberFormat;
out ADecimals: byte; out ACurrencySymbol: String; out AColor: TsColor): Boolean; out ADecimals: byte; out ACurrencySymbol: String; out AColor: TsColor): Boolean;
function IsDateAt(ASection,AIndex: Integer; out ANumberFormat: TsNumberFormat; function IsDateAt(ASection,AIndex: Integer; out ANumberFormat: TsNumberFormat;
var ANextIndex: Integer): Boolean; var ANextIndex: Integer): Boolean;
function IsFractionAt(ASection,AIndex: Integer;
out AIntPart, ANumPart, ADenomPart, ANextIndex: Integer): Boolean;
function IsNumberAt(ASection,AIndex: Integer; out ANumberFormat: TsNumberFormat; function IsNumberAt(ASection,AIndex: Integer; out ANumberFormat: TsNumberFormat;
out ADecimals: Byte; out ANextIndex: Integer): Boolean; out ADecimals: Byte; out ANextIndex: Integer): Boolean;
function IsTextAt(AText: string; ASection, AIndex: Integer): Boolean; function IsTextAt(AText: string; ASection, AIndex: Integer): Boolean;
@ -308,12 +316,14 @@ begin
if element.TextValue <> '' then result := Result + '"' + element.TextValue + '"'; if element.TextValue <> '' then result := Result + '"' + element.TextValue + '"';
nftThSep, nftDecSep: nftThSep, nftDecSep:
Result := Result + element.TextValue; Result := Result + element.TextValue;
nftDigit: nftDigit, nftFracIntZeroDigit, nftFracNumZeroDigit, nftFracDenomZeroDigit:
Result := Result + '0'; Result := Result + DupeString('0', element.IntValue);
nftOptDigit, nftOptDec: nftOptDigit, nftOptDec, nftFracIntDigit, nftFracNumDigit, nftFracDenomDigit:
Result := Result + '#'; Result := Result + DupeString('#', element.IntValue);
nftOptSpaceDigit: nftOptSpaceDigit, nftFracIntSpaceDigit, nftFracNumSpaceDigit, nftFracDenomSpaceDigit:
Result := Result + '#'; /// !!!!!!!!!!! TO BE CHANGED !!!!!!!!!!!!!!!!! Result := Result + DupeString('?', element.IntValue);
nftFracSymbol:
Result := Result + '/';
nftYear: nftYear:
Result := Result + DupeString(IfThen(ADialect = nfdExcel, 'Y', 'y'), element.IntValue); Result := Result + DupeString(IfThen(ADialect = nfdExcel, 'Y', 'y'), element.IntValue);
nftMonth: nftMonth:
@ -335,7 +345,7 @@ begin
nftDecs, nftExpDigits, nftMilliseconds: nftDecs, nftExpDigits, nftMilliseconds:
Result := Result + Dupestring('0', element.IntValue); Result := Result + Dupestring('0', element.IntValue);
nftSpace, nftSign, nftSignBracket, nftExpChar, nftExpSign, nftPercent, nftSpace, nftSign, nftSignBracket, nftExpChar, nftExpSign, nftPercent,
nftFraction, nftAMPM, nftDateTimeSep: nftAMPM, nftDateTimeSep:
if element.TextValue <> '' then Result := Result + element.TextValue; if element.TextValue <> '' then Result := Result + element.TextValue;
nftCurrSymbol: nftCurrSymbol:
if element.TextValue <> '' then begin if element.TextValue <> '' then begin
@ -383,6 +393,37 @@ begin
end; end;
procedure TsNumFormatParser.CheckSection(ASection: Integer); procedure TsNumFormatParser.CheckSection(ASection: Integer);
begin
FixMonthMinuteToken(ASection);
EvalNumFormatOfSection(ASection);
end;
procedure TsNumFormatParser.ClearAll;
var
i, j: Integer;
begin
for i:=0 to Length(FSections)-1 do begin
for j:=0 to Length(FSections[i].Elements) do
if FSections[i].Elements <> nil then
FSections[i].Elements[j].TextValue := '';
FSections[i].Elements := nil;
FSections[i].CurrencySymbol := '';
end;
FSections := nil;
end;
procedure TsNumFormatParser.DeleteElement(ASection, AIndex: Integer);
var
i, n: Integer;
begin
n := Length(FSections[ASection].Elements);
for i:= AIndex+1 to n-1 do
FSections[ASection].Elements[i-1] := FSections[ASection].Elements[i];
SetLength(FSections[ASection].Elements, n-1);
end;
{ Identify the ambiguous "m" token ("month" or "minute") }
procedure TsNumFormatParser.FixMonthMinuteToken(ASection: Integer);
var var
i, j: Integer; i, j: Integer;
@ -419,7 +460,6 @@ var
end; end;
begin begin
// Fix the ambiguous "m":
for i:=0 to High(FSections[ASection].Elements) do for i:=0 to High(FSections[ASection].Elements) do
// Find index of nftMonthMinute token... // Find index of nftMonthMinute token...
if FSections[ASection].Elements[i].Token = nftMonthMinute then begin if FSections[ASection].Elements[i].Token = nftMonthMinute then begin
@ -453,41 +493,6 @@ begin
end; end;
end; end;
end; end;
EvalNumFormatOfSection(ASection);
{
FSections[ASection].NumFormat,
FSections[ASection].Decimals,
FSections[ASection].Numerator,
FSections[ASection].Denominator,
FSections[ASection].CurrencySymbol,
FSections[ASection].Color
);
}
end;
procedure TsNumFormatParser.ClearAll;
var
i, j: Integer;
begin
for i:=0 to Length(FSections)-1 do begin
for j:=0 to Length(FSections[i].Elements) do
if FSections[i].Elements <> nil then
FSections[i].Elements[j].TextValue := '';
FSections[i].Elements := nil;
FSections[i].CurrencySymbol := '';
end;
FSections := nil;
end;
procedure TsNumFormatParser.DeleteElement(ASection, AIndex: Integer);
var
i, n: Integer;
begin
n := Length(FSections[ASection].Elements);
for i:= AIndex+1 to n-1 do
FSections[ASection].Elements[i-1] := FSections[ASection].Elements[i];
SetLength(FSections[ASection].Elements, n-1);
end; end;
procedure TsNumFormatParser.InsertElement(ASection, AIndex: Integer; procedure TsNumFormatParser.InsertElement(ASection, AIndex: Integer;
@ -542,22 +547,17 @@ begin
end; end;
procedure TsNumFormatParser.EvalNumFormatOfSection(ASection: Integer); procedure TsNumFormatParser.EvalNumFormatOfSection(ASection: Integer);
{
out ANumFormat: TsNumberFormat; out ADecimals: byte;
out ANumerator, ADenominator: Integer; out ACurrencySymbol: String;
out AColor: TsColor);
}
var var
nf, nf1: TsNumberFormat; nf, nf1: TsNumberFormat;
next: Integer = 0; next: Integer = 0;
decs, num, denom: Byte; decs: Byte;
intPart, numPart, denomPart: Integer;
cs: String; cs: String;
clr: TsColor; clr: TsColor;
tok: TsNumFormatToken;
begin begin
nf := nfCustom; nf := nfCustom;
decs := 0; decs := 0;
num := 0;
denom := 0;
cs := ''; cs := '';
clr := scNotDefined; clr := scNotDefined;
@ -567,7 +567,7 @@ begin
exit; exit;
end; end;
// Look for number formats // Look for number formats (note: fractions are rarely used --> at end)
if IsNumberAt(ASection, 0, nf, decs, next) then begin if IsNumberAt(ASection, 0, nf, decs, next) then begin
// nfFixed, nfFixedTh // nfFixed, nfFixedTh
if next = Length(Elements) then if next = Length(Elements) then
@ -583,28 +583,6 @@ begin
FSections[ASection].Decimals := decs; FSections[ASection].Decimals := decs;
exit; exit;
end; end;
// nfFraction
if (IsTokenAt(nftSpace, ASection, next) or IsTextAt(' ', ASection, next)) and
IsNumberAt(ASection, next+1, nf, num, next) and
IsTokenAt(nftFraction, ASection, next) and
IsNumberAt(ASection, next+1, nf, denom, next) and
(next = Length(Elements))
then begin
FSections[ASection].NumFormat := nfFraction;
FSections[ASection].FracInt := integer(decs); // "decs" means "number of integer digits", here
FSections[ASection].FracNumerator := integer(num);
FSections[ASection].FracDenominator := integer(denom);
exit;
end;
if IsTokenAt(nftFraction, ASection, next) and
IsNumberAt(ASection, next+1, nf, denom, next) and
(next = Length(Elements))
then begin
FSections[ASection].NumFormat := nfFraction;
FSections[ASection].FracNumerator := integer(decs);
FSections[ASection].FracDenominator := integer(denom);
exit;
end;
// nfExp // nfExp
if IsTokenAt(nftExpChar, ASection, next) then begin if IsTokenAt(nftExpChar, ASection, next) then begin
if IsTokenAt(nftExpSign, ASection, next+1) and IsTokenAt(nftExpDigits, ASection, next+2) and if IsTokenAt(nftExpSign, ASection, next+1) and IsTokenAt(nftExpDigits, ASection, next+2) and
@ -653,6 +631,17 @@ begin
FSections[ASection].NumFormat := nf; FSections[ASection].NumFormat := nf;
exit; exit;
end; end;
// Look for fractions
if IsFractionAt(ASection, 0, intPart, numPart, denomPart, next) then
if next = Length(Elements) then
begin
FSections[ASection].NumFormat := nfFraction;
FSections[ASection].FracInt := intPart;
FSections[ASection].FracNumerator := numPart;
FSections[ASection].FracDenominator := denomPart;
exit;
end;
end; end;
// If we get here it must be a custom format. // If we get here it must be a custom format.
@ -789,6 +778,15 @@ begin
Result := FSections[AIndex]; Result := FSections[AIndex];
end; end;
function TsNumFormatParser.GetTokenIntValueAt(AToken: TsNumFormatToken;
ASection, AIndex: Integer): Integer;
begin
if IsTokenAt(AToken, ASection, AIndex) then
Result := FSections[ASection].Elements[AIndex].IntValue
else
Result := -1;
end;
{ Checks if a currency-type of format string begins at index AIndex, and returns { Checks if a currency-type of format string begins at index AIndex, and returns
the numberformat code, the count of decimals, the currency sambol, and the the numberformat code, the count of decimals, the currency sambol, and the
color. color.
@ -969,10 +967,70 @@ begin
Result := false; Result := false;
end; end;
function TsNumFormatParser.IsFractionAt(ASection,AIndex: Integer;
out AIntPart, ANumPart, ADenomPart, ANextIndex: Integer): Boolean;
var
tok: TsNumFormatToken;
section: TsNumFormatSection;
begin
Result := false;
AIntPart := 0;
ANumPart := 0;
ADenomPart := 0;
ANextIndex := MaxInt;
if ASection > High(FSections) then
exit;
section := FSections[ASection];
if AIndex > High(section.Elements) then
exit;
// integer part of the fraction
tok := section.Elements[AIndex].Token;
if tok in [nftFracIntDigit, nftFracIntSpaceDigit, nftFracIntZeroDigit] then
begin
AIntPart := section.Elements[AIndex].IntValue;
inc(AIndex);
end;
// Skip space(s)
while (AIndex <= High(section.Elements)) and
(IsTokenAt(nftSpace, ASection, AIndex) or IsTextAt(' ', ASection, AIndex))
do
inc(AIndex);
if AIndex > High(section.Elements) then
exit;
// numerator
tok := section.Elements[AIndex].Token;
if tok in [nftFracNumDigit, nftFracNumSpaceDigit, nftFracNumZeroDigit] then
ANumPart := section.Elements[AIndex].IntValue
else
exit;
// Skip space(s) and fraction symbol
inc(AIndex);
while (AIndex <= High(section.Elements)) and
(IsTokenAt(nftSpace, ASection, AIndex) or
IsTextAt(' ', ASection, AIndex) or
IsTokenAt(nftFracSymbol, ASection, AIndex))
do
inc(AIndex);
// denominator
tok := section.Elements[AIndex].Token;
if tok in [nftFracDenomDigit, nftFracDenomSpaceDigit, nftFracDenomZeroDigit] then
begin
ADenomPart := section.Elements[AIndex].IntValue;
ANextIndex := AIndex + 1;
Result := true;
end;
end;
{ Checks whether the format tokens beginning at AIndex for ASection represent { Checks whether the format tokens beginning at AIndex for ASection represent
at standard number format, like nfFixed, nfPercentage etc. at standard number format, like nfFixed, nfPercentage etc.
Returns TRUE if it does. Returns TRUE if it does.
NOTE: ADecimals can have various meanings -- see EvalNumFormatOfSection} NOTE: Fraction format is not checked here --> see: IsFractionAt }
function TsNumFormatParser.IsNumberAt(ASection,AIndex: Integer; function TsNumFormatParser.IsNumberAt(ASection,AIndex: Integer;
out ANumberFormat: TsNumberFormat; out ADecimals: Byte; out ANumberFormat: TsNumberFormat; out ADecimals: Byte;
out ANextIndex: Integer): Boolean; out ANextIndex: Integer): Boolean;
@ -1005,54 +1063,26 @@ begin
// Now look also for optional digits ('#') // Now look also for optional digits ('#')
if IsTokenAt(nftOptDigit, ASection, AIndex) then begin // '#' if IsTokenAt(nftOptDigit, ASection, AIndex) then begin // '#'
if IsTokenAt(nftThSep, ASection, AIndex+1) and // ',' if IsTokenAt(nftThSep, ASection, AIndex+1) and // ','
IsTokenAt(nftOptDigit, ASection, AIndex+2) and // '#' (GetTokenIntValueAt(nftOptDigit, ASection, AIndex+2) = 2) and // '##'
IsTokenAt(nftOptDigit, ASection, Aindex+3) and // '#' (GetTokenIntValueAt(nftDigit, ASection, AIndex+3) = 1) // '0'
IsTokenAt(nftDigit, ASection, AIndex+4) // '0'
then begin then begin
if IsTokenAt(nftDecSep, ASection, AIndex+5) and // '.' if IsTokenAt(nftDecSep, ASection, AIndex+4) and // '.'
IsTokenAt(nftDecs, ASection, AIndex+6) // count of decimals IsTokenAt(nftDecs, ASection, AIndex+5) // count of decimals
then begin then begin
// This is the case with decimal separator, like "#,##0.000" // This is the case with decimal separator, like "#,##0.000"
Result := true; Result := true;
ANumberFormat := nfFixedTh; ANumberFormat := nfFixedTh;
ADecimals := FSections[ASection].Elements[AIndex+6].IntValue; ADecimals := FSections[ASection].Elements[AIndex+5].IntValue;
ANextIndex := AIndex+7; ANextIndex := AIndex + 6;
end else end else
if not IsTokenAt(nftDecSep, ASection, AIndex+5) then begin if not IsTokenAt(nftDecSep, ASection, AIndex+4) then begin
// and this is without decimal separator, "#,##0" // and this is without decimal separator, "#,##0"
result := true; result := true;
ANumberFormat := nfFixedTh; ANumberFormat := nfFixedTh;
ADecimals := 0; ADecimals := 0;
ANextIndex := AIndex + 5; ANextIndex := AIndex + 4;
end; end;
end else
begin // Isolated '#'
result := true;
inc(AIndex);
ANextIndex := AIndex;
ADecimals := 1;
while IsTokenAt(nftOptDigit, ASection, AIndex) do
begin
inc(AIndex);
inc(ANextIndex);
inc(ADecimals);
end; end;
ANumberFormat := nfFraction;
end;
end else
if IsTokenAt(nftOptSpaceDigit, ASection, AIndex) then // '?'
begin
Result := true;
inc(AIndex);
ANextIndex := AIndex;
ADecimals := 1;
while IsTokenAt(nftOptSpaceDigit, ASection, AIndex) do
begin
inc(AIndex);
inc(ANextIndex);
inc(ADecimals);
end;
ANumberFormat := nfFraction;
end; end;
end; end;
@ -1602,9 +1632,12 @@ end;
procedure TsNumFormatParser.ScanNumber; procedure TsNumFormatParser.ScanNumber;
var var
hasDecSep: Boolean; hasDecSep: Boolean;
isFrac: Boolean;
n: Integer; n: Integer;
elem: Integer;
begin begin
hasDecSep := false; hasDecSep := false;
isFrac := false;
while (FCurrent < FEnd) and (FStatus = psOK) do begin while (FCurrent < FEnd) and (FStatus = psOK) do begin
case FToken of case FToken of
',': AddElement(nftThSep, ','); ',': AddElement(nftThSep, ',');
@ -1612,12 +1645,17 @@ begin
AddElement(nftDecSep, '.'); AddElement(nftDecSep, '.');
hasDecSep := true; hasDecSep := true;
end; end;
'0': if hasDecSep then begin '0': begin
ScanAndCount('0', n); ScanAndCount('0', n);
FToken := PrevToken; FToken := PrevToken;
AddElement(nftDecs, n); if hasDecSep then
end else AddElement(nftDecs, n)
AddElement(nftDigit, '0'); else
if isFrac then
AddElement(nftFracDenomZeroDigit, n)
else
Addelement(nftDigit, n);
end;
'E', 'e': 'E', 'e':
begin begin
AddElement(nftExpChar, FToken); AddElement(nftExpChar, FToken);
@ -1633,10 +1671,52 @@ begin
end; end;
'+', '-': '+', '-':
AddElement(nftSign, FToken); AddElement(nftSign, FToken);
'#': AddElement(nftOptDigit, FToken); '#': begin
'?': AddElement(nftOptSpaceDigit, FToken); ScanAndCount('#', n);
FToken := PrevToken;
if isFrac then
AddElement(nftFracDenomDigit, n)
else
AddElement(nftOptDigit, n);
end;
'?': begin
ScanAndCount('?', n);
FToken := PrevToken;
if isFrac then
AddElement(nftFracDenomSpaceDigit, n)
else
AddElement(nftOptSpaceDigit, n);
end;
'%': AddElement(nftPercent, FToken); '%': AddElement(nftPercent, FToken);
'/': AddElement(nftFraction, FToken); '/': begin
isFrac := true;
AddElement(nftFracSymbol, FToken);
// go back and replace correct token for numerator (n=0) and integer part (n=1)
n := 0;
elem := High(FSections[FCurrSection].Elements);
while elem > 0 do begin
dec(elem);
case FSections[FCurrSection].Elements[elem].Token of
nftOptDigit:
if n = 0 then
FSections[FCurrSection].Elements[elem].Token := nftFracNumDigit
else
FSections[FCurrSection].Elements[elem].Token := nftFracIntDigit;
nftOptSpaceDigit:
if n = 0 then
FSections[FCurrSection].Elements[elem].Token := nftFracNumSpaceDigit
else
FSections[FCurrSection].Elements[elem].Token := nftFracIntSpaceDigit;
nftDigit:
if n = 0 then
FSections[FCurrSection].Elements[elem].Token := nftFracNumZeroDigit
else
FSections[FCurrSection].Elements[elem].Token := nftFracIntZeroDigit;
end;
inc(n);
end;
end;
else else
FToken := PrevToken; FToken := PrevToken;
Exit; Exit;

View File

@ -315,7 +315,7 @@ end;
function TsSpreadOpenDocNumFormatParser.BuildCurrencyXMLAsString(ASection: Integer): String; function TsSpreadOpenDocNumFormatParser.BuildCurrencyXMLAsString(ASection: Integer): String;
var var
el: Integer; el, next: Integer;
clr: TsColorValue; clr: TsColorValue;
nf: TsNumberFormat; nf: TsNumberFormat;
decs: byte; decs: byte;
@ -354,15 +354,21 @@ begin
inc(el); inc(el);
end; end;
nftOptDigit: nftOptDigit:
if IsNumberAt(ASection, el, nf, decs, el) then if IsNumberAt(ASection, el, nf, decs, next) then
begin
Result := Result + Result := Result +
' <number:number decimal-places="' + IntToStr(decs) + ' <number:number decimal-places="' + IntToStr(decs) +
'" number:min-integer-digits="1" number:grouping="true" />'; '" number:min-integer-digits="1" number:grouping="true" />';
el := next;
end;
nftDigit: nftDigit:
if IsNumberAt(ASection, el, nf, decs, el) then if IsNumberAt(ASection, el, nf, decs, next) then
begin
Result := Result + Result := Result +
' <number:number decimal-places="' + IntToStr(decs) + ' <number:number decimal-places="' + IntToStr(decs) +
'" number:min-integer-digits="1" />'; '" number:min-integer-digits="1" />';
el := next;
end;
nftRepeat: nftRepeat:
begin begin
if FSections[ASection].Elements[el].TextValue = ' ' then if FSections[ASection].Elements[el].TextValue = ' ' then
@ -498,7 +504,7 @@ var
nf : TsNumberFormat; nf : TsNumberFormat;
decs: Byte; decs: Byte;
expdig: Integer; expdig: Integer;
next: Integer; curr, next: Integer;
sGrouping: String; sGrouping: String;
sColor: String; sColor: String;
sStyleMap: String; sStyleMap: String;
@ -508,7 +514,7 @@ var
s: String; s: String;
isTimeOnly: Boolean; isTimeOnly: Boolean;
isInterval: Boolean; isInterval: Boolean;
num, denom: byte; intPart, numPart, denomPart: Integer;
begin begin
Result := ''; Result := '';
@ -545,14 +551,14 @@ begin
with FSections[ASection] do with FSections[ASection] do
begin begin
next := 0; curr := 0;
if IsTokenAt(nftColor, ASection, 0) then if IsTokenAt(nftColor, ASection, 0) then
begin begin
clr := FWorkbook.GetPaletteColor(Elements[0].IntValue); clr := FWorkbook.GetPaletteColor(Elements[0].IntValue);
sColor := '<style:text-properties fo:color="' + ColorToHTMLColorStr(clr) + '" />' + LineEnding; sColor := '<style:text-properties fo:color="' + ColorToHTMLColorStr(clr) + '" />' + LineEnding;
next := 1; curr := 1;
end; end;
if IsNumberAt(ASection, next, nf, decs, next) then if IsNumberAt(ASection, curr, nf, decs, next) then
begin begin
if nf = nfFixedTh then if nf = nfFixedTh then
sGrouping := 'number:grouping="true" '; sGrouping := 'number:grouping="true" ';
@ -572,39 +578,6 @@ begin
exit; exit;
end; end;
// nfFraction
if IsTextAt(' ', ASection, next) and
IsNumberAt(ASection, next+1, nf, num, next) and
IsTokenAt(nftFraction, ASection, next) and
IsNumberAt(ASection, next+1, nf, denom, next) and
(next = Length(Elements))
then begin
Result :=
'<number:number-style style:name="' + AFormatName + '">' +
sColor +
'<number:fraction ' +
'number:min-integer-digits="' + IntToStr(decs) + '" ' +
'number:min-numerator-digits="' + IntToStr(num) + '" ' +
'number:min-denominator-digits="' + IntToStr(denom) + '" ' +
'/>' +
'</number:number-style>';
exit;
end;
if IsTokenAt(nftFraction, ASection, next) and
IsNumberAt(ASection, next+1, nf, denom, next) and
(next = Length(Elements))
then begin
Result :=
'<number:number-style style:name="' + AFormatName + '">' +
sColor +
'<number:fraction ' +
'number:min-numerator-digits="' + IntToStr(decs) + '" ' +
'number:min-denominator-digits="' + IntToStr(denom) + '" ' +
'/>' +
'</number:number-style>';
exit;
end;
// nfPercentage // nfPercentage
if IsTokenAt(nftPercent, ASection, next) and (next+1 = Length(Elements)) then if IsTokenAt(nftPercent, ASection, next) and (next+1 = Length(Elements)) then
begin begin
@ -647,7 +620,25 @@ begin
end; end;
end; end;
// If the program gets here the format can only be nfSci, nfCurrency or date/time. // nfFraction
if IsFractionAt(ASection, curr, intPart, numPart, denomPart, next)
then begin
Result :=
'<number:number-style style:name="' + AFormatName + '">' +
sColor +
'<number:fraction ';
if intPart > 0 then
Result := Result +
'number:min-integer-digits="' + IntToStr(intPart) + '" ';
Result := Result +
'number:min-numerator-digits="' + IntToStr(numPart) + '" ' +
'number:min-denominator-digits="' + IntToStr(denomPart) + '" ' +
'/>' +
'</number:number-style>';
exit;
end;
// If the program gets here the format can only be Currency or date/time.
el := 0; el := 0;
decs := 0; decs := 0;
while el < Length(Elements) do while el < Length(Elements) do