Pārlūkot izejas kodu

Export Excel: use OExport to Export xls/xlsx

MaiXinRong 8 gadi atpakaļ
vecāks
revīzija
1b8ad62db4

+ 2 - 2
Forms/MainFrm.pas

@@ -722,7 +722,7 @@ var
   sFileName: string;
   Exportor: TIDTreeExcelExportor;
 begin
-  if SaveFile(sFileName, '.xls') then
+  if SaveExcelFile(sFileName) then
   begin
     Exportor := TIDTreeExcelExportor.Create;
     try
@@ -809,7 +809,7 @@ var
   sFileName: string;
   Exportor: TIDTreeExcelExportor;
 begin
-  if SaveFile(sFileName, '.xls') then
+  if SaveExcelFile(sFileName) then
   begin
     Exportor := TIDTreeExcelExportor.Create;
     try

+ 1 - 1
Frames/BillsCompileFme.pas

@@ -414,7 +414,7 @@ var
   sFileName: string;
   ExcelExportor: TExcelExportor;
 begin
-  if SaveFile(sFileName, '.xls') then
+  if SaveExcelFile(sFileName) then
   begin
     ExcelExportor := TExcelExportor.Create;
     try

+ 1 - 1
Frames/BillsMeasureFme.pas

@@ -271,7 +271,7 @@ var
   sFileName: string;
   ExcelExportor: TExcelExportor;
 begin
-  if SaveFile(sFileName, '.xls') then
+  if SaveExcelFile(sFileName) then
   begin
     ExcelExportor := TExcelExportor.Create;
     try

+ 2 - 2
TenderPartition/tpPartTenderSetFme.pas

@@ -114,7 +114,7 @@ var
   sFileName: string;
   Exportor: TMasterExcelExportor;
 begin
-  if SaveFile(sFileName, '.xls') then
+  if SaveExcelFile(sFileName) then
   begin
     Exportor := TMasterExcelExportor.Create;
     try
@@ -136,7 +136,7 @@ var
   sFileName: string;
   Exportor: TMasterExcelExportor;
 begin
-  if SaveFile(sFileName, '.xls') then
+  if SaveExcelFile(sFileName) then
   begin
     Exportor := TMasterExcelExportor.Create;
     try

+ 230 - 248
Units/ExportExcel.pas

@@ -4,24 +4,26 @@ interface
 
 uses
   Classes, ZjGrid, ScXlsOutput, ScXlsCustomUD, Windows, StdCtrls,
-  sdIDTree, sdDB, Graphics, SysUtils, ProgressHintFrm, Forms, Controls;
+  sdIDTree, sdDB, Graphics, SysUtils, ProgressHintFrm, Forms, Controls,
+  OExport, OExport_Vcl, OExport_VclForms;
 
 type
   TExcelExportor = class
   private
-    FXlsOutPut: TXlsOutPut;
+    FOExport: TOExport;
     FGrid: TZJGrid;
     FTempFile: string;
     FFileName: string;
 
-    procedure InitialPage(AGrid: TZJGrid; AXlsPage: TXlsCustomPage);
+    procedure InitialPage(AGrid: TZJGrid; ASheet: TExportWorkSheet);
   protected
     procedure BeforeExport;
     procedure EndExport;
   public
     constructor Create;
     destructor Destroy; override;
-    procedure ExportToXlsPage(AGrid: TZJGrid; AXlsPage: TXlsCustomPage);
+
+    procedure ExportToSheet(AGrid: TZJGrid; ASheet: TExportWorkSheet);
     procedure ExportToFile(AGrid: TZJGrid; const AFileName: string);
   end;
 
@@ -40,7 +42,7 @@ type
     // 列宽
     Width: Integer;
     // 对齐方式
-    HorTextAlign: TUDHTextAlign;
+    HorTextAlign: TCellHAlignment;
     //VerTextAlign: TUDVTextAlign;
   end;
 
@@ -48,11 +50,11 @@ type
 
   TColInfos = array [0..30] of TColInfo;
 
-  // 仿照DataSet的Lookup以及数据库的AutoUpdate达到关于sdIDTree导出数据至Excel的普适性
+  // 仿照DataSet的Lookup以及数据库的AutoUpdate, 以达到关于sdIDTree导出数据至Excel的普适性
   // 导出前须根据所需列信息,以及查询数据库(列信息须与查询数据库对等,否则将会报错,并不检查列与数据库是否匹配)
   TIDTreeExcelExportor = class
   private
-    FXlsOutPut: TXlsOutPut;
+    FOExport: TOExport;
     FDataSetList: TList;
     FColInfos: PColInfos;
     FColCount: Integer;
@@ -64,9 +66,9 @@ type
     function GetCellValue(ANode: TsdIDTreeNode; ColInfo: TColInfo): Variant;
     // 故换成直接使用String
     function GetCellStr(ANode: TsdIDTreeNode; ColInfo: TColInfo): string;
