Created
April 27, 2021 20:16
-
-
Save SmiSoft/5e14de917d2913795d813112e60c274c to your computer and use it in GitHub Desktop.
ODT/ODS import/export for Lazarus (no LibreOffice installed required)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unit OdtImport; | |
interface | |
uses | |
Classes, OdtFilter, OdtExport, laz2_Dom; | |
Type | |
{ TOdtImport } | |
TOdtImport=class(TOdtProcess) | |
protected | |
fTableName:string; | |
fTableData:PStringMatrix; | |
fContains:boolean; | |
// преобразует значение ячейки из таблицы текстовое представление | |
// в отличии от стандартного TextContent, сохраняет разбиение по абзацам | |
function ProcessTableCell(Cell:TDOMNode):string; | |
procedure ProcessTableRow(Row:TDOMNodeList;out RowData:TStringVector); | |
procedure ProcessContent({%H-}Doc:TXMLDocument);override; | |
public | |
class procedure FromFile(const Input,TableName:string;out TableData:TStringMatrix); | |
class function ContainsTable(const Input,TableName:string):boolean; | |
end; | |
implementation | |
{ TOdtImport } | |
function TOdtImport.ProcessTableCell(Cell: TDOMNode): string; | |
var | |
Par:TDOMNode; | |
begin | |
Result:=''; | |
For Par in Cell.GetEnumeratorAllChildren do begin | |
if String(Par.NodeName)<>'text:p' then continue; | |
if Result='' then | |
Result:=String(Par.TextContent) | |
else | |
Result:=Result+#13#10+String(Par.TextContent); | |
end; | |
end; | |
procedure TOdtImport.ProcessTableRow(Row: TDOMNodeList; out RowData:TStringVector); | |
var | |
I,Cnt:integer; | |
Node:TDOMNode; | |
begin | |
// считаем количество ячеек в данном ряду. Подстраховываемся на случай, если | |
// в ряду окажутся не только ячейки, из документации это не 100% следует | |
Cnt:=0; | |
For I:=0 to Row.Count-1 do begin | |
Node:=Row.Item[I]; | |
if String(Node.NodeName)<>'table:table-cell' then continue; | |
Inc(Cnt); | |
end; | |
SetLength(RowData,Cnt); | |
// производим заполнение данными из ячеек | |
Cnt:=0; | |
For I:=0 to Row.Count-1 do begin | |
Node:=Row.Item[I]; | |
if String(Node.NodeName)<>'table:table-cell' then continue; | |
RowData[Cnt]:=ProcessTableCell(Node); | |
Inc(Cnt); | |
end; | |
end; | |
procedure TOdtImport.ProcessContent(Doc: TXMLDocument); | |
var | |
Tables,Rows:TDOMNodeList; | |
Node,TableName:TDOMNode; | |
Attr:TDOMNamedNodeMap; | |
I,J,K:integer; | |
begin | |
Tables:=Doc.GetElementsByTagName('table:table'); | |
For I:=0 to Tables.Count-1 do begin | |
Node:=Tables.Item[I]; | |
Attr:=Node.Attributes; | |
if Attr=nil then continue; | |
TableName:=Attr.GetNamedItem('table:name'); | |
if TableName=nil then continue; | |
if String(TableName.NodeValue)<>fTableName then continue; | |
// мы находимся в таблице, имя которой нас интересует | |
fContains:=true; | |
if fTableData<>nil then begin | |
Rows:=Node.ChildNodes; | |
For J:=0 to Rows.Count-1 do begin | |
Node:=Rows.Item[J]; | |
if String(Node.NodeName)<>'table:table-row' then continue; | |
K:=Length(fTableData^); | |
SetLength(fTableData^,K+1); | |
ProcessTableRow(Node.ChildNodes,fTableData^[K]); | |
end; | |
end; | |
exit; | |
end; | |
inherited ProcessContent(Doc); | |
end; | |
class procedure TOdtImport.FromFile(const Input, TableName: string; out TableData: TStringMatrix); | |
var | |
Iam:TOdtImport; | |
begin | |
Iam:=TOdtImport.Create; | |
try | |
Iam.fTableData:=@TableData; | |
Iam.fTableName:=TableName; | |
Iam.Process(Input); | |
finally | |
Iam.Free; | |
end; | |
end; | |
class function TOdtImport.ContainsTable(const Input, TableName: string): boolean; | |
var | |
Iam:TOdtImport; | |
begin | |
Iam:=TOdtImport.Create; | |
try | |
Iam.fTableName:=TableName; | |
Iam.Process(Input); | |
Result:=Iam.fContains; | |
finally | |
Iam.Free; | |
end; | |
end; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment