⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qimport3odt.pas

📁 Advanced Data Import Component Suite for Borland Delphi and C++ Builder allows you to import your da
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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 + -