Skip to content

Instantly share code, notes, and snippets.

@SmiSoft
Created April 27, 2021 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SmiSoft/a8a8751d63466cfa68c37d696d242eb6 to your computer and use it in GitHub Desktop.
Save SmiSoft/a8a8751d63466cfa68c37d696d242eb6 to your computer and use it in GitHub Desktop.
ODT/ODS import/export for Lazarus (no LibreOffice installed required)
unit OdsExport;
interface
uses
Windows, Classes, SysUtils, OdtFilter, Hash, laz2_Dom;
Type
{ TOdsExport }
TOdsExport=class(TOdtFilter)
protected
fMap,fNotes:THash;
procedure FilterContent(Doc:TXMLDocument);override;
public
class procedure ExportToOdsUseFile(const TemplateFile,FileOut:string;Data, Notes:THash);
class procedure ExportToOdsUseTemplate(Template,FileOut:string;Data, Notes:THash);
end;
implementation
{ TOdsExport }
function SetNodeTextp(Node:TDOMNode;const Value:string):boolean;
var
Child:TDOMNode;
begin
if Node.NodeName='text:p' then begin
Node.TextContent:=Value;
Result:=true;
exit;
end;
For Child in Node do begin
Result:=SetNodeTextp(Child,Value);
if Result then exit;
end;
Result:=false;
end;
procedure TOdsExport.FilterContent(Doc: TXMLDocument);
var
Roots:TDOMNodeList;
Table,Row,Cell:TDOMNode;
I,RowNo:integer;
BlockId:string;
begin
Roots:=Doc.getElementsByTagName('table:table');
For I:=0 to Roots.Count-1 do begin
Table:=Roots.Item[I];
For Row in Table do begin
if Row.NodeName<>'table:table-row' then continue;
RowNo:=0;
For Cell in Row do begin
if Cell.NodeName<>'table:table-cell' then continue;
if RowNo=0 then
BlockId:=GetNodeTextp(Cell)
else if (RowNo=5) and (fMap.Contain(BlockId)) then
SetNodeTextp(Cell,fMap[BlockId])
else if (RowNo=7) and (fNotes.Contain(BlockId)) then
SetNodeTextp(Cell,fNotes[BlockId]);
Inc(RowNo);
end;
end;
end;
end;
class procedure TOdsExport.ExportToOdsUseFile(const TemplateFile, FileOut: string; Data, Notes: THash);
var
Temp:TOdsExport;
begin
Temp:=TOdsExport.Create(TemplateFile);
try
Temp.fMap:=Data;
Temp.fNotes:=Notes;
Temp.Filter(FileOut);
finally
Temp.Free;
end;
end;
class procedure TOdsExport.ExportToOdsUseTemplate(Template, FileOut: string; Data, Notes: THash);
var
Res:TResourceStream;
Flo:TFileStream;
TempPath,TempName:PChar;
begin
GetMem(TempPath,MAX_PATH);
GetMem(TempName,MAX_PATH);
GetTempPath(MAX_PATH,TempPath);
GetTempFileName(TempPath,'me_',random(1024),TempName);
FreeMem(TempPath);
DeleteFile(TempName);
Flo:=nil;
Res:=nil;
try
Flo:=TFileStream.Create(TempName,fmCreate);
Res:=TResourceStream.Create(hInstance,Template,RT_RCDATA);
Flo.CopyFrom(Res,Res.Size);
finally
Flo.Free;
Res.Free;
end;
ExportToOdsUseFile(TempName,FileOut,Data,Notes);
DeleteFile(TempName);
FreeMem(TempName);
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment