diff --git a/components/fpspreadsheet/docs/api/source-files.txt b/components/fpspreadsheet/docs/api/source-files.txt index b9a72f93c..ea295996b 100644 --- a/components/fpspreadsheet/docs/api/source-files.txt +++ b/components/fpspreadsheet/docs/api/source-files.txt @@ -7,5 +7,6 @@ ../../source/common/fpsrpn.pas ../../source/common/fpscurrency.pas ../../source/common/fpsconditionalformat.pas +../../source/common/fpschart.pas ../../source/visual/fpspreadsheetctrls.pas ../../source/visual/fpspreadsheetgrid.pas diff --git a/components/fpspreadsheet/docs/fpspreadsheet-api.chm b/components/fpspreadsheet/docs/fpspreadsheet-api.chm index 2936309d4..ee5260989 100644 Binary files a/components/fpspreadsheet/docs/fpspreadsheet-api.chm and b/components/fpspreadsheet/docs/fpspreadsheet-api.chm differ diff --git a/components/fpspreadsheet/docs/fpspreadsheet-wiki.chm b/components/fpspreadsheet/docs/fpspreadsheet-wiki.chm index f33940178..6f84dc477 100644 Binary files a/components/fpspreadsheet/docs/fpspreadsheet-wiki.chm and b/components/fpspreadsheet/docs/fpspreadsheet-wiki.chm differ diff --git a/components/fpspreadsheet/docs/wiki/make_docs.bat b/components/fpspreadsheet/docs/wiki/make_docs.bat index f8d086fa1..16ae06d3b 100644 --- a/components/fpspreadsheet/docs/wiki/make_docs.bat +++ b/components/fpspreadsheet/docs/wiki/make_docs.bat @@ -4,13 +4,14 @@ rem set FMT=html set FMT=chm echo Downloading wiki... -wikiget --page=FPSpreadsheet --page=FPSpreadsheet:_Examples --page=FPSpreadsheet:_List_of_formulas --page=RPN_Formulas_in_FPSpreadsheet +wikiget --page=FPSpreadsheet --page=FPSpreadsheet:_Examples --page=FPSpreadsheet:_List_of_formulas --page=RPN_Formulas_in_FPSpreadsheet +wikiget --page=FPSpreadsheet:_Chart_Tutorial wikiget --page=FPSpreadsheet_tutorial:_Writing_a_mini_spreadsheet_application wikiget --page=TsWorksheetGrid --page=TsWorksheetChartSource echo. echo Converting wiki to chm... -wikiconvert --format=%FMT% --css=css/wiki.css --root="FPSpreadsheet wiki pages" --title="FPSpreadsheet wiki pages (offline version, created %DATE%)" --chm="..\fpspreadsheet-wiki.chm" wikixml/FPSpreadsheet.s00.xml wikixml/FPSpreadsheet=3A_Examples.s0300.xml wikixml/FPSpreadsheet=3A_List_of_formulas.s03000.xml wikixml/RPN_Formulas_in_FPSpreadsheet.u03g00.xml wikixml/FPSpreadsheet_tutorial=3A_Writing_a_mini_spreadsheet_application.s000c0000000.xml wikixml/TsWorksheetGrid.k08.xml +wikiconvert --format=%FMT% --css=css/wiki.css --root="FPSpreadsheet wiki pages" --title="FPSpreadsheet wiki pages (offline version, created %DATE%)" --chm="..\fpspreadsheet-wiki.chm" wikixml/FPSpreadsheet.s00.xml wikixml/FPSpreadsheet=3A_Examples.s0300.xml wikixml/FPSpreadsheet=3A_List_of_formulas.s03000.xml wikixml/RPN_Formulas_in_FPSpreadsheet.u03g00.xml wikixml/FPSpreadsheet_tutorial=3A_Writing_a_mini_spreadsheet_application.s000c0000000.xml wikixml/TsWorksheetGrid.k08.xml wikixml/FPSpreadsheet=3A_Chart_Tutorial.s03100.xml set FMT= \ No newline at end of file diff --git a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/chart_demo.lpi b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/chart_demo.lpi index f818939b4..1a7fd4c9d 100644 --- a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/chart_demo.lpi +++ b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/chart_demo.lpi @@ -68,11 +68,6 @@ - - - - - diff --git a/components/fpspreadsheet/source/common/fpstypes.pas b/components/fpspreadsheet/source/common/fpstypes.pas index 3a51a855d..30a29da01 100644 --- a/components/fpspreadsheet/source/common/fpstypes.pas +++ b/components/fpspreadsheet/source/common/fpstypes.pas @@ -20,7 +20,7 @@ interface uses Classes, SysUtils, fpimage; -{$IF FPC_FullVersion < 30000} +{$IFDEF FPS_NO_RAWBYTESTRING} {@@ This string type is not re-encoded by FPC. It is a standard type of FPC 3.0+, its declaration must be repeated here in order to keep fpSpreadsheet usable by older FPC versions. } @@ -92,8 +92,8 @@ type @member LineEnding Specification for the line endings to be written (write-only) @member Delimiter Column delimiter (read/write) @member QuoteChar Character used for quoting text in special cases (read/write) - @member QuoteOuterWhiteSpace ...Determines whether cell content beginning/ending with white space will be quoted (write-only) - @member IgnoreOuterWhiteSpace...Ignores white space before/after cell content (read-only) + @member QuoteOuterWhiteSpace Determines whether cell content beginning/ending with white space will be quoted (write-only) + @member IgnoreOuterWhiteSpace Ignores white space before/after cell content (read-only) @member Encoding String identifying the endoding of the file, such as 'utf8', 'cp1252' etc (read/write) @member DetectContentType Try to convert strings to their content type (read-only) @member NumberFormat If empty numbers are written like in worksheet, otherwise this format string is applied (write-only) diff --git a/components/fpspreadsheet/source/common/xlsxooxmlchart.pas b/components/fpspreadsheet/source/common/xlsxooxmlchart.pas index db9bb851b..999e917a0 100644 --- a/components/fpspreadsheet/source/common/xlsxooxmlchart.pas +++ b/components/fpspreadsheet/source/common/xlsxooxmlchart.pas @@ -59,7 +59,7 @@ type procedure ReadChartSeriesLabels(ANode: TDOMNode; ASeries: TsChartSeries); procedure ReadChartSeriesMarker(ANode: TDOMNode; ASeries: TsCustomLineSeries); procedure ReadChartSeriesProps(ANode: TDOMNode; ASeries: TsChartSeries); - procedure ReadChartSeriesRange(ANode: TDOMNode; ARange: TsChartRange); + procedure ReadChartSeriesRange(ANode: TDOMNode; ARange: TsChartRange; var AFormat: String); procedure ReadChartSeriesTitle(ANode: TDOMNode; ASeries: TsChartSeries); procedure ReadChartSeriesTrendLine(ANode: TDOMNode; ASeries: TsChartSeries); procedure ReadChartStockSeries(ANode: TDOMNode; AChart: TsChart); @@ -374,6 +374,7 @@ var n: LongInt; x: Single; node: TDOMNode; + srcLinked: Boolean; begin if ANode = nil then exit; @@ -415,11 +416,20 @@ begin ReadChartTitle(ANode.FirstChild, AChartAxis.Title); 'c:numFmt': begin - s := GetAttrValue(ANode, 'formatCode'); - if s = 'm/d/yyyy' then - AChartAxis.LabelFormat := FReader.Workbook.FormatSettings.ShortDateFormat - else - AChartAxis.LabelFormat := s; + srcLinked := GetAttrValue(ANode, 'sourceLinked') = '1'; + if not srcLinked then + begin + s := GetAttrValue(ANode, 'formatCode'); + if s = 'm/d/yyyy' then + AChartAxis.LabelFormat := FReader.Workbook.FormatSettings.ShortDateFormat + else + if IsDateTimeFormat(s) then + begin + AChartAxis.DateTime := true; + AChartAxis.LabelFormatDateTime := s; + end else + AChartAxis.LabelFormat := s; + end; end; 'c:majorTickMark': AChartAxis.MajorTicks := ReadChartAxisTickMarks(ANode); @@ -1806,6 +1816,7 @@ var val: Double; errorBars: TsChartErrorBars = nil; part: String = ''; + fmt: String = ''; begin if ANode = nil then exit; @@ -1877,9 +1888,9 @@ begin errorBars.ValueNeg := val; end; 'c:plus': - ReadChartSeriesRange(node.FirstChild, errorBars.RangePos); + ReadChartSeriesRange(node.FirstChild, errorBars.RangePos, fmt); 'c:minus': - ReadChartSeriesRange(node.FirstChild, errorBars.RangeNeg); + ReadChartSeriesRange(node.FirstChild, errorBars.RangeNeg, fmt); 'c:spPr': ReadChartLineProps(node.FirstChild, ASeries.Chart, errorBars.Line); 'c:noEndCap': @@ -2021,9 +2032,10 @@ end; procedure TsSpreadOOXMLChartReader.ReadChartSeriesProps(ANode: TDOMNode; ASeries: TsChartSeries); var - nodeName, s: String; + nodeName, fmt, s: String; n: Integer; idx: Integer; + ax: TsChartAxis; smooth: Boolean = false; begin if ANode = nil then @@ -2040,16 +2052,32 @@ begin ASeries.Order := n; 'c:tx': ReadChartSeriesTitle(ANode.FirstChild, ASeries); - 'c:cat': - ReadChartSeriesRange(ANode.FirstChild, ASeries.LabelRange); - 'c:xVal': - ReadChartSeriesRange(ANode.FirstChild, ASeries.XRange); - 'c:val', 'c:yVal': + 'c:cat': // Category axis + begin + ReadChartSeriesRange(ANode.FirstChild, ASeries.LabelRange, fmt); + ax := ASeries.GetXAxis; + if IsDateTimeFormat(fmt) then + begin + if ax.LabelFormatDateTime = '' then + ax.LabelFormatDateTime := fmt; + end else + begin + if ax.LabelFormat = '' then + ax.LabelFormat := fmt; + end; + end; + 'c:xVal': // x value axis + ReadChartSeriesRange(ANode.FirstChild, ASeries.XRange, fmt); + 'c:val', // y value axis in categorized series + 'c:yVal': // y value axis if ASeries.YRange.IsEmpty then // TcStockSeries already has read the y range... - ReadChartSeriesRange(ANode.FirstChild, ASeries.YRange); + begin + ReadChartSeriesRange(ANode.FirstChild, ASeries.YRange, fmt); + ASeries.LabelFormat := fmt; + end; 'c:bubbleSize': if ASeries is TsBubbleSeries then - ReadChartSeriesRange(ANode.FirstChild, TsBubbleSeries(ASeries).BubbleRange); + ReadChartSeriesRange(ANode.FirstChild, TsBubbleSeries(ASeries).BubbleRange, fmt); 'c:bubble3D': ; 'c:spPr': @@ -2084,14 +2112,18 @@ end; @@param ANode First child of a , or node below . @@param ARange Cell range to which the range parameters will be assigned. + @@param AFormat Numberformat string -------------------------------------------------------------------------------} -procedure TsSpreadOOXMLChartReader.ReadChartSeriesRange(ANode: TDOMNode; ARange: TsChartRange); +procedure TsSpreadOOXMLChartReader.ReadChartSeriesRange(ANode: TDOMNode; + ARange: TsChartRange; var AFormat: String); var + node, child: TDomNode; nodeName, s: String; sheet1, sheet2: String; r1, c1, r2, c2: Cardinal; flags: TsRelFlags; begin + AFormat := ''; if ANode = nil then exit; while Assigned(ANode) do @@ -2099,6 +2131,38 @@ begin nodeName := ANode.NodeName; if (nodeName = 'c:strRef') or (nodeName = 'c:numRef') then begin + node := ANode.FirstChild; + while Assigned(node) do + begin + nodeName := node.NodeName; + case nodeName of + 'c:f': + begin + s := GetNodeValue(node); + if ParseCellRangeString(s, sheet1, sheet2, r1, c1, r2, c2, flags) then + begin + if sheet2 = '' then sheet2 := sheet1; + ARange.Sheet1 := sheet1; + ARange.Sheet2 := sheet2; + ARange.Row1 := r1; + ARange.Col1 := c1; + ARange.Row2 := r2; + ARange.Col2 := c2; + end; + end; + 'c:numCache': + begin + child := node.FindNode('c:formatCode'); + if Assigned(child) then + AFormat := GetNodeValue(child); + end; + end; + node := node.NextSibling; + end; + end; + ANode := ANode.NextSibling; + + (* ANode := ANode.FindNode('c:f'); if ANode <> nil then begin @@ -2117,6 +2181,7 @@ begin end; end; ANode := ANode.NextSibling; + *) end; end; @@ -2234,7 +2299,7 @@ procedure TsSpreadOOXMLChartReader.ReadChartStockSeries(ANode: TDOMNode; AChart: TsChart); var ser: TsStockSeries; - nodeName: String; + nodeName, fmt: String; sernode, child: TDOMNode; begin if ANode = nil then @@ -2266,14 +2331,14 @@ begin } 'c:val': if ser.CloseRange.IsEmpty then - ReadChartSeriesRange(child.FirstChild, ser.CloseRange) + ReadChartSeriesRange(child.FirstChild, ser.CloseRange, fmt) else if ser.LowRange.IsEmpty then - ReadChartSeriesRange(child.FirstChild, ser.LowRange) + ReadChartSeriesRange(child.FirstChild, ser.LowRange, fmt) else if ser.HighRange.IsEmpty then - ReadChartSeriesRange(child.FirstChild, ser.HighRange) + ReadChartSeriesRange(child.FirstChild, ser.HighRange, fmt) else if ser.OpenRange.IsEmpty then begin - ReadChartSeriesRange(child.FirstChild, ser.OpenRange); + ReadChartSeriesRange(child.FirstChild, ser.OpenRange, fmt); ser.CandleStick := true; end; end; diff --git a/components/fpspreadsheet/source/fps.inc b/components/fpspreadsheet/source/fps.inc index 1a0881be8..b11c224b7 100644 --- a/components/fpspreadsheet/source/fps.inc +++ b/components/fpspreadsheet/source/fps.inc @@ -25,6 +25,15 @@ { The next defines activate code duplicated from new compiler versions in case an old compiler is used. } +{ Activate the following define if your Lazarus version is older than v1.8 } +{.$DEFINE LCL_FullVersion_LT_v180} + +{ Activate the following define if your Lazarus version is older than v1.9 } +{.$DEFINE LCL_FullVersion_LT_v190} + +{ Activate the following define if your Lazarus version is older than v2.0 } +{.$DEFINE LCL_FullVersion_LT_v200} + { fpspreadsheet requires the function VarIsBool which was introduced by fpc 2.6.4. If an older FPC versions is used define FPS_VARISBOOL. Keep undefined for the current FPC version. } @@ -66,7 +75,22 @@ e.g. before v3.0 } {.$DEFINE FPS_NO_STRING_SPLIT} +{ FPC versions before 3.0 did not support TRawByteString. + Enable the define FPS_NO_RAWBYTESTRING here if this is the case. } +{.$DEFINE FPS_NO_RAWBYTESTRING} + { Very old FPC versions do not contain zip support in the unit zipper, and until v3.3 zipper did not read pass-word protected ods files correctly. Therefore, the following define must be activated if FPC is v3.3 or older. } {$DEFINE FPS_PATCHED_ZIPPER} + +// Fix dependent defines +{$IFDEF LCL_FULLVERSION_LT_200} + {$DEFINE LCL_FULLVERSION_LT_190} +{$ENDIF} + +{$IFDEF LCL_FULLVERSION_LT_190} + {$DEFINE LCL_FULLVERSION_LT_180} +{$ENDIF} + + diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas index c5ead4e66..cf278ba2e 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas @@ -688,11 +688,17 @@ begin if cell <> nil then case cell^.ContentType of - cctUTF8String, cctDateTime: // !!! Simplification here: we do not support real date values + cctUTF8String: begin ANumber := APointIndex; AText := FWorksheets[ARangeIndex, AListIndex].ReadAsText(cell); end; + cctDateTime: + begin + if not FWorksheets[ARangeIndex, AListIndex].ReadAsDateTime(cell, ANumber) then + ANumber := APointIndex; + AText := FWorksheets[ARangeIndex, AListIndex].ReadAsText(cell); + end; else ANumber := FWorksheets[ARangeIndex, AListIndex].ReadAsNumber(cell); AText := ''; @@ -2385,7 +2391,7 @@ begin FChart.BottomAxis.Marks.Style := smsLabel; end; end; - (* + // Date/time? if AWorkbookChart.XAxis.DateTime then begin @@ -2398,7 +2404,6 @@ begin DateTimeFormat := AWorkbookChart.XAxis.LabelFormat; end; end; - *) end; procedure TsWorkbookChartLink.UpdateChartBackground(AWorkbookChart: TsChart); diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas index b583cf581..dca06b098 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas @@ -702,7 +702,7 @@ type function SpreadsheetFormatInClipboard: Boolean; -{$IF LCL_FullVersion < 1080000} +{$IFDEF LCL_FULLVERSION_LT_180} function ScalePPI(ALength: Integer): Integer; {$IFEND} @@ -741,7 +741,7 @@ begin end; -{$IF LCL_FullVersion < 1080000} +{$IFDEF LCL_FullVersion_LT_180} function ScalePPI(ALength: Integer): Integer; begin Result := MulDiv(ALength, Screen.PixelsPerInch, 96); diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas b/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas index 29ee74c89..8b9c57782 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas @@ -330,7 +330,7 @@ type const ACellRect: TGridRect): Boolean; function MouseOnHeader(X, Y: Integer): Boolean; procedure MouseUp(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override; - {$IF LCL_FullVersion >= 1090000} + {$IFNDEF LCL_FullVersion_LT_190000} function MoveNextSelectable(Relative: Boolean; DCol, DRow: Integer): Boolean; override; {$ENDIF} procedure MoveSelection; override; @@ -596,10 +596,10 @@ type defined by the rectangle. } property TextRotations[ALeft, ATop, ARight, ABottom: Integer]: TsTextRotation read GetTextRotations write SetTextRotations; - {$IF LCL_FullVersion >= 1080000} + {$IFNDEF LCL_FullVersion_LT_180} {@@ Pixel coordinates of the top-left corner of the grid's cell area} property TopLeftPx: TPoint read GetPxTopLeft; - {$IFEND} + {$ENDIF} {@@ Parameter for vertical text alignment in the cell at column ACol and row ARow. } property VertAlignment[ACol, ARow: Integer]: TsVertAlignment read GetVertAlignment write SetVertAlignment; @@ -2771,11 +2771,11 @@ begin Canvas.Brush.Color := clRed; Canvas.Brush.Style := bsSolid; Canvas.Pen.Style := psClear; - {$IF LCL_FullVersion >= 1080000} - commentSize := Scale96ToFont(COMMENT_SIZE); - {$ELSE} + {$IFDEF LCL_FULLVERSION_LT_180} commentSize := ScalePPI(COMMENT_SIZE); - {$IFEND} + {$ELSE} + commentSize := Scale96ToFont(COMMENT_SIZE); + {$ENDIF} if IsRightToLeft then begin P[0] := Point(ARect.Left, ARect.Top); @@ -5256,7 +5256,7 @@ begin Refresh; end; -{$IF LCL_FullVersion >= 1090000} +{$IFNDEF LCL_FULLVERSION_LT_v190} // Supported by Laz v1.9+ function TsCustomWorksheetGrid.MoveNextSelectable(Relative: Boolean; DCol, DRow: Integer ): Boolean; var