瀏覽代碼

Merge branch 'master' of http://192.168.1.12:3000/MaiXinRong/Measure

Chenshilong 9 年之前
父節點
當前提交
7d50ce0bab

+ 2 - 2
Dprs/Pro/Measure.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MinorVer=1
 Release=6
-Build=116
+Build=1001
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横结算决算计量一体化专业版
-FileVersion=3.1.6.116
+FileVersion=3.1.6.1001
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 4 - 1
Dprs/Pro/Measure.dpr

@@ -192,7 +192,10 @@ uses
   CalcData in '..\..\Units\CalcData.pas',
   GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
   ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
-  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm};
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas';
 
 {$R *.res}
 

二進制
Dprs/Pro/Measure.res


+ 2 - 2
Dprs/Pro/Measure_Cloud.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MinorVer=1
 Release=6
-Build=116
+Build=1001
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横结算决算计量一体化云版
-FileVersion=3.1.6.116
+FileVersion=3.1.6.1001
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 4 - 1
Dprs/Pro/Measure_Cloud.dpr

@@ -196,7 +196,10 @@ uses
   CalcData in '..\..\Units\CalcData.pas',
   GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
   ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
-  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm};
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas';
 
 {$R *.res}
 

二進制
Dprs/Pro/Measure_Cloud.res


+ 2 - 2
Dprs/Pro/Measure_GuangDong.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MinorVer=1
 Release=6
-Build=117
+Build=1001
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横结算决算计量一体化广东专业版
-FileVersion=3.1.6.117
+FileVersion=3.1.6.1001
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 4 - 1
Dprs/Pro/Measure_GuangDong.dpr

@@ -192,7 +192,10 @@ uses
   CalcData in '..\..\Units\CalcData.pas',
   GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
   ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
-  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm};
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas';
 
 {$R *.res}
 

二進制
Dprs/Pro/Measure_GuangDong.res


+ 2 - 2
Dprs/Pro/Measure_GuangDong_Cloud.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MinorVer=1
 Release=6
-Build=116
+Build=1001
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横结算决算计量一体化广东云版
-FileVersion=3.1.6.116
+FileVersion=3.1.6.1001
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 4 - 1
Dprs/Pro/Measure_GuangDong_Cloud.dpr

@@ -196,7 +196,10 @@ uses
   CalcData in '..\..\Units\CalcData.pas',
   GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
   ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
-  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm};
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas';
 
 {$R *.res}
 

二進制
Dprs/Pro/Measure_GuangDong_Cloud.res


+ 2 - 2
Dprs/Pro/Measure_GuangDong_TZ.dof

@@ -115,7 +115,7 @@ AutoIncBuild=0
 MajorVer=3
 MinorVer=1
 Release=6
-Build=112
+Build=1000
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横0号台账广东专业版
-FileVersion=3.1.6.112
+FileVersion=3.1.6.1000
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 4 - 1
Dprs/Pro/Measure_GuangDong_TZ.dpr

@@ -192,7 +192,10 @@ uses
   CalcData in '..\..\Units\CalcData.pas',
   GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
   ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
-  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm};
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas';
 
 {$R *.res}
 

二進制
Dprs/Pro/Measure_GuangDong_TZ.res


+ 2 - 2
Dprs/Pro/Measure_TZ.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MinorVer=1
 Release=6
-Build=116
+Build=1001
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横0号台账专业版
-FileVersion=3.1.6.116
+FileVersion=3.1.6.1001
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 4 - 1
Dprs/Pro/Measure_TZ.dpr

@@ -192,7 +192,10 @@ uses
   CalcData in '..\..\Units\CalcData.pas',
   GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
   ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
-  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm};
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas';
 
 {$R *.res}
 

二進制
Dprs/Pro/Measure_TZ.res


+ 2 - 2
Dprs/Trail/Measure.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MinorVer=1
 Release=6
-Build=103
+Build=1001
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横结算决算计量一体化学习版
-FileVersion=3.1.6.103
+FileVersion=3.1.6.1001
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 19 - 1
Dprs/Trail/Measure.dpr

@@ -177,7 +177,25 @@ uses
   mPegFilter in '..\..\Units\mPegFilter.pas',
   ReportPrepare in '..\..\Report\ReportPrepare.pas',
   rdpBillsGatherDm in '..\..\Report\DataPrepare\rdpBillsGatherDm.pas' {rdpBillsGatherData: TDataModule},
-  rdpTables in '..\..\Report\DataPrepare\rdpTables.pas';
+  rdpTables in '..\..\Report\DataPrepare\rdpTables.pas',
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas',
+  ColVisibleManager in '..\..\Units\ColVisibleManager.pas',
+  ReportConnection in '..\..\Report\ReportConnection.pas',
+  rgpGatherControl in '..\..\Report\ProjGather\rgpGatherControl.pas',
+  rpgBillsCalcDm in '..\..\Report\ProjGather\rpgBillsCalcDm.pas' {rpgBillsCalcData: TDataModule},
+  rpgBillsDm in '..\..\Report\ProjGather\rpgBillsDm.pas' {rpgBillsData: TDataModule},
+  rpgGatherControl in '..\..\Report\ProjGather\rpgGatherControl.pas',
+  rpgGatherData in '..\..\Report\ProjGather\rpgGatherData.pas',
+  rpgGatherProjDm in '..\..\Report\ProjGather\rpgGatherProjDm.pas' {rpgGatherProjData: TDataModule},
+  rProjGatherTables in '..\..\Report\ProjGather\rProjGatherTables.pas',
+  ProjGather in '..\..\ProjGather\ProjGather.pas',
+  GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
+  ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  ProjGatherTree in '..\..\ProjGather\ProjGatherTree.pas',
+  CalcData in '..\..\Units\CalcData.pas';
 
 {$R *.res}
 

二進制
Dprs/Trail/Measure.res


+ 2 - 2
Dprs/Trail/Measure_GuangDong.dof

@@ -115,7 +115,7 @@ AutoIncBuild=1
 MajorVer=3
 MinorVer=1
 Release=6
-Build=103
+Build=1001
 Debug=0
 PreRelease=0
 Special=0
@@ -126,7 +126,7 @@ CodePage=936
 [Version Info Keys]
 CompanyName=珠海纵横创新软件有限公司
 FileDescription=纵横结算决算计量一体化广东学习版
-FileVersion=3.1.6.103
+FileVersion=3.1.6.1001
 InternalName=
 LegalCopyright=版权所有(C)珠海纵横创新软件有限公司2003-2016
 LegalTrademarks=Measure

+ 21 - 1
Dprs/Trail/Measure_GuangDong.dpr

@@ -175,9 +175,29 @@ uses
   tpSelectTendersFrm in '..\..\TenderPartition\tpSelectTendersFrm.pas' {SelectTendersForm},
   tpTrialPegInputFrm in '..\..\TenderPartition\tpTrialPegInputFrm.pas' {TrialPegInputForm},
   mPegFilter in '..\..\Units\mPegFilter.pas',
+
+  
   ReportPrepare in '..\..\Report\ReportPrepare.pas',
   rdpBillsGatherDm in '..\..\Report\DataPrepare\rdpBillsGatherDm.pas' {rdpBillsGatherData: TDataModule},
-  rdpTables in '..\..\Report\DataPrepare\rdpTables.pas';
+  rdpTables in '..\..\Report\DataPrepare\rdpTables.pas',
+  DealBillsExcelImport in '..\..\Units\DealBillsExcelImport.pas',
+  ExcelImport_Bills in '..\..\Units\ExcelImport_Bills.pas',
+  ExcelImport_GclBills in '..\..\Units\ExcelImport_GclBills.pas',
+  ColVisibleManager in '..\..\Units\ColVisibleManager.pas',
+  ReportConnection in '..\..\Report\ReportConnection.pas',
+  rgpGatherControl in '..\..\Report\ProjGather\rgpGatherControl.pas',
+  rpgBillsCalcDm in '..\..\Report\ProjGather\rpgBillsCalcDm.pas' {rpgBillsCalcData: TDataModule},
+  rpgBillsDm in '..\..\Report\ProjGather\rpgBillsDm.pas' {rpgBillsData: TDataModule},
+  rpgGatherControl in '..\..\Report\ProjGather\rpgGatherControl.pas',
+  rpgGatherData in '..\..\Report\ProjGather\rpgGatherData.pas',
+  rpgGatherProjDm in '..\..\Report\ProjGather\rpgGatherProjDm.pas' {rpgGatherProjData: TDataModule},
+  rProjGatherTables in '..\..\Report\ProjGather\rProjGatherTables.pas',
+  ProjGather in '..\..\ProjGather\ProjGather.pas',
+  GatherProjInfo in '..\..\ProjGather\GatherProjInfo.pas',
+  ProjGatherCalcData in '..\..\ProjGather\ProjGatherCalcData.pas',
+  ProjGatherSelectFrm in '..\..\ProjGather\ProjGatherSelectFrm.pas' {ProjGatherSelectForm},
+  ProjGatherTree in '..\..\ProjGather\ProjGatherTree.pas',
+  CalcData in '..\..\Units\CalcData.pas';
 
 {$R *.res}
 

