You've already forked lazarus-ccr
fpspreadsheet: Beginning to extend to number format parser for xml strings (for ods). Not finished, yet.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3170 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -25,10 +25,9 @@ const
|
|||||||
{ TsNumFormatParser }
|
{ TsNumFormatParser }
|
||||||
|
|
||||||
type
|
type
|
||||||
TsNumFormatDialect = (nfdDefault, nfdExcel, nfdOther);
|
TsNumFormatDialect = (nfdDefault, nfdExcel);
|
||||||
// nfdDefault is the dialect used by fpc,
|
// nfdDefault is the dialect used by fpc,
|
||||||
// nfdExcel is the dialect used by Excel
|
// nfdExcel is the dialect used by Excel
|
||||||
// nfdOther is used when writing xml for ods files. Separate implementation needed.
|
|
||||||
|
|
||||||
TsCompareOperation = (coNotUsed,
|
TsCompareOperation = (coNotUsed,
|
||||||
coEqual, coNotEqual, coLess, coGreater, coLessEqual, coGreaterEqual
|
coEqual, coNotEqual, coLess, coGreater, coLessEqual, coGreaterEqual
|
||||||
@ -69,13 +68,11 @@ type
|
|||||||
TsNumFormatParser = class
|
TsNumFormatParser = class
|
||||||
private
|
private
|
||||||
FCreateMethod: Byte;
|
FCreateMethod: Byte;
|
||||||
FWorkbook: TsWorkbook;
|
|
||||||
FToken: Char;
|
FToken: Char;
|
||||||
FCurrent: PChar;
|
FCurrent: PChar;
|
||||||
FStart: PChar;
|
FStart: PChar;
|
||||||
FEnd: PChar;
|
FEnd: PChar;
|
||||||
FCurrSection: Integer;
|
FCurrSection: Integer;
|
||||||
FSections: TsNumFormatSections;
|
|
||||||
FStatus: Integer;
|
FStatus: Integer;
|
||||||
function GetCurrencySymbol: String;
|
function GetCurrencySymbol: String;
|
||||||
function GetDecimals: byte;
|
function GetDecimals: byte;
|
||||||
@ -86,6 +83,9 @@ type
|
|||||||
procedure SetDecimals(AValue: Byte);
|
procedure SetDecimals(AValue: Byte);
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
FWorkbook: TsWorkbook;
|
||||||
|
FSections: TsNumFormatSections;
|
||||||
|
|
||||||
{ Administration while scanning }
|
{ Administration while scanning }
|
||||||
procedure AddElement(AToken: TsNumFormatToken; AText: String); overload;
|
procedure AddElement(AToken: TsNumFormatToken; AText: String); overload;
|
||||||
procedure AddElement(AToken: TsNumFormatToken; AIntValue: Integer); overload;
|
procedure AddElement(AToken: TsNumFormatToken; AIntValue: Integer); overload;
|
||||||
@ -275,13 +275,11 @@ end;
|
|||||||
|
|
||||||
{ Creates a formatstring for all sections.
|
{ Creates a formatstring for all sections.
|
||||||
Note: this implementation is only valid for the fpc and Excel dialects of
|
Note: this implementation is only valid for the fpc and Excel dialects of
|
||||||
format string. Needs to be overridden for xml. }
|
format string. }
|
||||||
function TsNumFormatParser.BuildFormatString(ADialect: TsNumFormatDialect): String;
|
function TsNumFormatParser.BuildFormatString(ADialect: TsNumFormatDialect): String;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if ADialect = nfdOther then
|
|
||||||
raise Exception.Create('nfdOther cannot be used in TsNumFormatParser.BuildFormatString');
|
|
||||||
if Length(FSections) > 0 then begin
|
if Length(FSections) > 0 then begin
|
||||||
Result := BuildFormatStringFromSection(0, ADialect);
|
Result := BuildFormatStringFromSection(0, ADialect);
|
||||||
for i := 1 to High(FSections) do
|
for i := 1 to High(FSections) do
|
||||||
@ -291,8 +289,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ Creates a format string for the given section. This implementation covers
|
{ Creates a format string for the given section. This implementation covers
|
||||||
the formatstring dialects of fpc (nfdDefault) and Excel (nfdExcel).
|
the formatstring dialects of fpc (nfdDefault) and Excel (nfdExcel). }
|
||||||
Needs to be overridden for xml. }
|
|
||||||
function TsNumFormatParser.BuildFormatStringFromSection(ASection: Integer;
|
function TsNumFormatParser.BuildFormatStringFromSection(ASection: Integer;
|
||||||
ADialect: TsNumFormatDialect): String;
|
ADialect: TsNumFormatDialect): String;
|
||||||
var
|
var
|
||||||
@ -301,9 +298,6 @@ var
|
|||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
|
|
||||||
if ADialect = nfdOther then
|
|
||||||
raise Exception.Create('nfdOther cannot be used in TsNumFormatParser.BuildFormatString');
|
|
||||||
|
|
||||||
if (ASection < 0) and (ASection >= GetParsedSectionCount) then
|
if (ASection < 0) and (ASection >= GetParsedSectionCount) then
|
||||||
exit;
|
exit;
|
||||||
for i := 0 to High(FSections[ASection].Elements) do begin
|
for i := 0 to High(FSections[ASection].Elements) do begin
|
||||||
|
@ -39,7 +39,7 @@ uses
|
|||||||
fpspreadsheet,
|
fpspreadsheet,
|
||||||
laz2_xmlread, laz2_DOM,
|
laz2_xmlread, laz2_DOM,
|
||||||
AVL_Tree, math, dateutils,
|
AVL_Tree, math, dateutils,
|
||||||
fpsutils;
|
fpsutils, fpsNumFormatParser;
|
||||||
|
|
||||||
type
|
type
|
||||||
TDateMode=(
|
TDateMode=(
|
||||||
@ -49,12 +49,22 @@ type
|
|||||||
);
|
);
|
||||||
|
|
||||||
{ TsSpreadOpenDocNumFormatList }
|
{ TsSpreadOpenDocNumFormatList }
|
||||||
|
|
||||||
TsSpreadOpenDocNumFormatList = class(TsCustomNumFormatList)
|
TsSpreadOpenDocNumFormatList = class(TsCustomNumFormatList)
|
||||||
protected
|
protected
|
||||||
procedure AddBuiltinFormats; override;
|
procedure AddBuiltinFormats; override;
|
||||||
public
|
public
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TsSpreadOpenDocNumFormatParser }
|
||||||
|
TsSpreadOpenDocNumFormatParser = class(TsNumFormatParser)
|
||||||
|
protected
|
||||||
|
function BuildXMLAsStringFromSection(ASection: Integer; AIndent: String;
|
||||||
|
AFormatNo: Integer): String;
|
||||||
|
public
|
||||||
|
function BuildXMLAsString(AIndent: String; AFormatNo: Integer): String;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TsSpreadOpenDocReader }
|
{ TsSpreadOpenDocReader }
|
||||||
|
|
||||||
TsSpreadOpenDocReader = class(TsCustomSpreadReader)
|
TsSpreadOpenDocReader = class(TsCustomSpreadReader)
|
||||||
@ -117,6 +127,7 @@ type
|
|||||||
// Routines to write parts of files
|
// Routines to write parts of files
|
||||||
function WriteCellStylesXMLAsString: string;
|
function WriteCellStylesXMLAsString: string;
|
||||||
function WriteColStylesXMLAsString: String;
|
function WriteColStylesXMLAsString: String;
|
||||||
|
function WriteNumFormatsXMLAsString: String;
|
||||||
function WriteRowStylesXMLAsString: String;
|
function WriteRowStylesXMLAsString: String;
|
||||||
|
|
||||||
function WriteColumnsXMLAsString(ASheet: TsWorksheet): String;
|
function WriteColumnsXMLAsString(ASheet: TsWorksheet): String;
|
||||||
@ -290,6 +301,105 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ TsSpreadOpenDocNumFormatParser }
|
||||||
|
|
||||||
|
function TsSpreadOpenDocNumFormatParser.BuildXMLAsString(AIndent: String;
|
||||||
|
AFormatNo: Integer): String;
|
||||||
|
var
|
||||||
|
i, ns: Integer;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
for i := Length(FSections)-1 downto 0 do
|
||||||
|
Result := Result + BuildXMLAsStringFromSection(i, AIndent, AFormatNo);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsSpreadOpenDocNumFormatParser.BuildXMLAsStringFromSection(
|
||||||
|
ASection: Integer; AIndent: String; AFormatNo: Integer): String;
|
||||||
|
var
|
||||||
|
nf : TsNumberFormat;
|
||||||
|
decs: Byte;
|
||||||
|
next: Integer;
|
||||||
|
sGrouping: String;
|
||||||
|
sColor: String;
|
||||||
|
sStyleMap: String;
|
||||||
|
ns: Integer;
|
||||||
|
fmtName: String;
|
||||||
|
clr: TsColorvalue;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
sGrouping := '';
|
||||||
|
sColor := '';
|
||||||
|
sStyleMap := '';
|
||||||
|
fmtName := Format('N%d', [AFormatNo]);
|
||||||
|
|
||||||
|
ns := Length(FSections);
|
||||||
|
if (ns > 1) then begin
|
||||||
|
if (ASection = ns - 1) then
|
||||||
|
case ns of
|
||||||
|
2: sStyleMap := AIndent +
|
||||||
|
' <style:map ' +
|
||||||
|
'style:apply-style-name="' + fmtName + 'P0" ' +
|
||||||
|
'style:condition="value()>=0" />' + LineEnding; // >= 0
|
||||||
|
3: sStyleMap := AIndent +
|
||||||
|
' <style:map '+
|
||||||
|
'style:apply-style-name="' + fmtName + 'P0" ' + // > 0
|
||||||
|
'style:condition="value()>0" />' + LineEnding + AIndent +
|
||||||
|
' <style:map '+
|
||||||
|
'style:apply-style-name="' + fmtName + 'P1" ' + // < 0
|
||||||
|
'style:condition="value()<0" />' + LineEnding;
|
||||||
|
else
|
||||||
|
raise Exception.Create('At most 3 format sections allowed.');
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fmtName := fmtName + 'P' + IntToStr(ASection);
|
||||||
|
end;
|
||||||
|
|
||||||
|
with FSections[ASection] do begin
|
||||||
|
next := 0;
|
||||||
|
if IsTokenAt(nftColor, ASection, 0) then begin
|
||||||
|
clr := FWorkbook.GetPaletteColor(Elements[0].IntValue);
|
||||||
|
sColor := AIndent + '<style:text-properties fo:color="' + ColorToHTMLColorStr(clr) + '" />' + LineEnding;
|
||||||
|
next := 1;
|
||||||
|
end;
|
||||||
|
if IsNumberAt(ASection, next, nf, decs, next) then begin
|
||||||
|
if nf = nfFixedTh then
|
||||||
|
sGrouping := 'number:grouping="true" ';
|
||||||
|
|
||||||
|
// nfFixed, nfFixedTh
|
||||||
|
if (next = Length(Elements)) then begin
|
||||||
|
Result := AIndent +
|
||||||
|
'<number:number-style style:name="' + fmtName + '">' + LineEnding +
|
||||||
|
sColor + AIndent +
|
||||||
|
' <number:number ' +
|
||||||
|
'number:min-integer-digits="1" ' + sGrouping +
|
||||||
|
'number:decimal-places="' + IntToStr(decs) +
|
||||||
|
'" />' + LineEnding +
|
||||||
|
sStylemap + AIndent +
|
||||||
|
'</number:number-style>' + LineEnding;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// nfPercentage
|
||||||
|
if IsTokenAt(nftPercent, ASection, next) and (next+1 = Length(Elements))
|
||||||
|
then begin
|
||||||
|
Result := AIndent +
|
||||||
|
'<number:percentage-style style:name="' + fmtName + '">' + LineEnding +
|
||||||
|
sColor + AIndent +
|
||||||
|
' <number:number ' +
|
||||||
|
'number:min-integer-digits="1" ' + sGrouping +
|
||||||
|
'number:decimal-places="' + IntToStr(decs) +
|
||||||
|
'" />' + LineEnding + AIndent +
|
||||||
|
' <number:text>%</number:text>' + LineEnding +
|
||||||
|
sStyleMap + AIndent +
|
||||||
|
'</number:percentage-style>' + LineEnding;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ... more to follow...
|
||||||
|
end;
|
||||||
|
|
||||||
{ TsSpreadOpenDocReader }
|
{ TsSpreadOpenDocReader }
|
||||||
|
|
||||||
constructor TsSpreadOpenDocReader.Create(AWorkbook: TsWorkbook);
|
constructor TsSpreadOpenDocReader.Create(AWorkbook: TsWorkbook);
|
||||||
@ -1905,11 +2015,14 @@ var
|
|||||||
lCellStylesCode: string;
|
lCellStylesCode: string;
|
||||||
lColStylesCode: String;
|
lColStylesCode: String;
|
||||||
lRowStylesCode: String;
|
lRowStylesCode: String;
|
||||||
|
lNumFmtCode: String;
|
||||||
begin
|
begin
|
||||||
ListAllColumnStyles;
|
ListAllColumnStyles;
|
||||||
ListAllRowStyles;
|
ListAllRowStyles;
|
||||||
ListAllFormattingStyles;
|
ListAllFormattingStyles;
|
||||||
|
|
||||||
|
lNumFmtCode := WriteNumFormatsXMLAsString;
|
||||||
|
|
||||||
lColStylesCode := WriteColStylesXMLAsString;
|
lColStylesCode := WriteColStylesXMLAsString;
|
||||||
if lColStylesCode = '' then lColStylesCode :=
|
if lColStylesCode = '' then lColStylesCode :=
|
||||||
' <style:style style:name="co1" style:family="table-column">' + LineEnding +
|
' <style:style style:name="co1" style:family="table-column">' + LineEnding +
|
||||||
@ -1956,6 +2069,7 @@ begin
|
|||||||
|
|
||||||
// Automatic styles
|
// Automatic styles
|
||||||
' <office:automatic-styles>' + LineEnding +
|
' <office:automatic-styles>' + LineEnding +
|
||||||
|
lNumFmtCode +
|
||||||
lColStylesCode +
|
lColStylesCode +
|
||||||
lRowStylesCode +
|
lRowStylesCode +
|
||||||
' <style:style style:name="ta1" style:family="table" style:master-page-name="Default">' + LineEnding +
|
' <style:style style:name="ta1" style:family="table" style:master-page-name="Default">' + LineEnding +
|
||||||
@ -2138,6 +2252,41 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TsSpreadOpenDocWriter.WriteNumFormatsXMLAsString: String;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
numFmtXML: String;
|
||||||
|
parser: TsSpreadOpenDocNumFormatParser;
|
||||||
|
begin
|
||||||
|
{
|
||||||
|
<number:number-style style:name="N2">
|
||||||
|
<number:number number:decimal-places="2" number:min-integer-digits="1" />
|
||||||
|
</number:number-style>
|
||||||
|
|
||||||
|
' <number:number-style style:name="N2">
|
||||||
|
<number:number number:min-integer-digits="1" number:grouping="true" number:decimal-places="2"/>
|
||||||
|
</number:number-style>
|
||||||
|
|
||||||
|
' <number:number-style style:name="N2">
|
||||||
|
<number:number number:decimal-places="2" number:min-integer-digits="1" />
|
||||||
|
</number:number-style>
|
||||||
|
}
|
||||||
|
Result := '';
|
||||||
|
|
||||||
|
ListAllNumFormats;
|
||||||
|
|
||||||
|
for i:=0 to FNumFormatList.Count-1 do begin
|
||||||
|
parser := TsSpreadOpenDocNumFormatParser.Create(Workbook, FNumFormatList.Items[i].FormatString);
|
||||||
|
try
|
||||||
|
numFmtXML := parser.BuildXMLAsString(' ', 1000+i); //120+i); // Don't know where the user numbers start...
|
||||||
|
if numFmtXML <> '' then
|
||||||
|
Result := Result + numFmtXML;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteRowsAndCellsXMLAsString(ASheet: TsWorksheet): String;
|
function TsSpreadOpenDocWriter.WriteRowsAndCellsXMLAsString(ASheet: TsWorksheet): String;
|
||||||
var
|
var
|
||||||
r, rr: Cardinal; // row index in sheet
|
r, rr: Cardinal; // row index in sheet
|
||||||
|
Reference in New Issue
Block a user