fpspreadsheet: ods reader supports number formats in charts.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9023 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2023-11-12 18:12:12 +00:00
parent 9b0e01149c
commit 3d9619fe06
3 changed files with 77 additions and 14 deletions

View File

@ -26,12 +26,27 @@ function GetLineStr(ALine: TsChartLine): String;
var
s: String;
begin
if ALine.Style = -1 then
s := 'solid'
else if ALine.Style = -2 then
s := 'noLine'
else if ALine.Style = clsFineDot then
s := 'fine-dot'
else if ALine.Style = clsDot then
s := 'dot'
else if ALine.Style = clsDash then
s := 'dash'
else if ALine.Style = clsDashDot then
s := 'dash-dot'
else if ALine.Style = clsLongDash then
s := 'long dash'
else if ALine.Style = clsLongDashDot then
s := 'long dash-dot'
else if ALine.Style = clsLongDashDotDot then
s := 'long dash-dot-dot'
else
s := IntToStr(ALine.Style);
s := 'custom #' + IntToStr(ALine.Style);
Result := Format('Style=%s, Width=%.0fmm, Color=%.6x, Transparency=%.2f', [
s, ALine.Width, ALine.Color, ALine.Transparency
@ -42,6 +57,8 @@ function GetRangeStr(ARange: TsChartRange): String;
begin
with ARange do
Result := GetCellRangeString(Sheet1, Sheet2, Row1, Col1, Row2, Col2, rfAllRel, false);
if Result = '' then
Result := '(none)';
end;
function GetCellAddrStr(ACellAddr: TsChartCellAddr): String;
@ -144,6 +161,7 @@ begin
WriteLn(' CATEGORIES ', GetRangeStr(chart.XAxis.CategoryRange));
WriteLn(' RANGE AutomaticMin=', chart.XAxis.AutomaticMin, ', Minimum=', chart.XAxis.Min:0:3);
WriteLn(' AutomaticMax=', chart.XAxis.AutomaticMax, ', Maximum=', chart.XAxis.Max:0:3);
WriteLn(' LABELS Format="', chart.XAxis.LabelFormat, '"');
WriteLn(' POSITION ', GetEnumName(TypeInfo(TsChartAxisPosition), ord(chart.XAXis.Position)),
', Value=', chart.XAxis.PositionValue:0:3);
WriteLn(' AXIS TICKS: Major interval=', chart.XAxis.MajorInterval:0:2,
@ -161,6 +179,7 @@ begin
WriteLn(' Font: ', GetFontStr(chart.YAxis.Title.Font));
WriteLn(' RANGE AutomaticMin=', chart.YAxis.AutomaticMin, ', Minimum=', chart.YAxis.Min:0:3);
WriteLn(' AutomaticMax=', chart.YAxis.AutomaticMax, ', Maximum=', chart.YAxis.Max:0:3);
WriteLn(' LABELS Format="', chart.YAxis.LabelFormat, '", FormatPercent="', chart.YAxis.LabelFormatPercent,'"');
WriteLn(' POSITION ', GetEnumName(TypeInfo(TsChartAxisPosition), ord(chart.YAXis.Position)),
', Value:', chart.YAxis.PositionValue:0:3);
WriteLn(' AXIS TICKS Major interval=', chart.YAxis.MajorInterval:0:2,
@ -177,7 +196,7 @@ begin
WriteLn;
WriteLn( ' SERIES #', j, ': ', series.ClassName);
WriteLn( ' TITLE: ', GetCellAddrStr(series.TitleAddr));
WriteLn( ' LABEL RANGE: ', GetRangeStr(series.LabelRange));
WriteLn( ' LABEL RANGE: ', GetRangeStr(series.LabelRange), ', Format="', series.LabelFormat, '"');
if (series is TsScatterSeries) or (series is TsBubbleSeries) then
WriteLn(' X RANGE: ', GetRangeStr(series.XRange));
WriteLn( ' Y RANGE: ', GetRangeStr(series.YRange));
@ -222,7 +241,7 @@ begin
begin
with regression.Equation do
begin
WriteLn(' REGR. EQUATION: XName="', XName,'", YName="', YName,'" ');
WriteLn(' REGR. EQUATION: XName="', XName,'", YName="', YName,'", Number format="', NumberFormat, '"');
WriteLn(' FONT: ', GetFontStr(regression.Equation.Font));
WriteLn(' FILL: ', GetFillStr(regression.Equation.Fill));
WriteLn(' BORDER: ', GetLineStr(regression.Equation.Border));

View File

@ -190,7 +190,6 @@ type
function NeedsPassword(AStream: TStream): Boolean; override;
procedure ReadAutomaticStyles(AStylesNode: TDOMNode);
procedure ReadMasterStyles(AStylesNode: TDOMNode);
procedure ReadNumFormats(AStylesNode: TDOMNode);
procedure ReadPageLayout(AStylesNode: TDOMNode; ATableStyleName: String;
APageLayout: TsPageLayout);
procedure ReadSettings(AOfficeSettingsNode: TDOMNode);
@ -232,6 +231,7 @@ type
{ Helper methods, public because needed by the chart reader }
function CreateXMLStream: TStream;
procedure ReadFont(ANode: TDOMNode; AFont: TsFont);
procedure ReadNumFormats(AStylesNode: TDOMNode; ANumFormatList: TStrings);
end;
{ TsSpreadOpenDocWriter }
@ -3046,7 +3046,7 @@ begin
ReadFontFaces(Doc.DocumentElement.FindNode('office:font-face-decls'));
StylesNode := Doc.DocumentElement.FindNode('office:styles');
ReadNumFormats(StylesNode);
ReadNumFormats(StylesNode, NumFormatList);
ReadStyles(StylesNode);
ReadAutomaticStyles(Doc.DocumentElement.FindNode('office:automatic-styles'));
ReadMasterStyles(Doc.DocumentElement.FindNode('office:master-styles'));
@ -3067,7 +3067,7 @@ begin
if Assigned(Doc) then begin
ReadFontFaces(Doc.DocumentElement.FindNode('office:font-face-decls'));
StylesNode := Doc.DocumentElement.FindNode('office:automatic-styles');
ReadNumFormats(StylesNode);
ReadNumFormats(StylesNode, NumFormatList);
ReadStyles(StylesNode);
BodyNode := Doc.DocumentElement.FindNode('office:body');
@ -3450,7 +3450,8 @@ begin
(Workbook as TsWorkbook).OnReadCellData(Workbook, ARow, ACol, cell);
end;
procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode;
ANumFormatList: TStrings);
procedure ReadStyleMap(ANode: TDOMNode; var ANumFormat: TsNumberFormat;
var AFormatStr: String);
@ -3502,7 +3503,7 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
continue;
end;
fmt := NumFormatList[styleIndex];
fmt := ANumFormatList[styleIndex];
fmt := Copy(fmt, pos(':', fmt)+1, Length(fmt));
parser := TsNumFormatParser.Create(fmt, Workbook.FormatSettings);
try
@ -3682,7 +3683,7 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
if (ANumFormatNode.NodeName = 'number:currency-style') then
nf := IfThen(hasColor, nfCurrencyRed, nfCurrency);
NumFormatList.Add(Format('%s:%s', [ANumFormatName, nfs]));
ANumFormatList.Add(Format('%s:%s', [ANumFormatName, nfs]));
end;
procedure ReadDateTimeStyle(ANumFormatNode: TDOMNode; ANumFormatName: String);
@ -3786,8 +3787,8 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
if node <> nil then
ReadStyleMap(node, nf, nfs);
NumFormatList.Add(ANumFormatName + ':' + nfs);
// NumFormatList.AddFormat(ANumFormatName, nf, nfs);
ANumFormatList.Add(ANumFormatName + ':' + nfs);
// ANumFormatList.AddFormat(ANumFormatName, nf, nfs);
end;
procedure ReadTextStyle(ANumFormatNode: TDOMNode; ANumFormatName: String);
@ -3825,9 +3826,9 @@ procedure TsSpreadOpenDocReader.ReadNumFormats(AStylesNode: TDOMNode);
ReadStyleMap(node, nf, nfs);
nf := nfCustom;
NumFormatList.Add(Format('%s:%s', [ANumFormatName, nfs]));
ANumFormatList.Add(Format('%s:%s', [ANumFormatName, nfs]));
//NumFormatList.AddFormat(ANumFormatName, nf, nfs);
//ANumFormatList.AddFormat(ANumFormatName, nf, nfs);
end;
var

View File

@ -22,6 +22,7 @@ type
private
FChartFiles: TStrings;
FPointSeparatorSettings: TFormatSettings;
FNumberFormatList: TStrings;
function FindStyleNode(AStyleNodes: TDOMNode; AStyleName: String): TDOMNode;
procedure GetChartFillProps(ANode: TDOMNode; AChart: TsChart; AFill: TsChartFill);
procedure GetChartLineProps(ANode: TDOMNode; AChart: TsChart; ALine: TsChartLine);
@ -261,6 +262,7 @@ type
public
constructor Create;
function Add(const ANumFormat: String): Integer; override;
function FindFormatByName(const AName: String): String;
end;
constructor TsChartNumberFormatList.Create;
@ -282,6 +284,22 @@ begin
end;
end;
{ The reader adds formats in the form "name:format" where "name" is the
identifier used in the style definition, e.g. "N0". }
function TsChartNumberFormatList.FindFormatByName(const AName: String): String;
var
idx: Integer;
begin
Result := '';
idx := IndexOfName(AName);
if idx <> -1 then
begin
Result := Values[AName];
if Result = 'General' then
Result := '';
end;
end;
{------------------------------------------------------------------------------}
{ TsSpreadOpenDocChartReader }
@ -295,10 +313,13 @@ begin
FPointSeparatorSettings.DecimalSeparator:='.';
FChartFiles := TStringList.Create;
FNumberFormatList := TsChartNumberFormatList.Create;
FNumberFormatList.NameValueSeparator := ':';
end;
destructor TsSpreadOpenDocChartReader.Destroy;
begin
FNumberFormatList.Free;
FChartFiles.Free;
inherited;
end;
@ -446,6 +467,10 @@ var
chartChartNode: TDOMNode;
chartElementNode: TDOMNode;
begin
nodeName := AStyleNode.NodeName;
if nodeName = 'office:automatic-styles' then
TsSpreadOpenDocReader(Reader).ReadNumFormats(AStyleNode, FNumberFormatList);
nodeName := AChartNode.NodeName;
officeChartNode := AChartNode.FirstChild;
while officeChartNode <> nil do
@ -544,6 +569,15 @@ var
n: Integer;
ticks: TsChartAxisTicks = [];
begin
nodeName := AStyleNode.NodeName;
s := GetAttrValue(AStyleNode, 'style:data-style-name');
if s <> '' then
s := TsChartNumberFormatList(FNumberFormatList).FindFormatByName(s);
if (AChart.StackMode = csmStackedPercentage) and ((Axis = AChart.YAxis) or (Axis = AChart.Y2Axis)) then
Axis.LabelFormatPercent := s
else
Axis.LabelFormat := s;
AStyleNode := AStyleNode.FirstChild;
while AStyleNode <> nil do
begin
@ -899,7 +933,11 @@ begin
series := TsScatterSeries(ASeries);
odsReader := TsSpreadOpenDocReader(Reader);
// here: read number format! (still missing...)
nodeName := AStyleNode.NodeName;
s := GetAttrValue(AStyleNode, 'style:data-style-name');
if s <> '' then
s := TsChartNumberFormatList(FNumberFormatList).FindFormatByName(s);
series.Regression.Equation.NumberFormat := s;
AStyleNode := AStyleNode.FirstChild;
while Assigned(AStyleNode) do
@ -1108,6 +1146,11 @@ var
rel: Boolean;
begin
nodeName := AStyleNode.NodeName;
s := GetAttrValue(AStyleNode, 'style:data-style-name');
if s <> '' then
s := TsChartNumberFormatList(FNumberFormatList).FindFormatByName(s);
ASeries.LabelFormat := s;
AStyleNode := AStyleNode.FirstChild;
while AStyleNode <> nil do begin
nodeName := AStyleNode.NodeName;