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