-    procedure ExportNodeData(ANode: TsdIDTreeNode; AXlsPage: TXlsCustomPage; const ALevelCode: string);
-    procedure ExportTreeNode(ANode: TsdIDTreeNode; AXlsPage: TXlsCustomPage; const ALevelCode: string);
-    procedure DefineHeader(AXlsPage: TXlsCustomPage);
+    procedure ExportNodeData(ANode: TsdIDTreeNode; ASheet: TExportWorkSheet; const ALevelCode: string);
+    procedure ExportTreeNode(ANode: TsdIDTreeNode; ASheet: TExportWorkSheet; const ALevelCode: string);
+    procedure DefineHeader(ASheet: TExportWorkSheet);
   protected
     procedure BeforeExport;
     procedure AfterExport;
@@ -77,7 +79,7 @@ type
     procedure AddLookupDataSet(ADataSet: TsdDataSet);
     procedure DefineCol(AColInfos: PColInfos; AColCount: Integer);
 
-    procedure ExportToXlsPage(ATree: TsdIDTree; AXlsPage: TXlsCustomPage);
+    procedure ExportToSheet(ATree: TsdIDTree; ASheet: TExportWorkSheet);
     procedure ExportToFile(ATree: TsdIDTree; const AFileName: string);
 
     property HasLevelCode: Boolean read FHasLevelCode write FHasLevelCode;
@@ -85,7 +87,7 @@ type
 
   TMasterExcelExportor = class
   private
-    FXlsOutPut: TXlsOutPut;
+    FOExport: TOExport;
     FColInfos: PColInfos;
     FRelaColInfos: PColInfos;
     FColCount: Integer;
@@ -97,9 +99,9 @@ type
     FMasterFieldName: string;
 
     function GetCellValue(ARec: TsdDataRecord; ColInfo: TColInfo): Variant;
-    procedure ExportRecord(ARec: TsdDataRecord; AXlsPage: TXlsCustomPage; ARow: Integer; AColInfos: PColInfos);
-    procedure ExportData(AXlsPage: TXlsCustomPage);
-    procedure DefineHeader(AXlsPage: TXlsCustomPage);
+    procedure ExportRecord(ARec: TsdDataRecord; ASheet: TExportWorkSheet; AColInfos: PColInfos);
+    procedure ExportData(ASheet: TExportWorkSheet);
+    procedure DefineHeader(ASheet: TExportWorkSheet);
   protected
     procedure BeforeExport;
     procedure AfterExport;
@@ -111,104 +113,104 @@ type
     procedure DefineMasterDataSet(ADataSet: TsdDataSet; const AKeyFieldName: string);
     procedure DefineRelaDataSet(ADataSet: TsdDataSet; const AMasterFieldName: string);
 
