diff --git a/components/fpspreadsheet/fpsnumformatparser.pas b/components/fpspreadsheet/fpsnumformatparser.pas index d562bd5d5..b0b416b18 100644 --- a/components/fpspreadsheet/fpsnumformatparser.pas +++ b/components/fpspreadsheet/fpsnumformatparser.pas @@ -23,7 +23,8 @@ const psErrMultipleCurrSymbols = 9; psErrMultipleFracSymbols = 10; psErrMultipleExpChars = 11; - psAmbiguousSymbol = 12; + psErrGeneralExpected = 12; + psAmbiguousSymbol = 13; type @@ -54,7 +55,7 @@ type { Administration while scanning } 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 AddSection; procedure DeleteElement(ASection, AIndex: Integer); @@ -72,6 +73,7 @@ type procedure ScanCurrSymbol; procedure ScanDateTime; procedure ScanFormat; + procedure ScanGeneral; procedure ScanNumber; procedure ScanQuotedText; // Main scanner @@ -190,7 +192,7 @@ begin FSections[FCurrSection].Elements[n].TextValue := AText; end; -procedure TsNumFormatParser.AddElement(AToken: TsNumFormatToken; AIntValue: Integer); +procedure TsNumFormatParser.AddElement(AToken: TsNumFormatToken; AIntValue: Integer=0); var n: Integer; begin @@ -359,7 +361,10 @@ begin section^.Kind := section^.Kind + [nfkTimeInterval]; end; nftColor: - section^.Kind := section^.Kind + [nfkHasColor]; + begin + section^.Kind := section^.Kind + [nfkHasColor]; + section^.Color := section^.Elements[el].IntValue; + end; nftIntTh: section^.Kind := section^.Kind + [nfkHasThSep]; end; @@ -932,8 +937,11 @@ begin FStatus := psOK; AddSection; - if (AFormatString = '') or SameText(AFormatString, 'General') then + if (AFormatString = '') then + begin + AddElement(nftGeneral); exit; + end; FStart := @AFormatString[1]; FEnd := FStart + Length(AFormatString); @@ -941,6 +949,7 @@ begin FToken := FCurrent^; while (FCurrent < FEnd) and (FStatus = psOK) do begin case FToken of + 'G','g': ScanGeneral; '[': ScanBrackets; '"': ScanQuotedText; ':': AddElement(nftDateTimeSep, ':'); @@ -1264,6 +1273,8 @@ begin ScanAMPM; FToken := PrevToken; end; + 'G', 'g': + ScanGeneral; ';': // End of the section. Important: Cursor must stay on ';' begin AddSection; @@ -1276,6 +1287,26 @@ begin 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 character of the format. } procedure TsNumFormatParser.ScanNumber; @@ -1427,7 +1458,8 @@ begin end; end; end; - + 'G', 'g': + ScanGeneral; else FToken := PrevToken; Exit; diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index a5c62f0b7..d6331ef8b 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -626,6 +626,9 @@ begin nftCurrSymbol: Result := Result + '' + Elements[el].TextValue + ''; + nftGeneral: + Result := Result + ''; + nftIntTh: begin Result := Result + ' '' then decs := StrToInt(s) else decs := 0; - grouping := GetAttrValue(node, 'number:grouping') = 'true'; - s := GetAttrValue(node, 'number:display-factor'); - if s <> '' then f := StrToFloat(s, FPointSeparatorSettings) else f := 1.0; - 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; + if s = '' then + s := GetAttrValue(node, 'decimal-places'); + if s = '' then + begin + if nfs='' then nf := nfGeneral else nf := nfCustom; + nfs := nfs + 'General'; + end else + begin + decs := StrToInt(s); + grouping := GetAttrValue(node, 'number:grouping') = 'true'; + s := GetAttrValue(node, 'number:display-factor'); + if s <> '' then f := StrToFloat(s, FPointSeparatorSettings) else f := 1.0; + 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 else diff --git a/components/fpspreadsheet/fpstypes.pas b/components/fpspreadsheet/fpstypes.pas index 03698ae2d..c838b016f 100644 --- a/components/fpspreadsheet/fpstypes.pas +++ b/components/fpspreadsheet/fpstypes.pas @@ -502,6 +502,7 @@ type {@@ Tokens used by the elements of the number format parser } TsNumFormatToken = ( + nftGeneral, // token for "general" number format nftText, // must be quoted, stored in TextValue nftThSep, // ',', replaced by FormatSettings.ThousandSeparator nftDecSep, // '.', replaced by FormatSettings.DecimalSeparator @@ -970,6 +971,8 @@ begin for i := 0 to High(ASection.Elements) do begin element := ASection.Elements[i]; case element.Token of + nftGeneral: + Result := Result + 'General'; nftIntOptDigit, nftOptDecs, nftFracNumOptDigit, nftFracDenomOptDigit: if element.IntValue > 0 then Result := Result + DupeString('#', element.IntValue); diff --git a/components/fpspreadsheet/fpsutils.pas b/components/fpspreadsheet/fpsutils.pas index 3b5a3da7e..f5b278c77 100644 --- a/components/fpspreadsheet/fpsutils.pas +++ b/components/fpspreadsheet/fpsutils.pas @@ -2880,6 +2880,13 @@ begin el := 0; 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 // Cases with thousand separator are handled here as well. if section.Elements[el].Token in (INT_TOKENS + [nftIntTh]) then begin diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index 3d81a3249..0b380a121 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -440,7 +440,6 @@ end;*) procedure TsSpreadBIFF2Reader.ReadFormat(AStream: TStream); var len: byte; - fmtIndex: Integer; fmtString: AnsiString; nfs: String; begin diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 40dc84665..0a7409963 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -1200,7 +1200,6 @@ procedure TsSpreadBIFF5Writer.WriteFont(AStream: TStream; AFont: TsFont); var Len: Byte; optn: Word; - cidx: Integer; begin if AFont = nil then // this happens for FONT4 in case of BIFF exit;