二進制
Dprs/Trail/Measure_GuangDong.res


+ 5 - 6
Forms/MainFrm.pas

@@ -233,7 +233,8 @@ implementation
 uses
   ProjectProperty, ConstUnit, PHPWebDm, Math, ShellAPI,
   FindUserFrm, ImportExcelHintFrm, ConfigDoc, ExportExcel,
-  ProjectCommands, BillsCompileDm, tpMainFrm;
+  ProjectCommands, BillsCompileDm, tpMainFrm,
+  DealBillsExcelImport, ExcelImport_Bills, DetailExcelImport;
 
 {$R *.dfm}
 {$R MeasureIcons.RES}
@@ -537,18 +538,16 @@ end;
 procedure TMainForm.actnImportExcelExecute(Sender: TObject);
 var
   sFileName: string;
-  Importor: TBillsEdtExcelImport;
+  Importor: Tdei_CustomBills;
   bWithLevelCode, bWithoutGclBills: Boolean;
 begin
   if HintAndImportTypeSelect(bWithLevelCode, bWithoutGclBills) then
   begin
     if SelectFile(sFileName, '.xls') then
     begin
-      Importor := TBillsEdtExcelImport.Create(CurProjectFrame.ProjectData);
+      Importor := Tdei_CustomBills.Create(CurProjectFrame.ProjectData);
       try
-        Importor.WithLevelCode := bWithLevelCode;
-        Importor.WithoutGclBills := bWithoutGclBills;
-        Importor.ImportFile(sFileName);
+        Importor.ImportFile(sFileName, bWithLevelCode, bWithoutGclBills);
       finally
         Importor.Free;
       end;

+ 4 - 5
Frames/BillsCompileFme.pas

@@ -114,7 +114,7 @@ implementation
 
 uses
   MainFrm, BatchInsertBillsFrm, ExportExcel, ProjectData, mEncryptEditions,
-  ExcelImport, DetailExcelImport, mDataRecord;
+  ExcelImport, DetailExcelImport, mDataRecord, ExcelImport_GclBills;
 
 {$R *.dfm}
 
@@ -524,16 +524,15 @@ procedure TBillsCompileFrame.actnImportGclBillsToXmjExecute(
   Sender: TObject);
 var
   sFileName: string;
-  Importor: TGclBillsExcelImport;
+  Importor: TDEI_GclBills;
 begin
   if TProjectData(FBillsCompileData.ProjectData).CanInsertNormalBills then
   begin
     if SelectFile(sFileName, '.xls') then
     begin
-      Importor := TGclBillsExcelImport.Create(TProjectData(FBillsCompileData.ProjectData));
+      Importor := TDEI_GclBills.Create(TProjectData(FBillsCompileData.ProjectData));
       try
-        Importor.ParentID := stdBillsCompile.IDTree.Selected.ID;
-        Importor.ImportFile(sFileName);
+        Importor.ImportToXmj(sFileName, stdBillsCompile.IDTree.Selected.ID);
       finally
         Importor.Free;
       end;

+ 289 - 0
Units/DealBillsExcelImport.pas

@@ -0,0 +1,289 @@
+unit DealBillsExcelImport;
+// 导入签约清单
+
+interface
+
+uses
+  DetailExcelImport, ProjectData, Classes, sdDB;
+
+type
+  TDealBill = class
+  private
+    FB_Code: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+    FQuantity: Double;
+    FTotalPrice: Double;
+  public
+    property B_Code: string read FB_Code write FB_Code;
+    property Name: string read FName write FName;
+    property Units: string read FUnits write FUnits;
+    property Price: Double read FPrice write FPrice;
+    property Quantity: Double read FQuantity write FQuantity;
+    property TotalPrice: Double read FTotalPrice write FTotalPrice;
+
+    function IsParent(AChild: TDealBill): Boolean;
+  end;
+
+  TDealBillList = class
+  private
+    FList: TList;
+
+    procedure ClearParent(ADealBill: TDealBill);
+
+    function GetCount: Integer;
+    function GetDealBills(AIndex: Integer): TDealBill;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    procedure AddDealBill(ADealBill: TDealBill);
+
+    property Count: Integer read GetCount;
+    property DealBills[AIndex: Integer]: TDealBill read GetDealBills;
+  end;
+
+  TDealBillsExcelImport = class(TDetailExcelImport)
+  private
+    FDealBills: TDealBillList;
+
+    FB_CodeCol: Integer;
+    FNameCol: Integer;
+    FUnitsCol: Integer;
+    FPriceCol: Integer;
+    FQuantityCol: Integer;
+    FTotalPriceCol: Integer;
+
+    FCurRow: Integer;
+
+    function LoadColumnsFromHead: Boolean;
+    procedure LoadDealBills;
+    procedure WriteDealBills;
+  protected
+    procedure BeginImport; override;
+    procedure EndImport; override;
+
+    procedure Import; override;
+  public
+    constructor Create(AProjectData: TProjectData); override;
+    destructor Destroy; override;
+  end;
+
+implementation
+
+uses DateUtils, DealBillsDm, UtilMethods, SysUtils;
+
+{ TDealBillsExcelImport }
+
+procedure TDealBillsExcelImport.BeginImport;
+begin
+  ProjectData.DealBillsData.DisableEvent;
+  ProjectData.DealBillsData.sddDealBills.BeginUpdate;
+end;
+
+constructor TDealBillsExcelImport.Create(AProjectData: TProjectData);
+begin
+  inherited;
+  FDealBills := TDealBillList.Create;
+end;
+
+destructor TDealBillsExcelImport.Destroy;
+begin
+  FDealBills.Free;
+  inherited;
+end;
+
+procedure TDealBillsExcelImport.EndImport;
+begin
+  ProjectData.DealBillsData.sddDealBills.EndUpdate;
+  ProjectData.DealBillsData.EnableEvent;
+end;
+
+procedure TDealBillsExcelImport.Import;
+begin
+  FCurRow := 1;
+  if LoadColumnsFromHead then
+  begin
+    LoadDealBills;
+    WriteDealBills;
+  end
+  else
+    ErrorMessage('导入的Excel格式有误!');
+end;
+
+function TDealBillsExcelImport.LoadColumnsFromHead: Boolean;
+var
+  iCol: Integer;
+  sColName: string;
+begin
+  Result := False;
+
+  FB_CodeCol := -1;
+  FNameCol := -1;
+  FUnitsCol := -1;
+  FPriceCol := -1;
+  FQuantityCol := -1;
+  FTotalPriceCol := -1;
+
+  while (not Result) and (FCurRow <= Excel.XlsFile.MaxRow) do
+  begin
+    for iCol := 1 to Excel.XlsFile.MaxCol do
+    begin
+      sColName := GetCellValue(Excel.XlsFile, FCurRow, iCol);
+      sColName := StringReplace(sColName, ' ', '', [rfReplaceAll]);
+
+      if SameText(sColName, '清单编号') or (Pos('子目号', sColName) > 0) then
+        FB_CodeCol := iCol
+      else if Pos('名称', sColName) > 0 then
+        FNameCol := iCol
+      else if SameText(sColName, '单位') then
+        FUnitsCol := iCol
+      else if Pos('单价', sColName) = 1 then
+        FPriceCol := iCol
+      else if Pos('数量', sColName) > 0 then
+        FQuantityCol := iCol
+      else if (Pos('金额', sColName) > 0) or (Pos('合价', sColName) > 0) then
+        FTotalPriceCol := iCol;
+    end;
+
+    Result := (FB_CodeCol <> -1) and (FNameCol <> -1) and (FUnitsCol <> -1)
+        and (FPriceCol <> -1) and (FQuantityCol <> -1) and (FTotalPriceCol <> -1);
+    Inc(FCurRow);
+  end;
+end;
+
+procedure TDealBillsExcelImport.LoadDealBills;
+
+  function CheckIsBillsCode(ACode: string): Boolean;
+  const
+    FBillsCodeSet: set of char = ['0'..'9', '-', 'a'..'z', 'A'..'Z'];
+  var
+    I: Integer;
+  begin
+    Result := True;
+    I := 1;
+    while I < Length(ACode) do
+      if ACode[I] in FBillsCodeSet then
+        Inc(I)
+      else
+      begin
+        Result := False;
+        Break;
+      end;
+  end;
+
+  function FilterBillsCode(ACode: string): string;
+  var
+    I: Integer;
+  begin
+    Result := StringReplace(ACode, ' ', '', [rfReplaceAll]);
+    Result := StringReplace(Result, ' ', '', [rfReplaceAll]);
+    Result := StringReplace(Result, '补', '', [rfReplaceAll]);
+  end;
+
+var
+  sB_Code, sFilterB_Code: string;
+  vDealBill: TDealBill;
+begin
+  while (FCurRow <= Excel.XlsFile.MaxRow) do
+  begin
+    sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
+    sFilterB_Code := FilterBillsCode(sB_Code);
+    if (sFilterB_Code <> '')then
+    begin
+      if CheckIsBillsCode(sFilterB_Code) then
+      begin
+        vDealBill := TDealBill.Create;
+        vDealBill.B_Code := sB_Code;
+        vDealBill.Name := GetCellTrimStr(Excel.XlsFile, FCurRow, FNameCol);
+        vDealBill.Units := GetCellTrimStr(Excel.XlsFile, FCurRow, FUnitsCol);
+        vDealBill.Price := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
+        vDealBill.Quantity := GetCellFloat(Excel.XlsFile, FCurRow, FQuantityCol);
+        vDealBill.TotalPrice := GetCellFloat(Excel.XlsFile, FCurRow, FTotalPriceCol);
+        FDealBills.AddDealBill(vDealBill);
+      end;
+    end;
+    Inc(FCurRow);
+  end;
+end;
+
+procedure TDealBillsExcelImport.WriteDealBills;
+var
+  i: Integer;
+  vDealBill: TDealBill;
+  Rec: TsdDataRecord;
+begin
+  with ProjectData.DealBillsData do
+  begin
+    Clear;
+    for i := 0 to FDealBills.Count - 1 do
+    begin
+      vDealBill := FDealBills.DealBills[i];
+      Rec := sddDealBills.Add;
+      Rec.ValueByName('ID').AsInteger := i;
+      Rec.ValueByName('B_Code').AsString := vDealBill.B_Code;
+      Rec.ValueByName('IndexCode').AsString := B_CodeToIndexCode(vDealBill.B_Code);
+      Rec.ValueByName('Name').AsString := vDealBill.Name;
+      Rec.ValueByName('Units').AsString := vDealBill.Units;
+      Rec.ValueByName('Price').AsFloat := PriceRoundTo(vDealBill.Price);
+      Rec.ValueByName('Quantity').AsFloat := QuantityRoundTo(vDealBill.Quantity);
+      Rec.ValueByName('TotalPrice').AsFloat := TotalPriceRoundTo(vDealBill.TotalPrice);
+    end;
+  end;
+end;
+
+{ TDealBill }
+
+function TDealBill.IsParent(AChild: TDealBill): Boolean;
+begin
+  Result := Pos(B_Code+'-', AChild.B_Code) = 1;
+end;
+
+{ TDealBillList }
+
+procedure TDealBillList.AddDealBill(ADealBill: TDealBill);
+begin
+  ClearParent(ADealBill);
+  FList.Add(ADealBill);
+end;
+
+procedure TDealBillList.ClearParent(ADealBill: TDealBill);
+var
+  i: Integer;
+  vDealBill: TDealBill;
+begin
+  for i := 0 to FList.Count - 1 do
+  begin
+    vDealBill := DealBills[i];
+    if vDealBill.IsParent(ADealBill) then
+    begin
+      FList.Delete(i);
+      vDealBill.Free;
+      Break;
+    end;
+  end;
+end;
+
+constructor TDealBillList.Create;
+begin
+  FList := TList.Create;
+end;
+
+destructor TDealBillList.Destroy;
+begin
+  FList.Free;
+  inherited;
+end;
+
+function TDealBillList.GetCount: Integer;
+begin
+  Result := FList.Count;
+end;
+
+function TDealBillList.GetDealBills(AIndex: Integer): TDealBill;
+begin
+  Result := TDealBill(FList.Items[AIndex]);
+end;
+
+end.