-    procedure ExportToXlsPage(AXlsPage: TXlsCustomPage);
+    procedure ExportToSheet(ASheet: TExportWorkSheet);
     procedure ExportToFile(const AFileName: string);
   end;
 
 const
   ciLedger: array [0..8] of TColInfo =(
-    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: htaLeft),
-    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: htaLeft),
-    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: htaCenter),
-    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: htaRight),
-    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'OrgTotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: htaLeft),
-    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: htaLeft)
+    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: cahLeft),
+    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: cahLeft),
+    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: cahCenter),
+    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: cahRight),
+    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'OrgTotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: cahLeft),
+    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: cahLeft)
   );
 
   ciLedgerWithMis: array [0..10] of TColInfo =(
-    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: htaLeft),
-    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: htaLeft),
-    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: htaCenter),
-    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: htaRight),
-    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '施工图数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'MisQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计错漏数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'OthQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '其他错漏数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: htaLeft),
-    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: htaLeft)
+    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: cahLeft),
+    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: cahLeft),
+    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: cahCenter),
+    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: cahRight),
+    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '施工图数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'MisQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计错漏数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'OthQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '其他错漏数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: cahLeft),
+    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: cahLeft)
   );
 
   ciFxBills: array [0..10] of TColInfo =(
-    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '预算项目节'; Width: 120; HorTextAlign: htaLeft),
-    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单子目号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: htaLeft),
-    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: htaCenter),
-    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单数量'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'DgnQuantity1'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量1'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'DgnQuantity2'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量2'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: htaRight),
-    (FieldName: 'OrgTotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '合价'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: htaLeft),
-    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: htaLeft)
+    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '预算项目节'; Width: 120; HorTextAlign: cahLeft),
+    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单子目号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: cahLeft),
+    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: cahCenter),
+    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单数量'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'DgnQuantity1'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量1'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'DgnQuantity2'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量2'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: cahRight),
+    (FieldName: 'OrgTotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '合价'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: cahLeft),
+    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: cahLeft)
   );
 
   ciFxBillsWithMis: array [0..12] of TColInfo =(
-    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '预算项目节'; Width: 120; HorTextAlign: htaLeft),
-    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单子目号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: htaLeft),
-    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: htaCenter),
-    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'MisQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计错漏数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'OthQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '其他错漏数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'DgnQuantity1'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量1'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'DgnQuantity2'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量2'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: htaRight),
-    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '合价'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: htaLeft),
-    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: htaLeft)
+    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '预算项目节'; Width: 120; HorTextAlign: cahLeft),
+    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单子目号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: cahLeft),
+    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: cahCenter),
+    (FieldName: 'OrgQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'MisQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计错漏数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'OthQuantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '其他错漏数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'DgnQuantity1'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量1'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'DgnQuantity2'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '设计数量2'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: cahRight),
+    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '合价'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 100; HorTextAlign: cahLeft),
+    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: cahLeft)
   );
 
   ciTpPegGcl: array [0..9] of TColInfo =(
-    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: htaLeft),
-    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: htaLeft),
-    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: htaCenter),
-    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: htaRight),
-    (FieldName: 'Quantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'Peg'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '桩号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: htaLeft)
+    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: cahLeft),
+    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: cahLeft),
+    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: cahCenter),
+    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: cahRight),
+    (FieldName: 'Quantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'Peg'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '桩号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: cahLeft)
   );
 
   ciTpGclPeg_Gcl: array [0..9] of TColInfo =(
-    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: htaLeft),
-    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: htaLeft),
-    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: htaCenter),
-    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: htaRight),
-    (FieldName: 'Quantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'Peg'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '桩号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: htaLeft)
+    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: cahLeft),
+    (FieldName: 'Name'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: cahLeft),
+    (FieldName: 'Units'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: cahCenter),
+    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: cahRight),
+    (FieldName: 'Quantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'Peg'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '桩号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: cahLeft)
   );
 
   ciTpGclPeg_Peg: array [0..9] of TColInfo =(
-    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'PegXmjCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: htaLeft),
-    (FieldName: 'PegXmjName'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: htaLeft),
-    (FieldName: 'PegXmjUnits'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: htaCenter),
-    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: htaRight),
-    (FieldName: 'Quantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 90; HorTextAlign: htaRight),
-    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: htaRight),
-    (FieldName: 'Peg'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '桩号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 80; HorTextAlign: htaLeft),
-    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: htaLeft)
+    (FieldName: 'B_Code'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '清单编号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'PegXmjCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '项目节编号'; Width: 120; HorTextAlign: cahLeft),
+    (FieldName: 'PegXmjName'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '名称'; Width: 200; HorTextAlign: cahLeft),
+    (FieldName: 'PegXmjUnits'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单位'; Width: 40; HorTextAlign: cahCenter),
+    (FieldName: 'Price'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '单价'; Width: 60; HorTextAlign: cahRight),
+    (FieldName: 'Quantity'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '数量'; Width: 90; HorTextAlign: cahRight),
+    (FieldName: 'TotalPrice'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '金额'; Width: 80; HorTextAlign: cahRight),
+    (FieldName: 'Peg'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '桩号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'DrawingCode'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '图号'; Width: 80; HorTextAlign: cahLeft),
+    (FieldName: 'MemoStr'; KeyField: ''; LookupKeyField: ''; LookupDataSetIndex: -1; TitleCaption: '备注'; Width: 80; HorTextAlign: cahLeft)
   );
 
 implementation
@@ -216,6 +218,14 @@ implementation
 uses
   ZhAPI, Variants, UtilMethods, Math;
 
+function GetExportor(const AFileType: string): TOCustomExporter;
+begin
+  if SameText(AFileType, '.xls') then
+    Result := TOCustomExporterXLS.Create
+  else if SameText(AFileType, '.xlsx') then
+    Result := TOCustomExporterXLSX.Create;
+end;
+
 { TExcelExportor }
 
 procedure TExcelExportor.BeforeExport;
@@ -226,7 +236,9 @@ end;
 
 constructor TExcelExportor.Create;
 begin
-  FXlsOutPut := TXlsOutPut.Create;
+  FOExport := TOExport.Create;
+  FOExport.UseProgress := False;
+
   FTempFile := GetTempFileName;
 end;
 
@@ -234,7 +246,7 @@ destructor TExcelExportor.Destroy;
 begin
   if FileExists(FTempFile) then
     DeleteFileOrFolder(FTempFile);
-  FXlsOutPut.Free;
+  FOExport.Free;
   inherited;
 end;
 
@@ -246,111 +258,122 @@ end;
 
 procedure TExcelExportor.ExportToFile(AGrid: TZJGrid;
   const AFileName: string);
+var
+  vExportor: TOCustomExporter;
 begin
   FFileName := AFileName;
   FGrid := AGrid;
   BeforeExport;
   try
-    ExportToXlsPage(AGrid, FXlsOutPut.AddPage);
-    FXlsOutPut.SaveToFile(FTempFile);
+    vExportor := GetExportor(ExtractFileExt(AFileName));
+    ExportToSheet(AGrid, FOExport.AddWorkSheet);
+    FOExport.SaveToFile(FTempFile, vExportor);
     if not FileExists(FFileName) or QuestMessage('存在同名文件,是否替换?') then
       CopyFileOrFolder(FTempFile, FFileName);
   finally
+    vExportor.Free;
     EndExport;
   end;
 end;
 
-procedure TExcelExportor.ExportToXlsPage(AGrid: TZJGrid;
-  AXlsPage: TXlsCustomPage);
+procedure TExcelExportor.ExportToSheet(AGrid: TZJGrid;
+  ASheet: TExportWorkSheet);
 
-  procedure SetXlsCellTextAlign(AXlsCell: TXlsCustomCell; AGridCell: TzjCell);
+  procedure SetXlsCellTextAlign(ACell: TExportCell; AGridCell: TzjCell);
   begin
     case AGridCell.TextAlign of
       gaTopLeft:
       begin
-        AXlsCell.VTextAlign := vtaTop;
-        AXlsCell.HTextAlign := htaLeft;
+        ACell.SetVAlignment(cavTop);
+        ACell.SetAlignment(cahLeft);
       end;
       gaTopCenter:
       begin
-        AXlsCell.VTextAlign := vtaTop;
-        AXlsCell.HTextAlign := htaCenter;
+        ACell.SetVAlignment(cavTop);
+        ACell.SetAlignment(cahCenter);
       end;
       gaTopRight:
       begin
-        AXlsCell.VTextAlign := vtaTop;
-        AXlsCell.HTextAlign := htaRight;
+        ACell.SetVAlignment(cavTop);
+        ACell.SetAlignment(cahRight);
       end;
       gaCenterLeft:
       begin
-        AXlsCell.VTextAlign := vtaCenter;
-        AXlsCell.HTextAlign := htaLeft;
+        ACell.SetVAlignment(cavCenter);
+        ACell.SetAlignment(cahLeft);
       end;
       gaCenterCenter:
       begin
-        AXlsCell.VTextAlign := vtaCenter;
-        AXlsCell.HTextAlign := htaCenter;
+        ACell.SetVAlignment(cavCenter);
+        ACell.SetAlignment(cahCenter);
       end;
       gaCenterRight:
       begin
-        AXlsCell.VTextAlign := vtaCenter;
-        AXlsCell.HTextAlign := htaRight;
+        ACell.SetVAlignment(cavCenter);
+        ACell.SetAlignment(cahRight);
       end;
       gaBottomLeft:
       begin
-        AXlsCell.VTextAlign := vtaBottom;
-        AXlsCell.HTextAlign := htaLeft;
+        ACell.SetVAlignment(cavBottom);
+        ACell.SetAlignment(cahLeft);
       end;
       gaBottomCenter:
       begin
-        AXlsCell.VTextAlign := vtaBottom;
-        AXlsCell.HTextAlign := htaCenter;
+        ACell.SetVAlignment(cavBottom);
+        ACell.SetAlignment(cahCenter);
       end;
       gaBottomRight:
       begin
-        AXlsCell.VTextAlign := vtaBottom;
-        AXlsCell.HTextAlign := htaRight;
+        ACell.SetVAlignment(cavBottom);
+        ACell.SetAlignment(cahRight);
       end;
     end;
     if goWarpText in AGridCell.Grid.Options then
-      AXlsCell.WartText := True;
+      ACell.WrapText := True;
   end;
 
-  procedure ExportGridCell(AGridCell: TzjCell);
+  procedure ExportGridCell(AGridCell: TzjCell; ARow: TExportRow);
   var
+    vCell: TExportCell;
     XlsCell: TXlsCustomCell;
   begin
-    if AGridCell = nil then Exit;
-    XlsCell := AXlsPage.AddCell(AGridCell.Col, AGridCell.Row, AGridCell.Text);
-    SetXlsCellTextAlign(XlsCell, AGridCell);
-    XlsCell.Font.Name := AGridCell.Font.Name;
-    XlsCell.Font.Size := AGridCell.Font.Size;
-    XlsCell.Width := AGridCell.Width;
-    XlsCell.Height := AGridCell.Height;
+    if (AGridCell = nil) then Exit;
+    if ARow.Cells.Count >= AGridCell.Col + 1 then
+      vCell := ARow.Cells[AGridCell.Col]
+    else
+      vCell := ARow.AddCellString(AGridCell.Text);
+    SetXlsCellTextAlign(vCell, AGridCell);
+    vCell.Font.Name := AGridCell.Font.Name;
+    vCell.Font.Size := AGridCell.Font.Size;
+    vCell.RowSpan := AGridCell.Height;
+    vCell.ColSpan := AGridCell.Width;
+    vCell.Width := FGrid.ColWidths[AGridCell.Col];
+    vCell.Height := FGrid.RowHeights[AGridCell.Row];
   end;
 
 var
   iColumn, iRow: Integer;
+  vRow: TExportRow;
 begin
-  InitialPage(AGrid, AXlsPage);
   for iRow := 0 to AGrid.RowCount - 1 do
   begin
     UpdateProgressHint(Format('导出第%d行数据', [iRow + 1]));
     UpdateProgressHint(1);
+    vRow := ASheet.AddRow;
     for iColumn := 0 to AGrid.ColCount - 1 do
-      ExportGridCell(AGrid.Cells[iColumn, iRow]);
+      ExportGridCell(AGrid.Cells[iColumn, iRow], vRow);
   end;
 end;
 
 procedure TExcelExportor.InitialPage(AGrid: TZJGrid;
-  AXlsPage: TXlsCustomPage);
+  ASheet: TExportWorkSheet);
 
   procedure InitialColumnWidth;
   var
     iColumn: Integer;
   begin
     for iColumn := 0 to AGrid.ColCount - 1 do
