Skip to content

Instantly share code, notes, and snippets.

@SmiSoft
Created April 27, 2021 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save SmiSoft/479c5d64d3bb9c5a66f1faebc853dcbc to your computer and use it in GitHub Desktop.
Save SmiSoft/479c5d64d3bb9c5a66f1faebc853dcbc to your computer and use it in GitHub Desktop.
ODT/ODS import/export for Lazarus (no LibreOffice installed required)
{ Последовательность проверок:
var
Matrix:TDynamicMatrix;
I,J:integer;
begin
SetLength(Matrix,2,4);
For I:=0 to 1 do
For J:=0 to 3 do
Matrix[I,J]:=inttostr(Random(100));
TOdtExport.Export('PageIn.odt','PageOut.odt',Utf8Decode('Таблица1'),Matrix);
}
unit OdtExport;
interface
uses
Windows, SysUtils, Classes, OdtFilter, laz2_Dom;
Type
PStringVector=^TStringVector;
TStringVector=array of string;
PStringMatrix=^TStringMatrix;
TStringMatrix=array of array of string;
{ TOdtExport }
TOdtExport=class(TOdtFilter)
protected
fTableName:string;
fTableData:TStringMatrix;
procedure FilterContent(Doc:TXMLDocument);override;
public
class procedure ToFile(const Input,Output,TableName:string;const TableData:TStringMatrix);
class procedure ToTemplate(const Template,Output,TableName:string;const TableData:TStringMatrix);
end;
implementation
{ TOdtExport }
procedure TOdtExport.FilterContent(Doc: TXMLDocument);
var
I,J,K,RowIndex,CellIndex:integer;
Roots:TDOMNodeList;
Table,lastRow,temp,templateNode:TDOMNode;
Cell:string;
begin
Roots:=Doc.getElementsByTagName('table:table');
For i:=0 to Roots.Count-1 do begin
Table:=Roots.Item[i];
Cell:=Table.Attributes.GetNamedItem('table:name').NodeValue;
if Cell<>fTableName then
continue;
// получаем последний table:table-row как образец
lastRow:=nil;
For J:=table.ChildNodes.Count-1 downto 0 do begin
if String(table.ChildNodes[J].NodeName)='table:table-row' then begin
lastRow:=table.ChildNodes[J];
break;
end;
end;
if lastRow=nil then
continue;
For RowIndex:=Low(fTableData) to High(fTableData) do begin
templateNode:=lastRow.CloneNode(true);
CellIndex:=0;
For J:=0 to templateNode.ChildNodes.Count-1 do begin
temp:=templateNode.ChildNodes[J];
if String(temp.NodeName)='table:table-cell' then begin
For K:=0 to temp.ChildNodes.Count-1 do begin
if String(temp.ChildNodes[K].NodeName)='text:p' then begin
temp.ChildNodes[K].TextContent:=DOMString(fTableData[RowIndex,CellIndex]);
break;
end;
end;
Inc(CellIndex);
if CellIndex>High(fTableData[0]) then
break;
end;
end;
table.appendChild(templateNode);
end;
table.RemoveChild(lastRow);
end;
end;
class procedure TOdtExport.ToFile(const Input, Output, TableName:string; const TableData:TStringMatrix);
var
Iam:TOdtExport;
begin
Iam:=TOdtExport.Create(Input);
try
Iam.fTableName:=TableName;
Iam.fTableData:=TableData;
Iam.Filter(Output);
finally
Iam.Free;
end;
end;
class procedure TOdtExport.ToTemplate(const Template, Output, TableName: string; const TableData: TStringMatrix);
var
Res:TResourceStream;
Flo:TFileStream;
TempName:PChar;
TempPath:string;
begin
GetMem(TempName,MAX_PATH);
TempPath:=GetTempDir;
GetTempFileName(PChar(TempPath),'me_',random(1024),TempName);
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;
ToFile(TempName,Output,TableName,TableData);
DeleteFile(TempName);
FreeMem(TempName);
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment