You've already forked lazarus-ccr
fpspreadsheet: Split shared code for ooxml and ods readers off into new unit fpsxmlcommon.pas
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3378 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -66,11 +66,16 @@
|
|||||||
<PackageName Value="LazUtils"/>
|
<PackageName Value="LazUtils"/>
|
||||||
</Item1>
|
</Item1>
|
||||||
</RequiredPackages>
|
</RequiredPackages>
|
||||||
<Units Count="1">
|
<Units Count="2">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
<Filename Value="ooxmlread.lpr"/>
|
<Filename Value="ooxmlread.lpr"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit0>
|
</Unit0>
|
||||||
|
<Unit1>
|
||||||
|
<Filename Value="..\..\fpsxmlcommon.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="fpsxmlcommon"/>
|
||||||
|
</Unit1>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
@ -10,7 +10,7 @@ program ooxmlread;
|
|||||||
{$mode delphi}{$H+}
|
{$mode delphi}{$H+}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, fpspreadsheet, xlsxooxml; //fpsallformats;
|
Classes, SysUtils, fpspreadsheet, xlsxooxml, fpsxmlcommon; //fpsallformats;
|
||||||
|
|
||||||
var
|
var
|
||||||
MyWorkbook: TsWorkbook;
|
MyWorkbook: TsWorkbook;
|
||||||
|
@ -39,7 +39,7 @@ uses
|
|||||||
fpspreadsheet,
|
fpspreadsheet,
|
||||||
laz2_xmlread, laz2_DOM,
|
laz2_xmlread, laz2_DOM,
|
||||||
AVL_Tree, math, dateutils,
|
AVL_Tree, math, dateutils,
|
||||||
fpsutils, fpsNumFormatParser;
|
fpsutils, fpsNumFormatParser, fpsxmlcommon;
|
||||||
|
|
||||||
type
|
type
|
||||||
TDateMode=(
|
TDateMode=(
|
||||||
@ -71,7 +71,7 @@ type
|
|||||||
|
|
||||||
{ TsSpreadOpenDocReader }
|
{ TsSpreadOpenDocReader }
|
||||||
|
|
||||||
TsSpreadOpenDocReader = class(TsCustomSpreadReader)
|
TsSpreadOpenDocReader = class(TsSpreadXMLReader)
|
||||||
private
|
private
|
||||||
FCellStyleList: TFPList;
|
FCellStyleList: TFPList;
|
||||||
FColumnStyleList: TFPList;
|
FColumnStyleList: TFPList;
|
||||||
@ -94,10 +94,6 @@ type
|
|||||||
function FindColumnByCol(AColIndex: Integer): Integer;
|
function FindColumnByCol(AColIndex: Integer): Integer;
|
||||||
function FindColStyleByName(AStyleName: String): integer;
|
function FindColStyleByName(AStyleName: String): integer;
|
||||||
function FindRowStyleByName(AStyleName: String): Integer;
|
function FindRowStyleByName(AStyleName: String): Integer;
|
||||||
// Gets value for the specified attribute. Returns empty string if attribute
|
|
||||||
// not found.
|
|
||||||
function GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
|
||||||
function GetNodeValue(ANode: TDOMNode): String;
|
|
||||||
procedure ReadColumns(ATableNode: TDOMNode);
|
procedure ReadColumns(ATableNode: TDOMNode);
|
||||||
procedure ReadColumnStyle(AStyleNode: TDOMNode);
|
procedure ReadColumnStyle(AStyleNode: TDOMNode);
|
||||||
// Figures out the base year for times in this file (dates are unambiguous)
|
// Figures out the base year for times in this file (dates are unambiguous)
|
||||||
@ -968,36 +964,6 @@ begin
|
|||||||
Result := -1;
|
Result := -1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocReader.GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
|
||||||
var
|
|
||||||
i : integer;
|
|
||||||
Found : Boolean;
|
|
||||||
begin
|
|
||||||
Found:=false;
|
|
||||||
i:=0;
|
|
||||||
Result:='';
|
|
||||||
while not Found and (i<ANode.Attributes.Length) do begin
|
|
||||||
if ANode.Attributes.Item[i].NodeName=AAttrName then begin
|
|
||||||
Found:=true;
|
|
||||||
Result:=ANode.Attributes.Item[i].NodeValue;
|
|
||||||
end;
|
|
||||||
inc(i);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Returns the text value of a node. Normally it would be sufficient to call
|
|
||||||
"ANode.NodeValue", but since the DOMParser needs to preserve white space
|
|
||||||
(for the spaces in date/time formats), we have to go more into detail. }
|
|
||||||
function TsSpreadOpenDocReader.GetNodeValue(ANode: TDOMNode): String;
|
|
||||||
var
|
|
||||||
child: TDOMNode;
|
|
||||||
begin
|
|
||||||
Result := '';
|
|
||||||
child := ANode.FirstChild;
|
|
||||||
if Assigned(child) and (child.NodeName = '#text') then
|
|
||||||
Result := child.NodeValue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TsSpreadOpenDocReader.ReadBlank(ARow, ACol: Word; ACellNode: TDOMNode);
|
procedure TsSpreadOpenDocReader.ReadBlank(ARow, ACol: Word; ACellNode: TDOMNode);
|
||||||
var
|
var
|
||||||
styleName: String;
|
styleName: String;
|
||||||
@ -1188,50 +1154,6 @@ var
|
|||||||
BodyNode, SpreadSheetNode, TableNode: TDOMNode;
|
BodyNode, SpreadSheetNode, TableNode: TDOMNode;
|
||||||
StylesNode: TDOMNode;
|
StylesNode: TDOMNode;
|
||||||
OfficeSettingsNode: TDOMNode;
|
OfficeSettingsNode: TDOMNode;
|
||||||
|
|
||||||
{ We have to use our own ReadXMLFile procedure (there is one in xmlread)
|
|
||||||
because we have to preserve spaces in element text for date/time separator.
|
|
||||||
As a side-effect we have to skip leading spaces by ourselves. }
|
|
||||||
procedure ReadXMLFile(out ADoc: TXMLDocument; AFileName: String);
|
|
||||||
var
|
|
||||||
parser: TDOMParser;
|
|
||||||
src: TXMLInputSource;
|
|
||||||
stream: TStream;
|
|
||||||
// fstream: TStream;
|
|
||||||
begin
|
|
||||||
{
|
|
||||||
if (boBufStream in Workbook.Options) then begin
|
|
||||||
fstream := TFileStream.Create(AFilename, fmOpenRead + fmShareDenyWrite);
|
|
||||||
stream := TMemorystream.Create;
|
|
||||||
stream.CopyFrom(fstream, fstream.Size);
|
|
||||||
stream.Position := 0;
|
|
||||||
fstream.free;
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boBufStream in Workbook.Options) then
|
|
||||||
stream := TBufStream.Create(AFileName, fmOpenRead + fmShareDenyWrite)
|
|
||||||
else
|
|
||||||
stream := TFileStream.Create(AFileName, fmOpenRead + fmShareDenyWrite);
|
|
||||||
|
|
||||||
try
|
|
||||||
parser := TDOMParser.Create;
|
|
||||||
try
|
|
||||||
parser.Options.PreserveWhiteSpace := true; // This preserves spaces!
|
|
||||||
src := TXMLInputSource.Create(stream);
|
|
||||||
try
|
|
||||||
parser.Parse(src, ADoc);
|
|
||||||
finally
|
|
||||||
src.Free;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
parser.Free;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
stream.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
//unzip files into AFileName path
|
//unzip files into AFileName path
|
||||||
FilePath := GetTempDir(false);
|
FilePath := GetTempDir(false);
|
||||||
|
91
components/fpspreadsheet/fpsxmlcommon.pas
Normal file
91
components/fpspreadsheet/fpsxmlcommon.pas
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
unit fpsxmlcommon;
|
||||||
|
|
||||||
|
{$mode objfpc}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils,
|
||||||
|
laz2_xmlread, laz2_DOM,
|
||||||
|
fpspreadsheet;
|
||||||
|
|
||||||
|
type
|
||||||
|
TsSpreadXMLReader = class(TsCustomSpreadReader)
|
||||||
|
protected
|
||||||
|
function GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
||||||
|
function GetNodeValue(ANode: TDOMNode): String;
|
||||||
|
procedure ReadXMLFile(out ADoc: TXMLDocument; AFileName: String);
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
fpsStreams;
|
||||||
|
|
||||||
|
{ Gets value for the specified attribute. Returns empty string if attribute
|
||||||
|
not found. }
|
||||||
|
function TsSpreadXMLReader.GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
Found: Boolean;
|
||||||
|
begin
|
||||||
|
Found := false;
|
||||||
|
i := 0;
|
||||||
|
Result := '';
|
||||||
|
while not Found and (i < ANode.Attributes.Length) do begin
|
||||||
|
if ANode.Attributes.Item[i].NodeName = AAttrName then begin
|
||||||
|
Found := true;
|
||||||
|
Result := ANode.Attributes.Item[i].NodeValue;
|
||||||
|
end;
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Returns the text value of a node. Normally it would be sufficient to call
|
||||||
|
"ANode.NodeValue", but since the DOMParser needs to preserve white space
|
||||||
|
(for the spaces in date/time formats), we have to go more into detail. }
|
||||||
|
function TsSpreadXMLReader.GetNodeValue(ANode: TDOMNode): String;
|
||||||
|
var
|
||||||
|
child: TDOMNode;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
child := ANode.FirstChild;
|
||||||
|
if Assigned(child) and (child.NodeName = '#text') then
|
||||||
|
Result := child.NodeValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ We have to use our own ReadXMLFile procedure (there is one in xmlread)
|
||||||
|
because we have to preserve spaces in element text for date/time separator.
|
||||||
|
As a side-effect we have to skip leading spaces by ourselves. }
|
||||||
|
procedure TsSpreadXMLReader.ReadXMLFile(out ADoc: TXMLDocument; AFileName: String);
|
||||||
|
var
|
||||||
|
parser: TDOMParser;
|
||||||
|
src: TXMLInputSource;
|
||||||
|
stream: TStream;
|
||||||
|
begin
|
||||||
|
if (boBufStream in Workbook.Options) then
|
||||||
|
stream := TBufStream.Create(AFileName, fmOpenRead + fmShareDenyWrite)
|
||||||
|
else
|
||||||
|
stream := TFileStream.Create(AFileName, fmOpenRead + fmShareDenyWrite);
|
||||||
|
|
||||||
|
try
|
||||||
|
parser := TDOMParser.Create;
|
||||||
|
try
|
||||||
|
parser.Options.PreserveWhiteSpace := true; // This preserves spaces!
|
||||||
|
src := TXMLInputSource.Create(stream);
|
||||||
|
try
|
||||||
|
parser.Parse(src, ADoc);
|
||||||
|
finally
|
||||||
|
src.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
parser.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
stream.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -41,7 +41,7 @@ uses
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
laz2_xmlread, laz2_DOM,
|
laz2_xmlread, laz2_DOM,
|
||||||
AVL_Tree,
|
AVL_Tree,
|
||||||
fpspreadsheet, fpsutils;
|
fpspreadsheet, fpsutils, fpsxmlcommon;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -56,12 +56,10 @@ type
|
|||||||
|
|
||||||
{ TsSpreadOOXMLReader }
|
{ TsSpreadOOXMLReader }
|
||||||
|
|
||||||
TsSpreadOOXMLReader = class(TsCustomSpreadReader)
|
TsSpreadOOXMLReader = class(TsSpreadXMLReader)
|
||||||
private
|
private
|
||||||
FPointSeparatorSettings: TFormatSettings;
|
FPointSeparatorSettings: TFormatSettings;
|
||||||
FSharedStrings: TStringList;
|
FSharedStrings: TStringList;
|
||||||
function GetAttrValue(ANode: TDOMNode; AAttrName: string): string;
|
|
||||||
function GetNodeValue(ANode: TDOMNode): String;
|
|
||||||
procedure ReadFont(ANode: TDOMNode);
|
procedure ReadFont(ANode: TDOMNode);
|
||||||
procedure ReadFonts(ANode: TDOMNode);
|
procedure ReadFonts(ANode: TDOMNode);
|
||||||
procedure ReadSharedStrings(ANode: TDOMNode);
|
procedure ReadSharedStrings(ANode: TDOMNode);
|
||||||
@ -271,33 +269,6 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOOXMLReader.GetAttrValue(ANode : TDOMNode; AAttrName : string) : string;
|
|
||||||
var
|
|
||||||
i : integer;
|
|
||||||
Found : Boolean;
|
|
||||||
begin
|
|
||||||
Found := false;
|
|
||||||
i := 0;
|
|
||||||
Result := '';
|
|
||||||
while not Found and (i < ANode.Attributes.Length) do begin
|
|
||||||
if ANode.Attributes.Item[i].NodeName = AAttrName then begin
|
|
||||||
Found := true;
|
|
||||||
Result := ANode.Attributes.Item[i].NodeValue;
|
|
||||||
end;
|
|
||||||
inc(i);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TsSpreadOOXMLReader.GetNodeValue(ANode: TDOMNode): String;
|
|
||||||
var
|
|
||||||
child: TDOMNode;
|
|
||||||
begin
|
|
||||||
Result := '';
|
|
||||||
child := ANode.FirstChild;
|
|
||||||
if Assigned(child) and (child.NodeName = '#text') then
|
|
||||||
Result := child.NodeValue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TsSpreadOOXMLReader.ReadFont(ANode: TDOMNode);
|
procedure TsSpreadOOXMLReader.ReadFont(ANode: TDOMNode);
|
||||||
var
|
var
|
||||||
node: TDOMNode;
|
node: TDOMNode;
|
||||||
@ -482,50 +453,6 @@ var
|
|||||||
StylesNode: TDOMNode;
|
StylesNode: TDOMNode;
|
||||||
OfficeSettingsNode: TDOMNode;
|
OfficeSettingsNode: TDOMNode;
|
||||||
|
|
||||||
{ We have to use our own ReadXMLFile procedure (there is one in xmlread)
|
|
||||||
because we have to preserve spaces in element text for date/time separator.
|
|
||||||
As a side-effect we have to skip leading spaces by ourselves. }
|
|
||||||
procedure ReadXMLFile(out ADoc: TXMLDocument; AFileName: String);
|
|
||||||
var
|
|
||||||
parser: TDOMParser;
|
|
||||||
src: TXMLInputSource;
|
|
||||||
stream: TStream;
|
|
||||||
// fstream: TStream;
|
|
||||||
begin
|
|
||||||
{
|
|
||||||
if (boBufStream in Workbook.Options) then begin
|
|
||||||
fstream := TFileStream.Create(AFilename, fmOpenRead + fmShareDenyWrite);
|
|
||||||
stream := TMemorystream.Create;
|
|
||||||
stream.CopyFrom(fstream, fstream.Size);
|
|
||||||
stream.Position := 0;
|
|
||||||
fstream.free;
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boBufStream in Workbook.Options) then
|
|
||||||
stream := TBufStream.Create(AFileName, fmOpenRead + fmShareDenyWrite)
|
|
||||||
else
|
|
||||||
stream := TFileStream.Create(AFileName, fmOpenRead + fmShareDenyWrite);
|
|
||||||
|
|
||||||
try
|
|
||||||
parser := TDOMParser.Create;
|
|
||||||
try
|
|
||||||
parser.Options.PreserveWhiteSpace := true; // This preserves spaces!
|
|
||||||
src := TXMLInputSource.Create(stream);
|
|
||||||
try
|
|
||||||
parser.Parse(src, ADoc);
|
|
||||||
finally
|
|
||||||
src.Free;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
parser.Free;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
stream.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
s: String;
|
s: String;
|
||||||
node: TDOMNode;
|
node: TDOMNode;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user