-      AXlsPage.Widths[iColumn] := AGrid.ColWidths[iColumn];
+      ASheet.Cols[iColumn].SetWidth(AGrid.ColWidths[iColumn]);
   end;
 
   procedure InitialRowHeight;
@@ -358,7 +381,7 @@ procedure TExcelExportor.InitialPage(AGrid: TZJGrid;
     iRow: Integer;
   begin
     for iRow := 0 to AGrid.RowCount - 1 do
-      AXlsPage.Heights.Items[iRow] := AGrid.RowHeights[iRow];
+      ASheet.Rows[iRow].SetHeight(AGrid.RowHeights[iRow]);
   end;
 
 begin
@@ -370,7 +393,7 @@ end;
 
 constructor TIDTreeExcelExportor.Create;
 begin
-  FXlsOutPut := TXlsOutPut.Create;
+  FOExport := TOExport.Create;
   FDataSetList := TList.Create;
   FTempFile := GetTempFileName;
 end;
@@ -380,28 +403,32 @@ begin
   if FileExists(FTempFile) then
     DeleteFileOrFolder(FTempFile);
   FDataSetList.Free;
-  FXlsOutPut.Free;
+  FOExport.Free;
   inherited;
 end;
 
 procedure TIDTreeExcelExportor.ExportToFile(ATree: TsdIDTree;
   const AFileName: string);
+var
+  vExportor: TOCustomExporter;
 begin
   FTree := ATree;
   BeforeExport;
   try
-    ExportToXlsPage(ATree, FXlsOutPut.AddPage);
+    vExportor := GetExportor(ExtractFileExt(AFileName));
+    ExportToSheet(ATree, FOExport.AddWorkSheet);
     UpdateProgressHint('保存0号台账Excel数据');
-    FXlsOutPut.SaveToFile(FTempFile);
+    FOExport.SaveToFile(FTempFile, vExportor);
     if not FileExists(AFileName) or QuestMessage('存在同名文件,是否替换?') then
       CopyFileOrFolder(FTempFile, AFileName);
   finally
+    vExportor.Free;
     AfterExport;
   end;
 end;
 
 procedure TIDTreeExcelExportor.ExportTreeNode(ANode: TsdIDTreeNode;
-  AXlsPage: TXlsCustomPage; const ALevelCode: string);
+  ASheet: TExportWorkSheet; const ALevelCode: string);
 
   function GetFirstChildLevelCode(const ACode: string): string;
   begin
