From 9f69ce203a233cf115c867ee952e2c3f3a182937 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Fri, 13 Jun 2014 20:11:41 +0000 Subject: [PATCH] fpspreadsheet: Fix ods number format issues introduced with new number format parser. No regressions in test suite any more. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3166 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/fpspreadsheet/fpsnumformatparser.pas | 17 ++++++++++------- components/fpspreadsheet/fpsopendocument.pas | 16 +++++++++++++--- components/fpspreadsheet/fpsutils.pas | 14 +++++++++++++- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/components/fpspreadsheet/fpsnumformatparser.pas b/components/fpspreadsheet/fpsnumformatparser.pas index 475141d7c..635b7f0b9 100644 --- a/components/fpspreadsheet/fpsnumformatparser.pas +++ b/components/fpspreadsheet/fpsnumformatparser.pas @@ -177,8 +177,6 @@ const '', '=', '<>', '<', '>', '<=', '>' ); -var - globalfmt: String; { TsNumFormatParser } @@ -187,11 +185,6 @@ var constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook; const AFormatString: String); begin - - - globalfmt := AFormatString; - - inherited Create; FCreateMethod := 0; FWorkbook := AWorkbook; @@ -1015,6 +1008,11 @@ function TsNumFormatParser.IsDateAt(ASection,AIndex: Integer; var i: Integer; begin + if FWorkbook = nil then begin + Result := false; + exit; + end; + // The default format nfShortDate is defined by the ShortDateFormat of the // Workbook's FormatSettings. Check whether the current format string matches. // But watch out for different date separators! @@ -1234,6 +1232,11 @@ var i: Integer; fmt: String; begin + if FWorkbook = nil then begin + Result := false; + exit; + end; + Result := true; fmt := AddAMPM(FWorkbook.FormatSettings.LongTimeFormat, FWorkbook.FormatSettings); if CheckFormat(fmt, ANextIndex, AMPM, isInterval) then begin diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index cc3789857..1414db4e1 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -891,6 +891,7 @@ var fs: TFormatSettings; valueType: String; valueStr: String; + node: TDOMNode; begin fs := DefaultFormatSettings; fs.DecimalSeparator := '.'; @@ -934,6 +935,14 @@ begin floatValue := ExtractDateTimeFromNode(ACellNode, cell^.NumberFormat, cell^.NumberFormatStr); FWorkSheet.WriteDateTime(cell, floatValue); end else + // text + if (valueType = 'string') then begin + node := ACellNode.FindNode('text:p'); + if (node <> nil) and (node.FirstChild <> nil) then begin + valueStr := node.FirstChild.Nodevalue; + FWorksheet.WriteUTF8Text(cell, valueStr); + end; + end else // Text FWorksheet.WriteUTF8Text(cell, valueStr); end; @@ -979,7 +988,8 @@ begin // We convert them to date/time and also correct the date origin offset if // needed. lCell := FWorksheet.FindCell(ARow, ACol); - if IsDateTimeFormat(lCell^.NumberFormat) then begin + if IsDateTimeFormat(lCell^.NumberFormat) or IsDateTimeFormat(lCell^.NumberFormatStr) + then begin lCell^.ContentType := cctDateTime; // No datemode correction for intervals and for time-only values if (lCell^.NumberFormat = nfTimeInterval) or (lCell^.NumberValue < 1) then @@ -1006,7 +1016,7 @@ begin ApplyStyleToCell(cell, stylename); dt := ExtractDateTimeFromNode(ACellNode, cell^.NumberFormat, cell^.NumberFormatStr); - FWorkSheet.WriteDateTime(cell, dt); + FWorkSheet.WriteDateTime(cell, dt, cell^.NumberFormat, cell^.NumberFormatStr); end; procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode); @@ -1272,7 +1282,7 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode); ReadStyleMap(node, nf, fmt); { if IsDateTimeFormat(fmt) then - nf := nfFmtDateTime + nf := nfCustom else } nf := nfCustom; diff --git a/components/fpspreadsheet/fpsutils.pas b/components/fpspreadsheet/fpsutils.pas index e5abbb6db..1d91df0bb 100644 --- a/components/fpspreadsheet/fpsutils.pas +++ b/components/fpspreadsheet/fpsutils.pas @@ -70,7 +70,7 @@ function IfThen(ACondition: Boolean; AValue1,AValue2: TsNumberFormat): TsNumberF function IsCurrencyFormat(AFormat: TsNumberFormat): Boolean; function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean; overload; -//function IsDateTimeFormat(AFormatStr: String): Boolean; overload; +function IsDateTimeFormat(AFormatStr: String): Boolean; overload; function BuildCurrencyFormatString(ADialect: TsNumFormatDialect; ANumberFormat: TsNumberFormat; const AFormatSettings: TFormatSettings; @@ -569,6 +569,18 @@ begin nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM, nfTimeInterval]; end; +function IsDateTimeFormat(AFormatStr: string): Boolean; +var + parser: TsNumFormatParser; +begin + parser := TsNumFormatParser.Create(nil, AFormatStr); + try + Result := parser.IsDateTimeFormat; + finally + parser.Free; + end; +end; + { Builds a date/time format string from the numberformat code. If the format code is nfFmtDateTime the given AFormatString is used. AFormatString can use the abbreviations "dm" (for "d/mmm"), "my" (for "mmm/yy"), "ms" (for "mm:ss")