+ 150 - 9
Units/DetailExcelImport.pas

@@ -11,20 +11,25 @@ type
   private
     FProjectData: TProjectData;
     FTempFile: string;
-    FExcel: TXlsOutPut;
-
+    FExcel: TXlsOutPut; 
+  protected
     function GetCellValue(AXlsFile: TXLSFile; ARow, ACol: Integer): string;
     function GetCellValueFormat(AXlsFile: TXLSFile; ARow, ACol: Integer): string;
+    function GetCellTrimStr(AXlsFile: TXLSFile; ARow, ACol: Integer): string;
+    function GetCellFloat(AXlsFile: TXLSFile; ARow, ACol: Integer): Double;
 
     procedure BeginImport; virtual; abstract;
     procedure EndImport; virtual; abstract;
 
     procedure Import; virtual; abstract;
   public
-    constructor Create(AProjectData: TProjectData);
+    constructor Create(AProjectData: TProjectData); virtual;
     destructor Destroy; override;
 
     procedure ImportFile(const AFileName: string);
+
+    property ProjectData: TProjectData read FProjectData;
+    property Excel: TXlsOutPut read FExcel;
   end;
 
   // 平面分项清单格式导入,导入至某项目节节点之下
@@ -66,7 +71,7 @@ type
 
     procedure WriteNode(ADataSet: TsdDataSet; ANode: TBillsCacheNode);
     procedure WriteNodes(ADataSet: TsdDataSet);
-
+ protected
     procedure BeginImport; override;
     procedure EndImport; override;
 
@@ -75,11 +80,29 @@ type
     property ParentID: Integer read FParentID write FParentID;
   end;
 
+  // 清单单价
+  TBillsPriceExcelImport = class(TDetailExcelImport)
+  private
+    FCurRow: Integer;
+
+    FB_CodeCol: Integer;
+    FNameCol: Integer;
+    FPriceCol: Integer;
+
+    procedure BeginImport; override;
+    procedure EndImport; override;
+
+    procedure LoadColumnsFromHead;
+    procedure UpdateBillsPrice(const AB_Code: string; APrice: Double);
+    procedure ImportBillsPriceData;
+    procedure Import; override;
+  end;
+
 implementation
 
 uses
   UtilMethods, SysUtils, ZhAPI, SheetSelectFrm, UExcelAdapter, UFlxMessages,
-  UFlxFormats, ProgressHintFrm;
+  UFlxFormats, ProgressHintFrm, mDataRecord;
 
 { TDetailExcelImport }
 
@@ -96,6 +119,18 @@ begin
   inherited;
 end;
 
+function TDetailExcelImport.GetCellFloat(AXlsFile: TXLSFile; ARow,
+  ACol: Integer): Double;
+begin
+  Result := StrToFloatDef(GetCellTrimStr(AXlsFile, ARow, ACol), 0);
+end;
+
+function TDetailExcelImport.GetCellTrimStr(AXlsFile: TXLSFile; ARow,
+  ACol: Integer): string;
+begin
+  Result := Trim(GetCellValue(AXlsFile, ARow, ACol));
+end;
+
 function TDetailExcelImport.GetCellValue(AXlsFile: TXLSFile; ARow,
   ACol: Integer): string;
 var
@@ -104,7 +139,7 @@ begin
   Result := '';
   if not Assigned(AXlsFile) or (ARow = -1) or (ACol = -1) then Exit;
   xlsCell := AXlsFile.CellValueX[ARow, ACol];