@@ -438,72 +465,45 @@ begin
   UpdateProgressHint(sHint);
   UpdateProgressHint(1);
 
-  ExportNodeData(ANode, AXlsPage, ALevelCode);
-  ExportTreeNode(ANode.FirstChild, AXlsPage, GetFirstChildLevelCode(ALevelCode));
-  ExportTreeNode(ANode.NextSibling, AXlsPage, GetNextSiblingLevelCode(ALevelCode));
+  ExportNodeData(ANode, ASheet, ALevelCode);
+  ExportTreeNode(ANode.FirstChild, ASheet, GetFirstChildLevelCode(ALevelCode));
+  ExportTreeNode(ANode.NextSibling, ASheet, GetNextSiblingLevelCode(ALevelCode));
 end;
 
 procedure TIDTreeExcelExportor.ExportNodeData(ANode: TsdIDTreeNode;
-  AXlsPage: TXlsCustomPage; const ALevelCode: string);
-
-  function ExportCell(ACol, ARow: Integer; AValue: Variant): TXlsCustomCell;
-  begin
-    Result := nil;
-
-    // -----------
-    if VarIsNull(AValue) then Exit;
-    // -----------
-    // 当数据超过3w3k行时,运行至某行时,AddCell会内存溢出
-    // 可能是Cell的数目超过某个限度时,报错
-    // 如果AValue为Null时不AddCell,则3w3k行可以安全度过
-
-    case VarType(AValue) of
-      varSmallInt, varInteger, varSingle, varDouble,
-      varCurrency, varShortInt, varByte, varWord,
-      varLongWord, varInt64:
-      begin
-        if AValue <> 0 then
-          Result := AXlsPage.AddCell(ACol, ARow, AValue);
-      end
-      else Result := AXlsPage.AddCell(ACol, ARow, AValue);
-    end;
-  end;
-
+  ASheet: TExportWorkSheet; const ALevelCode: string);
 var
   iCol: Integer;
   ColInfo: TColInfo;
