You've already forked lazarus-ccr
fpspreadsheet: Extend number format parser to accept the keyword "General" in custom formats
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4161 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -23,7 +23,8 @@ const
|
|||||||
psErrMultipleCurrSymbols = 9;
|
psErrMultipleCurrSymbols = 9;
|
||||||
psErrMultipleFracSymbols = 10;
|
psErrMultipleFracSymbols = 10;
|
||||||
psErrMultipleExpChars = 11;
|
psErrMultipleExpChars = 11;
|
||||||
psAmbiguousSymbol = 12;
|
psErrGeneralExpected = 12;
|
||||||
|
psAmbiguousSymbol = 13;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ type
|
|||||||
|
|
||||||
{ Administration while scanning }
|
{ Administration while scanning }
|
||||||
procedure AddElement(AToken: TsNumFormatToken; AText: String); overload;
|
procedure AddElement(AToken: TsNumFormatToken; AText: String); overload;
|
||||||
procedure AddElement(AToken: TsNumFormatToken; AIntValue: Integer); overload;
|
procedure AddElement(AToken: TsNumFormatToken; AIntValue: Integer=0); overload;
|
||||||
procedure AddElement(AToken: TsNumFormatToken; AFloatValue: Double); overload;
|
procedure AddElement(AToken: TsNumFormatToken; AFloatValue: Double); overload;
|
||||||
procedure AddSection;
|
procedure AddSection;
|
||||||
procedure DeleteElement(ASection, AIndex: Integer);
|
procedure DeleteElement(ASection, AIndex: Integer);
|
||||||
@ -72,6 +73,7 @@ type
|
|||||||
procedure ScanCurrSymbol;
|
procedure ScanCurrSymbol;
|
||||||
procedure ScanDateTime;
|
procedure ScanDateTime;
|
||||||
procedure ScanFormat;
|
procedure ScanFormat;
|
||||||
|
procedure ScanGeneral;
|
||||||
procedure ScanNumber;
|
procedure ScanNumber;
|
||||||
procedure ScanQuotedText;
|
procedure ScanQuotedText;
|
||||||
// Main scanner
|
// Main scanner
|
||||||
@ -190,7 +192,7 @@ begin
|
|||||||
FSections[FCurrSection].Elements[n].TextValue := AText;
|
FSections[FCurrSection].Elements[n].TextValue := AText;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsNumFormatParser.AddElement(AToken: TsNumFormatToken; AIntValue: Integer);
|
procedure TsNumFormatParser.AddElement(AToken: TsNumFormatToken; AIntValue: Integer=0);
|
||||||
var
|
var
|
||||||
n: Integer;
|
n: Integer;
|
||||||
begin
|
begin
|
||||||
@ -359,7 +361,10 @@ begin
|
|||||||
section^.Kind := section^.Kind + [nfkTimeInterval];
|
section^.Kind := section^.Kind + [nfkTimeInterval];
|
||||||
end;
|
end;
|
||||||
nftColor:
|
nftColor:
|
||||||
section^.Kind := section^.Kind + [nfkHasColor];
|
begin
|
||||||
|
section^.Kind := section^.Kind + [nfkHasColor];
|
||||||
|
section^.Color := section^.Elements[el].IntValue;
|
||||||
|
end;
|
||||||
nftIntTh:
|
nftIntTh:
|
||||||
section^.Kind := section^.Kind + [nfkHasThSep];
|
section^.Kind := section^.Kind + [nfkHasThSep];
|
||||||
end;
|
end;
|
||||||
@ -932,8 +937,11 @@ begin
|
|||||||
FStatus := psOK;
|
FStatus := psOK;
|
||||||
|
|
||||||
AddSection;
|
AddSection;
|
||||||
if (AFormatString = '') or SameText(AFormatString, 'General') then
|
if (AFormatString = '') then
|
||||||
|
begin
|
||||||
|
AddElement(nftGeneral);
|
||||||
exit;
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
FStart := @AFormatString[1];
|
FStart := @AFormatString[1];
|
||||||
FEnd := FStart + Length(AFormatString);
|
FEnd := FStart + Length(AFormatString);
|
||||||
@ -941,6 +949,7 @@ begin
|
|||||||
FToken := FCurrent^;
|
FToken := FCurrent^;
|
||||||
while (FCurrent < FEnd) and (FStatus = psOK) do begin
|
while (FCurrent < FEnd) and (FStatus = psOK) do begin
|
||||||
case FToken of
|
case FToken of
|
||||||
|
'G','g': ScanGeneral;
|
||||||
'[': ScanBrackets;
|
'[': ScanBrackets;
|
||||||
'"': ScanQuotedText;
|
'"': ScanQuotedText;
|
||||||
':': AddElement(nftDateTimeSep, ':');
|
':': AddElement(nftDateTimeSep, ':');
|
||||||
@ -1264,6 +1273,8 @@ begin
|
|||||||
ScanAMPM;
|
ScanAMPM;
|
||||||
FToken := PrevToken;
|
FToken := PrevToken;
|
||||||
end;
|
end;
|
||||||
|
'G', 'g':
|
||||||
|
ScanGeneral;
|
||||||
';': // End of the section. Important: Cursor must stay on ';'
|
';': // End of the section. Important: Cursor must stay on ';'
|
||||||
begin
|
begin
|
||||||
AddSection;
|
AddSection;
|
||||||
@ -1276,6 +1287,26 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Scans for the word "General", it may be used like other tokens }
|
||||||
|
procedure TsNumFormatParser.ScanGeneral;
|
||||||
|
begin
|
||||||
|
FStatus := psErrGeneralExpected;
|
||||||
|
FToken := NextToken;
|
||||||
|
if not (FToken in ['e', 'E']) then exit;
|
||||||
|
FToken := NextToken;
|
||||||
|
if not (FToken in ['n', 'N']) then exit;
|
||||||
|
FToken := NextToken;
|
||||||
|
if not (FToken in ['e', 'E']) then exit;
|
||||||
|
FToken := NextToken;
|
||||||
|
if not (FToken in ['r', 'R']) then exit;
|
||||||
|
FToken := NextToken;
|
||||||
|
if not (FToken in ['a', 'A']) then exit;
|
||||||
|
FToken := NextToken;
|
||||||
|
if not (FToken in ['l', 'L']) then exit;
|
||||||
|
AddElement(nftGeneral);
|
||||||
|
FStatus := psOK;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Scans a floating point format. Procedure is left with the cursor at the last
|
{ Scans a floating point format. Procedure is left with the cursor at the last
|
||||||
character of the format. }
|
character of the format. }
|
||||||
procedure TsNumFormatParser.ScanNumber;
|
procedure TsNumFormatParser.ScanNumber;
|
||||||
@ -1427,7 +1458,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
'G', 'g':
|
||||||
|
ScanGeneral;
|
||||||
else
|
else
|
||||||
FToken := PrevToken;
|
FToken := PrevToken;
|
||||||
Exit;
|
Exit;
|
||||||
|
@ -626,6 +626,9 @@ begin
|
|||||||
nftCurrSymbol:
|
nftCurrSymbol:
|
||||||
Result := Result + '<number:currency-symbol>' + Elements[el].TextValue + '</number:currency-symbol>';
|
Result := Result + '<number:currency-symbol>' + Elements[el].TextValue + '</number:currency-symbol>';
|
||||||
|
|
||||||
|
nftGeneral:
|
||||||
|
Result := Result + '<number:number number:min-integer-digits="1" />';
|
||||||
|
|
||||||
nftIntTh:
|
nftIntTh:
|
||||||
begin
|
begin
|
||||||
Result := Result + '<number:number number:min-integer-digits="1" number:grouping="true"';
|
Result := Result + '<number:number number:min-integer-digits="1" number:grouping="true"';
|
||||||
@ -2256,19 +2259,27 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
|
|||||||
if nodeName = 'number:number' then
|
if nodeName = 'number:number' then
|
||||||
begin
|
begin
|
||||||
s := GetAttrValue(node, 'number:decimal-places');
|
s := GetAttrValue(node, 'number:decimal-places');
|
||||||
if s = '' then s := GetAttrValue(node, 'decimal-places');
|
if s = '' then
|
||||||
if s <> '' then decs := StrToInt(s) else decs := 0;
|
s := GetAttrValue(node, 'decimal-places');
|
||||||
grouping := GetAttrValue(node, 'number:grouping') = 'true';
|
if s = '' then
|
||||||
s := GetAttrValue(node, 'number:display-factor');
|
begin
|
||||||
if s <> '' then f := StrToFloat(s, FPointSeparatorSettings) else f := 1.0;
|
if nfs='' then nf := nfGeneral else nf := nfCustom;
|
||||||
nf := IfThen(grouping, nfFixedTh, nfFixed);
|
nfs := nfs + 'General';
|
||||||
nfs := nfs + BuildNumberFormatString(nf, Workbook.FormatSettings, decs);
|
end else
|
||||||
if f <> 1.0 then begin
|
begin
|
||||||
nf := nfCustom;
|
decs := StrToInt(s);
|
||||||
while (f > 1.0) do
|
grouping := GetAttrValue(node, 'number:grouping') = 'true';
|
||||||
begin
|
s := GetAttrValue(node, 'number:display-factor');
|
||||||
nfs := nfs + ',';
|
if s <> '' then f := StrToFloat(s, FPointSeparatorSettings) else f := 1.0;
|
||||||
f := f / 1000;
|
nf := IfThen(grouping, nfFixedTh, nfFixed);
|
||||||
|
nfs := nfs + BuildNumberFormatString(nf, Workbook.FormatSettings, decs);
|
||||||
|
if f <> 1.0 then begin
|
||||||
|
nf := nfCustom;
|
||||||
|
while (f > 1.0) do
|
||||||
|
begin
|
||||||
|
nfs := nfs + ',';
|
||||||
|
f := f / 1000;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
|
@ -502,6 +502,7 @@ type
|
|||||||
|
|
||||||
{@@ Tokens used by the elements of the number format parser }
|
{@@ Tokens used by the elements of the number format parser }
|
||||||
TsNumFormatToken = (
|
TsNumFormatToken = (
|
||||||
|
nftGeneral, // token for "general" number format
|
||||||
nftText, // must be quoted, stored in TextValue
|
nftText, // must be quoted, stored in TextValue
|
||||||
nftThSep, // ',', replaced by FormatSettings.ThousandSeparator
|
nftThSep, // ',', replaced by FormatSettings.ThousandSeparator
|
||||||
nftDecSep, // '.', replaced by FormatSettings.DecimalSeparator
|
nftDecSep, // '.', replaced by FormatSettings.DecimalSeparator
|
||||||
@ -970,6 +971,8 @@ begin
|
|||||||
for i := 0 to High(ASection.Elements) do begin
|
for i := 0 to High(ASection.Elements) do begin
|
||||||
element := ASection.Elements[i];
|
element := ASection.Elements[i];
|
||||||
case element.Token of
|
case element.Token of
|
||||||
|
nftGeneral:
|
||||||
|
Result := Result + 'General';
|
||||||
nftIntOptDigit, nftOptDecs, nftFracNumOptDigit, nftFracDenomOptDigit:
|
nftIntOptDigit, nftOptDecs, nftFracNumOptDigit, nftFracDenomOptDigit:
|
||||||
if element.IntValue > 0 then
|
if element.IntValue > 0 then
|
||||||
Result := Result + DupeString('#', element.IntValue);
|
Result := Result + DupeString('#', element.IntValue);
|
||||||
|
@ -2880,6 +2880,13 @@ begin
|
|||||||
|
|
||||||
el := 0;
|
el := 0;
|
||||||
while (el < numEl) do begin
|
while (el < numEl) do begin
|
||||||
|
if section.Elements[el].Token = nftGeneral then
|
||||||
|
begin
|
||||||
|
s := FloatToStrF(AValue, ffGeneral, 20, 20, fs);
|
||||||
|
if (sidx=0) and isNeg then s := '-' + s;
|
||||||
|
Result := Result + s;
|
||||||
|
end
|
||||||
|
else
|
||||||
// Integer token: can be the start of a number, exp, or mixed fraction format
|
// Integer token: can be the start of a number, exp, or mixed fraction format
|
||||||
// Cases with thousand separator are handled here as well.
|
// Cases with thousand separator are handled here as well.
|
||||||
if section.Elements[el].Token in (INT_TOKENS + [nftIntTh]) then begin
|
if section.Elements[el].Token in (INT_TOKENS + [nftIntTh]) then begin
|
||||||
|
@ -440,7 +440,6 @@ end;*)
|
|||||||
procedure TsSpreadBIFF2Reader.ReadFormat(AStream: TStream);
|
procedure TsSpreadBIFF2Reader.ReadFormat(AStream: TStream);
|
||||||
var
|
var
|
||||||
len: byte;
|
len: byte;
|
||||||
fmtIndex: Integer;
|
|
||||||
fmtString: AnsiString;
|
fmtString: AnsiString;
|
||||||
nfs: String;
|
nfs: String;
|
||||||
begin
|
begin
|
||||||
|
@ -1200,7 +1200,6 @@ procedure TsSpreadBIFF5Writer.WriteFont(AStream: TStream; AFont: TsFont);
|
|||||||
var
|
var
|
||||||
Len: Byte;
|
Len: Byte;
|
||||||
optn: Word;
|
optn: Word;
|
||||||
cidx: Integer;
|
|
||||||
begin
|
begin
|
||||||
if AFont = nil then // this happens for FONT4 in case of BIFF
|
if AFont = nil then // this happens for FONT4 in case of BIFF
|
||||||
exit;
|
exit;
|
||||||
|
Reference in New Issue
Block a user