-  Result := xlsCell.Value;
+  Result := VarToStrDef(xlsCell.Value, '');
 end;
 
 function TDetailExcelImport.GetCellValueFormat(AXlsFile: TXLSFile; ARow,
@@ -210,13 +245,13 @@ begin
       vGclNode.B_Code := sB_Code;
       vGclNode.Name := sName;
       vGclNode.Units := sUnits;
-      vGclNode.Quantity := StrToFloatDef(GetCellValue(AXlsFile, FCurRow, FQuantityCol), 0);
+      vGclNode.OrgQuantity := StrToFloatDef(GetCellValue(AXlsFile, FCurRow, FQuantityCol), 0);
       vGclNode.Price := fPrice;
       vGclNode.DrawingCode := Trim(GetCellValue(AXlsFile, FCurRow, FDrawingCol));
       vGclNode.MemoStr := Trim(GetCellValue(AXlsFile, FCurRow, FMemoCol));
     end
     else
-      vGclNode.Quantity := vGclNode.Quantity + StrToFloatDef(GetCellValue(AXlsFile, FCurRow, FQuantityCol), 0);
+      vGclNode.OrgQuantity := vGclNode.OrgQuantity + StrToFloatDef(GetCellValue(AXlsFile, FCurRow, FQuantityCol), 0);
   end;
   Inc(FCurRow);
 end;
@@ -589,7 +624,7 @@ begin
   Rec.ValueByName('Name').AsString := ANode.Name;
   Rec.ValueByName('Units').AsString := ANode.Units;
   Rec.ValueByName('Price').AsFloat := PriceRoundTo(ANode.Price);
-  Rec.ValueByName('OrgQuantity').AsFloat := QuantityRoundTo(ANode.Quantity);
+  Rec.ValueByName('OrgQuantity').AsFloat := QuantityRoundTo(ANode.OrgQuantity);
   Rec.ValueByName('DrawingCode').AsString := ANode.DrawingCode;
   Rec.ValueByName('MemoStr').AsString := ANode.MemoStr;
   // 解锁前,新增清单为变更清单,解锁后,新增清单为0号台账清单
@@ -627,4 +662,110 @@ begin
   Screen.Cursor := crDefault;
 end;
 
+{ TBillsPriceExcelImport }
+
+procedure TBillsPriceExcelImport.BeginImport;
+begin
+  ShowProgressHint('导入Excel清单单价', 100);
+  FProjectData.BillsData.sddBills.BeginUpdate;
+  FCurRow := 1;
+end;
+
+procedure TBillsPriceExcelImport.EndImport;
+begin
+  FProjectData.BillsData.sddBills.EndUpdate;
+  UpdateProgressHint('正在计算导入后的数据');
+  FProjectData.BillsCompileData.CalculateAll;
+  CloseProgressHint;
+end;
+
+procedure TBillsPriceExcelImport.Import;
+begin
+  LoadColumnsFromHead;
+  ImportBillsPriceData;
+end;
+
+procedure TBillsPriceExcelImport.ImportBillsPriceData;
+
+  function CheckIsBillsCode(ACode: string): Boolean;
+  const
+    FBillsCodeSet: set of char = ['0'..'9', '-', 'a'..'z', 'A'..'Z'];
+  var
+    I: Integer;
+  begin
+    Result := True;
+    I := 1;
+    while I < Length(ACode) do
+      if ACode[I] in FBillsCodeSet then
+        Inc(I)
+      else
+      begin
+        Result := False;
+        Break;
+      end;
+  end;
+
+var
+  iPos: Integer;
+  sB_Code: string;
+  fPrice: Double;
+begin
+  UpdateProgressHint('写入读取的Excel数据');
+  UpdateProgressPosition(0);
+  while (FCurRow <= Excel.XlsFile.MaxRow) do
+  begin
+    sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
+    if (sB_Code <> '') and CheckIsBillsCode(sB_Code) then
+    begin
+      fPrice := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
+      UpdateBillsPrice(sB_Code, fPrice);
+    end;
+    Inc(FCurRow);
+    iPos := FCurRow * 100 div Excel.XlsFile.MaxRow;
+    UpdateProgressPosition(iPos);
+  end;
+  UpdateProgressPosition(100);
+end;
+
+procedure TBillsPriceExcelImport.LoadColumnsFromHead;
+var
+  iCol: Integer;
+  sColName: string;
+begin
+  FB_CodeCol := -1;
+  FNameCol := -1;
+  FPriceCol := -1;
+  while ((FB_CodeCol = -1) or (FPriceCol = -1)) and (FCurRow <= Excel.XlsFile.MaxRow) do
+  begin
+    for iCol := 1 to Excel.XlsFile.MaxCol do
+    begin
+      sColName := GetCellTrimStr(Excel.XlsFile, FCurRow, iCol);
+      if SameText(sColName, '清单编号') or SameText(sColName, '子目号') then
+        FB_CodeCol := iCol
+      else if SameText(sColName, '名称') then
+        FNameCol := iCol
+      else if Pos('单价', sColName) = 1 then
+        FPriceCol := iCol;
+    end;
+    Inc(FCurRow);
+  end;
+end;
+
+procedure TBillsPriceExcelImport.UpdateBillsPrice(const AB_Code: string;
+  APrice: Double);
+var
+  iIndex: Integer;
+  Rec: TBillsRecord;
+begin
+  with FProjectData.BillsData do
+  begin
+    for iIndex := 0 to sddBills.RecordCount - 1 do
+    begin
+      Rec := TBillsRecord(sddBills.Records[iIndex]);
+      if SameText(AB_Code, Rec.B_Code.AsString) then
+        Rec.Price.AsFloat := PriceRoundTo(APrice);
+    end;
+  end;
+end;
+
 end.

+ 2 - 407
Units/ExcelImport.pas

@@ -104,72 +104,6 @@ type
     property WithoutGclBills: Boolean read FWithoutGclBills write FWithoutGclBills;
   end;
 
-  TGclBillsExcelImport = class(TExcelImport)
-  private
-    FParentID: Integer;
-    FSelectSheets: TList;
-    FCacheTree: TGclCacheTree;
-    FCurRow: Integer;
-
-    FB_CodeCol: Integer;
-    FNameCol: Integer;
-    FUnitsCol: Integer;
-    FPriceCol: Integer;
-    FQuantityCol: Integer;
-
-    procedure BeginImport; override;
-    procedure EndImport; override;
-
-    procedure LoadNode(ASheet: TSpreadSheet);
-    procedure ImportSheet(ASheet: TSpreadSheet);
-
-    procedure WriteNode(ADataSet: TsdDataSet; ANode: TGclCacheNode);
-    procedure WriteNodes(ADataSet: TsdDataSet);
-
-    procedure Import; override;
-  public
-    property ParentID: Integer read FParentID write FParentID;
-  end;
-
-  // 清单单价
-  TBillsPriceExcelImport = class(TExcelImport)
-  private
-    FCurRow: Integer;
-
-    FB_CodeCol: Integer;
-    FNameCol: Integer;
-    FPriceCol: Integer;
-
-    procedure BeginImport; override;
-    procedure EndImport; override;
-
-    procedure LoadColumnsFromHead(ASheet: TSpreadSheet);
-    procedure UpdateBillsPrice(const AB_Code: string; APrice: Double);
-    procedure ImportBillsPriceData(ASheet: TSpreadSheet);
-    procedure Import; override;
-  end;
-
-  // 合同清单
-  TDealBillsExcelImport = class(TExcelImport)
-  private
-    FCurRow: Integer;
-    FBillsID: Integer;
-
-    FB_CodeCol: Integer;
-    FNameCol: Integer;
-    FUnitsCol: Integer;
-    FPriceCol: Integer;
-    FQuantityCol: Integer;
-    FTotalPriceCol: Integer;
-
-    procedure BeginImport; override;
-    procedure EndImport; override;
-
-    procedure LoadColumnsFromHead(ASheet: TSpreadSheet);
-    procedure LoadDealBillsData(ASheet: TSpreadSheet);
-    procedure Import; override;
-  end;
-
 implementation
 
 uses Variants, CacheTree, SysUtils, UtilMethods, sdDataSet, BillsDm,
@@ -538,7 +472,7 @@ begin
   Node.Name := sName;
   Node.Units := GetCellTrimText(ASheet, FUnitsCol, FCurRow);
   Node.Price := StrToFloatDef(VarToStrDef(GetCellValue(ASheet, FPriceCol, FCurRow), ''), 0);
-  Node.Quantity := StrToFloatDef(VarToStrDef(GetCellValue(ASheet, FQuantityCol, FCurRow), ''), 0);
+  Node.OrgQuantity := StrToFloatDef(VarToStrDef(GetCellValue(ASheet, FQuantityCol, FCurRow), ''), 0);
   Node.DgnQuantity1 := StrToFloatDef(VarToStrDef(GetCellValue(ASheet, FDgnQuantity1Col, FCurRow), ''), 0);
   Node.DgnQuantity2 := StrToFloatDef(VarToStrDef(GetCellValue(ASheet, FDgnQuantity2Col, FCurRow), ''), 0);
   Node.DrawingCode := GetCellTrimText(ASheet, FDrawingCol, FCurRow);
@@ -580,7 +514,7 @@ begin
   Rec.Name.AsString := ANode.Name;
   Rec.Units.AsString := ANode.Units;
   Rec.Price.AsFloat := PriceRoundTo(ANode.Price);
-  Rec.OrgQuantity.AsFloat := QuantityRoundTo(ANode.Quantity);
+  Rec.OrgQuantity.AsFloat := QuantityRoundTo(ANode.OrgQuantity);
   Rec.DgnQuantity1.AsFloat := QuantityRoundTo(ANode.DgnQuantity1);
   Rec.DgnQuantity2.AsFloat := QuantityRoundTo(ANode.DgnQuantity2);
   Rec.DrawingCode.AsString := ANode.DrawingCode;
@@ -662,343 +596,4 @@ begin
   end;
 end;
 
-{ TBillsPriceExcelImport }
-
-procedure TBillsPriceExcelImport.BeginImport;
-begin
-  ShowProgressHint('导入Excel清单单价', 100);
-  FProjectData.BillsData.sddBills.BeginUpdate;
-end;
-
-procedure TBillsPriceExcelImport.EndImport;
-begin
-  FProjectData.BillsData.sddBills.EndUpdate;
-  UpdateProgressHint('正在计算导入后的数据');
-  FProjectData.BillsCompileData.CalculateAll;
-  CloseProgressHint;
-end;
-
-procedure TBillsPriceExcelImport.Import;
-begin
-  LoadColumnsFromHead(FMSExcel.Sheets.Spreadsheet(0));
-  ImportBillsPriceData(FMSExcel.Sheets.Spreadsheet(0));
-end;
-
-procedure TBillsPriceExcelImport.ImportBillsPriceData(ASheet: TSpreadSheet);
-
-  function CheckIsBillsCode(ACode: string): Boolean;
-  const
-    FBillsCodeSet: set of char = ['0'..'9', '-', 'a'..'z', 'A'..'Z'];
-  var
-    I: Integer;
-  begin
-    Result := True;
-    I := 1;
-    while I < Length(ACode) do
-      if ACode[I] in FBillsCodeSet then
-        Inc(I)
-      else
-      begin
-        Result := False;
-        Break;
-      end;
-  end;
-
-var
-  iPos: Integer;
-  sB_Code: string;
-  fPrice: Double;
-begin
-  UpdateProgressHint('写入读取的Excel数据');
-  UpdateProgressPosition(0);
-  while (FCurRow < ASheet.Cells.UsedRowCount) do
-  begin
-    sB_Code := GetCellTrimText(ASheet, FB_CodeCol, FCurRow);
-    if (sB_Code <> '') and CheckIsBillsCode(sB_Code) then
-    begin
-      fPrice := StrToFloatDef(VarToStrDef(ASheet.Cells.GetValue(FPriceCol, FCurRow), ''), 0);
-      UpdateBillsPrice(sB_Code, fPrice);
-    end;
-    Inc(FCurRow);
-    iPos := FCurRow * 100 div ASheet.Cells.UsedRowCount;
-    UpdateProgressPosition(iPos);
-  end;
-  UpdateProgressPosition(100);
-end;
-
-procedure TBillsPriceExcelImport.LoadColumnsFromHead(ASheet: TSpreadSheet);
-var
-  iCol: Integer;
-  sColName: string;
-begin
-  FB_CodeCol := -1;
-  FNameCol := -1;
-  FPriceCol := -1;
-  while ((FB_CodeCol = -1) or (FPriceCol = -1)) and (FCurRow < ASheet.Cells.UsedRowCount) do
-  begin
-    for iCol := 0 to ASheet.Cells.UsedColCount do
-    begin
-      sColName := GetCellTrimText(ASheet, iCol, FCurRow);
-      if SameText(sColName, '清单编号') or SameText(sColName, '子目号') then
-        FB_CodeCol := iCol
-      else if SameText(sColName, '名称') then
-        FNameCol := iCol
-      else if Pos('单价', sColName) = 1 then
-        FPriceCol := iCol;
-    end;
-    Inc(FCurRow);
-  end;
-end;
-
-procedure TBillsPriceExcelImport.UpdateBillsPrice(const AB_Code: string;
-  APrice: Double);
-var
-  iIndex: Integer;
-  Rec: TBillsRecord;
-begin
-  with FProjectData.BillsData do
-  begin
-    for iIndex := 0 to sddBills.RecordCount - 1 do
-    begin
-      Rec := TBillsRecord(sddBills.Records[iIndex]);
-      if SameText(AB_Code, Rec.B_Code.AsString) then
-        Rec.Price.AsFloat := PriceRoundTo(APrice);
-    end;
-  end;
-end;
-
-{ TDealBillsExcelImport }
-
-procedure TDealBillsExcelImport.BeginImport;
-begin
-  FProjectData.DealBillsData.sddDealBills.BeginUpdate;
-end;
-
-procedure TDealBillsExcelImport.EndImport;
-begin
-  FProjectData.DealBillsData.sddDealBills.EndUpdate;
-end;
-
-procedure TDealBillsExcelImport.Import;
-begin
-  LoadColumnsFromHead(FMSExcel.Sheets.Spreadsheet(0));
-  FBillsID := 1;
-  FProjectData.DealBillsData.Clear;
-  FProjectData.DealBillsData.DisableEvent;
-  LoadDealBillsData(FMSExcel.Sheets.Spreadsheet(0));
-  FProjectData.DealBillsData.EnableEvent;
-end;
-
-procedure TDealBillsExcelImport.LoadColumnsFromHead(ASheet: TSpreadSheet);
-var
-  iCol: Integer;
-  sColName: string;
-begin
-  FB_CodeCol := -1;
-  FNameCol := 1;
-  FUnitsCol := 2;
-  FPriceCol := 3;
-  FQuantityCol := 4;
-  FTotalPriceCol := 5;
-  while ((FB_CodeCol = -1) or (FPriceCol = -1)) and (FCurRow < ASheet.Cells.UsedRowCount) do
-  begin
-    for iCol := 0 to ASheet.Cells.UsedColCount do
-    begin
-      sColName := GetCellTrimText(ASheet, iCol, FCurRow);
-      if SameText(sColName, '清单编号') or SameText(sColName, '子目号') then
-        FB_CodeCol := iCol
-      else if SameText(sColName, '名称') then
-        FNameCol := iCol
-      else if SameText(sColName, '单位') then
-        FUnitsCol := iCol
-      else if Pos('单价', sColName) = 1 then
-        FPriceCol := iCol
-      else if SameText(sColName, '数量') then
-        FQuantityCol := iCol
-      else if SameText(sColName, '金额') then
-        FTotalPriceCol := iCol;
-    end;
-    Inc(FCurRow);
-  end;
-end;
-
-procedure TDealBillsExcelImport.LoadDealBillsData(ASheet: TSpreadSheet);
-
-  function CheckIsBillsCode(ACode: string): Boolean;
-  const
-    FBillsCodeSet: set of char = ['0'..'9', '-', 'a'..'z', 'A'..'Z'];
-  var
-    I: Integer;
-  begin
-    Result := True;
-    I := 1;
-    while I < Length(ACode) do
-      if ACode[I] in FBillsCodeSet then
-        Inc(I)
-      else
-      begin
-        Result := False;
-        Break;
-      end;
-  end;
-
-var
-  sB_Code: string;
-  Rec: TsdDataRecord;
-begin
-  while (FCurRow < ASheet.Cells.UsedRowCount) do
-  begin
-    sB_Code := GetCellTrimText(ASheet, FB_CodeCol, FCurRow);
-    if (sB_Code <> '') and CheckIsBillsCode(sB_Code) then
-    begin
-      Rec := FProjectData.DealBillsData.sddDealBills.Add;
-      Rec.ValueByName('ID').AsInteger := FBillsID;
-      Rec.ValueByName('B_Code').AsString := sB_Code; 
-      Rec.ValueByName('IndexCode').AsString := B_CodeToIndexCode(sB_Code);
-      Rec.ValueByName('Name').AsString := GetCellTrimText(ASheet, FNameCol, FCurRow);
-      Rec.ValueByName('Units').AsString := GetCellTrimText(ASheet, FUnitsCol, FCurRow);
-      Rec.ValueByName('Price').AsFloat := PriceRoundTo(
-          StrToFloatDef(GetCellTrimText(ASheet, FPriceCol, FCurRow), 0));
-      Rec.ValueByName('Quantity').AsFloat := QuantityRoundTo(
-          StrToFloatDef(GetCellTrimText(ASheet, FQuantityCol, FCurRow), 0));
-      Rec.ValueByName('TotalPrice').AsFloat := TotalPriceRoundTo(
-          StrToFloatDef(GetCellTrimText(ASheet, FTotalPriceCol, FCurRow), 0));
-      Inc(FBillsID);
-    end;
-    Inc(FCurRow);
-  end;
-end;
-
-{ TGclBillsExcelImport }
-
-procedure TGclBillsExcelImport.BeginImport;
-begin
-  Screen.Cursor := crHourGlass;
-  ShowProgressHint('导入Excel数据', 100);
-
-  FCacheTree := TGclCacheTree.Create;
-  FCacheTree.NewNodeID := FProjectData.BillsData.GetMaxBillsID + 1;
-
-  FProjectData.DisConnectTree;
-  FProjectData.BillsData.DisableEvents;
-
-  FSelectSheets := TList.Create;
-
-  FB_CodeCol := 0;
-  FNameCol := 1;
-  FUnitsCol := 2;
-  FQuantityCol := 3;
-  FPriceCol := 4;
-end;
-
-procedure TGclBillsExcelImport.EndImport;
-var
-  ParentRec: TsdDataRecord;
-begin
-  FSelectSheets.Free;
-
-  FCacheTree.Free;
-
-  FProjectData.BillsData.EnableEvents;
-  FProjectData.ReConnectTree;
-
-  ParentRec := FProjectData.BillsData.sddBills.FindKey('idxID', ParentID);
-  FProjectData.BillsCompileData.sdvBillsCompile.LocateInControl(ParentRec);
-
-  FProjectData.BillsCompileData.CalculateAll;
-
-  CloseProgressHint;
-  Screen.Cursor := crDefault;
-end;
-
-procedure TGclBillsExcelImport.Import;
-var
-  i: Integer;
-begin
-  {if SelectSheets(FMSExcel, FSelectSheets) then
-  begin
-    for i := 0 to FSelectSheets.Count - 1 do
-    begin
-      UpdateProgressHint(Format('导入Excel数据--工作表[%s]', [FMSExcel.SheetNames.Strings[i]]));
-      UpdateProgressPosition(0);
-      ImportSheet(FSelectSheets.Items[i]);
-    end;
-  end;}
-  ImportSheet(FMSExcel.Sheets.Spreadsheet(0));
-  WriteNodes(FProjectData.BillsData.sddBills);
-end;
-
-procedure TGclBillsExcelImport.ImportSheet(ASheet: TSpreadSheet);
-var
-  iPos: Integer;
-begin
-  FCurRow := 1;
-  while (FCurRow < ASheet.Cells.UsedRowCount) do
-  begin
-    LoadNode(ASheet);
-    Inc(FCurRow);
-    iPos := FCurRow * 100 div ASheet.Cells.UsedRowCount;
-    UpdateProgressPosition(iPos);
-  end;
-end;
-
-procedure TGclBillsExcelImport.LoadNode(ASheet: TSpreadSheet);
-var
-  sB_Code, sName: string;
-  Node: TGclCacheNode;
-begin
-  with ASheet.Cells do
-  begin
-    sB_Code := Trim(VarToStrDef(GetValue(FB_CodeCol, FCurRow), ''));
-    sName := Trim(VarToStrDef(GetValue(FNameCol, FCurRow), ''));
-
-    Node := FCacheTree.AddNodeByData(sB_Code, sName);
-
-    Node.B_Code := sB_Code;
-    Node.Name := sName;
-    Node.Units := Trim(VarToStrDef(GetValue(FUnitsCol, FCurRow), ''));
-    Node.Price := StrToFloatDef(VarToStrDef(GetValue(FPriceCol, FCurRow), ''), 0);
-    Node.Quantity := StrToFloatDef(VarToStrDef(GetValue(FQuantityCol, FCurRow), ''), 0);
-  end;
-end;
-
-procedure TGclBillsExcelImport.WriteNodes(ADataSet: TsdDataSet);
-var
-  i, iPos: Integer;
-begin
-  UpdateProgressHint('写入读取的Excel数据');
-  UpdateProgressPosition(0);
-  for i := 0 to FCacheTree.CacheNodes.Count - 1 do
-  begin
-    WriteNode(ADataSet, TGclCacheNode(FCacheTree.CacheNodes[i]));
-    iPos := i*100 div FCacheTree.CacheNodes.Count;
-    UpdateProgressPosition(iPos);
-  end;
-  UpdateProgressPosition(100);
-end;
-
-procedure TGclBillsExcelImport.WriteNode(ADataSet: TsdDataSet;
-  ANode: TGclCacheNode);
-var
-  Rec: TBillsRecord;
-begin
-  if ANode.B_Code <> '' then
-    UpdateProgressHint('写入读取的Excel数据 ' + ANode.B_Code)
-  else
-    UpdateProgressHint('写入读取的Excel数据 ' + ANode.Name);
-
-  Rec := TBillsRecord(ADataSet.Add);
-  Rec.ID.AsInteger := ANode.ID;
-  if ANode.ParentID = -1 then
-    Rec.ParentID.AsInteger := ParentID
-  else
-    Rec.ParentID.AsInteger := ANode.ParentID;
-  Rec.NextSiblingID.AsInteger := ANode.NextSiblingID;
-  Rec.B_Code.AsString := ANode.B_Code;
-  Rec.Name.AsString := ANode.Name;
-  Rec.Units.AsString := ANode.Units;
-  Rec.Price.AsFloat := PriceRoundTo(ANode.Price);
-  Rec.OrgQuantity.AsFloat := QuantityRoundTo(ANode.Quantity);
-end;
-
 end.

+ 417 - 0
Units/ExcelImport_Bills.pas

@@ -0,0 +1,417 @@
+unit ExcelImport_Bills;
+
+// 导入0号台账/分项清单
+
+interface
+
+uses
+  DetailExcelImport, Classes, MCacheTree, sdDB, ProjectData;
+
+type
+  Tdei_CustomBills = class(TDetailExcelImport)
+  private
+    FCacheTree: TBillsCacheTree;
+    FCurRow: Integer;
+    FIsFirstPart: Boolean;
+
+    FWithLevelCode: Boolean;
+    FWithoutGclBills: Boolean;
+
+    FBaseTree: TBillsCacheTree;
+    FFixedIDNodes: TList;
+
+    FCodeCol: Integer;
+    FB_CodeCol: Integer;
+    FNameCol: Integer;
+    FUnitsCol: Integer;
+    FPriceCol: Integer;
+    FOrgQuantityCol: Integer;
+    FMisQuantityCol: Integer;
+    FOthQuantityCol: Integer;
+    FDgnQuantity1Col: Integer;
+    FDgnQuantity2Col: Integer;
+    FDrawingCol: Integer;
+    FMemoCol: Integer;
+    FLevelCol: Integer;
+  protected
+    procedure BeginImport; override;
+    procedure EndImport; override;
+
+    function GetFixedIDNode(AID: Integer): TBillsCacheNode;
+    function GetFixedID(ACode, AName: string): Integer;
+
+    procedure CheckFixedIDNodes;
+
+    procedure LoadColumnsFromHead;
+
+    procedure LoadBaseTree(ATree: TBillsCacheTree);
+
+    procedure LoadNode;
+    procedure LoadNodes;
+
+    procedure WriteNode(ADataSet: TsdDataSet; ANode: TBillsCacheNode);
+    procedure WriteNodes(ADataSet: TsdDataSet);
+
+    procedure Import; override;
+  public
+    procedure ImportFile(const AFileName: string; AWithLevelCode, AWithoutGclBills: Boolean); overload;
+  end;
+
+implementation
+
+uses
+  Forms, Controls, ProgressHintFrm, ConstUnit, UtilMethods, ExcelImport,
+  SysUtils, mDataRecord, XLSAdapter;
+
+{ Tdei_CustomBills }
+
+procedure Tdei_CustomBills.BeginImport;
+begin
+  Screen.Cursor := crHourGlass;
+  ShowProgressHint('导入Excel数据', 100, '读取Excel数据', 100);
+
+  FCurRow := 1;
+  FIsFirstPart := True;
+  FCacheTree := TBillsCacheTree.Create;
+  FCacheTree.NewNodeID := 101;
+  // 以层次编号为依据,分隔用'.',以项目节、清单编号为依据,分隔用'-'
+  if FWithLevelCode then
+    FCacheTree.SeparateChar := '.'
+  else
+    FCacheTree.SeparateChar := '-';
+  FCacheTree.AutoSort := True;
+
+  ProjectData.DisConnectTree;
+  ProjectData.BillsData.DisableEvents;
+
+  FBaseTree := TBillsCacheTree.Create;
+  FBaseTree.NewNodeID := 101;
+  FBaseTree.SeparateChar := '.';
+  FFixedIDNodes := TList.Create;
+end;
+
+procedure Tdei_CustomBills.CheckFixedIDNodes;
+
+  function GetHintStr(ANode: TBillsCacheNode): string;
+  begin
+    Result := '';
+    if ANode.Code <> '' then
+      Result := Result + '编号:' + ANode.Code + ';';
+    if ANode.Name <> '' then
+      Result := Result + '名称:' + ANode.Name + ';';
+  end;
+
+  function GetInvalidModel(ANoPM: Boolean; ACount: Integer): string;
+  begin
+    if ANoPM then
+    begin
+      if ACount > 1 then
+        Result := '价差功能,部分报表'
+      else
+        Result := '价差功能'
+    end
+    else
+      Result := '部分报表';
+    Result := Result + '将不可使用' + #13#10 + '如有疑问,请联系纵横客服,企业QQ:800003850 电话:(0756)3850888';
+  end;
+
+var
+  sgs: TStrings;
+  iBase: Integer;
+  vBase, vImport: TBillsCacheNode;
+  sHint: string;
+  bNoPM: Boolean;
+begin
+  bNoPM := False;
+  sgs := TStringList.Create;
+  try
+    sgs.Add('缺少如下固定清单节点:');
+    for iBase := 0 to FBaseTree.FixedIDNodes.Count - 1 do
+    begin
+      vBase := TBillsCacheNode(FBaseTree.FixedIDNodes.Items[iBase]);
+
+      vImport := FCacheTree.FindFixedIDNode(vBase.ID);
+      if not Assigned(vImport) then
+      begin
+        sgs.Add(GetHintStr(vBase));
+        if vBase.ID = iPriceMarginID then
+          bNoPM := True;
+      end;
+    end;
+  finally
+    if sgs.Count > 1 then
+    begin
+      sgs.Add(GetInvalidModel(bNoPM, sgs.Count - 1));
+      WarningMessage(sgs.Text);
+    end;
+    sgs.Free;
+  end;
+end;
+
+procedure Tdei_CustomBills.EndImport;
+begin
+  // For Test
+  // FCacheTree.SaveTreeToFile('E:\Tree.txt');
+
+  if FWithLevelCode then
+    CheckFixedIDNodes;
+
+  FFixedIDNodes.Free;
+  FBaseTree.Free;
+  ProjectData.BillsData.EnableEvents;
+  ProjectData.ReConnectTree;
+  FCacheTree.Free;
+  ProjectData.BillsCompileData.CalculateAll;
+  CloseProgressHint;
+  Screen.Cursor := crDefault;
+end;
+
+function Tdei_CustomBills.GetFixedID(ACode, AName: string): Integer;
+var
+  i: Integer;
+  Node: TBillsCacheNode;
+begin
+  Result := -1;
+  for i := 0 to FBaseTree.CacheNodes.Count - 1 do
+  begin
+    Node := TBillsCacheNode(FBaseTree.CacheNodes.Items[i]);
+    if (Node.Code = ACode) and (Node.Name = AName) then
+    begin
+      if Node.ID < 100 then
+        Result := Node.ID;
+      Break;
+    end;
+  end;
+end;
+
+function Tdei_CustomBills.GetFixedIDNode(AID: Integer): TBillsCacheNode;
+var
+  i: Integer;
+  Node: TBillsCacheNode;
+begin
+  Result := nil;
+  for i := 0 to FFixedIDNodes.Count - 1 do
+  begin
+    Node := TBillsCacheNode(FFixedIDNodes.Items[i]);
+    if (AID = Node.ID) then
+    begin
+      Result := Node;
+      Break;
+    end;
+  end;
+end;
+
+procedure Tdei_CustomBills.Import;
+begin
+  if FWithLevelCode then
+    LoadBaseTree(FBaseTree)
+  else
+    LoadBaseTree(FCacheTree);
+  LoadColumnsFromHead;
+  LoadNodes;
+  WriteNodes(ProjectData.BillsData.sddBills);
+end;
+
+procedure Tdei_CustomBills.ImportFile(const AFileName: string;
+  AWithLevelCode, AWithoutGclBills: Boolean);
+begin
+  FWithLevelCode := AWithLevelCode;
+  FWithoutGclBills := AWithoutGclBills;
+  ImportFile(AFileName);
+end;
+
+procedure Tdei_CustomBills.LoadBaseTree(ATree: TBillsCacheTree);
+var
+  BaseImportor: TBillsExcelImport;
+begin
+  BaseImportor := TBillsExcelImport.Create(nil);
+  try
+    BaseImportor.ImportToTree(ATree, GetTemplateBillsFileName);
+  finally
+    BaseImportor.Free;
+  end;
+end;
+
+procedure Tdei_CustomBills.LoadColumnsFromHead;
+var
+  iCol: Integer;
+  sColName: string;
+begin
+  FCodeCol := -1;
+  FB_CodeCol := -1;
+  FNameCol := -1;
+  FUnitsCol := -1;
+  FPriceCol := -1;
+  FOrgQuantityCol := -1;
+  FMisQuantityCol := -1;
+  FOthQuantityCol := -1;
+  FDgnQuantity1Col := -1;
+  FDgnQuantity2Col := -1;
+  FDrawingCol := -1;
+  FMemoCol := -1;
+  FLevelCol := -1;
+
+  for iCol := 1 to Excel.XlsFile.MaxCol do
+  begin
+    sColName := GetCellTrimStr(Excel.XlsFile, FCurRow, iCol);
+
+    if Pos('项目节', sColName) > 0 then
+      FCodeCol := iCol
+    else if (sColName = '清单编号') or (Pos('子目号', sColName) > 0) then
+      FB_CodeCol := iCol
+    else if sColName = '名称' then
+      FNameCol := iCol
+    else if sColName = '单位' then
+      FUnitsCol := iCol
+    else if sColName = '单价' then
+      FPriceCol := iCol
+    else if (sColName = '清单数量') or (sColName = '工程量') or (sColName = '数量') or (sColName = '施工图数量') then
+      FOrgQuantityCol := iCol
+    else if (sColName = '设计错漏数量') then
+      FMisQuantityCol := iCol
+    else if (sColName = '其他错漏数量') then
+      FOthQuantityCol := iCol
+    else if (sColName = '设计数量1') or (sColName = '数量1') then
+      FDgnQuantity1Col := iCol
+    else if (sColName = '设计数量2') or (sColName = '数量2') then
+      FDgnQuantity2Col := iCol
+    else if sColName = '图号' then
+      FDrawingCol := iCol
+    else if sColName = '备注' then
+      FMemoCol := iCol
+    else if sColName = '层次编号' then
+      FLevelCol := iCol;
+  end;
+  Inc(FCurRow);
+end;
+
+procedure Tdei_CustomBills.LoadNode;
+var
+  sLevelCode, sCode, sB_Code, sName: string;
+  Node: TBillsCacheNode;
+  vValue: Variant;
+  iFixedID: Integer;
+begin
+  sLevelCode := GetCellTrimStr(Excel.XlsFile, FCurRow, FLevelCol);
+  sCode := GetCellTrimStr(Excel.XlsFile, FCurRow, FCodeCol);
+  sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
+  sName := GetCellTrimStr(Excel.XlsFile, FCurRow, FNameCol);
+
+  // 含层次编号时,层次编号为空不导入
+  // 不含层次编号时,仅导入第一部分,且项目节编号、清单编号均未空时不导入
+  if FWithLevelCode then
+  begin
+    if sLevelCode = '' then Exit;
+  end
+  else
+  begin
+    if ((sCode = '') and (sB_Code = '')) or SameText(sCode, '2') or
+        (Pos('第二部分', sName) > 0) then
+    begin
+      FIsFirstPart := False;
+      Exit;
+    end;
+  end;
+
+  if (sCode = '') and FWithoutGclBills then Exit;
+
+  // 含层次编号时,以层次编号为依据新增节点;反之以项目节编号为依据新增节点
+  if not FWithLevelCode then
+  begin
+    if (sCode <> '') then
+      Node := FCacheTree.AddNodeByCode(sCode, -1)
+    else
+      Node := FCacheTree.AddLeafBillsNode(sB_Code);
+  end
+  else
+  begin
+    // 1. 从模板树中查询当前节点是否为固定ID,否则为-1
+    iFixedID := GetFixedID(sCode, sName);
+    // 2. 从导入树中查询是否添加过该固定ID,防止存在两个固定ID节点主键冲突
+    //    如果已添加过固定ID节点,则其他节点未非固定ID节点
+    Node := GetFixedIDNode(iFixedID);
+    if Assigned(Node) then
+      iFixedID := -1;
+    // 3. 添加当前节点
+    Node := FCacheTree.AddNodeByCode(sLevelCode, iFixedID);
+    // 4. 如果当前添加的节点为固定ID节点,则添加到List中便于2快速查找
+    if Node.ID < 100 then
+      FFixedIDNodes.Add(Node);
+  end;
+
+  Node.Code := sCode;
+  Node.B_Code := sB_Code;
+  Node.Name := sName;
+  Node.Units := GetCellTrimStr(Excel.XlsFile, FCurRow, FUnitsCol);
+  Node.Price := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
+  Node.OrgQuantity := GetCellFloat(Excel.XlsFile, FCurRow, FOrgQuantityCol);
+  Node.MisQuantity := GetCellFloat(Excel.XlsFile, FCurRow, FMisQuantityCol);
+  Node.OthQuantity := GetCellFloat(Excel.XlsFile, FCurRow, FOthQuantityCol);
+  Node.DgnQuantity1 := GetCellFloat(Excel.XlsFile, FCurRow, FDgnQuantity1Col);
+  Node.DgnQuantity2 := GetCellFloat(Excel.XlsFile, FCurRow, FDgnQuantity2Col);
+  Node.DrawingCode := GetCellTrimStr(Excel.XlsFile, FCurRow, FDrawingCol);
+  Node.MemoStr := GetCellTrimStr(Excel.XlsFile, FCurRow, FMemoCol);
+end;
+
+procedure Tdei_CustomBills.LoadNodes;
+var
+  iPos, iSubPos: Integer;
+begin
+  while (FCurRow <= Excel.XlsFile.MaxRow){ and FIsFirstPart }do
+  begin
+    LoadNode;
+    Inc(FCurRow);
+    iSubPos := FCurRow * 100 div Excel.XlsFile.MaxRow;
+    iPos := iSubPos div 2;
+    UpdateProgressPosition(iPos, iSubPos);
+  end;
+end;
+
+procedure Tdei_CustomBills.WriteNode(ADataSet: TsdDataSet;
+  ANode: TBillsCacheNode);
+var
+  Rec: TBillsRecord;
+begin
+  if ANode.Code <> '' then
+    UpdateProgressHint('写入读取的Excel数据 ' + ANode.Code)
+  else if ANode.B_Code <> '' then
+    UpdateProgressHint('写入读取的Excel数据 ' + ANode.B_Code)
+  else
+    UpdateProgressHint('写入读取的Excel数据 ' + ANode.Name);
+
+  Rec := TBillsRecord(ADataSet.Add);
+  Rec.ID.AsInteger := ANode.ID;
+  Rec.ParentID.AsInteger := ANode.ParentID;
+  Rec.NextSiblingID.AsInteger := ANode.NextSiblingID;
+  Rec.Code.AsString := ANode.Code;
+  Rec.B_Code.AsString := ANode.B_Code;
+  Rec.Name.AsString := ANode.Name;
+  Rec.Units.AsString := ANode.Units;
+  Rec.Price.AsFloat := PriceRoundTo(ANode.Price);
+  Rec.OrgQuantity.AsFloat := QuantityRoundTo(ANode.OrgQuantity);
+  Rec.MisQuantity.AsFloat := QuantityRoundTo(ANode.MisQuantity);
+  Rec.OthQuantity.AsFloat := QuantityRoundTo(ANode.OthQuantity);
+  Rec.DgnQuantity1.AsFloat := QuantityRoundTo(ANode.DgnQuantity1);
+  Rec.DgnQuantity2.AsFloat := QuantityRoundTo(ANode.DgnQuantity2);
+  Rec.DrawingCode.AsString := ANode.DrawingCode;
+  Rec.MemoStr.AsString := ANode.MemoStr;
+end;
+
+procedure Tdei_CustomBills.WriteNodes(ADataSet: TsdDataSet);
+var
+  i, iPos, iSubPos: Integer;
+begin
+  UpdateProgressHint('写入读取的Excel数据', True);
+  UpdateProgressPosition(50, 0);
+  ADataSet.DeleteAll;
+  for i := 0 to FCacheTree.CacheNodes.Count - 1 do
+  begin
+    WriteNode(ADataSet, TBillsCacheNode(FCacheTree.CacheNodes[i]));
+    iSubPos := i*100 div FCacheTree.CacheNodes.Count;
+    iPos := 50 + iSubPos div 2;
+    UpdateProgressPosition(iPos, iSubPos);
+  end;
+  UpdateProgressPosition(100, 100);
+end;
+
+end.

+ 174 - 0
Units/ExcelImport_GclBills.pas

@@ -0,0 +1,174 @@
+unit ExcelImport_GclBills;
+// 导入工程量清单至项目节
+
+interface
+
+uses
+  Classes, DetailExcelImport, MCacheTree, sdDB;
+
+type
+  TDEI_GclBills = class(TDetailExcelImport)
+  private
+    FParentID: Integer;
+    FSelectSheets: TList;
+    FCacheTree: TGclCacheTree;
+    FCurRow: Integer;
+
+    FB_CodeCol: Integer;
+    FNameCol: Integer;
+    FUnitsCol: Integer;
+    FPriceCol: Integer;
+    FQuantityCol: Integer;
+  protected
+    procedure BeginImport; override;
+    procedure EndImport; override;
+
+    procedure Import; override;
+
+    procedure ImportSheet;
+
+    procedure WriteNode(ADataSet: TsdDataSet; ANode: TGclCacheNode);
+    procedure WriteNodes(ADataSet: TsdDataSet);
+  public
+    procedure ImportToXmj(const AFileName: string; AParentID: Integer);
+  end;
+
+implementation
+
+uses
+  Forms, mDataRecord, Controls, ProgressHintFrm, UtilMethods;
+
+{ TDEI_GclBills }
+
+procedure TDEI_GclBills.BeginImport;
+begin
+  Screen.Cursor := crHourGlass;
+  ShowProgressHint('导入Excel数据', 100);
+
+  FCacheTree := TGclCacheTree.Create;
+  FCacheTree.NewNodeID := ProjectData.BillsData.GetMaxBillsID + 1;
+
+  ProjectData.DisConnectTree;
+  ProjectData.BillsData.DisableEvents;
+
+  FSelectSheets := TList.Create;
+
+  FB_CodeCol := 1;
+  FNameCol := 2;
+  FUnitsCol := 3;
+  FQuantityCol := 4;
+  FPriceCol :=  5;
+end;
+
+procedure TDEI_GclBills.EndImport;
+var
+  ParentRec: TsdDataRecord;
+begin
+  FSelectSheets.Free;
+
+  FCacheTree.Free;
+
+  ProjectData.BillsData.EnableEvents;
+  ProjectData.ReConnectTree;
+
+  ParentRec := ProjectData.BillsData.sddBills.FindKey('idxID', FParentID);
+  ProjectData.BillsCompileData.sdvBillsCompile.LocateInControl(ParentRec);
+
+  ProjectData.BillsCompileData.CalculateAll;
+
+  CloseProgressHint;
+  Screen.Cursor := crDefault;
+end;
+
+procedure TDEI_GclBills.Import;
+var
+  i: Integer;
+begin
+  {if SelectSheets(FMSExcel, FSelectSheets) then
+  begin
+    for i := 0 to FSelectSheets.Count - 1 do
+    begin
+      UpdateProgressHint(Format('导入Excel数据--工作表[%s]', [FMSExcel.SheetNames.Strings[i]]));
+      UpdateProgressPosition(0);
+      ImportSheet(FSelectSheets.Items[i]);
+    end;
+  end;}
+  ImportSheet;
+  WriteNodes(ProjectData.BillsData.sddBills);
+end;
+
+procedure TDEI_GclBills.ImportSheet;
+var
+  iPos: Integer; 
+  sB_Code, sName: string;
+  Node: TGclCacheNode;
+begin
+  FCurRow := 2;
+  while (FCurRow <= Excel.XlsFile.MaxRow) do
+  begin
+    sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
+    sName := GetCellTrimStr(Excel.XlsFile, FCurRow, FNameCol);
+
+    if (sB_Code <> '') or (sName <> '') then
+    begin
+      Node := FCacheTree.AddNodeByData(sB_Code, sName);
+      Node.B_Code := sB_Code;
+      Node.Name := sName;
+      Node.Units := GetCellTrimStr(Excel.XlsFile, FCurRow, FUnitsCol);
+      Node.Price := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
+      Node.Quantity := GetCellFloat(Excel.XlsFile, FCurRow, FQuantityCol);
+    end;
+
+    Inc(FCurRow);
+    iPos := FCurRow * 100 div Excel.XlsFile.MaxRow;
+    UpdateProgressPosition(iPos);
+  end;
+end;
+
+procedure TDEI_GclBills.ImportToXmj(const AFileName: string;
+  AParentID: Integer);
+begin
+  FParentID := AParentID;
+  ImportFile(AFileName);
+end;
+
+procedure TDEI_GclBills.WriteNode(ADataSet: TsdDataSet;
+  ANode: TGclCacheNode);
+var
+  Rec: TBillsRecord;
+begin
+  if ANode.B_Code <> '' then
+    UpdateProgressHint('写入读取的Excel数据 ' + ANode.B_Code)
+  else
+    UpdateProgressHint('写入读取的Excel数据 ' + ANode.Name);
+
+  Rec := TBillsRecord(ADataSet.Add);
+  Rec.ID.AsInteger := ANode.ID;
+  if ANode.ParentID = -1 then
+    Rec.ParentID.AsInteger := FParentID
+  else
+    Rec.ParentID.AsInteger := ANode.ParentID;
+  Rec.NextSiblingID.AsInteger := ANode.NextSiblingID;
+  Rec.B_Code.AsString := ANode.B_Code;
+  Rec.Name.AsString := ANode.Name;
+  Rec.Units.AsString := ANode.Units;
+  Rec.Price.AsFloat := PriceRoundTo(ANode.Price);
+  Rec.OrgQuantity.AsFloat := QuantityRoundTo(ANode.Quantity);
+end;
+
+procedure TDEI_GclBills.WriteNodes(ADataSet: TsdDataSet);
+var
+  i, iPos: Integer;
+begin
+  UpdateProgressHint('写入读取的Excel数据');
+  UpdateProgressPosition(0);
+  for i := 0 to FCacheTree.CacheNodes.Count - 1 do
+  begin
+    WriteNode(ADataSet, TGclCacheNode(FCacheTree.CacheNodes[i]));
+    iPos := i*100 div FCacheTree.CacheNodes.Count;
+    UpdateProgressPosition(iPos);
+  end;
+  UpdateProgressPosition(100);
+end;
+
+end.

+ 6 - 2
Units/MCacheTree.pas

@@ -16,7 +16,9 @@ type
     FName: string;
     FUnits: string;
     FCanDelete: Boolean;
-    FQuantity: Double;
+    FOrgQuantity: Double;
+    FMisQuantity: Double;
+    FOthQuantity: Double;
     FDgnQuantity1: Double;
     FDgnQuantity2: Double;
     FMemoStr: string;
@@ -30,7 +32,9 @@ type
     property Units: string read FUnits write FUnits;
     property CanDelete: Boolean read FCanDelete write FCanDelete;
     property Price: Double read FPrice write FPrice;
-    property Quantity: Double read FQuantity write FQuantity;
+    property OrgQuantity: Double read FOrgQuantity write FOrgQuantity;
+    property MisQuantity: Double read FMisQuantity write FMisQuantity;
+    property OthQuantity: Double read FOthQuantity write FOthQuantity;
     property DgnQuantity1: Double read FDgnQuantity1 write FDgnQuantity1;
     property DgnQuantity2: Double read FDgnQuantity2 write FDgnQuantity2;
     property DrawingCode: string read FDrawingCode write FDrawingCode;

+ 12 - 0
Units/ProjectData.pas

@@ -1658,9 +1658,21 @@ procedure TProjectData.ResetFloatDigitView;
     end;
   end;
 
+  procedure SetDealPaymentDigit;
+  begin
+    with FDealPaymentData.sdvDealPayment do
+    begin
+      Columns.FindColumn('CurTotalPrice').DisplayFormat := FProjProperties.TotalPriceFormat;
+      Columns.FindColumn('TotalPrice').DisplayFormat := FProjProperties.TotalPriceFormat;
+      Columns.FindColumn('StartedPrice').DisplayFormat := FProjProperties.TotalPriceFormat;
+      Columns.FindColumn('RangePrice').DisplayFormat := FProjProperties.TotalPriceFormat;
+    end;
+  end;
+
 begin
   SetBillsCompileDigit;
   SetBillsMeasureDigit;
+  SetDealPaymentDigit;
   SetBillsGatherDigit;
 end;