📄 qimport3odt.pas
字号:
unit QImport3ODT;
{$I QImport3VerCtrl.Inc}
interface
{$IFDEF ODT}
{$IFDEF VCL6}
uses
QImport3StrTypes, Classes, SysUtils, MSXML, BaseDocumentFile,
QImport3, QImport3Common, IniFiles;
type
TODTCell = class(TCollectionItem)
private
FRow: Integer;
FCol: Integer;
FValue: qiString;
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
property Value: qiString read FValue write FValue;
property Row: Integer read FRow write FRow;
property Col: Integer read FCol write FCol;
end;
TODTCellList = class(TCollection)
private
function GetItem(Index: Integer): TODTCell;
procedure SetItem(Index: Integer; const Value: TODTCell);
public
function Add: TODTCell;
property Items[Index: Integer]: TODTCell read GetItem write SetItem; default;
function GetItemByCoords(X, Y: Integer): TODTCell;
end;
TODTSpreadSheet = class(TCollectionItem)
private
FName: qiString;
FColCount: Integer;
FRowCount: Integer;
FCells: TODTCellList;
FDataCells: TqiStringGrid;
FX: Integer;
FY: Integer;
FIsAfterSubTable: Boolean;
FIsComplexTable: Boolean;
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
procedure LoadDataCells;
property Cells: TODTCellList read FCells;
property ColCount: Integer read FColCount write FColCount;
property RowCount: Integer read FRowCount write FRowCount;
property X: Integer read FX write FX;
property Y: Integer read FY write FY;
property Name: qiString read FName write FName;
property IsAfterSubTable: Boolean read FIsAfterSubTable
write FIsAfterSubTable;
property DataCells: TqiStringGrid read FDataCells;
property IsComplexTable: Boolean read FIsComplexTable write FIsComplexTable;
end;
TODTSpreadSheetList = class(TCollection)
private
function GetItems(Index: integer): TODTSpreadSheet;
procedure SetItems(Index: integer; Value: TODTSpreadSheet);
public
function Add: TODTSpreadSheet;
property Items[Index: integer]: TODTSpreadSheet read GetItems
write SetItems; default;
function GetSheetByName(Name: qiString): TODTSpreadSheet;
end;
TODTWorkbook = class
private
FWorkDir: qiString;
FileName: qiString;
FSpreadSheets: TODTSpreadSheetList;
FXMLDoc: IXMLDOMDocument;
procedure SetSpreadSheets;
procedure FindTables(NameOfFile: qiString);
procedure ParseTable(Table: TODTSpreadSheet; Nodes: IXMLDOMNodeList;
NumbOfRepColumns, NumbOfRepRows: Integer; IsSpanning: Boolean);
procedure ExpandRowsNCols(Table: TODTSpreadSheet;
ExpandValue: qiString; NumbOfRepRows, NumbOfRepColumns: Integer;
IsSpanning: Boolean);
public
constructor Create;
destructor Destroy; override;
procedure Load;
property WorkDir: qiString read FWorkDir write FWorkDir;
property SpreadSheets: TODTSpreadSheetList read FSpreadSheets;
end;
TODTFile = class(TBaseDocumentFile)
private
FWorkbook: TODTWorkbook;
protected
procedure LoadXML(WorkDir: qiString); override;
public
constructor Create; override;
destructor Destroy; override;
property Workbook: TODTWorkbook read FWorkbook;
end;
TQImport3ODT = class(TQImport3)
private
FODTFile: TODTFile;
FCounter: Integer;
FSheetName: AnsiString;
FUseHeader: Boolean;
FUseComplexTables: Boolean;
procedure SetSheetName(const Value: AnsiString);
protected
procedure BeforeImport; override;
procedure StartImport; override;
function CheckCondition: Boolean; override;
function Skip: Boolean; override;
procedure ChangeCondition; override;
procedure FinishImport; override;
procedure AfterImport; override;
procedure FillImportRow; override;
function ImportData: TQImportResult; override;
procedure DoLoadConfiguration(IniFile: TIniFile); override;
procedure DoSaveConfiguration(IniFile: TIniFile); override;
public
constructor Create(AOwner: TComponent); override;
published
property FileName;
property SkipFirstRows default 0;
property SheetName: AnsiString read FSheetName write SetSheetName;
property UseHeader: Boolean read FUseHeader write FUseHeader default false;
property UseComplexTables: Boolean read FUseComplexTables
write FUseComplexTables default true;
end;
{$ENDIF}
{$ENDIF}
implementation
{$IFDEF ODT}
{$IFDEF VCL6}
uses
EmsWideStrUtils;
{ TODTCell }
constructor TODTCell.Create(Collection: TCollection);
begin
inherited;
FValue := '';
FCol := 0;
FRow := 0;
end;
destructor TODTCell.Destroy;
begin
inherited;
end;
{ TODTCellList }
function TODTCellList.Add: TODTCell;
begin
Result := TODTCell(inherited Add);
end;
function TODTCellList.GetItem(Index: Integer): TODTCell;
begin
Result := TODTCell(inherited Items[Index]);
end;
function TODTCellList.GetItemByCoords(X, Y: Integer): TODTCell;
var
i: Integer;
begin
Result := nil;
for i := 0 to Self.Count - 1 do
if (Items[i].Row = Y) and (Items[i].Col = X) then
begin
Result := Items[i];
Break;
end;
end;
procedure TODTCellList.SetItem(Index: Integer; const Value: TODTCell);
begin
inherited Items[Index] := Value;
end;
{ TODTSpreadSheet }
constructor TODTSpreadSheet.Create(Collection: TCollection);
begin
inherited;
FColCount := 0;
FRowCount := 0;
FX := -1;
FY := -1;
FIsAfterSubTable := false;
FCells := TODTCellList.Create(TODTCell);
FDataCells := TqiStringGrid.Create(nil);
FIsComplexTable := false;
end;
destructor TODTSpreadSheet.Destroy;
begin
FCells.Free;
FDataCells.Free;
inherited;
end;
procedure TODTSpreadSheet.LoadDataCells;
var
i: Integer;
begin
FDataCells.ColCount := FColCount;
FDataCells.RowCount := FRowCount;
for i := 0 to FCells.Count - 1 do
FDataCells.Cells[FCells[i].Col, Cells[i].Row] := Cells[i].Value;
end;
{ TODTSpreadSheetList }
function TODTSpreadSheetList.GetItems(Index: integer): TODTSpreadSheet;
begin
Result := TODTSpreadSheet(inherited Items[Index]);
end;
procedure TODTSpreadSheetList.SetItems(Index: integer;
Value: TODTSpreadSheet);
begin
inherited Items[Index] := Value;
end;
function TODTSpreadSheetList.Add: TODTSpreadSheet;
begin
Result := TODTSpreadSheet(inherited Add);
end;
function TODTSpreadSheetList.GetSheetByName(Name: qiString): TODTSpreadSheet;
var
i: Integer;
begin
Result := nil;
for i := 0 to Self.Count - 1 do
if UpperCase(Items[i].Name) = UpperCase(Name) then
begin
Result := Items[i];
Break;
end;
end;
{ TODTWorkbook }
procedure TODTWorkBook.FindTables(NameOfFile: qiString);
var
TableNodes: IXMLDOMNodeList;
I: Integer;
NumberOfSprSh: Integer;
begin
NumberOfSprSh := -1;
FXMLDoc.load(NameOfFile);
TableNodes := FXMLDoc.selectNodes('//table:table');
for I := 0 to TableNodes.length - 1 do
begin
if not
assigned(TableNodes[I].attributes.getNamedItem('table:is-sub-table')) then
begin
FSpreadSheets.Add;
Inc(NumberOfSprSh);
FSpreadSheets[NumberOfSprSh].Name :=
TableNodes[I].attributes.getNamedItem('table:name').nodeValue;
ParseTable(FSpreadSheets[NumberOfSprSh],TableNodes[I].childNodes, 0, 0, false);
FSpreadSheets[NumberOfSprSh].LoadDataCells;
end;
end;
if TableNodes.length = 0 then
raise Exception.Create('No tables were found');
end;
procedure TODTWorkBook.ParseTable(Table: TODTSpreadSheet; Nodes: IXMLDOMNodeList;
NumbOfRepColumns, NumbOfRepRows: Integer; IsSpanning: Boolean);
var
I, J: Integer;
NORR, NORC: Integer;
IsSp: Boolean;
TempSpreadSheet: TODTSpreadSheet;
TempCell: TODTCell;
begin
NORC := NumbOfRepColumns;
NORR := NumbOfRepRows;
IsSp := IsSpanning;
for I := 0 to Nodes.length - 1 do
begin
NumbOfRepColumns := NORC;
NumbOfRepRows := NORR;
IsSpanning := IsSp;
if Nodes[I].NodeName <> '#text' then
begin
if Nodes[I].NodeName = 'table:table-row' then
begin
Table.IsAfterSubTable := false;
if Table.RowCount - 1 > Table.Y then
Table.Y := Table.RowCount
else
Table.Y := Table.Y + 1;
Table.X := -1;
if assigned(Nodes[I].attributes.getNamedItem('table:number-rows-repeated')) then
NumbOfRepRows :=
Nodes[I].attributes.getNamedItem('table:number-rows-repeated').nodeValue - 1;
if Table.Y + 1 > Table.RowCount then
Table.RowCount := Table.Y + 1;
end;
if (Nodes[I].NodeName = 'table:covered-table-cell') then
if not Table.IsAfterSubTable then
begin
Table.X := Table.X + 1;
if Table.X + 1 > Table.ColCount then
Table.ColCount := Table.X + 1;
end;
if (Nodes[I].NodeName = 'table:table-cell') then
begin
Table.IsAfterSubTable := false;
Table.X := Table.X + 1;
if Table.X + 1 > Table.ColCount then
Table.ColCount := Table.X + 1;
if Assigned(Nodes[I].attributes.getNamedItem('table:number-columns-repeated')) then
NumbOfRepColumns :=
Nodes[I].attributes.getNamedItem('table:number-columns-repeated').nodeValue - 1;
if Assigned(Nodes[I].attributes.getNamedItem('table:number-rows-spanned')) then
begin
NumbOfRepRows :=
Nodes[I].attributes.getNamedItem('table:number-rows-spanned').nodeValue - 1;
IsSpanning := true;
end;
if Assigned(Nodes[I].attributes.getNamedItem('table:number-columns-spanned')) then
begin
NumbOfRepColumns :=
Nodes[I].attributes.getNamedItem('table:number-columns-spanned').nodeValue - 1;
IsSpanning := true;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -