Browse Source

导入Excel,全部替换控件,以识别“×”

MaiXinRong 9 years ago
parent
commit
d420a400f1

+ 5 - 7
Forms/MainFrm.pas

@@ -9,7 +9,6 @@ uses
   AuthFrm,
   AuthFrm,
   // Model & Data & Data Control ...
   // Model & Data & Data Control ...
   ProjectData, SupportUnit, Globals, ZhAPI, ExcelImport, ConditionalDefines,
   ProjectData, SupportUnit, Globals, ZhAPI, ExcelImport, ConditionalDefines,
-  DealBillsExcelImport,
   // Controls & Delphi Default ... (Almost By Add Controls)
   // Controls & Delphi Default ... (Almost By Add Controls)
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, cxGraphics, JimPages, ComCtrls, dxStatusBar, cxControls, JimTabs,
   Dialogs, cxGraphics, JimPages, ComCtrls, dxStatusBar, cxControls, JimTabs,
@@ -234,7 +233,8 @@ implementation
 uses
 uses
   ProjectProperty, ConstUnit, PHPWebDm, Math, ShellAPI,
   ProjectProperty, ConstUnit, PHPWebDm, Math, ShellAPI,
   FindUserFrm, ImportExcelHintFrm, ConfigDoc, ExportExcel,
   FindUserFrm, ImportExcelHintFrm, ConfigDoc, ExportExcel,
-  ProjectCommands, BillsCompileDm, tpMainFrm;
+  ProjectCommands, BillsCompileDm, tpMainFrm,
+  DealBillsExcelImport, ExcelImport_Bills, DetailExcelImport;
 
 
 {$R *.dfm}
 {$R *.dfm}
 {$R MeasureIcons.RES}
 {$R MeasureIcons.RES}
@@ -538,18 +538,16 @@ end;
 procedure TMainForm.actnImportExcelExecute(Sender: TObject);
 procedure TMainForm.actnImportExcelExecute(Sender: TObject);
 var
 var
   sFileName: string;
   sFileName: string;
-  Importor: TBillsEdtExcelImport;
+  Importor: Tdei_CustomBills;
   bWithLevelCode, bWithoutGclBills: Boolean;
   bWithLevelCode, bWithoutGclBills: Boolean;
 begin
 begin
   if HintAndImportTypeSelect(bWithLevelCode, bWithoutGclBills) then
   if HintAndImportTypeSelect(bWithLevelCode, bWithoutGclBills) then
   begin
   begin
     if SelectFile(sFileName, '.xls') then
     if SelectFile(sFileName, '.xls') then
     begin
     begin
-      Importor := TBillsEdtExcelImport.Create(CurProjectFrame.ProjectData);
+      Importor := Tdei_CustomBills.Create(CurProjectFrame.ProjectData);
       try
       try
-        Importor.WithLevelCode := bWithLevelCode;
-        Importor.WithoutGclBills := bWithoutGclBills;
-        Importor.ImportFile(sFileName);
+        Importor.ImportFile(sFileName, bWithLevelCode, bWithoutGclBills);
       finally
       finally
         Importor.Free;
         Importor.Free;
       end;
       end;

+ 4 - 5
Frames/BillsCompileFme.pas

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

+ 1 - 0
Units/DealBillsExcelImport.pas

@@ -1,4 +1,5 @@
 unit DealBillsExcelImport;
 unit DealBillsExcelImport;
+// µ¼ÈëǩԼÇåµ¥
 
 
 interface
 interface
 
 

+ 125 - 1
Units/DetailExcelImport.pas

@@ -80,11 +80,29 @@ type
     property ParentID: Integer read FParentID write FParentID;
     property ParentID: Integer read FParentID write FParentID;
   end;
   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
 implementation
 
 
 uses
 uses
   UtilMethods, SysUtils, ZhAPI, SheetSelectFrm, UExcelAdapter, UFlxMessages,
   UtilMethods, SysUtils, ZhAPI, SheetSelectFrm, UExcelAdapter, UFlxMessages,
-  UFlxFormats, ProgressHintFrm;
+  UFlxFormats, ProgressHintFrm, mDataRecord;
 
 
 { TDetailExcelImport }
 { TDetailExcelImport }
 
 
@@ -644,4 +662,110 @@ begin
   Screen.Cursor := crDefault;
   Screen.Cursor := crDefault;
 end;
 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.
 end.

+ 0 - 405
Units/ExcelImport.pas

@@ -104,72 +104,6 @@ type
     property WithoutGclBills: Boolean read FWithoutGclBills write FWithoutGclBills;
     property WithoutGclBills: Boolean read FWithoutGclBills write FWithoutGclBills;
   end;
   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
 implementation
 
 
 uses Variants, CacheTree, SysUtils, UtilMethods, sdDataSet, BillsDm,
 uses Variants, CacheTree, SysUtils, UtilMethods, sdDataSet, BillsDm,
@@ -662,343 +596,4 @@ begin
   end;
   end;
 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.
 end.

+ 403 - 0
Units/ExcelImport_Bills.pas

@@ -0,0 +1,403 @@
+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;
+    FQuantityCol: 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;
+
+{ 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;
+  FQuantityCol := -1;
+  FDgnQuantity1Col := -1;
+  FDgnQuantity2Col := -1;
+  FDrawingCol := -1;
+  FMemoCol := -1;
+  for iCol := 1 to Excel.XlsFile.MaxRow do
+  begin
+    sColName := GetCellTrimStr(Excel.XlsFile, FCurRow, iCol);
+
+    if (sColName = '预算项目节') or (sColName = '项目节编号') then
+      FCodeCol := iCol
+    else if (sColName = '清单子目号') or (sColName = '清单编号') 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 = '数量') then
+      FQuantityCol := 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.Quantity := GetCellFloat(Excel.XlsFile, FCurRow, FQuantityCol);
+  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.Quantity);
+  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.