+  vRow: TExportRow;
+  vCell: TExportCell;
   XlsCell: TXlsCustomCell;
   sStr: string;
 begin
   if not Assigned(ANode) then Exit;
+  vRow := ASheet.AddRow;
+  vRow.Height := 20;
   for iCol := 0 to FColCount - 1 do
   begin
     ColInfo := FColInfos[iCol];
-    XlsCell := ExportCell(iCol, ANode.MajorIndex + 1, GetCellValue(ANode, ColInfo));
-    {sStr := GetCellStr(ANode, ColInfo);
-    if sStr = '' then Continue;
-    XlsCell := AXlsPage.AddCell(iCol, ANode.MajorIndex + 1, sStr);}
-    if Assigned(XlsCell) then
-    begin
-      XlsCell.HTextAlign := ColInfo.HorTextAlign;
-      //XlsCell.VTextAlign := ColInfo.VerTextAlign;
-      XlsCell.Font.Name := 'SmartSimSun';
-      XlsCell.Font.Size := 9;
-    end;
+    vCell := vRow.AddCellString(GetCellStr(ANode, ColInfo));
+    vCell.Alignment := ColInfo.HorTextAlign;
+    vCell.Font.Name := 'SmartSimSun';
+    vCell.Font.Size := 9;
   end;
   if HasLevelCode then
   begin
-    XlsCell := ExportCell(FColCount, ANode.MajorIndex + 1, ALevelCode);
-    XlsCell.Font.Name := 'SmartSimSun';
-    XlsCell.Font.Size := 9;
+    vCell := vRow.AddCellString(ALevelCode);
+    vCell.Font.Name := 'SmartSimSun';
+    vCell.Font.Size := 9;
   end;
 end;
 
-procedure TIDTreeExcelExportor.ExportToXlsPage(ATree: TsdIDTree;
-  AXlsPage: TXlsCustomPage);
+procedure TIDTreeExcelExportor.ExportToSheet(ATree: TsdIDTree;
+  ASheet: TExportWorkSheet);
 begin
-  DefineHeader(AXlsPage);
-  ExportTreeNode(ATree.FirstNode, AXlsPage, '1');
+  DefineHeader(ASheet);
+  ExportTreeNode(ATree.FirstNode, ASheet, '1');
 end;
 
 function TIDTreeExcelExportor.GetCellValue(ANode: TsdIDTreeNode;
@@ -532,29 +532,33 @@ begin
     Result := ARec.ValueByName(ColInfo.FieldName).Value;
 end;
 
-procedure TIDTreeExcelExportor.DefineHeader(AXlsPage: TXlsCustomPage);
+procedure TIDTreeExcelExportor.DefineHeader(ASheet: TExportWorkSheet);
 var
   iCol: Integer;
   ColInfo: TColInfo;
+  vRow: TExportRow;
+  vCell: TExportCell;
   XlsCell: TXlsCustomCell;
 begin
+  vRow := ASheet.AddRow;
+  vRow.Height := 20;
   for iCol := 0 to FColCount - 1 do
   begin
     ColInfo := FColInfos[iCol];
-    XlsCell := AXlsPage.AddCell(iCol, 0, ColInfo.TitleCaption);
-    XlsCell.HTextAlign := htaCenter;
-    XlsCell.Font.Name := '黑体';
-    XlsCell.Font.Size := 10;
-    XlsCell.Font.Style := [fsBold];
-    AXlsPage.Widths[iCol] := ColInfo.Width;
+    vCell := vRow.AddCellString(ColInfo.TitleCaption);
+    vCell.SetAlignment(cahCenter);
+    vCell.SetVAlignment(cavCenter);
+    vCell.Font.Name := '黑体';
+    vCell.Font.Size := 10;
+    vCell.Width := ColInfo.Width;
   end;
   if HasLevelCode then
   begin
-    XlsCell := AXlsPage.AddCell(iCol, 0, '层次编号');
-    XlsCell.HTextAlign := htaCenter;
-    XlsCell.Font.Name := '黑体';
-    XlsCell.Font.Size := 10;
-    XlsCell.Font.Style := [fsBold];
+    vCell := vRow.AddCellString('层次编号');
+    vCell.SetAlignment(cahCenter);
+    vCell.SetVAlignment(cavCenter);
+    vCell.Font.Name := '黑体';
+    vCell.Font.Size := 10;
   end;
 end;
 
@@ -619,7 +623,7 @@ end;
 
 constructor TMasterExcelExportor.Create;
 begin
-  FXlsOutPut := TXlsOutPut.Create;
+  FOExport := TOExport.Create;
   FTempFile := GetTempFileName;
 end;
 
@@ -631,21 +635,24 @@ begin
   FRelaColInfos := ARelaColInfo;
 end;
 
-procedure TMasterExcelExportor.DefineHeader(AXlsPage: TXlsCustomPage);
+procedure TMasterExcelExportor.DefineHeader(ASheet: TExportWorkSheet);
 var
   iCol: Integer;
   ColInfo: TColInfo;
-  XlsCell: TXlsCustomCell;
+  vRow: TExportRow;
+  vCell: TExportCell;
 begin
+  vRow := ASheet.AddRow;
+  vRow.Height := 20;
   for iCol := 0 to FColCount - 1 do
   begin
     ColInfo := FColInfos[iCol];
-    XlsCell := AXlsPage.AddCell(iCol, 0, ColInfo.TitleCaption);
-    XlsCell.HTextAlign := htaCenter;
-    XlsCell.Font.Name := '黑体';
-    XlsCell.Font.Size := 10;
-    XlsCell.Font.Style := [fsBold];
-    AXlsPage.Widths[iCol] := ColInfo.Width;
+    vCell := vRow.AddCellString(ColInfo.TitleCaption);
+    vCell.SetAlignment(cahCenter);
+    vCell.SetVAlignment(cavCenter);
+    vCell.Font.Name := '黑体';
+    vCell.Font.Size := 10;
+    vCell.Width := ColInfo.Width;
   end;
 end;
 
@@ -667,7 +674,7 @@ destructor TMasterExcelExportor.Destroy;
 begin
   if FileExists(FTempFile) then
     DeleteFileOrFolder(FTempFile);
-  FXlsOutPut.Free;
+  FOExport.Free;
   inherited;
 end;
 
@@ -676,100 +683,75 @@ begin
   Screen.Cursor := crDefault;
 end;
 
-procedure TMasterExcelExportor.ExportData(AXlsPage: TXlsCustomPage);
+procedure TMasterExcelExportor.ExportData(ASheet: TExportWorkSheet);
 var
-  i, j, iRow: Integer;
+  i, j: Integer;
   Rec, RelaRec: TsdDataRecord;
 begin
-  iRow := 1;
   for i := 0 to FMasterDataSet.RecordCount - 1 do
   begin
     Rec := FMasterDataSet.Records[i];
-    ExportRecord(Rec, AXlsPage, iRow, FColInfos);
-    Inc(iRow);
+    ExportRecord(Rec, ASheet, FColInfos);
     for j := 0 to FRelaDataSet.RecordCount - 1 do
     begin
       RelaRec := FRelaDataSet.Records[j];
       if (RelaRec.ValueByName(FMasterFieldName).Value = Rec.ValueByName(FKeyFieldName).Value) then
       begin
         if Assigned(FRelaColInfos) then
-          ExportRecord(RelaRec, AXlsPage, iRow, FRelaColInfos)
+          ExportRecord(RelaRec, ASheet, FRelaColInfos)
         else
-          ExportRecord(RelaRec, AXlsPage, iRow, FColInfos);
-        Inc(iRow);
+          ExportRecord(RelaRec, ASheet, FColInfos);
       end;
     end;
   end;
 end;
 
 procedure TMasterExcelExportor.ExportRecord(ARec: TsdDataRecord;
-  AXlsPage: TXlsCustomPage; ARow: Integer; AColInfos: PColInfos);
-
-  function ExportCell(ACol, ARow: Integer; AValue: Variant): TXlsCustomCell;
-  begin
-    Result := nil;
-
-    // -----------
-    if VarIsNull(AValue) then Exit;
-    // -----------
-    // 当数据超过3w3k行时,运行至某行时,AddCell会内存溢出
-    // 可能是Cell的数目超过某个限度时,报错
-    // 如果AValue为Null时不AddCell,则3w3k行可以安全度过
-
-    case VarType(AValue) of
-      varSmallInt, varInteger, varSingle, varDouble,
-      varCurrency, varShortInt, varByte, varWord,
-      varLongWord, varInt64:
-      begin
-        if AValue <> 0 then
-          Result := AXlsPage.AddCell(ACol, ARow, AValue);
-      end
-      else Result := AXlsPage.AddCell(ACol, ARow, AValue);
-    end;
-  end;
-
+  ASheet: TExportWorkSheet; AColInfos: PColInfos);
 var
   iCol: Integer;
   ColInfo: TColInfo;
-  XlsCell: TXlsCustomCell;
+  vRow: TExportRow;
+  vCell: TExportCell;
   sStr: string;
 begin
   if not Assigned(ARec) then Exit;
 
+  vRow := ASheet.AddRow;
   for iCol := 0 to FColCount - 1 do
   begin
     ColInfo := AColInfos[iCol];
-    XlsCell := ExportCell(iCol, ARow, GetCellValue(ARec, ColInfo));
-    if Assigned(XlsCell) then
-    begin
-      XlsCell.HTextAlign := ColInfo.HorTextAlign;
-      XlsCell.Font.Name := 'SmartSimSun';
-      XlsCell.Font.Size := 9;
-    end;
+    vCell := vRow.AddCellVariant(GetCellValue(ARec, ColInfo));
+    vCell.Font.Name := 'SmartSimSun';
+    vCell.Font.Size := 9;
   end;
 end;
 
 procedure TMasterExcelExportor.ExportToFile(const AFileName: string);
+var
+  vExportor: TOCustomExporter;
 begin
   if not Assigned(FMasterDataSet) then Exit;
 
   BeforeExport;
   try
-    ExportToXlsPage(FXlsOutPut.AddPage);
-    FXlsOutPut.SaveToFile(FTempFile);
+    vExportor := GetExportor(ExtractFileExt(AFileName));
+    ExportToSheet(FOExport.AddWorkSheet);
+    FOExport.SaveToFile(FTempFile, vExportor);
     if not FileExists(AFileName) or QuestMessage('存在同名文件,是否替换?') then
       CopyFile(PChar(FTempFile), PChar(AFileName), False);
   finally
+    vExportor.Free;
     AfterExport;
   end;
 end;
 
-procedure TMasterExcelExportor.ExportToXlsPage(AXlsPage: TXlsCustomPage);
+procedure TMasterExcelExportor.ExportToSheet(ASheet: TExportWorkSheet);
 begin
   if not Assigned(FMasterDataSet) then Exit;
 
-  DefineHeader(AXlsPage);
-  ExportData(AXlsPage);
+  DefineHeader(ASheet);
+  ExportData(ASheet);
 end;
 
 function TMasterExcelExportor.GetCellValue(ARec: TsdDataRecord;

+ 38 - 0
Units/UtilMethods.pas

@@ -50,6 +50,7 @@ type
   function SelectFile(var AFileName: string; const AExt: string): Boolean;
   function SelectFiles(AFiles: TStrings; const AExt: string): Boolean;
   function SaveFile(var FileName: string; const AExt: string): Boolean;
+  function SaveExcelFile(var FileName: string): Boolean;
   function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
     AParentHandle: THandle = 0; AHasNewFolderBtn: Boolean = True): Boolean;
   function FixPathByAppPath(AFileName: string): string;
@@ -447,6 +448,43 @@ begin
   end;
 end;
 
+function SaveExcelFile(var FileName: string): Boolean;
+
+  function CheckFileName(AFileName: string; AExt: string): string;
+  begin
+    if SameText(ExtractFileExt(AFileName), AExt) then
+      Result := AFileName
+    else
+      Result := ExtractFilePath(AFileName) + ExtractFileName(AFileName) + AExt;
+  end;
+
+var
+  sdFile: TSaveDialog;
+begin
+  sdFile := TSaveDialog.Create(nil);
+  try
+    sdFile.FileName := FileName;
+    sdFile.Filter := 'ExcelÎļþ(*.xls)|*.xls;|ExcelÎļþ(*.xlsx)|*.xlsx;';
+    Result := sdFile.Execute;
+    if Result then
+    begin
+      case sdFile.FilterIndex of
+        1: FileName := CheckFileName(sdFile.FileName, '.xls');
+        2: FileName := CheckFileName(sdFile.FileName, '.xlsx');
+      end;
+    end;
+    (*
+      if sdFile.FilterIndex = 1 then
+      if not SameText(ExtractFileExt(sdFile.FileName), sdFile.DefaultExt) then
+        FileName := ExtractFileName(sdFile.FileName) + sdFile.DefaultExt
+      else
+        FileName := sdFile.FileName;
+    *)
+  finally
+    sdFile.Free;
+  end;
+end;
+
 function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
   AParentHandle: THandle; AHasNewFolderBtn: Boolean): Boolean;
 var