浏览代码

计量支付313基础版本

MaiXinRong 10 年之前
当前提交
54e18cd8e4
共有 100 个文件被更改,包括 25467 次插入0 次删除
  1. 16 0
      .gitignore
  2. 218 0
      DataModules/BGLDm.dfm
  3. 666 0
      DataModules/BGLDm.pas
  4. 71 0
      DataModules/BillsBookmarkDm.dfm
  5. 118 0
      DataModules/BillsBookmarkDm.pas
  6. 106 0
      DataModules/BillsCompileDm.dfm
  7. 1002 0
      DataModules/BillsCompileDm.pas
  8. 203 0
      DataModules/BillsDm.dfm
  9. 583 0
      DataModules/BillsDm.pas
  10. 471 0
      DataModules/BillsGatherDm.dfm
  11. 532 0
      DataModules/BillsGatherDm.pas
  12. 220 0
      DataModules/BillsMeasureDm.dfm
  13. 874 0
      DataModules/BillsMeasureDm.pas
  14. 65 0
      DataModules/DealBillsDm.dfm
  15. 126 0
      DataModules/DealBillsDm.pas
  16. 105 0
      DataModules/DealPaymentDm.dfm
  17. 640 0
      DataModules/DealPaymentDm.pas
  18. 67 0
      DataModules/MainDataListDm.dfm
  19. 75 0
      DataModules/MainDataListDm.pas
  20. 25 0
      DataModules/PHPWebDm.dfm
  21. 651 0
      DataModules/PHPWebDm.pas
  22. 39 0
      DataModules/PhaseCompareDm.dfm
  23. 237 0
      DataModules/PhaseCompareDm.pas
  24. 195 0
      DataModules/PhasePayDm.dfm
  25. 362 0
      DataModules/PhasePayDm.pas
  26. 194 0
      DataModules/ProjectManagerDm.dfm
  27. 587 0
      DataModules/ProjectManagerDm.pas
  28. 50 0
      DataModules/ReportMemoryDm/rmBGLExecutionDm.dfm
  29. 361 0
      DataModules/ReportMemoryDm/rmBGLExecutionDm.pas
  30. 1410 0
      DataModules/ReportMemoryDm/rmBillsGatherDm.dfm
  31. 1303 0
      DataModules/ReportMemoryDm/rmBillsGatherDm.pas
  32. 323 0
      DataModules/ReportMemoryDm/rmCacheData.pas
  33. 51 0
      DataModules/ReportMemoryDm/rmCustomized2Dm.dfm
  34. 468 0
      DataModules/ReportMemoryDm/rmCustomized2Dm.pas
  35. 140 0
      DataModules/ReportMemoryDm/rmDealInfosDm.dfm
  36. 269 0
      DataModules/ReportMemoryDm/rmDealInfosDm.pas
  37. 852 0
      DataModules/ReportMemoryDm/rmFxBillsAddDm.dfm
  38. 344 0
      DataModules/ReportMemoryDm/rmFxBillsAddDm.pas
  39. 247 0
      DataModules/ReportMemoryDm/rmFxBillsCompareDm.dfm
  40. 252 0
      DataModules/ReportMemoryDm/rmFxBillsCompareDm.pas
  41. 416 0
      DataModules/ReportMemoryDm/rmGclBillsAddDm.dfm
  42. 431 0
      DataModules/ReportMemoryDm/rmGclBillsAddDm.pas
  43. 247 0
      DataModules/ReportMemoryDm/rmGclBillsAuditCompareDm.dfm
  44. 293 0
      DataModules/ReportMemoryDm/rmGclBillsAuditCompareDm.pas
  45. 356 0
      DataModules/ReportMemoryDm/rmGclBillsBGDm.dfm
  46. 475 0
      DataModules/ReportMemoryDm/rmGclBillsBGDm.pas
  47. 136 0
      DataModules/ReportMemoryDm/rmGclBillsCompareDm.dfm
  48. 240 0
      DataModules/ReportMemoryDm/rmGclBillsCompareDm.pas
  49. 81 0
      DataModules/ReportMemoryDm/rmGclBillsPlaneDm.dfm
  50. 302 0
      DataModules/ReportMemoryDm/rmGclBillsPlaneDm.pas
  51. 251 0
      DataModules/ReportMemoryDm/rmGcl_XmjBillsDm.dfm
  52. 614 0
      DataModules/ReportMemoryDm/rmGcl_XmjBillsDm.pas
  53. 85 0
      DataModules/ReportMemoryDm/rmGridHeaderDm.dfm
  54. 48 0
      DataModules/ReportMemoryDm/rmGridHeaderDm.pas
  55. 163 0
      DataModules/ReportMemoryDm/rmMentalCustomized1Dm.dfm
  56. 884 0
      DataModules/ReportMemoryDm/rmMentalCustomized1Dm.pas
  57. 90 0
      DataModules/ReportMemoryDm/rmOtherReport1Dm.dfm
  58. 251 0
      DataModules/ReportMemoryDm/rmOtherReport1Dm.pas
  59. 34 0
      DataModules/ReportMemoryDm/rmTestFrm.dfm
  60. 45 0
      DataModules/ReportMemoryDm/rmTestFrm.pas
  61. 185 0
      DataModules/ReportMemoryDm/rmXmjBGLDetailDm.dfm
  62. 422 0
      DataModules/ReportMemoryDm/rmXmjBGLDetailDm.pas
  63. 106 0
      DataModules/SearchDm.dfm
  64. 243 0
      DataModules/SearchDm.pas
  65. 104 0
      DataModules/StaffDm.dfm
  66. 201 0
      DataModules/StaffDm.pas
  67. 47 0
      DataModules/StageBookmarkDm.dfm
  68. 21 0
      DataModules/StageBookmarkDm.pas
  69. 104 0
      DataModules/StageCompareDm.dfm
  70. 160 0
      DataModules/StageCompareDm.pas
  71. 151 0
      DataModules/StageDm.dfm
  72. 748 0
      DataModules/StageDm.pas
  73. 64 0
      DataModules/StandardBillsDm.dfm
  74. 80 0
      DataModules/StandardBillsDm.pas
  75. 80 0
      DataModules/TenderBackupDm.dfm
  76. 220 0
      DataModules/TenderBackupDm.pas
  77. 90 0
      DataModules/ZJJLDm.dfm
  78. 547 0
      DataModules/ZJJLDm.pas
  79. 41 0
      Dprs/Pro/Measure.cfg
  80. 165 0
      Dprs/Pro/Measure.dof
  81. 169 0
      Dprs/Pro/Measure.dpr
  82. 二进制
      Dprs/Pro/Measure.res
  83. 41 0
      Dprs/Pro/Measure_Cloud.cfg
  84. 162 0
      Dprs/Pro/Measure_Cloud.dof
  85. 194 0
      Dprs/Pro/Measure_Cloud.dpr
  86. 二进制
      Dprs/Pro/Measure_Cloud.res
  87. 41 0
      Dprs/Pro/Measure_GuangDong.cfg
  88. 157 0
      Dprs/Pro/Measure_GuangDong.dof
  89. 167 0
      Dprs/Pro/Measure_GuangDong.dpr
  90. 二进制
      Dprs/Pro/Measure_GuangDong.res
  91. 41 0
      Dprs/Pro/Measure_GuangDong_Cloud.cfg
  92. 165 0
      Dprs/Pro/Measure_GuangDong_Cloud.dof
  93. 196 0
      Dprs/Pro/Measure_GuangDong_Cloud.dpr
  94. 二进制
      Dprs/Pro/Measure_GuangDong_Cloud.res
  95. 40 0
      Dprs/Pro/Measure_GuangDong_TZ.cfg
  96. 146 0
      Dprs/Pro/Measure_GuangDong_TZ.dof
  97. 168 0
      Dprs/Pro/Measure_GuangDong_TZ.dpr
  98. 二进制
      Dprs/Pro/Measure_GuangDong_TZ.res
  99. 41 0
      Dprs/Pro/Measure_TZ.cfg
  100. 0 0
      Dprs/Pro/Measure_TZ.dof

+ 16 - 0
.gitignore

@@ -0,0 +1,16 @@
+*.ddp
+*.vcx
+*.scc
+*.~bpl
+*.~dfm
+*.dcu
+*.~pas
+*.~ddp
+*.~dpk
+*.~dpr
+*.log
+*.map
+/Components/SmartDataSet/Sample
+/Components/SmartDataSet/Source/bak
+/Components/SmartDataSet/SmartDataSet.zip
+/Components/SmartDataSet/Source/sdIDTree.no link.pas

+ 218 - 0
DataModules/BGLDm.dfm

@@ -0,0 +1,218 @@
+object BGLData: TBGLData
+  OldCreateOrder = False
+  Left = 456
+  Top = 291
+  Height = 220
+  Width = 397
+  object atBGL: TADOTable
+    TableName = 'BGL'
+    Left = 32
+    Top = 16
+  end
+  object dspBGL: TDataSetProvider
+    DataSet = atBGL
+    UpdateMode = upWhereKeyOnly
+    Left = 32
+    Top = 72
+  end
+  object cdsBGL: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    ProviderName = 'dspBGL'
+    Left = 32
+    Top = 128
+    object cdsBGLID: TIntegerField
+      FieldName = 'ID'
+    end
+    object cdsBGLCode: TWideStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsBGLName: TWideStringField
+      FieldName = 'Name'
+      Size = 100
+    end
+    object cdsBGLTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsBGLPos_Reason: TWideStringField
+      FieldName = 'Pos_Reason'
+      Size = 255
+    end
+    object cdsBGLDirection: TWideStringField
+      FieldName = 'Direction'
+      Size = 255
+    end
+    object cdsBGLDrawingCode: TWideStringField
+      FieldName = 'DrawingCode'
+      Size = 50
+    end
+    object cdsBGLLocked: TBooleanField
+      FieldName = 'Locked'
+    end
+    object cdsBGLApprovalCode: TWideStringField
+      FieldName = 'ApprovalCode'
+      Size = 50
+    end
+    object cdsBGLCreatePhaseID: TIntegerField
+      FieldName = 'CreatePhaseID'
+    end
+    object cdsBGLExecutionRate: TFloatField
+      FieldName = 'ExecutionRate'
+    end
+  end
+  object cdsBGLView: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    BeforePost = cdsBGLViewBeforePost
+    BeforeDelete = cdsBGLViewBeforeDelete
+    OnNewRecord = cdsBGLViewNewRecord
+    Left = 96
+    Top = 128
+    object cdsBGLViewID: TIntegerField
+      FieldName = 'ID'
+    end
+    object cdsBGLViewCode: TWideStringField
+      FieldName = 'Code'
+      OnChange = cdsBGLViewCodeChange
+      Size = 50
+    end
+    object cdsBGLViewName: TWideStringField
+      FieldName = 'Name'
+      Size = 100
+    end
+    object cdsBGLViewTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsBGLViewPos_Reason: TWideStringField
+      FieldName = 'Pos_Reason'
+      Size = 255
+    end
+    object cdsBGLViewDirection: TWideStringField
+      FieldName = 'Direction'
+      Size = 255
+    end
+    object cdsBGLViewLocked: TBooleanField
+      FieldName = 'Locked'
+    end
+    object cdsBGLViewDrawingCode: TWideStringField
+      FieldName = 'DrawingCode'
+      Size = 50
+    end
+    object cdsBGLViewApprovalCode: TWideStringField
+      FieldName = 'ApprovalCode'
+      Size = 50
+    end
+    object cdsBGLViewCreatePhaseID: TIntegerField
+      FieldName = 'CreatePhaseID'
+    end
+    object cdsBGLViewExecutionRate: TFloatField
+      FieldName = 'ExecutionRate'
+    end
+  end
+  object dsBGL: TDataSource
+    DataSet = cdsBGLView
+    Left = 160
+    Top = 128
+  end
+  object atBGBills: TADOTable
+    TableName = 'BGBills'
+    Left = 240
+    Top = 16
+  end
+  object dspBGBills: TDataSetProvider
+    DataSet = atBGBills
+    UpdateMode = upWhereKeyOnly
+    Left = 240
+    Top = 72
+  end
+  object cdsBGBills: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    ProviderName = 'dspBGBills'
+    Left = 240
+    Top = 128
+    object cdsBGBillsID: TIntegerField
+      FieldName = 'ID'
+    end
+    object cdsBGBillsBGID: TIntegerField
+      FieldName = 'BGID'
+    end
+    object cdsBGBillsB_Code: TWideStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBGBillsName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsBGBillsUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBGBillsPrice: TFloatField
+      FieldName = 'Price'
+    end
+    object cdsBGBillsQuantity: TFloatField
+      FieldName = 'Quantity'
+    end
+    object cdsBGBillsTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsBGBillsUsedQuantity: TFloatField
+      FieldName = 'UsedQuantity'
+    end
+    object cdsBGBillsLocked: TBooleanField
+      FieldName = 'Locked'
+    end
+  end
+  object cdsBGBillsView: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    AfterInsert = cdsBGBillsViewAfterInsert
+    BeforePost = cdsBGBillsViewBeforePost
+    AfterPost = cdsBGBillsViewAfterPost
+    BeforeDelete = cdsBGBillsViewBeforeDelete
+    AfterDelete = cdsBGBillsViewAfterDelete
+    Left = 312
+    Top = 128
+    object cdsBGBillsViewID: TIntegerField
+      FieldName = 'ID'
+    end
+    object cdsBGBillsViewBGID: TIntegerField
+      FieldName = 'BGID'
+    end
+    object cdsBGBillsViewB_Code: TWideStringField
+      FieldName = 'B_Code'
+      OnChange = cdsBGBillsViewQuantityChange
+      Size = 50
+    end
+    object cdsBGBillsViewName: TWideStringField
+      FieldName = 'Name'
+      OnChange = cdsBGBillsViewQuantityChange
+      Size = 200
+    end
+    object cdsBGBillsViewUnits: TWideStringField
+      FieldName = 'Units'
+      OnChange = cdsBGBillsViewQuantityChange
+    end
+    object cdsBGBillsViewPrice: TFloatField
+      FieldName = 'Price'
+      OnChange = cdsBGBillsViewQuantityChange
+      OnSetText = cdsBGBillsViewPriceSetText
+    end
+    object cdsBGBillsViewQuantity: TFloatField
+      FieldName = 'Quantity'
+      OnChange = cdsBGBillsViewQuantityChange
+      OnSetText = cdsBGBillsViewQuantitySetText
+    end
+    object cdsBGBillsViewTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsBGBillsViewUsedQuantity: TFloatField
+      FieldName = 'UsedQuantity'
+    end
+    object cdsBGBillsViewLocked: TBooleanField
+      FieldName = 'Locked'
+    end
+  end
+end

+ 666 - 0
DataModules/BGLDm.pas

@@ -0,0 +1,666 @@
+unit BGLDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, Provider, ADODB, sdIDTree,
+  sdDB;
+
+type
+  TBGLSelectInfo = class(TObject)
+  private
+    FB_Code: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+
+    FIsOrg: Boolean;
+    FTotalNum: Double;
+    FNums: TStrings;
+    FCodes: TStrings;
+    procedure SetMergedCode(const Value: string);
+    procedure SetMergedNum(const Value: string);
+    function GetCount: Integer;
+    function GetMergedCode: string;
+    function GetMergedNum: string;
+  public
+    constructor Create(ARec: TsdDataRecord; ATotalNum: Double; AIsOrg: Boolean);
+    destructor Destroy; override;
+    procedure Clear;
+
+    property MergedCode: string read GetMergedCode write SetMergedCode;
+    property MergedNum: string read GetMergedNum write SetMergedNum;
+    property Codes: TStrings read FCodes;
+    property Nums: TStrings read FNums;
+    property Count: Integer read GetCount;
+    property TotalNum: Double read FTotalNum write FTotalNum;
+    property IsOrg: Boolean read FIsOrg;
+
+    property B_Code: string read FB_Code;
+    property Name: string read FName;
+    property Units: string read FUnits;
+    property Price: Double read FPrice;
+  end;
+
+  TBGLData = class(TDataModule)
+    atBGL: TADOTable;
+    dspBGL: TDataSetProvider;
+    cdsBGL: TClientDataSet;
+    cdsBGLID: TIntegerField;
+    cdsBGLTotalPrice: TFloatField;
+    cdsBGLName: TWideStringField;
+    cdsBGLCode: TWideStringField;
+    cdsBGLPos_Reason: TWideStringField;
+    cdsBGLDirection: TWideStringField;
+    cdsBGLDrawingCode: TWideStringField;
+    cdsBGLLocked: TBooleanField;
+    cdsBGLApprovalCode: TWideStringField;
+    cdsBGLCreatePhaseID: TIntegerField;
+    cdsBGLView: TClientDataSet;
+    cdsBGLViewID: TIntegerField;
+    cdsBGLViewName: TWideStringField;
+    cdsBGLViewTotalPrice: TFloatField;
+    cdsBGLViewCode: TWideStringField;
+    cdsBGLViewPos_Reason: TWideStringField;
+    cdsBGLViewDirection: TWideStringField;
+    cdsBGLViewDrawingCode: TWideStringField;
+    cdsBGLViewLocked: TBooleanField;
+    cdsBGLViewApprovalCode: TWideStringField;
+    cdsBGLViewCreatePhaseID: TIntegerField;
+
+    dsBGL: TDataSource;
+
+    atBGBills: TADOTable;
+    dspBGBills: TDataSetProvider;
+    cdsBGBills: TClientDataSet;
+    cdsBGBillsID: TIntegerField;
+    cdsBGBillsBGID: TIntegerField;
+    cdsBGBillsB_Code: TWideStringField;
+    cdsBGBillsName: TWideStringField;
+    cdsBGBillsUnits: TWideStringField;
+    cdsBGBillsPrice: TFloatField;
+    cdsBGBillsQuantity: TFloatField;
+    cdsBGBillsTotalPrice: TFloatField;
+    cdsBGBillsUsedQuantity: TFloatField;
+    cdsBGBillsLocked: TBooleanField;
+    cdsBGBillsView: TClientDataSet;
+    cdsBGBillsViewID: TIntegerField;
+    cdsBGBillsViewBGID: TIntegerField;
+    cdsBGBillsViewB_Code: TWideStringField;
+    cdsBGBillsViewName: TWideStringField;
+    cdsBGBillsViewUnits: TWideStringField;
+    cdsBGBillsViewPrice: TFloatField;
+    cdsBGBillsViewQuantity: TFloatField;
+    cdsBGBillsViewTotalPrice: TFloatField;
+    cdsBGBillsViewUsedQuantity: TFloatField;
+    cdsBGBillsViewLocked: TBooleanField;
+    cdsBGLExecutionRate: TFloatField;
+    cdsBGLViewExecutionRate: TFloatField;
+    procedure cdsBGBillsViewAfterInsert(DataSet: TDataSet);
+    procedure cdsBGBillsViewAfterPost(DataSet: TDataSet);
+    procedure cdsBGBillsViewQuantityChange(Sender: TField);
+    procedure cdsBGBillsViewBeforePost(DataSet: TDataSet);
+    procedure cdsBGLViewBeforePost(DataSet: TDataSet);
+    procedure cdsBGLViewBeforeDelete(DataSet: TDataSet);
+    procedure cdsBGBillsViewBeforeDelete(DataSet: TDataSet);
+    procedure cdsBGBillsViewAfterDelete(DataSet: TDataSet);
+    procedure cdsBGLViewNewRecord(DataSet: TDataSet);
+    procedure cdsBGBillsViewQuantitySetText(Sender: TField;
+      const Text: String);
+    procedure cdsBGBillsViewPriceSetText(Sender: TField;
+      const Text: String);
+    procedure cdsBGLViewCodeChange(Sender: TField);
+  private
+    FProjectData: TObject;
+
+    procedure GatherBGLTotalPrice(ABGLID: Integer);
+    procedure UpdateBGLTotalPrice(ABGLID: Integer; ADiffer: Double);
+
+    procedure UpdateBGLExecutionRate(ABGLID: Integer);
+    procedure ApplyBGL(ABGLInfo: TBGLSelectInfo); overload;
+
+    procedure DeleteBGBills(ABGID: Integer);
+
+    function CheckSameB_Code(ABGID: Integer; const AB_Code: string): Boolean;
+    function CheckBGLUsed(ABGID: Integer): Boolean;
+
+    function LocateBGL(const ACode: string): Boolean;
+
+    procedure LockAllBGL;
+    procedure LockAllBGBills;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Close;
+    procedure Save;
+
+    function AllBGLTotalPrice: Double;
+
+    procedure AddBGL(const sCode: string);
+    procedure ApplyBGL(AOrgBGL, ANewBGL: TBGLSelectInfo); overload;
+
+    procedure BatchWritePos_Reason;
+
+    procedure LockAll;
+
+    property ProjectData: TObject read FProjectData;
+  end;
+
+implementation
+
+uses
+  ZhAPI, Math, ProjectData, BillsDm, Variants, UtilMethods;
+
+{$R *.dfm}
+
+{ TBGLSelectInfo }
+
+procedure TBGLSelectInfo.Clear;
+begin
+  FCodes.Clear;
+  FNums.Clear;
+end;
+
+constructor TBGLSelectInfo.Create(ARec: TsdDataRecord;
+  ATotalNum: Double; AIsOrg: Boolean);
+begin
+  FB_Code := ARec.ValueByName('B_Code').AsString;
+  FName := ARec.ValueByName('Name').AsString;
+  FUnits := ARec.ValueByName('Units').AsString;
+  FPrice := ARec.ValueByName('Price').AsFloat;
+
+  FTotalNum := ATotalNum;
+  FIsOrg := AIsOrg;
+
+  FCodes := TStringList.Create;
+  FCodes.Delimiter := ';';
+  FNums := TStringList.Create;
+  FNums.Delimiter := ';';
+end;
+
+destructor TBGLSelectInfo.Destroy;
+begin
+  FNums.Free;
+  FCodes.Free;
+  inherited;
+end;
+
+function TBGLSelectInfo.GetCount: Integer;
+begin
+  Result := Min(FCodes.Count, FNums.Count);
+end;
+
+function TBGLSelectInfo.GetMergedCode: string;
+begin
+  Result := FCodes.DelimitedText;
+end;
+
+function TBGLSelectInfo.GetMergedNum: string;
+begin
+  Result := FNums.DelimitedText;
+end;
+
+procedure TBGLSelectInfo.SetMergedCode(const Value: string);
+begin
+  if Value <> '' then
+    FCodes.DelimitedText := Value
+  else
+    FCodes.Clear;
+end;
+
+procedure TBGLSelectInfo.SetMergedNum(const Value: string);
+begin
+  if Value <> '' then
+    FNums.DelimitedText := Value
+  else
+    FNums.Clear;
+end;
+
+{ TBGLData }
+
+constructor TBGLData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+end;
+
+destructor TBGLData.Destroy;
+begin
+  inherited;
+end;
+
+procedure TBGLData.Open(AConnection: TADOConnection);
+begin
+  atBGL.Connection := AConnection;
+  cdsBGL.Open;
+  cdsBGL.AddIndex('idxID', 'ID', []);
+  cdsBGL.AddIndex('idxCode', 'Code', []);
+  cdsBGL.IndexName := 'idxID';
+  cdsBGLView.CloneCursor(cdsBGL, True);
+
+  atBGBills.Connection := AConnection;
+  cdsBGBills.Open;
+  cdsBGBillsView.CloneCursor(cdsBGBills, True);
+  cdsBGBills.IndexFieldNames := 'ID';
+  cdsBGBillsView.MasterSource := dsBGL;
+  cdsBGBillsView.MasterFields := 'ID';
+  cdsBGBillsView.IndexFieldNames := 'BGID;ID';
+end;
+
+procedure TBGLData.Save;
+begin
+  cdsBGL.ApplyUpdates(0);
+  cdsBGBills.ApplyUpdates(0);
+end;
+
+procedure TBGLData.cdsBGBillsViewAfterInsert(DataSet: TDataSet);
+begin
+  cdsBGBillsViewID.AsInteger := GetNewIDOfIndex(cdsBGBills);
+  cdsBGBillsViewBGID.AsInteger := cdsBGLViewID.AsInteger;
+end;
+
+procedure TBGLData.AddBGL(const sCode: string);
+begin
+  cdsBGLView.DisableControls;
+  cdsBGLView.Append;
+  cdsBGLViewCode.AsString := sCode;
+  cdsBGLView.Post;
+  cdsBGLView.EnableControls;
+end;
+
+procedure TBGLData.cdsBGBillsViewAfterPost(DataSet: TDataSet);
+
+  procedure DoB_CodeChange;
+  var
+    Rec: TsdDataRecord;
+  begin
+    cdsBGBillsViewB_Code.Tag := 0;
+    cdsBGBillsView.Edit;
+    with TProjectData(FProjectData).BillsData do
+    begin
+      Rec := sddBills.Locate('B_Code', cdsBGBillsViewB_Code.AsString);
+      if Rec <> nil then
+      begin
+        cdsBGBillsViewName.AsString := Rec.ValueByName('Name').AsString;
+        cdsBGBillsViewUnits.AsString := Rec.ValueByName('Units').AsString;
+        cdsBGBillsViewPrice.AsString := Rec.ValueByName('Price').AsString;
+      end;
+    end;
+    cdsBGBillsView.Post;
+  end;
+
+  procedure ClearChangeTag;
+  begin
+    cdsBGBillsViewB_Code.Tag := 0;
+    cdsBGBillsViewName.Tag := 0;
+    cdsBGBillsViewUnits.Tag := 0;
+    cdsBGBillsViewPrice.Tag := 0;
+    cdsBGBillsViewQuantity.Tag := 0;
+  end;
+
+var
+  fTotalPrice, Differ: Double;
+begin
+  if (cdsBGBillsViewB_Code.Tag = 1) then
+    DoB_CodeChange;
+
+  if (cdsBGBillsViewPrice.Tag = 1) or
+      (cdsBGBillsViewQuantity.Tag = 1) then
+  begin
+    cdsBGBillsViewPrice.Tag := 0;
+    cdsBGBillsViewQuantity.Tag := 0;
+    fTotalPrice := TotalPriceRoundTo(cdsBGBillsViewPrice.AsFloat * cdsBGBillsViewQuantity.AsFloat);
+    UpdateBGLTotalPrice(cdsBGBillsViewBGID.AsInteger, fTotalPrice - cdsBGBillsViewTotalPrice.AsFloat);
+    cdsBGBillsView.Edit;
+    cdsBGBillsViewTotalPrice.AsFloat := fTotalPrice;
+    cdsBGBillsView.Post;
+  end;
+
+  ClearChangeTag;
+end;
+
+procedure TBGLData.cdsBGBillsViewQuantityChange(Sender: TField);
+begin
+  Sender.Tag := 1;
+end;
+
+procedure TBGLData.GatherBGLTotalPrice(ABGLID: Integer);
+var
+  fGather: Double;
+begin
+  cdsBGBills.Filter := 'BGID = ' + IntToStr(ABGLID);
+  cdsBGBills.Filtered := True;
+  try
+    fGather := 0;
+    cdsBGBills.First;
+    while not cdsBGBills.Eof do
+    begin
+      fGather := fGather + cdsBGBillsTotalPrice.AsFloat;
+      cdsBGBills.Next;
+    end;
+    if cdsBGL.FindKey([ABGLID]) then
+    begin
+      cdsBGL.Edit;
+      cdsBGLTotalPrice.AsFloat := fGather;
+      cdsBGL.Post;
+    end;
+  finally
+    cdsBGBills.Filtered := False;
+  end;
+end;
+
+procedure TBGLData.UpdateBGLTotalPrice(ABGLID: Integer; ADiffer: Double);
+begin
+  if cdsBGL.FindKey([ABGLID]) then
+  begin
+    cdsBGL.Edit;
+    cdsBGLTotalPrice.AsFloat := cdsBGLTotalPrice.AsFloat + ADiffer;
+    cdsBGL.Post;
+  end;
+end;
+
+procedure TBGLData.ApplyBGL(AOrgBGL, ANewBGL: TBGLSelectInfo);
+begin
+  ApplyBGL(AOrgBGL);
+  ApplyBGL(ANewBGL);
+end;
+
+procedure TBGLData.ApplyBGL(ABGLInfo: TBGLSelectInfo);
+var
+  I: Integer;
+begin
+  for I := 0 to ABGLInfo.Count - 1 do
+    if LocateBGL(ABGLInfo.Codes[I]) and
+        cdsBGBills.Locate('BGID;B_Code', VarArrayOf([cdsBGLID.AsInteger, ABGLInfo.B_Code]), []) then
+    begin
+      cdsBGBills.Edit;
+      if ABGLInfo.IsOrg then
+        cdsBGBillsUsedQuantity.AsFloat := cdsBGBillsUsedQuantity.AsFloat
+            - QuantityRoundTo(StrToFloatDef(ABGLInfo.Nums[I], 0))
+      else
+        cdsBGBillsUsedQuantity.AsFloat := cdsBGBillsUsedQuantity.AsFloat
+            + QuantityRoundTo(StrToFloatDef(ABGLInfo.Nums[I], 0));
+      cdsBGBills.Post;
+      UpdateBGLExecutionRate(cdsBGBillsBGID.AsInteger);
+    end;
+end;
+
+procedure TBGLData.cdsBGBillsViewBeforePost(DataSet: TDataSet);
+
+  procedure DisplayErrorMessage(const AHint: string);
+  begin
+    cdsBGBillsViewB_Code.Tag := 0;
+    cdsBGBillsViewName.Tag := 0;
+    cdsBGBillsViewUnits.Tag := 0;
+    cdsBGBillsViewPrice.Tag := 0;
+    cdsBGBillsViewQuantity.Tag := 0;
+    ShowErrorMessage(AHint);
+    Abort;
+  end;
+
+begin
+  if (cdsBGBillsViewB_Code.Tag = 1) or
+      (cdsBGBillsViewName.Tag = 1) or
+      (cdsBGBillsViewUnits.Tag = 1) or
+      (cdsBGBillsViewPrice.Tag = 1) then
+  begin
+    if cdsBGBillsViewLocked.AsBoolean then
+      DisplayErrorMessage('变更清单已被锁定,不可修改!');
+    if cdsBGBillsViewUsedQuantity.AsFloat <> 0 then
+      DisplayErrorMessage('变更令已被应用至清单,不可修改!');
+  end;
+
+  if (cdsBGBillsViewQuantity.Tag = 1) then
+  begin
+    if cdsBGBillsViewLocked.AsBoolean then
+      DisplayErrorMessage('变更清单已被锁定,不可修改!');
+    if (cdsBGBillsViewUsedQuantity.AsFloat <> 0) and
+       (cdsBGBillsViewQuantity.AsFloat < cdsBGBillsViewUsedQuantity.AsFloat) then
+      DisplayErrorMessage('变更清单的清单数量应大于已变更数量!');
+  end;
+
+  if cdsBGBillsViewB_Code.Tag = 1 then
+    if CheckSameB_Code(cdsBGBillsViewBGID.AsInteger, cdsBGBillsViewB_Code.AsString) then
+    begin
+      cdsBGBillsViewB_Code.Tag := 0;
+      ShowErrorMessage('不允许存在同编号变更清单!');
+      Abort;
+    end;
+end;
+
+procedure TBGLData.cdsBGLViewBeforePost(DataSet: TDataSet);
+var
+  iIncrement: Integer;
+  sNewCode: string;
+begin
+  if cdsBGLViewCode.Tag = 1 then
+  begin
+    cdsBGLViewCode.Tag := 0;
+    if cdsBGLViewLocked.AsBoolean then
+    begin
+      ShowErrorMessage('当前变更令已锁定,不可修改');
+      Abort;
+    end;
+    if CheckBGLUsed(cdsBGLViewID.AsInteger) then
+    begin
+      ShowErrorMessage('当前变更令下变更清单已被应用到清单,不可修改');
+      Abort;
+    end;
+  end;
+
+  sNewCode := cdsBGLViewCode.AsString;
+  if Pos(';', sNewCode) > 0 then
+  begin
+    ShowErrorMessage('变更令号不可输入'';'',请使用其他符号代替!');
+    Abort;
+  end;
+  
+  // 相同变更令号应递增[1],[2]...
+  iIncrement := 1;
+  while LocateBGL(sNewCode) and (cdsBGLID.AsInteger <> cdsBGLViewID.AsInteger) do
+  begin
+    sNewCode := Format('%s[%d]', [cdsBGLViewCode.AsString, iIncrement]);
+    Inc(iIncrement);
+  end;
+  cdsBGLViewCode.AsString := sNewCode;
+end;
+
+procedure TBGLData.DeleteBGBills(ABGID: Integer);
+begin
+  cdsBGBills.Filter := 'BGID = ' + IntToStr(ABGID);
+  cdsBGBills.Filtered := True;
+  try
+    cdsBGBills.First;
+    while not cdsBGBills.Eof do
+      cdsBGBills.Delete;
+  finally
+    cdsBGBills.Filtered := False;
+  end;
+end;
+
+procedure TBGLData.cdsBGLViewBeforeDelete(DataSet: TDataSet);
+begin
+  if cdsBGLViewLocked.AsBoolean then
+    raise Exception.Create('变更令已被锁定,不可删除!');
+  if CheckBGLUsed(cdsBGLViewID.AsInteger) then
+    raise Exception.Create('变更令下变更清单已被应用到清单,不可删除!');
+  DeleteBGBills(cdsBGLViewID.AsInteger);
+end;
+
+function TBGLData.CheckSameB_Code(ABGID: Integer;
+  const AB_Code: string): Boolean;
+begin
+  Result := False;
+  cdsBGBills.Filter := 'BGID = ' + IntToStr(ABGID);
+  cdsBGBills.Filtered := True;
+  try
+    cdsBGBills.First;
+    while (not cdsBGBills.Eof) and (not Result) do
+    begin
+      Result := Result or SameText(cdsBGBillsB_Code.AsString, AB_Code);
+      cdsBGBills.Next;
+    end;
+  finally
+    cdsBGBills.Filtered := False;
+  end;
+end;
+
+procedure TBGLData.cdsBGBillsViewBeforeDelete(DataSet: TDataSet);
+begin
+  if cdsBGBillsViewLocked.AsBoolean then
+    raise Exception.Create('变更清单已被锁定,不可删除!');
+  if cdsBGBillsViewUsedQuantity.AsFloat <> 0 then
+    raise Exception.Create('变更清单已被应用至清单,不可删除!');
+end;
+
+function TBGLData.CheckBGLUsed(ABGID: Integer): Boolean;
+begin
+  Result := False;
+  cdsBGBills.Filter := 'BGID = ' + IntToStr(ABGID);
+  cdsBGBills.Filtered := True;
+  try
+    cdsBGBills.First;
+    while (not cdsBGBills.Eof) and (not Result) do
+    begin
+      Result := Result or (cdsBGBillsUsedQuantity.AsFloat <> 0);
+      cdsBGBills.Next;
+    end;
+  finally
+    cdsBGBills.Filtered := False;
+  end;
+end;
+
+procedure TBGLData.LockAll;
+begin
+  LockAllBGL;
+  LockAllBGBills;
+end;
+
+procedure TBGLData.LockAllBGBills;
+begin
+  cdsBGBills.First;
+  while not cdsBGBills.Eof do
+  begin
+    cdsBGBills.Edit;
+    cdsBGBillsLocked.AsBoolean := True;
+    cdsBGBills.Post;
+    cdsBGBills.Next;
+  end;
+end;
+
+procedure TBGLData.LockAllBGL;
+begin
+  cdsBGL.First;
+  while not cdsBGL.Eof do
+  begin
+    cdsBGL.Edit;
+    cdsBGLLocked.AsBoolean := True;
+    cdsBGL.Post;
+    cdsBGL.Next;
+  end;
+end;
+
+procedure TBGLData.cdsBGBillsViewAfterDelete(DataSet: TDataSet);
+begin
+  GatherBGLTotalPrice(cdsBGLViewID.AsInteger);
+end;
+
+procedure TBGLData.BatchWritePos_Reason;
+begin
+  cdsBGL.First;
+  while not cdsBGL.Eof do
+  begin
+    cdsBGL.Edit;
+    cdsBGLPos_Reason.AsString := cdsBGLName.AsString;
+    cdsBGL.Post;
+    cdsBGL.Next;
+  end;
+end;
+
+procedure TBGLData.cdsBGLViewNewRecord(DataSet: TDataSet);
+begin
+  cdsBGLViewID.AsInteger := GetNewIDOfIndex(cdsBGL);
+  cdsBGLViewCreatePhaseID.AsInteger := TProjectData(FProjectData).PhaseIndex;
+end;
+
+procedure TBGLData.UpdateBGLExecutionRate(ABGLID: Integer);
+
+  function GetBGLExecutionTotalPrice: Double;
+  var
+    cdsTemp: TClientDataSet;
+  begin
+    Result := 0;
+    cdsTemp := TClientDataSet.Create(nil);
+    try
+      cdsTemp.CloneCursor(cdsBGBills, True);
+      cdsTemp.Filter := Format('BGID = %d', [ABGLID]);
+      cdsTemp.Filtered := True;
+      cdsTemp.First;
+      while not cdsTemp.Eof do
+      begin
+        Result := Result + TotalPriceRoundTo(
+            cdsTemp.FieldByName('UsedQuantity').AsFloat * cdsTemp.FieldByName('Price').AsFloat);
+        cdsTemp.Next;
+      end;
+    finally
+      cdsTemp.Free;
+    end;
+  end;
+
+begin
+  if cdsBGL.FindKey([ABGLID]) then
+  begin
+    cdsBGL.Edit;
+    cdsBGLExecutionRate.AsFloat := AdvRoundTo(GetBGLExecutionTotalPrice/cdsBGLTotalPrice.AsFloat*100);
+    cdsBGL.Post;
+  end;
+end;
+
+function TBGLData.AllBGLTotalPrice: Double;
+begin
+  Result := 0;
+  cdsBGL.First;
+  while not cdsBGL.Eof do
+  begin
+    Result := Result + cdsBGLTotalPrice.AsFloat;
+    cdsBGL.Next;
+  end;
+end;
+
+procedure TBGLData.cdsBGBillsViewQuantitySetText(Sender: TField;
+  const Text: String);
+begin
+  Sender.AsFloat := QuantityRoundTo(StrToFloatDef(Text, 0));
+end;
+
+procedure TBGLData.cdsBGBillsViewPriceSetText(Sender: TField;
+  const Text: String);
+begin
+  Sender.AsFloat := PriceRoundTo(StrToFloatDef(Text, 0));
+end;
+
+procedure TBGLData.cdsBGLViewCodeChange(Sender: TField);
+begin
+  Sender.Tag := 1;
+end;
+
+procedure TBGLData.Close;
+begin
+  cdsBGL.IndexName := '';
+  cdsBGL.Close;
+  cdsBGBills.Close;
+end;
+
+function TBGLData.LocateBGL(const ACode: string): Boolean;
+begin
+  cdsBGL.IndexName := 'idxCode';
+  try
+    Result := cdsBGL.FindKey([ACode]);
+  finally
+    cdsBGL.IndexName := 'idxID';
+  end;
+end;
+
+end.

+ 71 - 0
DataModules/BillsBookmarkDm.dfm

@@ -0,0 +1,71 @@
+object BillsBookmarkData: TBillsBookmarkData
+  OldCreateOrder = False
+  Left = 506
+  Top = 326
+  Height = 182
+  Width = 275
+  object sdvBillsBookmark: TsdDataView
+    Active = False
+    Filtered = True
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'Code'
+      end
+      item
+        FieldName = 'B_Code'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Units'
+      end
+      item
+        FieldName = 'HasBookmark'
+      end
+      item
+        FieldName = 'MarkMemo'
+      end>
+    OnFilterRecord = sdvBillsBookmarkFilterRecord
+    Left = 56
+    Top = 48
+  end
+  object sdvStageBookmark: TsdDataView
+    Active = False
+    Filtered = True
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'Code'
+      end
+      item
+        FieldName = 'B_Code'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Units'
+      end
+      item
+        FieldName = 'HasBookmark'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'HasBookmark'
+      end
+      item
+        FieldName = 'MarkMemo'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'MarkMemo'
+      end>
+    OnFilterRecord = sdvStageBookmarkFilterRecord
+    Left = 160
+    Top = 48
+  end
+end

+ 118 - 0
DataModules/BillsBookmarkDm.pas

@@ -0,0 +1,118 @@
+unit BillsBookmarkDm;
+
+interface
+
+uses
+  SysUtils, Classes, sdDB;
+
+type
+  TBillsBookmarkData = class(TDataModule)
+    sdvBillsBookmark: TsdDataView;
+    sdvStageBookmark: TsdDataView;
+    procedure sdvBillsBookmarkFilterRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+    procedure sdvStageBookmarkFilterRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+  private
+    FProjectData: TObject;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open;
+    procedure Close;
+
+    procedure ResetPhaseStageLink;
+
+    procedure RefreshBillsBookmark;
+    procedure RefreshStageBookmark;
+  end;
+
+implementation
+
+uses
+  ProjectData, BillsDm, BillsTree;
+
+{$R *.dfm}
+
+{ TBillsBookmarkData }
+
+procedure TBillsBookmarkData.Close;
+begin
+  sdvBillsBookmark.Close;
+  sdvStageBookmark.Close;
+end;
+
+constructor TBillsBookmarkData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+end;
+
+destructor TBillsBookmarkData.Destroy;
+begin
+
+  inherited;
+end;
+
+procedure TBillsBookmarkData.Open;
+begin
+  sdvBillsBookmark.DataSet := TProjectData(FProjectData).BillsData.sddBills;
+  sdvBillsBookmark.Open;
+  sdvStageBookmark.DataSet := TProjectData(FProjectData).BillsData.sddBills;
+  sdvStageBookmark.Open;
+end;
+
+procedure TBillsBookmarkData.RefreshBillsBookmark;
+begin
+  sdvBillsBookmark.RefreshFilter;
+end;
+
+procedure TBillsBookmarkData.RefreshStageBookmark;
+begin
+  sdvStageBookmark.RefreshFilter;
+end;
+
+procedure TBillsBookmarkData.ResetPhaseStageLink;
+begin
+  with TProjectData(FProjectData).PhaseData do
+  begin
+    sdvStageBookmark.Columns.FindColumn('HasBookmark').LookupDataSet := StageData.sddStage;
+    sdvStageBookmark.Columns.FindColumn('MarkMemo').LookupDataSet := StageData.sddStage;
+  end;
+  sdvStageBookmark.RefreshFilter;
+end;
+
+procedure TBillsBookmarkData.sdvBillsBookmarkFilterRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+begin
+  Allow := ARecord.ValueByName('HasBookmark').AsBoolean;
+end;
+
+procedure TBillsBookmarkData.sdvStageBookmarkFilterRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+var
+  vNode: TBillsIDTreeNode;
+  StageRec: TsdDataRecord;
+begin
+  if (TProjectData(FProjectData).ProjProperties.PhaseCount > 0) and
+     (TProjectData(FProjectData).PhaseData.Active) then
+  begin
+    with TProjectData(FProjectData).BillsMeasureData do
+      vNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(ARecord.ValueByName('ID').AsInteger));
+    if Assigned(vNode) then
+    begin
+      StageRec := vNode.StageRec;
+      if Assigned(StageRec) then
+        Allow := StageRec.ValueByName('HasBookmark').AsBoolean
+      else
+        Allow := False;
+    end
+    else
+      Allow := False;
+  end
+  else
+    Allow := False;
+end;
+
+end.

+ 106 - 0
DataModules/BillsCompileDm.dfm

@@ -0,0 +1,106 @@
+object BillsCompileData: TBillsCompileData
+  OldCreateOrder = False
+  Left = 498
+  Top = 278
+  Height = 150
+  Width = 215
+  object sdvBillsCompile: TsdDataView
+    Active = False
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'ParentID'
+      end
+      item
+        FieldName = 'NextSiblingID'
+      end
+      item
+        FieldName = 'Code'
+      end
+      item
+        FieldName = 'B_Code'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Units'
+      end
+      item
+        FieldName = 'Price'
+      end
+      item
+        FieldName = 'OrgQuantity'
+      end
+      item
+        FieldName = 'OrgTotalPrice'
+      end
+      item
+        FieldName = 'MisQuantity'
+      end
+      item
+        FieldName = 'MisTotalPrice'
+      end
+      item
+        FieldName = 'OthQuantity'
+      end
+      item
+        FieldName = 'OthTotalPrice'
+      end
+      item
+        FieldName = 'Quantity'
+      end
+      item
+        FieldName = 'QtyFormula'
+      end
+      item
+        FieldName = 'TotalPrice'
+      end
+      item
+        FieldName = 'Peg'
+      end
+      item
+        FieldName = 'DrawingCode'
+      end
+      item
+        FieldName = 'MemoStr'
+      end
+      item
+        FieldName = 'IsMeasureAdd'
+      end
+      item
+        FieldName = 'LockedInfo'
+      end
+      item
+        FieldName = 'DgnQuantity1'
+      end
+      item
+        FieldName = 'DgnQuantity2'
+      end
+      item
+        FieldName = 'DealCode'
+      end
+      item
+        FieldName = 'DealCompany'
+      end
+      item
+        FieldName = 'Alias'
+      end
+      item
+        FieldName = 'DgnPrice'
+      end>
+    AfterAddRecord = sdvBillsCompileAfterAddRecord
+    BeforeValueChange = sdvBillsCompileBeforeValueChange
+    AfterValueChanged = sdvBillsCompileAfterValueChanged
+    AfterClose = sdvBillsCompileAfterClose
+    AfterOpen = sdvBillsCompileAfterOpen
+    OnCurrentChanged = sdvBillsCompileCurrentChanged
+    OnGetText = sdvBillsCompileGetText
+    OnSetText = sdvBillsCompileSetText
+    Left = 56
+    Top = 36
+  end
+end

文件差异内容过多而无法显示
+ 1002 - 0
DataModules/BillsCompileDm.pas


+ 203 - 0
DataModules/BillsDm.dfm

@@ -0,0 +1,203 @@
+object BillsData: TBillsData
+  OldCreateOrder = False
+  Left = 775
+  Top = 246
+  Height = 226
+  Width = 216
+  object sdpBills: TsdADOProvider
+    TableName = 'Bills'
+    Left = 48
+    Top = 16
+  end
+  object sddBills: TsdDataSet
+    Active = False
+    Provider = sdpBills
+    AfterAddRecord = sddBillsAfterAddRecord
+    BeforeDeleteRecord = sddBillsBeforeDeleteRecord
+    BeforeValueChange = sddBillsBeforeValueChange
+    OnGetRecordClass = sddBillsGetRecordClass
+    Left = 48
+    Top = 80
+    FieldListData = {
+      0101044E616D6506024944094669656C644E616D650602494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D650608506172656E744944094669656C644E61
+      6D650608506172656E7449440844617461547970650203084461746153697A65
+      02040549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      65060D4E6578745369626C696E674944094669656C644E616D65060D4E657874
+      5369626C696E6749440844617461547970650203084461746153697A65020405
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650608
+      53657269616C4E6F094669656C644E616D65060853657269616C4E6F08446174
+      61547970650203084461746153697A6502040549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D65060649734C656166094669656C644E
+      616D65060649734C6561660844617461547970650205084461746153697A6502
+      010549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060F4C656166586D6A506172656E744944094669656C644E616D65060F4C6561
+      66586D6A506172656E7449440844617461547970650203084461746153697A65
+      02040549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      6506095869616E67436F6465094669656C644E616D6506095869616E67436F64
+      650844617461547970650218084461746153697A65020A0549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D6506064D75436F64650946
+      69656C644E616D6506064D75436F646508446174615479706502180844617461
+      53697A65020A0549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D6506074A6965436F6465094669656C644E616D6506074A6965436F64
+      650844617461547970650218084461746153697A65020A0549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D65060858694D75436F6465
+      094669656C644E616D65060858694D75436F6465084461746154797065021808
+      4461746153697A65021E0549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D650609496E646578436F6465094669656C644E616D650609
+      496E646578436F64650844617461547970650201084461746153697A65023205
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650604
+      436F6465094669656C644E616D650604436F6465084461746154797065020108
+      4461746153697A6502320549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D650606425F436F6465094669656C644E616D650606425F43
+      6F64650844617461547970650201084461746153697A6502320549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D6506044E616D650946
+      69656C644E616D6506044E616D65084461746154797065021808446174615369
+      7A6503C8000549734B6579080F4E65656450726F636573734E616D6509000104
+      4E616D650605556E697473094669656C644E616D650605556E69747308446174
+      61547970650218084461746153697A6502140549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D6506055072696365094669656C644E61
+      6D65060550726963650844617461547970650206084461746153697A65020805
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650608
+      4E65775072696365094669656C644E616D6506084E6577507269636508446174
+      61547970650206084461746153697A6502080549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D65060B4F72675175616E746974790946
+      69656C644E616D65060B4F72675175616E746974790844617461547970650206
+      084461746153697A6502080549734B6579080F4E65656450726F636573734E61
+      6D65090001044E616D65060D4F7267546F74616C5072696365094669656C644E
+      616D65060D4F7267546F74616C50726963650844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D65060B4D69735175616E74697479094669656C644E616D65060B
+      4D69735175616E746974790844617461547970650206084461746153697A6502
+      080549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060D4D6973546F74616C5072696365094669656C644E616D65060D4D6973546F
+      74616C50726963650844617461547970650206084461746153697A6502080549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060B4F
+      74685175616E74697479094669656C644E616D65060B4F74685175616E746974
+      790844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D65060D4F7468546F74616C
+      5072696365094669656C644E616D65060D4F7468546F74616C50726963650844
+      617461547970650206084461746153697A6502080549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D6506085175616E74697479094669
+      656C644E616D6506085175616E74697479084461746154797065020608446174
+      6153697A6502080549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060A517479466F726D756C61094669656C644E616D65060A5174
+      79466F726D756C610844617461547970650201084461746153697A6503FF0005
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650607
+      517479466C6167094669656C644E616D650607517479466C6167084461746154
+      7970650203084461746153697A6502040549734B6579080F4E65656450726F63
+      6573734E616D65090001044E616D65060A546F74616C5072696365094669656C
+      644E616D65060A546F74616C5072696365084461746154797065020608446174
+      6153697A6502080549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060F4164644465616C5175616E74697479094669656C644E616D
+      65060F4164644465616C5175616E746974790844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D6506114164644465616C546F74616C5072696365094669656C64
+      4E616D6506114164644465616C546F74616C5072696365084461746154797065
+      0206084461746153697A6502080549734B6579080F4E65656450726F63657373
+      4E616D65090001044E616D65060D41646451635175616E74697479094669656C
+      644E616D65060D41646451635175616E74697479084461746154797065020608
+      4461746153697A6502080549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D65060F4164645163546F74616C5072696365094669656C64
+      4E616D65060F4164645163546F74616C50726963650844617461547970650206
+      084461746153697A6502080549734B6579080F4E65656450726F636573734E61
+      6D65090001044E616D65060C416464516342474C436F6465094669656C644E61
+      6D65060C416464516342474C436F646508446174615479706502180844617461
+      53697A6503FF000549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060B416464516342474C4E756D094669656C644E616D65060B41
+      6464516342474C4E756D0844617461547970650218084461746153697A6503FF
+      000549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060D41646450635175616E74697479094669656C644E616D65060D4164645063
+      5175616E746974790844617461547970650206084461746153697A6502080549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060F41
+      64645063546F74616C5072696365094669656C644E616D65060F416464506354
+      6F74616C50726963650844617461547970650206084461746153697A65020805
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D65060C
+      416464506342474C436F6465094669656C644E616D65060C416464506342474C
+      436F64650844617461547970650218084461746153697A6503FF000549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060B41646450
+      6342474C4E756D094669656C644E616D65060B416464506342474C4E756D0844
+      617461547970650218084461746153697A6503FF000549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D65061141646447617468657251
+      75616E74697479094669656C644E616D6506114164644761746865725175616E
+      746974790844617461547970650206084461746153697A6502080549734B6579
+      080F4E65656450726F636573734E616D65090001044E616D6506134164644761
+      74686572546F74616C5072696365094669656C644E616D650613416464476174
+      686572546F74616C50726963650844617461547970650206084461746153697A
+      6502080549734B6579080F4E65656450726F636573734E616D65090001044E61
+      6D65060B4C6F636B65644C6576656C094669656C644E616D65060B4C6F636B65
+      644C6576656C0844617461547970650205084461746153697A6502010549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060A4C6F63
+      6B6564496E666F094669656C644E616D65060A4C6F636B6564496E666F084461
+      7461547970650205084461746153697A6502010549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D65060E4C6F636B65644E6577507269
+      6365094669656C644E616D65060E4C6F636B65644E6577507269636508446174
+      61547970650205084461746153697A6502010549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D65060D43726561746550686173654944
+      094669656C644E616D65060D4372656174655068617365494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D65060C49734D65617375726541646409466965
+      6C644E616D65060C49734D656173757265416464084461746154797065020508
+      4461746153697A6502010549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D650603506567094669656C644E616D650603506567084461
+      7461547970650218084461746153697A6503FF000549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D65060B44726177696E67436F6465
+      094669656C644E616D65060B44726177696E67436F6465084461746154797065
+      0218084461746153697A6503FF000549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D6506074D656D6F537472094669656C644E616D65
+      06074D656D6F5374720844617461547970650210084461746153697A6503A00F
+      0549734B6579080F4E65656450726F636573734E616D65090001044E616D6506
+      0C44676E5175616E7469747931094669656C644E616D65060C44676E5175616E
+      74697479310844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060C44676E51
+      75616E7469747932094669656C644E616D65060C44676E5175616E7469747932
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D6506104465616C44676E5175
+      616E7469747931094669656C644E616D6506104465616C44676E5175616E7469
+      7479310844617461547970650206084461746153697A6502080549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D6506104465616C4467
+      6E5175616E7469747932094669656C644E616D6506104465616C44676E517561
+      6E74697479320844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060D434467
+      6E5175616E7469747931094669656C644E616D65060D4344676E5175616E7469
+      7479310844617461547970650206084461746153697A6502080549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D65060D4344676E5175
+      616E7469747932094669656C644E616D65060D4344676E5175616E7469747932
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D65060B486173426F6F6B6D61
+      726B094669656C644E616D65060B486173426F6F6B6D61726B08446174615479
+      70650205084461746153697A6502010549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D6506084D61726B4D656D6F094669656C644E61
+      6D6506084D61726B4D656D6F0844617461547970650218084461746153697A65
+      03FF000549734B6579080F4E65656450726F636573734E616D65090001044E61
+      6D6506084465616C436F6465094669656C644E616D6506084465616C436F6465
+      0844617461547970650218084461746153697A6502320549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D65060B4465616C436F6D7061
+      6E79094669656C644E616D65060B4465616C436F6D70616E7908446174615479
+      70650218084461746153697A6502320549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D6506084465616C54797065094669656C644E61
+      6D6506084465616C547970650844617461547970650218084461746153697A65
+      02140549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      650610416464437574546F74616C5072696365094669656C644E616D65061041
+      6464437574546F74616C50726963650844617461547970650206084461746153
+      697A6502080549734B6579080F4E65656450726F636573734E616D6508000104
+      4E616D650610416464506179546F74616C5072696365094669656C644E616D65
+      0610416464506179546F74616C50726963650844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D650605416C696173094669656C644E616D650605416C69617308
+      44617461547970650218084461746153697A6502640549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D65060F416464436F6D706C6574
+      6552617465094669656C644E616D65060F416464436F6D706C65746552617465
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D65060844676E507269636509
+      4669656C644E616D65060844676E507269636508446174615479706502060844
+      61746153697A6502080549734B6579080F4E65656450726F636573734E616D65
+      090001044E616D65060B41646444676E5072696365094669656C644E616D6506
+      0B41646444676E50726963650844617461547970650206084461746153697A65
+      02080549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      65060D4861734174746163686D656E74094669656C644E616D65060D48617341
+      74746163686D656E740844617461547970650205084461746153697A65020105
+      49734B6579080F4E65656450726F636573734E616D65090000}
+  end
+end

+ 583 - 0
DataModules/BillsDm.pas

@@ -0,0 +1,583 @@
+unit BillsDm;
+
+interface
+
+uses
+  StandardBillsFme,
+  ZhAPI, StandardLib, StageDm, BillsTree, mDataRecord,
+  SysUtils, Classes, sdDB, sdProvider, ADODB, sdIDTree, Math;
+
+const
+  DealIndex = 0;
+  AddDealIndex = 1;
+  AddQcIndex = 2;
+  AddPcIndex = 3;
+  AddGatherIndex = 4;
+
+type
+  TRecChangeEvent = procedure (ARec: TsdDataRecord) of object;
+
+  TBillsData = class(TDataModule)
+    sdpBills: TsdADOProvider;
+    sddBills: TsdDataSet;
+    procedure sddBillsAfterAddRecord(ARecord: TsdDataRecord);
+    procedure sddBillsBeforeDeleteRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+    procedure sddBillsBeforeValueChange(AValue: TsdValue;
+      const NewValue: Variant; var Allow: Boolean);
+    procedure sddBillsGetRecordClass(var ARecordClass: TsdRecordClass);
+  private
+    FProjectData: TObject;
+    FCurPhaseIndex: Integer;
+    FBeforeChangeTotalPrice: Double;
+    FBeforeChangeParentID: Integer;
+
+    //procedure RecursiveCalculate(ABillsID: Integer);
+
+    function GetStageData: TStageData;
+
+    function GetBuildLoadInterest(AIndex: Integer): Double;
+    function GetFirstPart(AIndex: Integer): Double;
+    function GetOtherFee(AIndex: Integer): Double;
+    function GetOtherProjectFee(AIndex: Integer): Double;
+    function GetRecyclingFee(AIndex: Integer): Double;
+    function GetReservedFee(AIndex: Integer): Double;
+    function GetSecondPart(AIndex: Integer): Double;
+    function GetStageSettlement(AIndex: Integer): Double;
+    function GetThirdPart(AIndex: Integer): Double;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Close;
+    procedure Save;
+    procedure InitBills;
+
+    // 计算 -- 均采用增量汇总方式计算父项
+   {procedure Calculate(ABillsID: Integer);
+    procedure CalculateDeal(ABillsID: Integer);           // 合同计量
+    procedure CalculateQuantityChange(ABillsID: Integer); // 数量变更计量
+    procedure CalculatePriceChange(ABillsID: Integer);    // 单价变更计量}
+
+    // 上报审核批复过程 -- 锁定数据
+    procedure LockedBaseData;
+    // 解锁数据
+    procedure UnLockedBaseData;
+
+    procedure DisableEvents;
+    procedure EnableEvents;
+
+    function GetMaxBillsID: Integer;
+
+    function GetGatherTotalPrice(ABillsID, AIndex: Integer): Double;
+
+    property ProjectData: TObject read FProjectData;
+    property StageData: TStageData read GetStageData;
+
+    {累计完成 可查数据}
+    // AIndex表示不同类型,取值如下:
+    // 0: 0号台账合同 1: 累计合同计量 2: 累计数量变更计量 3: 累计单价变更计量 4: 累计完成计量
+    // 第一部分
+    property FirstPart[AIndex: Integer]: Double read GetFirstPart;
+    // 第二部分
+    property SecondPart[AIndex: Integer]: Double read GetSecondPart;
+    // 第三部分
+    property ThirdPart[AIndex: Integer]: Double read GetThirdPart;
+    // 预留费用
+    property ReservedFee[AIndex: Integer]: Double read GetReservedFee;
+    // 其他费用项目
+    property OtherFee[AIndex: Integer]: Double read GetOtherFee;
+    // 建设期贷款利息
+    property BuildLoadInterest[AIndex: Integer]: Double read GetBuildLoadInterest;
+    // 回收金额
+    property RecyclingFee[AIndex: Integer]: Double read GetRecyclingFee;
+    // 公路工程以外的工程费用
+    property OtherProjectFee[AIndex: Integer]: Double read GetOtherProjectFee;
+    // 结算价
+    property Settlement[AIndex: Integer]: Double read GetStageSettlement;
+  end;
+
+implementation
+
+uses
+  Variants, UtilMethods, Globals, ProjectData, ExcelImport, BillsCommand,
+  PhaseData, BillsCompileDm, ConditionalDefines, FormulaCalc;
+
+{$R *.dfm}
+
+{ TBillsData }
+
+procedure TBillsData.Close;
+begin
+  sddBills.Close;
+end;
+
+constructor TBillsData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+end;
+
+destructor TBillsData.Destroy;
+begin
+  inherited;
+end;
+
+procedure TBillsData.Open(AConnection: TADOConnection);
+begin
+  sdpBills.Connection := AConnection;
+  sddBills.Open;
+  if not Assigned(sddBills.IndexList.FindByName('idxID')) then
+    sddBills.AddIndex('idxID', 'ID');
+    
+  sddBills.FieldByName('OrgQuantity').ValidChars := sddBills.FieldByName('Quantity').ValidChars + ArithmeticCharSet;
+  sddBills.FieldByName('MisQuantity').ValidChars := sddBills.FieldByName('Quantity').ValidChars + ArithmeticCharSet;
+  sddBills.FieldByName('OthQuantity').ValidChars := sddBills.FieldByName('Quantity').ValidChars + ArithmeticCharSet;
+end;
+
+procedure TBillsData.Save;
+
+  procedure ResolveCode(ARec: TsdDataRecord);
+  var
+    sgs: TStrings;
+    i: Integer;
+    sXiangCode, sMuCode, sJieCode, sXiMuCode: string;
+  begin
+    sgs := TStringList.Create;
+    try
+      sgs.Delimiter := '-';
+      sgs.DelimitedText := ARec.ValueByName('Code').AsString;
+      case sgs.Count of
+        1: sXiangCode := '';
+        2: sXiangCode := ChinessNum(StrToIntDef(sgs[1], 0));
+        3: sMuCode := sgs[2];
+        4: sJieCode := sgs[3];
+        else
+        begin
+          for i := 4 to sgs.Count - 1 do
+            if sXiMuCode = '' then
+              sXiMuCode := sgs[i]
+            else
+              sXiMuCode := sXiMuCode + '-' + sgs[i];
+        end;
+      end;
+    finally
+      if (ARec.ValueByName('XiangCode').AsString <> sXiangCode) then
+        ARec.ValueByName('XiangCode').AsString := sXiangCode;
+      if (ARec.ValueByName('MuCode').AsString <> sMuCode) then
+        ARec.ValueByName('MuCode').AsString := sMuCode;
+      if (ARec.ValueByName('JieCode').AsString <> sJieCode) then
+        ARec.ValueByName('JieCode').AsString := sJieCode;
+      if (ARec.ValueByName('XiMuCode').AsString <> sXiMuCode) then
+        ARec.ValueByName('XiMuCode').AsString := sXiMuCode;
+      sgs.Free;
+    end;
+  end;
+
+  procedure SaveReportsRela;
+  var
+    iIndex: Integer;
+    stnNode: TsdIDTreeNode;
+    iLeafXmjParentID: Integer;
+    sIndexCode: string;
+  begin
+    sddBills.BeginUpdate;
+    try
+      with TProjectData(FProjectData).BillsCompileData do
+        for iIndex := 0 to BillsCompileTree.Count - 1 do
+        begin
+          stnNode := BillsCompileTree.Items[iIndex];
+          // 分项清单排序
+          if (stnNode.Rec.ValueByName('SerialNo').AsString = '') or
+              (stnNode.MajorIndex <> stnNode.Rec.ValueByName('SerialNo').AsInteger) then
+            stnNode.Rec.ValueByName('SerialNo').AsInteger := stnNode.MajorIndex;
+
+          // 叶子节点
+          if (stnNode.Rec.ValueByName('IsLeaf').asBoolean <> not stnNode.HasChildren) then
+            stnNode.Rec.ValueByName('IsLeaf').AsBoolean := not stnNode.HasChildren;
+
+          // 最底项目节父节点ID
+          if (stnNode.Rec.ValueByName('B_Code').AsString <> '') then
+            iLeafXmjParentID := GetLeafXmjParentID(stnNode.ID)
+          else
+            iLeafXmjParentID := -1;
+          if (stnNode.Rec.ValueByName('LeafXmjParentID').AsInteger <> iLeafXmjParentID) then
+            stnNode.Rec.ValueByName('LeafXmjParentID').AsInteger := iLeafXmjParentID;
+
+          // 分解项目节编号为项、目、节、细目
+          if stnNode.Rec.ValueByName('Code').AsString <> '' then
+            ResolveCode(stnNode.Rec);
+
+          // 工程量清单排序Code
+          if (stnNode.Rec.ValueByName('B_Code').AsString <> '') then
+          begin
+            sIndexCode := B_CodeToIndexCode(stnNode.Rec.ValueByName('B_Code').AsString);
+            if (stnNode.Rec.ValueByName('IndexCode').AsString <> sIndexCode) then
+              stnNode.Rec.ValueByName('IndexCode').AsString := sIndexCode;
+          end;
+        end;
+    finally
+      sddBills.EndUpdate;
+    end;
+  end;
+
+begin
+  if TProjectData(FProjectData).BillsCompileData.Active then
+    SaveReportsRela; // 保存 SerialNo, IsLeaf, LeafXmjParentID, 分解Code
+  sddBills.Save;
+end;
+
+{procedure TBillsData.Calculate(ABillsID: Integer);
+var
+  stnNode: TsdIDTreeNode;
+  iChild: Integer;
+begin
+  stnNode := FBillsTree.FindNode(ABillsID);
+  if stnNode.HasChildren then
+  begin
+    for iChild := 0 to stnNode.ChildCount - 1 do
+      Calculate(stnNode.ChildNodes[iChild].ID);
+  end
+  else
+  begin
+    CalculateOrg(ABillsID);
+    CalculateDeal(ABillsID);
+    CalculateQuantityChange(ABillsID);
+    CalculatePriceChange(ABillsID);
+  end;
+end;
+
+procedure TBillsData.CalculateDeal(ABillsID: Integer);
+var
+  iIndex: Integer;
+  fQuantity, fTotalPrice: Double;
+  Rec: TsdDataRecord;
+begin
+  fQuantity := 0;
+  fTotalPrice := 0;
+  with TProjectData(FProjectData) do
+    for iIndex := 0 to PhaseCount - 1 do
+    begin
+      Rec := PhaseData[iIndex].PhaseRecord(ABillsID);
+      if not Assigned(Rec) then Continue;
+      fQuantity := fQuantity + Rec.ValueByName('DealQuantity').AsFloat;
+      fTotalPrice := fTotalPrice + Rec.ValueByName('DealTotalPrice').AsFloat;
+    end;
+  with FBillsTree.FindNode(ABillsID).Rec do
+    UpdateRecordDeal(ABillsID, fQuantity - ValueByName('AddDealQuantity').AsFloat,
+      fTotalPrice - ValueByName('AddDealTotalPrice').AsFloat);
+end;
+
+procedure TBillsData.CalculatePriceChange(ABillsID: Integer);
+var
+  iIndex: Integer;
+  fQuantity, fTotalPrice: Double;
+  Rec: TsdDataRecord;
+begin
+  fQuantity := 0;
+  fTotalPrice := 0;
+  with TProjectData(FProjectData) do
+    for iIndex := 0 to PhaseCount - 1 do
+    begin
+      Rec := PhaseData[iIndex].PhaseRecord(ABillsID);
+      if not Assigned(Rec) then Continue;
+      fQuantity := fQuantity + Rec.ValueByName('PcQuantity').AsFloat;
+      fTotalPrice := fTotalPrice + Rec.ValueByName('PcTotalPrice').AsFloat;
+    end;
+  with FBillsTree.FindNode(ABillsID).Rec do
+    UpdateRecordPc(ABillsID, fQuantity - ValueByName('AddPcQuantity').AsFloat,
+      fTotalPrice - ValueByName('AddPcTotalPrice').AsFloat);
+end;
+
+procedure TBillsData.CalculateQuantityChange(ABillsID: Integer);
+var
+  iIndex: Integer;
+  fQuantity, fTotalPrice: Double;
+  Rec: TsdDataRecord;
+begin
+  fQuantity := 0;
+  fTotalPrice := 0;
+  with TProjectData(FProjectData) do
+    for iIndex := 0 to PhaseCount - 1 do
+    begin
+      Rec := PhaseData[iIndex].PhaseRecord(ABillsID);
+      if not Assigned(Rec) then Continue;
+      fQuantity := fQuantity + Rec.ValueByName('QcQuantity').AsFloat;
+      fTotalPrice := fTotalPrice + Rec.ValueByName('QcTotalPrice').AsFloat;
+    end;
+  with FBillsTree.FindNode(ABillsID).Rec do
+    UpdateRecordQc(ABillsID, fQuantity - ValueByName('AddQcQuantity').AsFloat,
+      fTotalPrice - ValueByName('AddQcTotalPrice').AsFloat);
+end; }
+
+{
+procedure TBillsData.RecursiveCalculate(ABillsID: Integer);
+
+  procedure GatherChildValue(ANode: TsdIDTreeNode);
+  var
+    CacheRecord: TCacheRecord;
+    iChild: Integer;
+  begin
+    CacheRecord := TCacheRecord.Create;
+    try
+      for iChild := 0 to ANode.ChildCount - 1 do
+        with ANode.ChildNodes[iChild].Rec do
+        begin
+          CacheRecord.FTotalPrice := CacheRecord.FTotalPrice + ValueByName('TotalPrice').AsFloat;
+          CacheRecord.FDealQuantity := CacheRecord.FDealQuantity + ValueByName('AddDealQuantity').AsFloat;
+          CacheRecord.FDealTotalPrice := CacheRecord.FDealTotalPrice + ValueByName('AddDealTotalPrice').AsFloat;
+          CacheRecord.FQcQuantity := CacheRecord.FQcQuantity + ValueByName('AddQcQuantity').AsFloat;
+          CacheRecord.FQcTotalPrice := CacheRecord.FQcTotalPrice + ValueByName('AddQcTotalPrice').AsFloat;
+          CacheRecord.FPcQuantity := CacheRecord.FPcQuantity + ValueByName('AddPcQuantity').AsFloat;
+          CacheRecord.FPcTotalPrice := CacheRecord.FPcTotalPrice + ValueByName('AddPcTotalPrice').AsFloat;
+        end;
+    finally
+      CacheRecord.SetBillsRecord(ANode);
+      CacheRecord.Free;
+    end;
+  end;
+
+  procedure CalculateLeafNode(ANode: TsdIDTreeNode; ACacheRecord: TCacheRecord);
+  begin
+    with ANode.Rec do
+    begin
+      if ValueByName('QtyFlag').AsInteger = 1 then
+        ValueByName('Quantity').AsFloat := EvaluateExprs(ValueByName('QtyFormula').AsString);
+      if ValueByName('QtyFlag').AsInteger < 2 then
+        ACacheRecord.FTotalPrice := ValueByName('Quantity').AsFloat * ValueByName('Price').AsFloat
+      else
+      begin
+        FFormulaCalc.SetRecordText(ValueByName('QtyFormula').AsString);
+        ACacheRecord.FTotalPrice := FFormulaCalc.Value;
+      end;
+    end;
+  end;
+
+  procedure GatherPhaseValue(ANode: TsdIDTreeNode);
+  var
+    CacheRecord: TCacheRecord;
+    iIndex: Integer;
+    Rec: TsdDataRecord;
+  begin
+    CacheRecord := TCacheRecord.Create;
+    try
+      CalculateLeafNode(ANode, CacheRecord);
+      {with TProjectData(FProjectData) do
+        for iIndex := 0 to PhaseCount - 1 do
+        begin
+          PhaseData[iIndex].ReCalculate(ANode.ID);
+          Rec := PhaseData[iIndex].PhaseRecord(ANode.ID);
+          if not Assigned(Rec) then Continue;
+          CacheRecord.FDealQuantity := CacheRecord.FDealQuantity + Rec.ValueByName('DealQuantity').AsFloat;
+          CacheRecord.FDealTotalPrice := CacheRecord.FDealTotalPrice + Rec.ValueByName('DealTotalPrice').AsFloat;
+          CacheRecord.FQcQuantity := CacheRecord.FQcQuantity + Rec.ValueByName('QcQuantity').AsFloat;
+          CacheRecord.FQcTotalPrice := CacheRecord.FQcTotalPrice + Rec.ValueByName('QcTotalPrice').AsFloat;
+          CacheRecord.FPcQuantity := CacheRecord.FPcQuantity + Rec.ValueByName('PcQuantity').AsFloat;
+          CacheRecord.FPcTotalPrice := CacheRecord.FPcTotalPrice + Rec.ValueByName('PcTotalPrice').AsFloat;
+        end;}
+{    finally
+      CacheRecord.SetBillsRecord(ANode);
+      CacheRecord.Free;
+    end;
+  end;
+
+  procedure CalculateCurNode(ANode: TsdIDTreeNode);
+  begin
+    if ANode.HasChildren then
+      GatherChildValue(ANode)
+    else
+      GatherPhaseValue(ANode);
+  end;
+
+  procedure CalculateAllChildren(ANode: TsdIDTreeNode);
+  var
+    iChild: Integer;
+  begin
+    if ANode.HasChildren then
+      for iChild := 0 to ANode.ChildCount - 1 do
+        RecursiveCalculate(ANode.ChildNodes[iChild].ID);
+  end;
+
+var
+  stnNode: TsdIDTreeNode;
+begin
+  stnNode := FBillsTree.FindNode(ABillsID);
+  CalculateAllChildren(stnNode);
+  CalculateCurNode(stnNode);
+end;  }
+
+procedure TBillsData.InitBills;
+var
+  Import: TBillsExcelImport;
+begin
+  Import := TBillsExcelImport.Create(TProjectData(ProjectData));
+  try
+    Import.ImportFile(GetTemplateBillsFileName);
+  finally
+    Import.Free;
+  end;
+end;
+
+function TBillsData.GetStageData: TStageData;
+begin
+  Result := TProjectData(FProjectData).PhaseData.StageData;
+end;
+
+procedure TBillsData.LockedBaseData;
+var
+  iIndex: Integer;
+begin
+  sddBills.BeginUpdate;
+  for iIndex := 0 to sddBills.RecordCount - 1 do
+  begin
+    if not sddBills.Records[iIndex].ValueByName('LockedLevel').AsBoolean then
+      sddBills.Records[iIndex].ValueByName('LockedLevel').AsBoolean := True;
+    if not sddBills.Records[iIndex].ValueByName('LockedInfo').AsBoolean then
+      sddBills.Records[iIndex].ValueByName('LockedInfo').AsBoolean := True;
+    if sddBills.Records[iIndex].ValueByName('NewPrice').AsFloat <> 0 then
+      sddBills.Records[iIndex].ValueByName('LockedNewPrice').AsBoolean := True;
+  end;
+  sddBills.EndUpdate;
+end;
+
+procedure TBillsData.sddBillsAfterAddRecord(ARecord: TsdDataRecord);
+begin
+  ARecord.ValueByName('CreatePhaseID').AsInteger := TProjectData(FProjectData).PhaseIndex;
+end;
+
+function TBillsData.GetBuildLoadInterest(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(34, AIndex);
+end;
+
+function TBillsData.GetFirstPart(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(1, AIndex);
+end;
+
+function TBillsData.GetOtherFee(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(15, AIndex);
+end;
+
+function TBillsData.GetOtherProjectFee(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(9, AIndex);
+end;
+
+function TBillsData.GetRecyclingFee(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(16, AIndex);
+end;
+
+function TBillsData.GetReservedFee(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(7, AIndex);
+end;
+
+function TBillsData.GetSecondPart(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(2, AIndex);
+end;
+
+function TBillsData.GetStageSettlement(AIndex: Integer): Double;
+begin
+  // 全国
+  // 第一部分+第二部分+第三部分+预备费+新增加费用项目(其他费用_广东)-回收金额
+  Result := FirstPart[AIndex] + SecondPart[AIndex] + ThirdPart[AIndex]
+         + ReservedFee[AIndex] + OtherFee[AIndex] - RecyclingFee[AIndex];
+  // 广东
+  // 全国的基础上+建设期贷款利息+公路功能以外的项目
+  if _IsGuangDong then
+    Result := Result + BuildLoadInterest[AIndex] + OtherProjectFee[AIndex];
+end;
+
+function TBillsData.GetThirdPart(AIndex: Integer): Double;
+begin
+  Result := GetGatherTotalPrice(3, AIndex);
+end;
+
+function TBillsData.GetGatherTotalPrice(ABillsID, AIndex: Integer): Double;
+var
+  Rec: TsdDataRecord;
+begin
+  Result := 0;
+  Rec := sddBills.FindKey('idxID', ABillsID);
+  if Assigned(Rec) then
+  begin
+    case AIndex of
+      0: Result := Rec.ValueByName('TotalPrice').AsFloat;
+      1: Result := Rec.ValueByName('AddDealTotalPrice').AsFloat;
+      2: Result := Rec.ValueByName('AddQcTotalPrice').AsFloat;
+      3: Result := Rec.ValueByName('AddPcTotalPrice').AsFloat;
+      4: Result := Rec.ValueByName('AddGatherTotalPrice').AsFloat;
+    end;
+  end;
+end;
+
+procedure TBillsData.DisableEvents;
+begin
+  sddBills.BeforeValueChange := nil;
+  sddBills.AfterValueChanged := nil;
+end;
+
+procedure TBillsData.EnableEvents;
+begin
+  {sddBills.BeforeValueChange := sddBillsBeforeValueChange;
+  sddBills.AfterValueChanged := sddBillsAfterValueChanged;}
+end;
+
+procedure TBillsData.UnLockedBaseData;
+var
+  iIndex: Integer;
+begin
+  for iIndex := 0 to sddBills.RecordCount - 1 do
+    sddBills.Records[iIndex].ValueByName('LockedInfo').AsBoolean := False;
+end;
+
+procedure TBillsData.sddBillsBeforeDeleteRecord(ARecord: TsdDataRecord;
+  var Allow: Boolean);
+begin
+  with TProjectData(FProjectData) do
+  begin
+    if ProjProperties.PhaseCount > 0 then
+      PhaseData.StageData.DeletePhaseRecord(ARecord.ValueByName('ID').AsInteger);
+  end;
+end;
+
+procedure TBillsData.sddBillsBeforeValueChange(AValue: TsdValue;
+  const NewValue: Variant; var Allow: Boolean);
+begin
+  if (Pos('DgnQuantity', AValue.FieldName) > 0) and
+     not (VarIsNull(NewValue) or (NewValue = 0)) then
+  begin
+    if AValue.Owner.ValueByName('B_Code').AsString <> '' then
+    begin
+      ErrorMessage('仅项目节可以输入设计数量!');
+      Allow := False;
+    end;
+  end;
+end;
+
+function TBillsData.GetMaxBillsID: Integer;
+var
+  Rec: TsdDataRecord;
+  i: Integer;
+begin
+  Result := 100;
+  for i := 0 to sddBills.RecordCount - 1 do
+  begin
+    Rec := sddBills.Records[i];
+    if Rec.ValueByName('ID').AsInteger > Result then
+      Result := Rec.ValueByName('ID').AsInteger;
+  end;
+end;
+
+procedure TBillsData.sddBillsGetRecordClass(
+  var ARecordClass: TsdRecordClass);
+begin
+  ARecordClass := TBillsRecord;
+end;
+
+end.

+ 471 - 0
DataModules/BillsGatherDm.dfm

@@ -0,0 +1,471 @@
+object BillsGatherData: TBillsGatherData
+  OldCreateOrder = False
+  Left = 571
+  Top = 314
+  Height = 207
+  Width = 215
+  object cdsBillsGather: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'IndexCode'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'Price'
+        DataType = ftFloat
+      end
+      item
+        Name = 'NewPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'BGLQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'BGLTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Deal_BGLQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Deal_BGLTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CompletionRate'
+        DataType = ftFloat
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    AfterScroll = cdsBillsGatherAfterScroll
+    Left = 64
+    Top = 16
+    Data = {
+      B60300009619E0BD010000001800000027000000000003000000B60306425F43
+      6F6465010049000000010005574944544802000200320009496E646578436F64
+      650100490000000100055749445448020002003200044E616D6502004A000000
+      010005574944544802000200900105556E69747301004A000000010005574944
+      54480200020028000550726963650800040000000000084E6577507269636508
+      000400000000000C4465616C5175616E7469747908000400000000000E446561
+      6C546F74616C50726963650800040000000000085175616E7469747908000400
+      000000000A546F74616C507269636508000400000000000F4375724465616C51
+      75616E746974790800040000000000114375724465616C546F74616C50726963
+      6508000400000000000D43757251635175616E7469747908000400000000000F
+      4375725163546F74616C507269636508000400000000000D4375725063517561
+      6E7469747908000400000000000F4375725063546F74616C5072696365080004
+      0000000000114375724761746865725175616E74697479080004000000000013
+      437572476174686572546F74616C507269636508000400000000000F41646444
+      65616C5175616E746974790800040000000000114164644465616C546F74616C
+      507269636508000400000000000D41646451635175616E746974790800040000
+      0000000F4164645163546F74616C507269636508000400000000000D41646450
+      635175616E7469747908000400000000000F4164645063546F74616C50726963
+      650800040000000000114164644761746865725175616E746974790800040000
+      00000013416464476174686572546F74616C507269636508000400000000000F
+      456E644465616C5175616E74697479080004000000000011456E644465616C54
+      6F74616C507269636508000400000000000D456E6451635175616E7469747908
+      000400000000000F456E645163546F74616C507269636508000400000000000D
+      456E6450635175616E7469747908000400000000000F456E645063546F74616C
+      5072696365080004000000000011456E644761746865725175616E7469747908
+      0004000000000013456E64476174686572546F74616C50726963650800040000
+      0000000B42474C5175616E7469747908000400000000000D42474C546F74616C
+      50726963650800040000000000104465616C5F42474C5175616E746974790800
+      040000000000124465616C5F42474C546F74616C507269636508000400000000
+      000E436F6D706C6574696F6E5261746508000400000000000000}
+    object cdsBillsGatherB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBillsGatherIndexCode: TStringField
+      DisplayWidth = 50
+      FieldName = 'IndexCode'
+      Size = 50
+    end
+    object cdsBillsGatherName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsBillsGatherUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBillsGatherPrice: TFloatField
+      FieldName = 'Price'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherNewPrice: TFloatField
+      FieldName = 'NewPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherDealQuantity: TFloatField
+      FieldName = 'DealQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherDealTotalPrice: TFloatField
+      FieldName = 'DealTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherQuantity: TFloatField
+      FieldName = 'Quantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurDealQuantity: TFloatField
+      FieldName = 'CurDealQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurDealTotalPrice: TFloatField
+      FieldName = 'CurDealTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurQcQuantity: TFloatField
+      FieldName = 'CurQcQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurQcTotalPrice: TFloatField
+      FieldName = 'CurQcTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurPcQuantity: TFloatField
+      FieldName = 'CurPcQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurPcTotalPrice: TFloatField
+      FieldName = 'CurPcTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurGatherQuantity: TFloatField
+      FieldName = 'CurGatherQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCurGatherTotalPrice: TFloatField
+      FieldName = 'CurGatherTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddDealQuantity: TFloatField
+      FieldName = 'AddDealQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddDealTotalPrice: TFloatField
+      FieldName = 'AddDealTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddQcQuantity: TFloatField
+      FieldName = 'AddQcQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddQcTotalPrice: TFloatField
+      FieldName = 'AddQcTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddPcQuantity: TFloatField
+      FieldName = 'AddPcQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddPcTotalPrice: TFloatField
+      FieldName = 'AddPcTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddGatherQuantity: TFloatField
+      FieldName = 'AddGatherQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherAddGatherTotalPrice: TFloatField
+      FieldName = 'AddGatherTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndDealQuantity: TFloatField
+      FieldName = 'EndDealQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndDealTotalPrice: TFloatField
+      FieldName = 'EndDealTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndQcQuantity: TFloatField
+      FieldName = 'EndQcQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndQcTotalPrice: TFloatField
+      FieldName = 'EndQcTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndPcQuantity: TFloatField
+      FieldName = 'EndPcQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndPcTotalPrice: TFloatField
+      FieldName = 'EndPcTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndGatherQuantity: TFloatField
+      FieldName = 'EndGatherQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherEndGatherTotalPrice: TFloatField
+      FieldName = 'EndGatherTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherBGLQuantity: TFloatField
+      FieldName = 'BGLQuantity'
+    end
+    object cdsBillsGatherBGLTotalPrice: TFloatField
+      FieldName = 'BGLTotalPrice'
+    end
+    object cdsBillsGatherDeal_BGLQuantity: TFloatField
+      FieldName = 'Deal_BGLQuantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherDeal_BGLTotalPrice: TFloatField
+      FieldName = 'Deal_BGLTotalPrice'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsBillsGatherCompletionRate: TFloatField
+      FieldName = 'CompletionRate'
+    end
+  end
+  object cdsRelaXmj: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Peg'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'Quantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'NameDanWei'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'NameFenBu'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'NameFenXiang'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'NameUnit'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'DrawingCode'
+        DataType = ftWideString
+        Size = 50
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 64
+    Top = 88
+    Data = {
+      2A0100009619E0BD01000000180000000A0000000000030000002A0104436F64
+      6501004900000001000557494454480200020032000350656702004A00000001
+      00055749445448020002009001044E616D6502004A0000000100055749445448
+      02000200900105556E69747301004A0000000100055749445448020002002800
+      085175616E7469747908000400000000000A4E616D6544616E57656902004A00
+      00000100055749445448020002009001094E616D6546656E427502004A000000
+      01000557494454480200020090010C4E616D6546656E5869616E6702004A0000
+      000100055749445448020002009001084E616D65556E697402004A0000000100
+      0557494454480200020090010B44726177696E67436F646501004A0000000100
+      0557494454480200020064000000}
+    object cdsRelaXmjCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsRelaXmjPeg: TWideStringField
+      FieldName = 'Peg'
+      Size = 200
+    end
+    object cdsRelaXmjName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsRelaXmjUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsRelaXmjQuantity: TFloatField
+      FieldName = 'Quantity'
+      OnGetText = cdsBillsGatherQuantityGetText
+    end
+    object cdsRelaXmjNameDanWei: TWideStringField
+      FieldName = 'NameDanWei'
+      Size = 200
+    end
+    object cdsRelaXmjNameFenBu: TWideStringField
+      FieldName = 'NameFenBu'
+      Size = 200
+    end
+    object cdsRelaXmjNameFenXiang: TWideStringField
+      FieldName = 'NameFenXiang'
+      Size = 200
+    end
+    object cdsRelaXmjNameUnit: TWideStringField
+      FieldName = 'NameUnit'
+      Size = 200
+    end
+    object cdsRelaXmjDrawingCode: TWideStringField
+      FieldName = 'DrawingCode'
+      Size = 50
+    end
+  end
+end

+ 532 - 0
DataModules/BillsGatherDm.pas

@@ -0,0 +1,532 @@
+unit BillsGatherDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, sdIDTree, sdDB;
+
+type
+  TGclNode = class
+  private
+    FB_Code: string;
+    FIndexCode: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+    FNewPrice: Double;
+    FDealQuantity: Double;
+    FDealTotalPrice: Double;
+    FQuantity: Double;
+    FTotalPrice: Double;
+    FBGLQuantity: Double;
+    FBGLTotalPrice: Double;
+    FCurDealQuantity: Double;
+    FCurDealTotalPrice: Double;
+    FCurQcQuantity: Double;
+    FCurQcTotalPrice: Double;
+    FCurPcQuantity: Double;
+    FCurPcTotalPrice: Double;
+    FCurGatherQuantity: Double;
+    FCurGatherTotalPrice: Double;
+    FEndDealQuantity: Double;
+    FEndDealTotalPrice: Double;
+    FEndQcQuantity: Double;
+    FEndQcTotalPrice: Double;
+    FEndPcQuantity: Double;
+    FEndPcTotalPrice: Double;
+    FEndGatherQuantity: Double;
+    FEndGatherTotalPrice: Double;
+    FAddDealQuantity: Double;
+    FAddDealTotalPrice: Double;
+    FAddQcQuantity: Double;
+    FAddQcTotalPrice: Double;
+    FAddPcQuantity: Double;
+    FAddPcTotalPrice: Double;
+    FAddGatherQuantity: Double;
+    FAddGatherTotalPrice: Double;
+  end;
+
+  TBillsGatherData = class(TDataModule)
+    cdsBillsGather: TClientDataSet;
+    cdsBillsGatherB_Code: TStringField;
+    cdsBillsGatherName: TWideStringField;
+    cdsBillsGatherUnits: TWideStringField;
+    cdsBillsGatherPrice: TFloatField;
+    cdsBillsGatherNewPrice: TFloatField;
+    cdsBillsGatherQuantity: TFloatField;
+    cdsBillsGatherTotalPrice: TFloatField;
+
+    cdsBillsGatherCurDealQuantity: TFloatField;
+    cdsBillsGatherCurDealTotalPrice: TFloatField;
+    cdsBillsGatherCurQcQuantity: TFloatField;
+    cdsBillsGatherCurQcTotalPrice: TFloatField;
+    cdsBillsGatherCurPcQuantity: TFloatField;
+    cdsBillsGatherCurPcTotalPrice: TFloatField;
+    cdsBillsGatherCurGatherQuantity: TFloatField;
+    cdsBillsGatherCurGatherTotalPrice: TFloatField;
+
+    cdsBillsGatherAddDealQuantity: TFloatField;
+    cdsBillsGatherAddDealTotalPrice: TFloatField;
+    cdsBillsGatherAddQcQuantity: TFloatField;
+    cdsBillsGatherAddQcTotalPrice: TFloatField;
+    cdsBillsGatherAddPcQuantity: TFloatField;
+    cdsBillsGatherAddPcTotalPrice: TFloatField;
+    cdsBillsGatherAddGatherQuantity: TFloatField;
+    cdsBillsGatherAddGatherTotalPrice: TFloatField;
+
+    cdsRelaXmj: TClientDataSet;
+    cdsRelaXmjCode: TStringField;
+    cdsRelaXmjName: TWideStringField;
+    cdsRelaXmjUnits: TWideStringField;
+    cdsRelaXmjQuantity: TFloatField;
+    cdsRelaXmjNameFenBu: TWideStringField;
+    cdsRelaXmjNameFenXiang: TWideStringField;
+    cdsRelaXmjNameDanWei: TWideStringField;
+    cdsRelaXmjPeg: TWideStringField;
+    cdsRelaXmjNameUnit: TWideStringField;
+    cdsRelaXmjDrawingCode: TWideStringField;
+    cdsBillsGatherIndexCode: TStringField;
+    cdsBillsGatherDealQuantity: TFloatField;
+    cdsBillsGatherDealTotalPrice: TFloatField;
+    cdsBillsGatherEndDealQuantity: TFloatField;
+    cdsBillsGatherEndDealTotalPrice: TFloatField;
+    cdsBillsGatherEndQcQuantity: TFloatField;
+    cdsBillsGatherEndQcTotalPrice: TFloatField;
+    cdsBillsGatherEndPcQuantity: TFloatField;
+    cdsBillsGatherEndPcTotalPrice: TFloatField;
+    cdsBillsGatherEndGatherQuantity: TFloatField;
+    cdsBillsGatherEndGatherTotalPrice: TFloatField;
+    cdsBillsGatherBGLQuantity: TFloatField;
+    cdsBillsGatherBGLTotalPrice: TFloatField;
+    cdsBillsGatherCompletionRate: TFloatField;
+    cdsBillsGatherDeal_BGLQuantity: TFloatField;
+    cdsBillsGatherDeal_BGLTotalPrice: TFloatField;
+    procedure cdsBillsGatherQuantityGetText(Sender: TField;
+      var Text: String; DisplayText: Boolean);
+    procedure cdsBillsGatherAfterScroll(DataSet: TDataSet);
+  private
+    FProjectData: TObject;
+    FGclList: TList;
+
+    function GetGclNode(ARec: TsdDataRecord): TGclNode;
+    procedure FilterGclBills(ANode: TsdIDTreeNode);
+    procedure FilterBills(ANode: TsdIDTreeNode);
+    procedure FilterDealBills;
+    procedure WriteGclBills;
+
+    procedure RefreshRelaXmj;
+    procedure AddRelaXmjs(const AB_Code, AName, AUnits: string; APrice: Double);
+
+    function GetMainBillsTree: TsdIDTree;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure RefreshBills;
+
+    property MainBillsTree: TsdIDTree read GetMainBillsTree;
+  end;
+
+implementation
+
+uses
+  ProjectData, PhaseData, StageDm, BillsDm, UtilMethods,
+  ZhAPI, BillsCompileDm, DealBillsDm, BGLDm, BillsTree, BillsMeasureDm;
+
+{$R *.dfm}
+
+{ TBillsGatherData }
+
+procedure TBillsGatherData.FilterBills(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    FilterBills(ANode.FirstChild)
+  else
+    FilterGclBills(ANode);
+  FilterBills(ANode.NextSibling);
+end;
+
+procedure TBillsGatherData.FilterGclBills(ANode: TsdIDTreeNode);
+
+  procedure LoadPhaseData(AGclNode: TGclNode; AID: Integer);
+  var
+    Rec: TsdDataRecord;
+  begin
+    Rec := TBillsIDTreeNode(ANode).StageRec;
+    if not Assigned(Rec) then Exit;
+    AGclNode.FCurDealQuantity := AGclNode.FCurDealQuantity + Rec.ValueByName('DealQuantity').AsFloat;
+    AGclNode.FCurDealTotalPrice := AGclNode.FCurDealTotalPrice + Rec.ValueByName('DealTotalPrice').AsFloat;
+    AGclNode.FCurQcQuantity := AGclNode.FCurQcQuantity + Rec.ValueByName('QcQuantity').AsFloat;
+    AGclNode.FCurQcTotalPrice := AGclNode.FCurQcTotalPrice + Rec.ValueByName('QcTotalPrice').AsFloat;
+    AGclNode.FCurPcQuantity := AGclNode.FCurPcQuantity + Rec.ValueByName('PcQuantity').AsFloat;
+    AGclNode.FCurPcTotalPrice := AGclNode.FCurPcTotalPrice + Rec.ValueByName('PcTotalPrice').AsFloat;
+    AGclNode.FCurGatherQuantity := AGclNode.FCurGatherQuantity + Rec.ValueByName('GatherQuantity').AsFloat;
+    AGclNode.FCurGatherTotalPrice := AGclNode.FCurGatherTotalPrice + Rec.ValueByName('GatherTotalPrice').AsFloat;
+
+    AGclNode.FEndDealQuantity := AGclNode.FEndDealQuantity + Rec.ValueByName('EndDealQuantity').AsFloat;
+    AGclNode.FEndDealTotalPrice := AGclNode.FEndDealTotalPrice + Rec.ValueByName('EndDealTotalPrice').AsFloat;
+    AGclNode.FEndQcQuantity := AGclNode.FEndQcQuantity + Rec.ValueByName('EndQcQuantity').AsFloat;
+    AGclNode.FEndQcTotalPrice := AGclNode.FEndQcTotalPrice + Rec.ValueByName('EndQcTotalPrice').AsFloat;
+    AGclNode.FEndPcQuantity := AGclNode.FEndPcQuantity + Rec.ValueByName('EndPcQuantity').AsFloat;
+    AGclNode.FEndPcTotalPrice := AGclNode.FEndPcTotalPrice + Rec.ValueByName('EndPcTotalPrice').AsFloat;
+    AGclNode.FEndGatherQuantity := AGclNode.FEndGatherQuantity + Rec.ValueByName('EndGatherQuantity').AsFloat;
+    AGclNode.FEndGatherTotalPrice := AGclNode.FEndGatherTotalPrice + Rec.ValueByName('EndGatherTotalPrice').AsFloat;
+  end;
+
+  procedure LoadMeasureData(AGclNode: TGclNode; ARec: TsdDataRecord);
+  begin
+    AGclNode.FQuantity := AGclNode.FQuantity + ARec.ValueByName('Quantity').AsFloat;
+    AGclNode.FTotalPrice := AGclNode.FTotalPrice + ARec.ValueByName('TotalPrice').AsFloat;
+    if TProjectData(FProjectData).ProjProperties.PhaseCount = 0 then Exit;
+    LoadPhaseData(AGclNode, ARec.ValueByName('ID').AsInteger);
+    AGclNode.FAddDealQuantity := AGclNode.FAddDealQuantity + ARec.ValueByName('AddDealQuantity').AsFloat;
+    AGclNode.FAddDealTotalPrice := AGclNode.FAddDealTotalPrice + ARec.ValueByName('AddDealTotalPrice').AsFloat;
+    AGclNode.FAddQcQuantity := AGclNode.FAddQcQuantity + ARec.ValueByName('AddQcQuantity').AsFloat;
+    AGclNode.FAddQcTotalPrice := AGclNode.FAddQcTotalPrice + ARec.ValueByName('AddQcTotalPrice').AsFloat;
+    AGclNode.FAddPcQuantity := AGclNode.FAddPcQuantity + ARec.ValueByName('AddPcQuantity').AsFloat;
+    AGclNode.FAddPcTotalPrice := AGclNode.FAddPcTotalPrice + ARec.ValueByName('AddPcTotalPrice').AsFloat;
+    AGclNode.FAddGatherQuantity := AGclNode.FAddGatherQuantity + ARec.ValueByName('AddGatherQuantity').AsFloat;
+    AGclNode.FAddGatherTotalPrice := AGclNode.FAddGatherTotalPrice + ARec.ValueByName('AddGatherTotalPrice').AsFloat;
+  end;
+
+var
+  Rec: TsdDataRecord;
+  GclNode: TGclNode;
+begin
+  if not Assigned(ANode) then Exit;
+  Rec := ANode.Rec;
+  if Rec.ValueByName('B_Code').AsString = '' then Exit;
+  GclNode := GetGclNode(Rec);
+  LoadMeasureData(GclNode, Rec);
+end;
+
+constructor TBillsGatherData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+  cdsBillsGather.IndexFieldNames := 'IndexCode';
+end;
+
+destructor TBillsGatherData.Destroy;
+begin
+  inherited;
+end;
+
+function TBillsGatherData.GetMainBillsTree: TsdIDTree;
+begin
+  Result := TProjectData(FProjectData).BillsMeasureData.BillsMeasureTree;
+end;
+
+procedure TBillsGatherData.RefreshBills;
+begin
+  cdsBillsGather.DisableControls;
+  cdsBillsGather.AfterScroll := nil;
+  try
+    cdsBillsGather.EmptyDataSet;
+    FGclList := TList.Create;
+    FilterBills(MainBillsTree.FirstNode);
+    FilterDealBills;
+    WriteGclBills;
+  finally
+    ClearObjects(FGclList);
+    FGclList.Free;
+    cdsBillsGather.EnableControls;
+    cdsBillsGather.AfterScroll := cdsBillsGatherAfterScroll;
+  end;
+end;
+
+procedure TBillsGatherData.cdsBillsGatherQuantityGetText(Sender: TField;
+  var Text: String; DisplayText: Boolean);
+begin
+  if Sender.AsFloat <> 0 then
+    Text := FormatFloat('0.###', Sender.AsFloat)
+  else
+    Text := '';
+end;
+
+procedure TBillsGatherData.cdsBillsGatherAfterScroll(DataSet: TDataSet);
+begin
+  RefreshRelaXmj;
+end;
+
+procedure TBillsGatherData.RefreshRelaXmj;
+begin
+  cdsRelaXmj.EmptyDataSet;
+  AddRelaXmjs(cdsBillsGatherB_Code.AsString, cdsBillsGatherName.AsString,
+    cdsBillsGatherUnits.AsString, cdsBillsGatherPrice.AsFloat);
+end;
+
+procedure TBillsGatherData.AddRelaXmjs(
+  const AB_Code, AName, AUnits: string; APrice: Double);
+
+  function GetFirstXmjParent(AID: Integer): TsdIDTreeNode;
+  begin
+    Result := MainBillsTree.FindNode(AID);
+    while Assigned(Result) and (Result.Rec.ValueByName('B_Code').AsString <> '') do
+      Result := Result.Parent;
+  end;
+
+  // 取树结构的第ALevel层节点的名称(level从0开始)
+  function GetNameByLevel(ANode: TsdIDTreeNode; ALevel: Integer): string;
+  begin
+    Result := '';
+    if not Assigned(ANode) then Exit;
+    if ANode.Level = ALevel then
+      Result := ANode.Rec.ValueByName('Name').AsString
+    else if ANode.Level > ALevel then
+      Result := GetNameByLevel(ANode.Parent, ALevel);
+  end;
+
+  function GetPegNode(ANode: TsdIDTreeNode): TsdIDTreeNode;
+  begin
+    Result := nil;
+    if not Assigned(ANode) then Exit;
+    if CheckPeg(ANode.Rec.ValueByName('Name').AsString) then
+      Result := ANode
+    else
+      Result := GetPegNode(ANode.Parent);
+  end;
+
+  function GetNameDanWei(ANode: TsdIDTreeNode): string;
+  begin
+    // 取树结构的第二层节点的名称
+    Result := GetNameByLevel(ANode, 1);
+  end;
+
+  // ANode为计量单元节点,APegNode为桩号节点
+  function GetNameFenBu(ANode, APegNode: TsdIDTreeNode): string;
+  var
+    vCurNode: TsdIDTreeNode;
+  begin
+    // 如果计量单元节点的名称为桩号(转化为判断计量单元节点与桩号节点为同一个)
+    if not Assigned(APegNode) or (ANode.ID = APegNode.ID) then
+      // 取树结构的第三层节点的名称
+      Result := GetNameByLevel(ANode, 2)
+    // 否则,取桩号节点的子节点的名称
+    else
+    begin
+      vCurNode := ANode;
+      while vCurNode.Level > APegNode.Level + 1 do
+        vCurNode := vCurNode.Parent;
+      Result := vCurNode.Rec.ValueByName('Name').AsString;
+    end;
+  end;
+
+  function GetNameFenXiang(ANode, APegNode: TsdIDTreeNode): string;
+  var
+    iTopLevel: Integer;
+    vCurNode: TsdIDTreeNode;
+  begin
+    if Assigned(APegNode) then
+    begin
+      iTopLevel := 3;
+      if APegNode.ID <> ANode.ID then
+        iTopLevel := APegNode.Level + 2;
+      Result := '';
+      vCurNode := ANode.Parent;
+      while vCurNode.Level >= iTopLevel do
+      begin
+        Result := vCurNode.Rec.ValueByName('Name').AsString + ';' + Result;
+        vCurNode := vCurNode.Parent;
+      end;
+    end
+    else
+      Result := GetNameByLevel(ANode, 3);
+  end;
+
+  function GetNameUnit(ANode: TsdIDTreeNode): string;
+  begin
+    Result := ANode.Rec.ValueByName('Name').AsString;
+  end;
+
+  function GetDrawingCode(ANode: TsdIDTreeNode): string;
+  begin
+    Result := '';
+    if not Assigned(ANode) then Exit;
+    Result := ANode.Rec.ValueByName('DrawingCode').AsString;
+    if Result = '' then
+      Result := GetDrawingCode(ANode.Parent);
+  end;
+
+  function GetPegName(APegNode: TsdIDTreeNode): string;
+  begin
+    if Assigned(APegNode) then
+      Result := APegNode.Rec.ValueByName('Name').AsString
+    else
+      Result := '';
+  end;
+
+  procedure AddRelaXmj(ARec: TsdDataRecord);
+  var
+    vNode, vPeg: TsdIDTreeNode;
+  begin
+    vNode := GetFirstXmjParent(ARec.ValueByName('ID').AsInteger);
+    if not Assigned(vNode) then Exit;
+    cdsRelaXmj.Append;
+    cdsRelaXmjQuantity.AsFloat := ARec.ValueByName('Quantity').AsFloat;
+    cdsRelaXmjCode.AsString := vNode.Rec.ValueByName('Code').AsString;
+    cdsRelaXmjName.AsString := vNode.Rec.ValueByName('Name').AsString;
+    cdsRelaXmjUnits.AsString := vNode.Rec.ValueByName('Units').AsString;
+    vPeg := GetPegNode(vNode);
+    cdsRelaXmjPeg.AsString := GetPegName(vPeg);
+    cdsRelaXmjNameDanWei.AsString := GetNameDanWei(vNode);
+    cdsRelaXmjNameFenBu.AsString := GetNameFenBu(vNode, vPeg);
+    cdsRelaXmjNameFenXiang.AsString := GetNameFenXiang(vNode, vPeg);
+    cdsRelaXmjNameUnit.AsString := GetNameUnit(vNode);
+    cdsRelaXmjDrawingCode.AsString := GetDrawingCode(vNode);
+    cdsRelaXmj.Post;
+  end;
+
+var
+  I: Integer;
+  Rec: TsdDataRecord;
+begin
+  if AB_Code = '' then Exit;
+  with TProjectData(FProjectData).BillsData do
+    for I := 0 to sddBills.RecordCount - 1 do
+    begin
+      Rec := sddBills.Records[I];
+      if SameText(AB_Code, Rec.ValueByName('B_Code').AsString) and
+          SameText(AName, Trim(Rec.ValueByName('Name').AsString)) and
+          SameText(AUnits, Rec.ValueByName('Units').AsString) and
+          (APrice = Rec.ValueByName('Price').AsFloat) then
+        AddRelaXmj(Rec);
+    end;
+end;
+
+procedure TBillsGatherData.WriteGclBills;
+var
+  I: Integer;
+  GclNode: TGclNode;
+begin
+  for I := 0 to FGclList.Count - 1 do
+  begin
+    GclNode := TGclNode(FGclList.Items[I]);
+    cdsBillsGather.Append;
+    cdsBillsGatherB_Code.AsString := GclNode.FB_Code;
+    cdsBillsGatherIndexCode.AsString := GclNode.FIndexCode;
+    cdsBillsGatherName.AsString := GclNode.FName;
+    cdsBillsGatherUnits.AsString := GclNode.FUnits;
+    cdsBillsGatherPrice.AsFloat := GclNode.FPrice;
+    cdsBillsGatherNewPrice.AsFloat := GclNode.FNewPrice;
+
+    cdsBillsGatherDealQuantity.AsFloat := GclNode.FDealQuantity;
+    cdsBillsGatherDealTotalPrice.AsFloat := GclNode.FDealTotalPrice;
+    cdsBillsGatherQuantity.AsFloat := GclNode.FQuantity;
+    cdsBillsGatherTotalPrice.AsFloat := GclNode.FTotalPrice;
+    cdsBillsGatherBGLQuantity.AsFloat := GclNode.FBGLQuantity;
+    cdsBillsGatherBGLTotalPrice.AsFloat := GclNode.FBGLTotalPrice;
+    cdsBillsGatherDeal_BGLQuantity.AsFloat := GclNode.FQuantity + GclNode.FBGLQuantity;
+    cdsBillsGatherDeal_BGLTotalPrice.AsFloat := GclNode.FTotalPrice + GclNode.FBGLTotalPrice;
+
+    cdsBillsGatherCurDealQuantity.AsFloat := GclNode.FCurDealQuantity;
+    cdsBillsGatherCurDealTotalPrice.AsFloat := GclNode.FCurDealTotalPrice;
+    cdsBillsGatherCurQcQuantity.AsFloat := GclNode.FCurQcQuantity;
+    cdsBillsGatherCurQcTotalPrice.AsFloat := GclNode.FCurQcTotalPrice;
+    cdsBillsGatherCurPcQuantity.AsFloat := GclNode.FCurPcQuantity;
+    cdsBillsGatherCurPcTotalPrice.AsFloat := GclNode.FCurPcTotalPrice;
+    cdsBillsGatherCurGatherQuantity.AsFloat := GclNode.FCurGatherQuantity;
+    cdsBillsGatherCurGatherTotalPrice.AsFloat := GclNode.FCurGatherTotalPrice;
+
+    cdsBillsGatherEndDealQuantity.AsFloat := GclNode.FEndDealQuantity;
+    cdsBillsGatherEndDealTotalPrice.AsFloat := GclNode.FEndDealTotalPrice;
+    cdsBillsGatherEndQcQuantity.AsFloat := GclNode.FEndQcQuantity;
+    cdsBillsGatherEndQcTotalPrice.AsFloat := GclNode.FEndQcTotalPrice;
+    cdsBillsGatherEndPcQuantity.AsFloat := GclNode.FEndPcQuantity;
+    cdsBillsGatherEndPcTotalPrice.AsFloat := GclNode.FEndPcTotalPrice;
+    cdsBillsGatherEndGatherQuantity.AsFloat := GclNode.FEndGatherQuantity;
+    cdsBillsGatherEndGatherTotalPrice.AsFloat := GclNode.FEndGatherTotalPrice;
+
+    cdsBillsGatherAddDealQuantity.AsFloat := GclNode.FAddDealQuantity;
+    cdsBillsGatherAddDealTotalPrice.AsFloat := GclNode.FAddDealTotalPrice;
+    cdsBillsGatherAddQcQuantity.AsFloat := GclNode.FAddQcQuantity;
+    cdsBillsGatherAddQcTotalPrice.AsFloat := GclNode.FAddQcTotalPrice;
+    cdsBillsGatherAddPcQuantity.AsFloat := GclNode.FAddPcQuantity;
+    cdsBillsGatherAddPcTotalPrice.AsFloat := GclNode.FAddPcTotalPrice;
+    cdsBillsGatherAddGatherQuantity.AsFloat := GclNode.FAddGatherQuantity;
+    cdsBillsGatherAddGatherTotalPrice.AsFloat := GclNode.FAddGatherTotalPrice;
+
+    if (GclNode.FTotalPrice + GclNode.FBGLTotalPrice) <> 0 then
+      cdsBillsGatherCompletionRate.AsFloat := AdvRoundTo(
+          GclNode.FEndGatherTotalPrice/(GclNode.FTotalPrice + GclNode.FBGLTotalPrice)*100);
+    cdsBillsGather.Post;
+  end;
+end;
+
+procedure TBillsGatherData.FilterDealBills;
+var
+  iIndex: Integer;
+  Rec: TsdDataRecord;
+  GclNode: TGclNode;
+begin
+  with TProjectData(FProjectData).DealBillsData do
+    for iIndex := 0 to sddDealBills.RecordCount - 1 do
+    begin
+      Rec := sddDealBills.Records[iIndex];
+      GclNode := GetGclNode(Rec);
+      GclNode.FDealQuantity := GclNode.FDealQuantity + Rec.ValueByName('Quantity').AsFloat;
+      GclNode.FDealTotalPrice := GclNode.FDealTotalPrice + Rec.ValueByName('TotalPrice').AsFloat;
+    end;
+end;
+
+function TBillsGatherData.GetGclNode(ARec: TsdDataRecord): TGclNode;
+
+  procedure LoadBGLData(AGclNode: TGclNode);
+  begin
+    with TProjectData(FProjectData).BGLData do
+    begin
+      cdsBGBills.First;
+      while not cdsBGBills.Eof do
+      begin
+        if SameText(AGclNode.FB_Code, cdsBGBillsB_Code.AsString) and
+           SameText(AGclNode.FName, Trim(cdsBGBillsName.AsString)) and
+           SameText(AGclNode.FUnits, cdsBGBillsUnits.AsString) and
+           (AGclNode.FPrice = cdsBGBillsPrice.AsFloat) then
+        begin
+          AGclNode.FBGLQuantity := AGclNode.FBGLQuantity + cdsBGBillsQuantity.AsFloat;
+          AGclNode.FBGLTotalPrice := AGclNode.FBGLTotalPrice + cdsBGBillsTotalPrice.AsFloat;
+        end;
+        cdsBGBills.Next;
+      end;
+    end;
+  end;
+
+  function CreateGclNode: TGclNode;
+  begin
+    Result := TGclNode.Create;
+    FGclList.Add(Result);
+    Result.FB_Code := ARec.ValueByName('B_Code').AsString;
+    Result.FIndexCode := B_CodeToIndexCode(ARec.ValueByName('B_Code').AsString);
+    Result.FName := Trim(ARec.ValueByName('Name').AsString);
+    Result.FUnits := ARec.ValueByName('Units').AsString;
+    Result.FPrice := ARec.ValueByName('Price').AsFloat;
+    if Assigned(ARec.ValueByName('NewPrice')) then
+      Result.FNewPrice := ARec.ValueByName('NewPrice').AsFloat
+    else
+      Result.FNewPrice := 0;
+    LoadBGLData(Result);
+  end;
+
+var
+  I: Integer;
+  GclNode: TGclNode;
+begin
+  Result := nil;
+  for I := 0 to FGclList.Count - 1 do
+  begin
+    GclNode := TGclNode(FGclList.Items[I]);
+    if SameText(GclNode.FB_Code, ARec.ValueByName('B_Code').AsString) and
+        SameText(GclNode.FName, Trim(ARec.ValueByName('Name').AsString)) and
+        SameText(GclNode.FUnits, ARec.ValueByName('Units').AsString) and
+        (PriceRoundTo(GclNode.FPrice - ARec.ValueByName('Price').AsFloat) = 0) then
+    begin
+      Result := GclNode;
+      Break;
+    end;
+  end;
+  if not Assigned(Result) then
+    Result := CreateGclNode;
+end;
+
+end.

+ 220 - 0
DataModules/BillsMeasureDm.dfm

@@ -0,0 +1,220 @@
+object BillsMeasureData: TBillsMeasureData
+  OldCreateOrder = False
+  Left = 622
+  Top = 342
+  Height = 150
+  Width = 299
+  object sdvBillsMeasure: TsdDataView
+    Active = False
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'ParentID'
+      end
+      item
+        FieldName = 'NextSiblingID'
+      end
+      item
+        FieldName = 'Code'
+      end
+      item
+        FieldName = 'B_Code'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Units'
+      end
+      item
+        FieldName = 'Price'
+      end
+      item
+        FieldName = 'NewPrice'
+      end
+      item
+        FieldName = 'Quantity'
+      end
+      item
+        FieldName = 'QtyFormula'
+      end
+      item
+        FieldName = 'TotalPrice'
+      end
+      item
+        FieldName = 'CurDealQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'DealQuantity'
+      end
+      item
+        FieldName = 'CurDealTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'DealTotalPrice'
+      end
+      item
+        FieldName = 'CurQcQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'QcQuantity'
+      end
+      item
+        FieldName = 'CurQcTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'QcTotalPrice'
+      end
+      item
+        FieldName = 'CurQcBGLCode'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'QcBGLCode'
+      end
+      item
+        FieldName = 'CurPcQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'PcQuantity'
+      end
+      item
+        FieldName = 'CurPcTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'PcTotalPrice'
+      end
+      item
+        FieldName = 'CurPcBGLCode'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'PcBGLCode'
+      end
+      item
+        FieldName = 'CurGatherQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'GatherQuantity'
+      end
+      item
+        FieldName = 'CurGatherTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'GatherTotalPrice'
+      end
+      item
+        FieldName = 'EndDealQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndDealQuantity'
+      end
+      item
+        FieldName = 'EndDealTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndDealTotalPrice'
+      end
+      item
+        FieldName = 'EndQcQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndQcQuantity'
+      end
+      item
+        FieldName = 'EndQcTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndQcTotalPrice'
+      end
+      item
+        FieldName = 'EndPcQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndPcQuantity'
+      end
+      item
+        FieldName = 'EndPcTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndPcTotalPrice'
+      end
+      item
+        FieldName = 'EndGatherQuantity'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndGatherQuantity'
+      end
+      item
+        FieldName = 'EndGatherTotalPrice'
+        KeyFields = 'ID'
+        LookupKeyFields = 'BillsID'
+        LookupResultField = 'EndGatherTotalPrice'
+      end
+      item
+        FieldName = 'AddDealQuantity'
+      end
+      item
+        FieldName = 'AddDealTotalPrice'
+      end
+      item
+        FieldName = 'AddQcQuantity'
+      end
+      item
+        FieldName = 'AddQcTotalPrice'
+      end
+      item
+        FieldName = 'AddPcQuantity'
+      end
+      item
+        FieldName = 'AddPcTotalPrice'
+      end
+      item
+        FieldName = 'AddGatherQuantity'
+      end
+      item
+        FieldName = 'AddGatherTotalPrice'
+      end
+      item
+        FieldName = 'Peg'
+      end
+      item
+        FieldName = 'DrawingCode'
+      end
+      item
+        FieldName = 'MemoStr'
+      end
+      item
+        FieldName = 'DealDgnQuantity1'
+      end
+      item
+        FieldName = 'DealDgnQuantity2'
+      end
+      item
+        FieldName = 'CDgnQuantity1'
+      end
+      item
+        FieldName = 'CDgnQuantity2'
+      end
+      item
+        FieldName = 'Alias'
+      end
+      item
+        FieldName = 'AddDgnPrice'
+      end
+      item
+        FieldName = 'AddCompleteRate'
+      end>
+    AfterAddRecord = sdvBillsMeasureAfterAddRecord
+    AfterValueChanged = sdvBillsMeasureAfterValueChanged
+    AfterClose = sdvBillsMeasureAfterClose
+    AfterOpen = sdvBillsMeasureAfterOpen
+    OnCurrentChanged = sdvBillsMeasureCurrentChanged
+    OnGetText = sdvBillsMeasureGetText
+    OnSetText = sdvBillsMeasureSetText
+    OnNeedLookupRecord = sdvBillsMeasureNeedLookupRecord
+    Left = 48
+    Top = 32
+  end
+end

+ 874 - 0
DataModules/BillsMeasureDm.pas

@@ -0,0 +1,874 @@
+unit BillsMeasureDm;
+
+interface
+
+uses
+  BillsDm, BillsTree, FormulaCalc, sdIDTree, StageDm,
+  SysUtils, Classes, sdDB;
+
+type
+  TBillsMeasureData = class(TDataModule)
+    sdvBillsMeasure: TsdDataView;
+    procedure sdvBillsMeasureAfterOpen(Sender: TObject);
+    procedure sdvBillsMeasureAfterAddRecord(ARecord: TsdDataRecord);
+    procedure sdvBillsMeasureGetText(var Text: String;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      DisplayText: Boolean);
+    procedure sdvBillsMeasureSetText(var Text: String;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      var Allow: Boolean);
+    procedure sdvBillsMeasureNeedLookupRecord(ARecord: TsdDataRecord;
+      AColumn: TsdViewColumn; ANewText: String);
+    procedure sdvBillsMeasureAfterClose(Sender: TObject);
+    procedure sdvBillsMeasureAfterValueChanged(AValue: TsdValue);
+    procedure sdvBillsMeasureCurrentChanged(ARecord: TsdDataRecord);
+  private
+    FProjectData: TObject;
+    FBillsData: TBillsData;
+    FBillsMeasureTree: TBillsIDTree;
+
+    FFormulaCalc: TFormulaCalc;
+    FShowParentData: Boolean;
+    FOnRecChange: TRecChangeEvent;
+
+    function OnGetCardinalNum(const ACardinalNum: string): Double;
+
+    procedure CalcAddCompleteRate(ANode: TsdIDTreeNode);
+    procedure CalcAddDgnPrice(ANode: TsdIDTreeNode);
+    procedure UpdateRecordGather(ANode: TsdIDTreeNode; AQuantity, ATotalPrice: Double);
+
+    function SelectAndUpdateBGL(ABillsID: Integer; ARec: TsdDataRecord;
+      ANewValue: Double; const AType: string): Boolean;
+
+    function GetStageData: TStageData;
+    procedure SetOnRecChange(const Value: TRecChangeEvent);
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open;
+    procedure Close;
+    procedure ReConnectTree;
+
+    procedure CalculateAll;
+
+    procedure ResetPhaseStageLink;
+    procedure ResetTreeNodeStageRec;
+
+    procedure ExpandNodeTo(ALevel: Integer);
+    procedure ExpandXmjNode;
+    procedure ExpandCurPhase;
+
+    function GatherRelaBGL(ANode: TsdIDTreeNode): string;
+
+    // 计算 修改各期原报审核数据时,需对累计数据做增量
+    procedure UpdateRecordDeal(ABillsID: Integer; AQuantity, ATotalPrice: Double);
+    procedure UpdateRecordQc(ABillsID: Integer; AQuantity, ATotalPrice: Double);
+    procedure UpdateRecordPc(ABillsID: Integer; AQuantity, ATotalPrice: Double);
+    procedure UpdateBGLInfo(ABillsID: Integer; ARec: TsdDataRecord; const AType: string);
+
+    property ProjectData: TObject read FProjectData;
+    property BillsData: TBillsData read FBillsData;
+    property BillsMeasureTree: TBillsIDTree read FBillsMeasureTree;
+
+    property StageData: TStageData read GetStageData;
+    property ShowParentData: Boolean read FShowParentData write FShowParentData;
+    property OnRecChange: TRecChangeEvent read FOnRecChange write SetOnRecChange;
+  end;
+
+implementation
+
+uses
+  ProjectData, PhaseData, Math, ZhAPI, BillsCommand, BGLSelectFrm,
+  BGLDm, UtilMethods, mDataRecord;
+
+{$R *.dfm}
+
+{ TBillsMeasureData }
+
+constructor TBillsMeasureData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+  FBillsData := TProjectData(FProjectData).BillsData;
+  FBillsMeasureTree := TBillsIDTree.Create;
+  FBillsMeasureTree.KeyFieldName := 'ID';
+  FBillsMeasureTree.ParentFieldName := 'ParentID';
+  FBillsMeasureTree.NextSiblingFieldName := 'NextSiblingID';
+  FBillsMeasureTree.AutoCreateKeyID := True;
+  FBillsMeasureTree.AutoExpand := True;
+  FBillsMeasureTree.DataView := sdvBillsMeasure;
+  FBillsMeasureTree.SeedID := Max(FBillsMeasureTree.SeedID, 100);
+  FBillsMeasureTree.Link(TProjectData(FProjectData).BillsCompileData.BillsCompileTree, True);
+
+  FFormulaCalc := TFormulaCalc.Create(FBillsMeasureTree);
+  FFormulaCalc.OnGetValue := OnGetCardinalNum;
+end;
+
+destructor TBillsMeasureData.Destroy;
+begin
+  FFormulaCalc.Free;
+  FBillsMeasureTree.Free;
+  inherited;
+end;
+
+procedure TBillsMeasureData.Open;
+begin
+  sdvBillsMeasure.DataSet := TProjectData(FProjectData).BillsData.sddBills;
+  sdvBillsMeasure.Open;
+end;
+
+procedure TBillsMeasureData.ReConnectTree;
+begin
+  FBillsMeasureTree.DataView := nil;
+  FBillsMeasureTree.DataView := sdvBillsMeasure;
+  FBillsMeasureTree.Link(TProjectData(FProjectData).BillsCompileData.BillsCompileTree, True);  
+end;
+
+procedure TBillsMeasureData.ResetPhaseStageLink;
+begin
+  with TProjectData(FProjectData).PhaseData do
+  begin
+    sdvBillsMeasure.Columns.FindColumn('CurDealQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurDealTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurQcQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurQcTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurQcBGLCode').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurPcQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurPcTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurPcBGLCode').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurGatherQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('CurGatherTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndDealQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndDealTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndQcQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndQcTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndPcQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndPcTotalPrice').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndGatherQuantity').LookupDataSet := StageData.sddStage;
+    sdvBillsMeasure.Columns.FindColumn('EndGatherTotalPrice').LookupDataSet := StageData.sddStage;
+  end;
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureAfterOpen(Sender: TObject);
+begin
+  FBillsMeasureTree.Active := True;
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureAfterAddRecord(
+  ARecord: TsdDataRecord);
+begin
+  ARecord.ValueByName('IsMeasureAdd').AsBoolean := True;
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureGetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  DisplayText: Boolean);
+
+  function GetQuantityValueOrFormula(const AQtyType: string): string;
+  begin
+    with AValue.Owner do
+    begin
+      if ValueByName(AQtyType + 'Flag').AsInteger = 1 then
+        Result := ValueByName(AQtyType + 'Formula').AsString
+      else
+        Result := Text;
+    end;
+  end;
+
+  function GetTotalPriceValueOrFormula(const AQtyType: string): string;
+  begin
+    with AValue.Owner do
+    begin
+      if ValueByName(AQtyType + 'Flag').AsInteger = 2 then
+      begin
+        FFormulaCalc.SetRecordText(ValueByName(AQtyType + 'Formula').AsString);
+        Result := FFormulaCalc.DisplayText;
+      end
+      else
+        Result := Text;
+    end;
+  end;
+
+  procedure GetDisplayText(var AText: string; AValue: TsdValue;
+    AColumn: TsdViewColumn);
+  var
+    stnNode: TsdIDTreeNode;
+  begin
+    if (Pos('TotalPrice', AColumn.FieldName) > 0) or
+       (Pos('Quantity', AColumn.FieldName) > 0) or
+       (Pos('Price', AColumn.FieldName) > 0) then
+    begin
+      if AValue.AsFloat = 0 then
+        Text := '';
+    end;
+
+    if SameText('Quantity', AColumn.FieldName) or
+        SameText('Price', AColumn.FieldName) or
+        SameText('NewPrice', AColumn.FieldName) or
+        SameText('AddGatherQuantity', AColumn.FieldName) then
+    begin
+      stnNode := BillsMeasureTree.FindNode(AValue.Owner.ValueByName('ID').AsInteger);
+      if stnNode.HasChildren then
+        Text := '';
+    end;
+    // 所有本期数据,当节点为父节点时,不显示值(实际上需要计算其中的金额值,但又不能显示)
+    // 有病。每天都在变。
+    if not ShowParentData and (Pos('Cur', AColumn.FieldName) > 0) and (Pos('Gather', AColumn.FieldName) = 0) then
+    begin
+      stnNode := BillsMeasureTree.FindNode(AValue.Owner.ValueByName('BillsID').AsInteger);
+      if stnNode.HasChildren then
+        Text := '';
+    end;
+  end;
+
+  procedure GetEditText(var AText: string; AValue: TsdValue;
+    AColumn: TsdViewColumn);
+  begin
+    if SameText(AColumn.FieldName, 'Quantity') then
+      Text := GetQuantityValueOrFormula('Qty')
+    else if SameText(AColumn.FieldName, 'CurDealQuantity') then
+      Text := GetQuantityValueOrFormula('Deal')
+    else if SameText(AColumn.FieldName, 'CurQcQuantity') then
+      Text := GetQuantityValueOrFormula('Qc')
+    else if SameText(AColumn.FieldName, 'CurPcQuantity') then
+      Text := GetQuantityValueOrFormula('Pc')
+    else if SameText(AColumn.FieldName, 'CurDealTotalPrice') then
+      Text := GetTotalPriceValueOrFormula('Deal')
+    else if SameText(AColumn.FieldName, 'CurQcTotalPrice') then
+      Text := GetTotalPriceValueOrFormula('Qc')
+    else if SameText(AColumn.FieldName, 'CurPcTotalPrice') then
+      Text := GetTotalPriceValueOrFormula('Pc');
+  end;
+
+var
+  fPercent: Double;
+begin
+  if not Assigned(AValue) then Exit;
+
+  if DisplayText then
+    GetDisplayText(Text, AValue, AColumn)
+  else
+    GetEditText(Text, AValue, AColumn);
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureSetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  var Allow: Boolean);
+
+  function GetBillsID: Integer;
+  begin
+    if Pos('Cur', AColumn.FieldName) = 1 then
+      Result := AValue.Owner.ValueByName('BillsID').AsInteger
+    else
+      Result := ARecord.ValueByName('ID').AsInteger;
+  end;
+
+  procedure CheckLockedData;
+  begin
+    if SameText(AColumn.FieldName, 'Code') or
+       SameText(AColumn.FieldName, 'B_Code') or
+       SameText(AColumn.FieldName, 'Name') or
+       SameText(AColumn.FieldName, 'Units') or
+       SameText(AColumn.FieldName, 'Price') then
+       if ARecord.ValueByName('LockedInfo').AsBoolean then
+         DataSetErrorMessage(Allow, '清单信息已被锁定,不允许修改编号、名称、单位、清单单价!');
+    if not Allow then Exit;
+
+    if SameText(AColumn.FieldName, 'NewPrice') then
+      if ARecord.ValueByName('LockedNewPrice').AsBoolean then
+        DataSetErrorMessage(Allow, '变更单价已被锁定,不允许修改!');
+  end;
+
+  procedure CheckNodeWritable;
+  var
+    vNode: TsdIDTreeNode;
+    iCreatePhase: Integer;
+  begin
+    vNode := BillsMeasureTree.FindNode(GetBillsID);
+    iCreatePhase := vNode.Rec.ValueByName('CreatePhaseID').AsInteger;
+
+    if SameText('Price', AColumn.FieldName) then
+      if vNode.Rec.ValueByName('AddGatherTotalPrice').AsFloat <> 0 then
+        DataSetErrorMessage(Allow, '该清单已经计量,不可修改清单单价!');
+    if SameText('NewPrice', AColumn.FieldName) then
+      if vNode.Rec.ValueByName('AddPcTotalPrice').AsFloat <> 0 then
+        DataSetErrorMessage(Allow, '该清单已经计量,不可修改清单变更单价!');
+    if not Allow then Exit;
+
+    if vNode.HasChildren then
+    begin
+      if Text = '' then
+        Exit
+      else if ((Pos('Quantity', AColumn.FieldName) > 0) and (Pos('Dgn', AColumn.FieldName) <=0)) or
+          (Pos('TotalPrice', AColumn.FieldName) > 0) then
+        DataSetErrorMessage(Allow, '该清单有子计算项,不能直接修改!')
+      else if (Pos('Price', AColumn.FieldName) > 0) then
+        DataSetErrorMessage(Allow, '仅最底层清单可输入单价!');
+    end
+    else
+      if (Pos('TotalPrice', AColumn.FieldName) > 0) and
+          (vNode.Rec.ValueByName('Price').AsFloat <> 0) then
+        DataSetErrorMessage(Allow, '不可直接输入!如需直接输入金额,请先删除清单单价!');
+    if not Allow then Exit;
+    // 变更清单允许填写本期合同计量,按超计论
+    {if vNode.Rec.ValueByName('IsMeasureAdd').AsBoolean and (iCreatePhase > 0) and
+        (SameText('CurDealQuantity', AColumn.FieldName) or
+        SameText('CurDealTotalPrice', AColumn.FieldName)) then
+      DataSetErrorMessage(Allow, Format('该清单为第%d期新增清单,不可填写本期合同计量数据!', [iCreatePhase]));}
+  end;
+
+  procedure SetQuantity(const AField: string);
+  begin
+    // 变更应选择变更令
+    if SameText(AField , 'Qc') or SameText(AField , 'Pc') then
+      Allow := SelectAndUpdateBGL(GetBillsID, AValue.Owner, StrToFloatDef(Text, 0), AField);
+    if not Allow then Exit;
+
+    if CheckStringNull(Text) or CheckNumeric(Text) then
+    begin
+      AValue.Owner.ValueByName(AField + 'Flag').AsInteger := 0;
+      AValue.Owner.ValueByName(AField + 'Formula').AsString := '';
+      Text := FloatToStr(QuantityRoundTo(StrToFloatDef(Text, 0)));
+    end
+    else
+    begin
+      AValue.Owner.ValueByName(AField + 'Flag').AsInteger := 1;
+      AValue.Owner.ValueByName(AField + 'Formula').AsString := Text;
+      Text := FloatToStr(QuantityRoundTo(EvaluateExprs(Text)));
+    end;
+  end;
+
+  procedure SetTotalPrice(const AField: string);
+  begin
+    // 变更应选择变更令
+    if SameText(AField , 'Qc') or SameText(AField , 'Pc') then
+      Allow := SelectAndUpdateBGL(GetBillsID, AValue.Owner, StrToFloatDef(Text, 0), AField);
+    if not Allow then Exit;
+
+    AValue.Owner.ValueByName(AField + 'Flag').AsInteger := 2;
+    AValue.Owner.ValueByName(AField + 'Quantity').AsString := '';
+    if CheckStringNull(Text) or CheckNumeric(Text) then
+    begin
+      AValue.Owner.ValueByName('Formula').AsString := '';
+      Text := FloatToStr(TotalPriceRoundTo(StrToFloatDef(Text, 0)));
+    end
+    else
+    begin
+      AValue.Owner.ValueByName('Formula').AsString := Text;
+      Text := FloatToStr(TotalPriceRoundTo(EvaluateExprs(Text)));
+    end;
+  end;
+
+  procedure DoCurChanged;
+  begin
+    if SameText(AColumn.FieldName, 'CurDealQuantity') then
+      SetQuantity('Deal')
+    else if SameText(AColumn.FieldName, 'CurQcQuantity') then
+      SetQuantity('Qc')
+    else if SameText(AColumn.FieldName, 'CurPcQuantity') then
+      SetQuantity('Pc')
+    else if SameText(AColumn.FieldName, 'CurDealTotalPrice') then
+      SetTotalPrice('Deal')
+    else if SameText(AColumn.FieldName, 'CurQcTotalPrice') then
+      SetTotalPrice('Qc')
+    else if SameText(AColumn.FieldName, 'CurPcTotalPrice') then
+      SetTotalPrice('Pc')
+    else if (Pos('DgnQuantity', AColumn.FieldName) > 0) or
+        SameText(AColumn.FieldName, 'Quantity') then
+      Text := FloatToStr(QuantityRoundTo(StrToFloatDef(Text, 0)))
+    else if SameText(AColumn.FieldName, 'NewPrice') or
+        SameText(AColumn.FieldName, 'Price') then
+      Text := FloatToStr(PriceRoundTo(StrToFloatDef(Text, 0)));
+  end;
+
+begin
+  if not Assigned(AValue) then Exit;
+
+  CheckLockedData;
+  if not Allow then Exit;
+
+  CheckNodeWritable;
+  if not Allow then Exit;
+
+  Text := Trim(Text);
+  if Pos('=', Text) = 1 then
+    Text := Copy(Text, 2, Length(Text) - 1);
+  DoCurChanged;
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureNeedLookupRecord(
+  ARecord: TsdDataRecord; AColumn: TsdViewColumn; ANewText: String);
+
+  function CheckNeedAddPhaseRecord(ANode: TBillsIDTreeNode): Boolean;
+  begin
+    Result := SameText(AColumn.FieldName, 'CurDealQuantity') or
+              SameText(AColumn.FieldName, 'CurQcQuantity') or
+              SameText(AColumn.FieldName, 'CurPcQuantity') or
+              SameText(AColumn.FieldName, 'CurDealTotalPrice') or
+              SameText(AColumn.FieldName, 'CurQcTotalPrice') or
+              SameText(AColumn.FieldName, 'CurPcTotalPrice');
+    Result := Result and not ANode.HasChildren;
+    Result := Result and not Assigned(ANode.StageRec);
+  end;
+
+  function HasCardinalNum(AFormula: string): Boolean;
+  var
+    iCharIndex: Integer;
+  begin
+    Result := False;
+    iCharIndex := 1;
+    while ((iCharIndex <= Length(AFormula)) and not Result) do
+    begin
+      if AFormula[iCharIndex] in ['A'..'D', 'a'..'d'] then
+        Result := True;
+      Inc(iCharIndex);
+    end;
+  end;
+
+  procedure SetQuantityRec(APhaseRec: TsdDataRecord; const AType: string);
+  var
+    bAllow: Boolean;
+  begin
+    bAllow := True;
+    // 变更应选择变更令
+    if SameText(AType , 'Qc') or SameText(AType , 'Pc') then
+      bAllow := SelectAndUpdateBGL(ARecord.ValueByName('ID').AsInteger,
+          APhaseRec, StrToFloatDef(ANewText, 0), AType);
+
+    if bAllow then
+    begin
+      if CheckNumeric(ANewText) then
+        APhaseRec.ValueByName(AType + 'Quantity').AsFloat := QuantityRoundTo(StrToFloatDef(ANewText, 0))
+      else
+      begin
+        APhaseRec.ValueByName(AType + 'Flag').AsInteger := 1;
+        APhaseRec.ValueByName(AType + 'Quantity').AsFloat := QuantityRoundTo(EvaluateExprs(ANewText));
+        APhaseRec.ValueByName(AType + 'Formula').AsString := ANewText;
+      end;
+    end;
+  end;
+
+  procedure SetTotalPriceRec(APhaseRec: TsdDataRecord; const AType: string);
+  begin
+    APhaseRec.ValueByName(AType + 'Flag').AsInteger := 2;
+    if CheckNumeric(ANewText) then
+      APhaseRec.ValueByName(AType + 'TotalPrice').AsFloat := TotalPriceRoundTo(StrToFloatDef(ANewText, 0))
+    else
+    begin
+      APhaseRec.ValueByName(AType + 'TotalPrice').AsFloat := TotalPriceRoundTo(EvaluateExprs(ANewText));
+      APhaseRec.ValueByName(AType + 'Formula').AsString := ANewText;
+    end;
+  end;
+
+  procedure SetNewRecValue(APhaseRec: TsdDataRecord);
+  begin
+    if SameText(AColumn.FieldName, 'CurDealQuantity') then
+      SetQuantityRec(APhaseRec, 'Deal')
+    else if SameText(AColumn.FieldName, 'CurQcQuantity') then
+      SetQuantityRec(APhaseRec, 'Qc')
+    else if SameText(AColumn.FieldName, 'CurPcQuantity') then
+      SetQuantityRec(APhaseRec, 'Pc')
+    else if SameText(AColumn.FieldName, 'CurDealTotalPrice') then
+      SetTotalPriceRec(APhaseRec, 'Deal')
+    else if SameText(AColumn.FieldName, 'CurQcTotalPrice') then
+      SetTotalPriceRec(APhaseRec, 'Qc')
+    else if SameText(AColumn.FieldName, 'CurPcTotalPrice') then
+      SetTotalPriceRec(APhaseRec, 'Pc');
+  end;
+
+  function CheckNodeWritable(ANode: TBillsIDTreeNode): Boolean;
+  var
+    iCreatePhase: Integer;
+  begin
+    Result := True;
+    if ANode.HasChildren then
+    begin
+      if ANewText = '' then
+        Result := False
+      else
+        DataSetErrorMessage(Result, '该清单有子计算项,不能直接修改!');
+    end
+    else if (Pos('TotalPrice', AColumn.FieldName) > 0) and
+        (ANode.Rec.ValueByName('Price').AsFloat <> 0) then
+      DataSetErrorMessage(Result, '不可直接输入!如需直接输入金额,请先删除清单单价!');
+
+    // 变更清单允许填写本期合同计量,按超计论
+    {iCreatePhase := ANode.Rec.ValueByName('CreatePhaseID').AsInteger;
+    if ANode.Rec.ValueByName('IsMeasureAdd').AsBoolean and (iCreatePhase > 0) and
+        (SameText('CurDealQuantity', AColumn.FieldName) or
+        SameText('CurDealTotalPrice', AColumn.FieldName)) then
+    begin
+      ErrorMessage(Format('该清单为第%d期新增清单,不可填写本期合同计量数据!', [iCreatePhase]));
+      Exit;
+    end; }
+  end;
+
+var
+  NewRec: TStageRecord;
+  vNode: TBillsIDTreeNode;
+begin
+  vNode := TBillsIDTreeNode(BillsMeasureTree.FindNode(ARecord.ValueByName('ID').AsInteger));
+  if not CheckNodeWritable(vNode) then
+    Exit;
+
+  if CheckNeedAddPhaseRecord(vNode) then
+  begin
+    if Pos('Quantity', AColumn.FieldName) > 0 then
+      if HasCardinalNum(ANewText) then
+        raise Exception.Create('数量列公式不可输入参数');
+    NewRec := StageData.AddStageRecord(ARecord.ValueByName('ID').AsInteger);
+    SetNewRecValue(NewRec);
+    vNode.StageRec := NewRec;
+  end;
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureAfterClose(Sender: TObject);
+begin
+  FBillsMeasureTree.Active := False;
+end;
+
+function TBillsMeasureData.OnGetCardinalNum(
+  const ACardinalNum: string): Double;
+{
+  function GetTotalPrice(ABillsID: Integer): Double;
+  var
+    stnNode: TsdIDTreeNode;
+  begin
+    stnNode := FBillsTree.FindNode(ABillsID);
+    if Assigned(stnNode) then
+      Result := stnNode.Rec.ValueByName('TotalPrice').AsFloat;
+  end;
+
+  function GetPhaseTotalPrice(ABillsID: Integer; const AType: string): Double;
+  var
+    Rec: TsdDataRecord;
+  begin
+    Rec := CurPhaseData.PhaseRecord(ABillsID);
+    if Assigned(Rec) then
+      Result := Rec.ValueByName(AType + 'TotalPrice').AsFloat;
+  end;
+}
+  function GetTotalPrice(ANode: TsdIDTreeNode): Double;
+  var
+    iChild: Integer;
+  begin
+    Result := 0;
+    if not Assigned(ANode) then Exit;
+    if ANode.HasChildren then
+      for iChild := 0 to ANode.ChildCount - 1 do
+        Result := Result + GetTotalPrice(ANode.ChildNodes[iChild])
+    else
+      Result := ANode.Rec.ValueByName('TotalPrice').AsFloat;
+  end;
+
+  function GetPhaseTotalPrice(ANode: TsdIDTreeNode; const AType: string): Double;
+  var
+    iChild: Integer;
+    Rec: TsdDataRecord;
+  begin
+    Result := 0;
+    if not Assigned(ANode) then Exit;
+    if ANode.HasChildren then
+      for iChild := 0 to ANode.ChildCount - 1 do
+        Result := Result + GetPhaseTotalPrice(ANode.ChildNodes[iChild], AType)
+    else
+    begin
+      Rec := StageData.StageRecord(ANode.ID);
+      if Assigned(Rec) then
+        Result := Rec.ValueByName(AType + 'TotalPrice').AsFloat;
+    end;
+  end;
+
+var
+  iNodeID: Integer;
+begin
+  Result := 0;
+  iNodeID := StrToIntDef(Copy(ACardinalNum, 2, Length(ACardinalNum) - 1), -1);
+  case ACardinalNum[1] of
+    'A','a': Result := GetTotalPrice(BillsMeasureTree.FindNode(iNodeID));
+    'B','b': Result := GetPhaseTotalPrice(BillsMeasureTree.FindNode(iNodeID), 'Deal');
+    'C','c': Result := GetPhaseTotalPrice(BillsMeasureTree.FindNode(iNodeID), 'Qc');
+    'D','d': Result := GetPhaseTotalPrice(BillsMeasureTree.FindNode(iNodeID), 'Pc');
+    {'A','a': Result := GetTotalPrice(iNodeID);
+    'B','b': Result := GetPhaseTotalPrice(iNodeID, 'Deal');
+    'C','c': Result := GetPhaseTotalPrice(iNodeID, 'Qc');
+    'D','d': Result := GetPhaseTotalPrice(iNodeID, 'Pc');}
+  end;
+end;
+
+function TBillsMeasureData.GetStageData: TStageData;
+begin
+  Result := TProjectData(FProjectData).PhaseData.StageData;
+end;
+
+procedure TBillsMeasureData.ExpandNodeTo(ALevel: Integer);
+begin
+  BillsMeasureTree.ExpandLevel := ALevel;
+end;
+
+procedure TBillsMeasureData.ExpandXmjNode;
+var
+  iIndex: Integer;
+  stnNode: TsdIDTreeNode;
+begin
+  for iIndex := 0 to BillsMeasureTree.Count - 1 do
+  begin
+    stnNode := BillsMeasureTree.Items[iIndex];
+    if (stnNode.ParentID <> -1) then
+      stnNode.Parent.Expanded := stnNode.Rec.ValueByName('B_Code').AsString = '';
+  end;
+end;
+
+procedure TBillsMeasureData.CalculateAll;
+var
+  Cacl: TBillsCalculate;
+begin
+  Cacl := TBillsCalculate.Create(Self);
+  try
+    Cacl.Execute;
+  finally
+    Cacl.Free;
+  end;
+end;
+
+procedure TBillsMeasureData.UpdateRecordDeal(ABillsID: Integer; AQuantity,
+  ATotalPrice: Double);
+var
+  stnNode: TsdIDTreeNode;
+begin
+  stnNode := BillsMeasureTree.FindNode(ABillsID);
+  if not Assigned(stnNode) then Exit;
+  with stnNode.Rec do
+  begin
+    if not stnNode.HasChildren then
+      ValueByName('AddDealQuantity').AsFloat := QuantityRoundTo(
+        ValueByName('AddDealQuantity').AsFloat + AQuantity);
+    ValueByName('AddDealTotalPrice').AsFloat := TotalPriceRoundTo(
+      ValueByName('AddDealTotalPrice').AsFloat + ATotalPrice);
+  end;
+  UpdateRecordGather(stnNode, AQuantity, ATotalPrice);
+  UpdateRecordDeal(stnNode.ParentID, AQuantity, ATotalPrice);
+end;
+
+procedure TBillsMeasureData.UpdateRecordPc(ABillsID: Integer; AQuantity,
+  ATotalPrice: Double);
+var
+  stnNode: TsdIDTreeNode;
+begin
+  stnNode := BillsMeasureTree.FindNode(ABillsID);
+  if not Assigned(stnNode) then Exit;
+  with stnNode.Rec do
+  begin
+    if not stnNode.HasChildren then
+      ValueByName('AddPcQuantity').AsFloat := QuantityRoundTo(
+        ValueByName('AddPcQuantity').AsFloat + AQuantity);
+    ValueByName('AddPcTotalPrice').AsFloat := TotalPriceRoundTo(
+      ValueByName('AddPcTotalPrice').AsFloat + ATotalPrice);
+  end;
+  UpdateRecordGather(stnNode, 0, ATotalPrice);
+  UpdateRecordPc(stnNode.ParentID, AQuantity, ATotalPrice);
+end;
+
+procedure TBillsMeasureData.UpdateRecordQc(ABillsID: Integer; AQuantity,
+  ATotalPrice: Double);
+var
+  stnNode: TsdIDTreeNode;
+begin
+  stnNode := BillsMeasureTree.FindNode(ABillsID);
+  if not Assigned(stnNode) then Exit;
+  with stnNode.Rec do
+  begin
+    if not stnNode.HasChildren then
+      ValueByName('AddQcQuantity').AsFloat := QuantityRoundTo(
+        ValueByName('AddQcQuantity').AsFloat + AQuantity);
+    ValueByName('AddQcTotalPrice').AsFloat := TotalPriceRoundTo(
+      ValueByName('AddQcTotalPrice').AsFloat + ATotalPrice);
+  end;
+  UpdateRecordGather(stnNode, AQuantity, ATotalPrice);
+  UpdateRecordQc(stnNode.ParentID, AQuantity, ATotalPrice);
+end;
+
+procedure TBillsMeasureData.UpdateRecordGather(ANode: TsdIDTreeNode;
+  AQuantity, ATotalPrice: Double);
+begin
+  with ANode.Rec do
+  begin
+    if not ANode.HasChildren then
+      ValueByName('AddGatherQuantity').AsFloat := QuantityRoundTo(
+        ValueByName('AddGatherQuantity').AsFloat + AQuantity);
+    ValueByName('AddGatherTotalPrice').AsFloat := TotalPriceRoundTo(
+      ValueByName('AddGatherTotalPrice').AsFloat + ATotalPrice);
+  end;
+  CalcAddDgnPrice(ANode);
+  CalcAddCompleteRate(ANode);
+end;
+
+function TBillsMeasureData.GatherRelaBGL(ANode: TsdIDTreeNode): string;
+var
+  iChild: Integer;
+  Rec: TsdDataRecord;
+begin
+  Result := '';
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+  begin
+    for iChild := 0 to ANode.ChildCount - 1 do
+      Result := MergeRelaBGL(Result, GatherRelaBGL(ANode.ChildNodes[iChild]));
+  end
+  else
+  begin
+    with TProjectData(FProjectData).PhaseData.StageData do
+      Rec := StageRecord(ANode.ID);
+    if Assigned(Rec) then
+      Result := MergeRelaBGL(Rec.ValueByName('QcBGLCode').AsString, Rec.ValueByName('PcBGLCode').AsString);
+  end;
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureAfterValueChanged(
+  AValue: TsdValue);
+var
+  stnNode: TsdIDTreeNode;
+begin
+  if TProjectData(FProjectData).PhaseData.Active then
+  begin
+    if AValue.FieldName = 'Price' then
+      StageData.ReCalculate(AValue.Owner.ValueByName('ID').AsInteger);
+    if AValue.FieldName = 'NewPrice' then
+      StageData.ReCalculate(AValue.Owner.ValueByName('ID').AsInteger);
+  end;
+  if Pos('DgnQuantity1', AValue.FieldName) > 0 then
+  begin
+    stnNode := BillsMeasureTree.FindNode(AValue.Owner.ValueByName('ID').AsInteger);
+    CalcAddDgnPrice(stnNode);
+  end;
+end;
+
+procedure TBillsMeasureData.ExpandCurPhase;
+var
+  iIndex: Integer;
+  stnNode: TsdIDTreeNode;
+  StageRec: TsdDataRecord;
+begin
+  for iIndex := 0 to BillsMeasureTree.Count - 1 do
+  begin
+    stnNode := BillsMeasureTree.Items[iIndex];
+    StageRec := TBillsIDTreeNode(stnNode).StageRec;
+    if (stnNode.ParentID <> -1) then
+      if Assigned(StageRec) then
+        stnNode.Expanded := StageRec.ValueByName('GatherTotalPrice').AsFloat <> 0
+      else
+        stnNode.Expanded := False;
+  end;
+end;
+
+procedure TBillsMeasureData.UpdateBGLInfo(ABillsID: Integer;
+  ARec: TsdDataRecord; const AType: string);
+var
+  stnNode: TsdIDTreeNode;
+begin
+  stnNode := BillsMeasureTree.FindNode(ABillsID);
+  if not Assigned(stnNode) then Exit;
+  stnNode.Rec.ValueByName('Add' + AType + 'BGLCode').AsString :=
+      ARec.ValueByName('End' + AType + 'BGLCode').AsString;
+  stnNode.Rec.ValueByName('Add' + AType + 'BGLNum').AsString :=
+      ARec.ValueByName('End' + AType + 'BGLNum').AsString;
+end;
+
+function TBillsMeasureData.SelectAndUpdateBGL(ABillsID: Integer;
+  ARec: TsdDataRecord; ANewValue: Double; const AType: string): Boolean;
+var
+  AOrgBGL, ANewBGL: TBGLSelectInfo;
+  ACurNode: TsdIDTreeNode;
+
+  procedure UpdateBGL;
+  begin
+    ARec.ValueByName(AType + 'BGLCode').AsString := ANewBGL.MergedCode;
+    ARec.ValueByName(AType + 'BGLNum').AsString := ANewBGL.MergedNum;
+    TProjectData(ProjectData).BGLData.ApplyBGL(AOrgBGL, ANewBGL);
+  end;
+
+begin
+  Result := True;
+  ACurNode := BillsMeasureTree.FindNode(ABillsID);
+
+  AOrgBGL := TBGLSelectInfo.Create(ACurNode.Rec,
+      ARec.ValueByName(AType + 'Quantity').AsFloat, True);
+  AOrgBGL.MergedCode := ARec.ValueByName(AType + 'BGLCode').AsString;
+  AOrgBGL.MergedNum := ARec.ValueByName(AType + 'BGLNum').AsString;
+
+  ANewBGL := TBGLSelectInfo.Create(ACurNode.Rec, ANewValue, False);
+  try
+    if ANewBGL.TotalNum <> 0 then
+    begin
+      Result := SelectBGL(AOrgBGL, ANewBGL, ProjectData);
+      if Result then
+        UpdateBGL;
+    end
+    else
+      UpdateBGL;
+    StageData.UpdateBGLInfo(ARec, AType);
+    UpdateBGLInfo(ABillsID, ARec, AType);
+  finally
+    AOrgBGL.Free;
+    ANewBGL.Free;
+  end;
+end;
+
+procedure TBillsMeasureData.Close;
+begin
+  sdvBillsMeasure.Close;
+end;
+
+procedure TBillsMeasureData.CalcAddCompleteRate(ANode: TsdIDTreeNode);
+var
+  fDividend, fDivisor: Double;
+begin
+  with ANode.Rec do
+  begin
+    fDividend := ValueByName('AddGatherTotalPrice').AsFloat;
+    fDivisor := ValueByName('TotalPrice').AsFloat + ValueByName('AddQcTotalPrice').AsFloat
+        + ValueByName('AddPcTotalPrice').AsFloat;
+    if fDivisor <> 0 then
+      ValueByName('AddCompleteRate').AsFloat := AdvRoundTo(fDividend/fDivisor*100);
+  end;
+end;
+
+procedure TBillsMeasureData.CalcAddDgnPrice(ANode: TsdIDTreeNode);
+var
+  fDividend, fDivisor: Double;
+begin
+  with ANode.Rec do
+  begin
+    fDividend := ValueByName('AddGatherTotalPrice').AsFloat;
+    fDivisor := ValueByName('DealDgnQuantity1').AsFloat + ValueByName('CDgnQuantity1').AsFloat;
+    if fDivisor <> 0 then
+      ValueByName('AddDgnPrice').AsFloat := AdvRoundTo(fDividend/fDivisor);
+  end;
+end;
+
+procedure TBillsMeasureData.SetOnRecChange(const Value: TRecChangeEvent);
+begin
+  FOnRecChange := Value;
+end;
+
+procedure TBillsMeasureData.sdvBillsMeasureCurrentChanged(
+  ARecord: TsdDataRecord);
+begin
+  if Assigned(FOnRecChange) then
+    FOnRecChange(ARecord);
+end;
+
+procedure TBillsMeasureData.ResetTreeNodeStageRec;
+var
+  i: Integer;
+  vNode: TBillsIDTreeNode;
+begin
+  for i := 0 to BillsMeasureTree.Count - 1 do
+  begin
+    vNode := TBillsIDTreeNode(BillsMeasureTree.Items[i]);
+    vNode.StageRec := StageData.StageRecord(vNode.ID);
+  end;
+end;
+
+end.

+ 65 - 0
DataModules/DealBillsDm.dfm

@@ -0,0 +1,65 @@
+object DealBillsData: TDealBillsData
+  OldCreateOrder = False
+  Left = 589
+  Top = 368
+  Height = 256
+  Width = 215
+  object sdpDealBills: TsdADOProvider
+    TableName = 'DealBills'
+    Left = 72
+    Top = 24
+  end
+  object sddDealBills: TsdDataSet
+    Active = False
+    Provider = sdpDealBills
+    BeforeAddRecord = sddDealBillsBeforeAddRecord
+    Left = 72
+    Top = 88
+    FieldListData = {
+      0101044E616D6506024944094669656C644E616D650602494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D650606425F436F6465094669656C644E616D65
+      0606425F436F64650844617461547970650201084461746153697A6503FF0005
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650604
+      4E616D65094669656C644E616D6506044E616D65084461746154797065021808
+      4461746153697A6503FF000549734B6579080F4E65656450726F636573734E61
+      6D65090001044E616D650605556E697473094669656C644E616D650605556E69
+      74730844617461547970650218084461746153697A6503FF000549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D650605507269636509
+      4669656C644E616D650605507269636508446174615479706502060844617461
+      53697A6502080549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D6506085175616E74697479094669656C644E616D6506085175616E74
+      6974790844617461547970650206084461746153697A6502080549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D65060A546F74616C50
+      72696365094669656C644E616D65060A546F74616C5072696365084461746154
+      7970650206084461746153697A6502080549734B6579080F4E65656450726F63
+      6573734E616D65090000}
+  end
+  object sdvDealBills: TsdDataView
+    Active = False
+    DataSet = sddDealBills
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'B_Code'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Units'
+      end
+      item
+        FieldName = 'Price'
+      end
+      item
+        FieldName = 'Quantity'
+      end
+      item
+        FieldName = 'TotalPrice'
+      end>
+    OnSetText = sdvDealBillsSetText
+    Left = 72
+    Top = 152
+  end
+end

+ 126 - 0
DataModules/DealBillsDm.pas

@@ -0,0 +1,126 @@
+unit DealBillsDm;
+
+interface
+
+uses
+  SysUtils, Classes, sdDB, sdProvider, ADODB;
+
+type
+  TDealBillsData = class(TDataModule)
+    sdpDealBills: TsdADOProvider;
+    sddDealBills: TsdDataSet;
+    sdvDealBills: TsdDataView;
+    procedure sddDealBillsBeforeAddRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+    procedure sdvDealBillsSetText(var Text: String; ARecord: TsdDataRecord;
+      AValue: TsdValue; AColumn: TsdViewColumn; var Allow: Boolean);
+  private
+    FProjectData: TObject;
+
+    function GetNewID: Integer;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Close;
+    procedure Save;
+    procedure Clear;
+
+    procedure DisableEvent;
+    procedure EnableEvent;
+
+    function DealRecord(const AB_Code: string): TsdDataRecord;
+
+    property ProjectData: TObject read FProjectData;
+  end;
+
+implementation
+
+uses
+  UtilMethods;
+
+{$R *.dfm}
+
+{ TDealBillsData }
+
+procedure TDealBillsData.Clear;
+begin
+  sddDealBills.DeleteAll;
+end;
+
+procedure TDealBillsData.Close;
+begin
+  sddDealBills.Close;
+end;
+
+constructor TDealBillsData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+end;
+
+function TDealBillsData.DealRecord(const AB_Code: string): TsdDataRecord;
+begin
+  Result := sddDealBills.Locate('B_Code', AB_Code);
+end;
+
+destructor TDealBillsData.Destroy;
+begin
+  inherited;
+end;
+
+procedure TDealBillsData.DisableEvent;
+begin
+  sddDealBills.BeforeAddRecord := nil;
+end;
+
+procedure TDealBillsData.EnableEvent;
+begin
+  sddDealBills.BeforeAddRecord := sddDealBillsBeforeAddRecord;
+end;
+
+function TDealBillsData.GetNewID: Integer;
+var
+  idx: TsdIndex;
+begin
+  Result := 1;
+  if sddDealBills.RecordCount = 0 then Exit;
+  idx := sddDealBills.FindIndex('idxID');
+  Result := idx.Records[sddDealBills.RecordCount - 1].ValueByName('ID').AsInteger + 1;
+end;
+
+procedure TDealBillsData.Open(AConnection: TADOConnection);
+begin
+  sdpDealBills.Connection := AConnection;
+  sddDealBills.Open;
+  if not Assigned(sddDealBills.IndexList.FindByName('idxID')) then
+    sddDealBills.AddIndex('idxID', 'ID');
+  sdvDealBills.Open;
+  sdvDealBills.IndexName := 'idxID';
+end;
+
+procedure TDealBillsData.Save;
+begin
+  sddDealBills.Save;
+end;
+
+procedure TDealBillsData.sddDealBillsBeforeAddRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+begin
+  ARecord.ValueByName('ID').AsInteger := GetNewID;
+end;
+
+procedure TDealBillsData.sdvDealBillsSetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  var Allow: Boolean);
+begin
+  if SameText(AColumn.FieldName, 'Price') then
+    Text := FloatToStr(PriceRoundTo(StrToFloatDef(Text, 0)))
+  else if SameText(AColumn.FieldName, 'Quantity') then
+    Text := FloatToStr(QuantityRoundTo(StrToFloatDef(Text, 0)))
+  else if SameText(AColumn.FieldName, 'TotalPrice') then
+    Text := FloatToStr(TotalPriceRoundTo(StrToFloatDef(Text, 0)));
+end;
+
+end.

+ 105 - 0
DataModules/DealPaymentDm.dfm

@@ -0,0 +1,105 @@
+object DealPaymentData: TDealPaymentData
+  OldCreateOrder = False
+  Left = 690
+  Top = 663
+  Height = 226
+  Width = 153
+  object sdpDealPayment: TsdADOProvider
+    TableName = 'DealPayment'
+    Left = 48
+    Top = 16
+  end
+  object sddDealPayment: TsdDataSet
+    Active = False
+    Provider = sdpDealPayment
+    BeforeAddRecord = sddDealPaymentBeforeAddRecord
+    AfterAddRecord = sddDealPaymentAfterAddRecord
+    BeforeDeleteRecord = sddDealPaymentBeforeDeleteRecord
+    AfterValueChanged = sddDealPaymentAfterValueChanged
+    Left = 48
+    Top = 72
+    FieldListData = {
+      0101044E616D6506024944094669656C644E616D650602494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D6506044E616D65094669656C644E616D650604
+      4E616D650844617461547970650218084461746153697A6503FF000549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060843616C63
+      54797065094669656C644E616D65060843616C63547970650844617461547970
+      650203084461746153697A6502040549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D65060749734D696E7573094669656C644E616D65
+      060749734D696E75730844617461547970650205084461746153697A65020105
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D65060A
+      546F74616C5072696365094669656C644E616D65060A546F74616C5072696365
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D65060C537461727465645072
+      696365094669656C644E616D65060C5374617274656450726963650844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D65060853466F726D756C61094669656C64
+      4E616D65060853466F726D756C61084461746154797065021808446174615369
+      7A6503FF000549734B6579080F4E65656450726F636573734E616D6509000104
+      4E616D65060A52616E67655072696365094669656C644E616D65060A52616E67
+      6550726963650844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060852466F
+      726D756C61094669656C644E616D65060852466F726D756C6108446174615479
+      70650218084461746153697A6503FF000549734B6579080F4E65656450726F63
+      6573734E616D65090001044E616D65060D437265617465506861736549440946
+      69656C644E616D65060D43726561746550686173654944084461746154797065
+      0203084461746153697A6502040549734B6579080F4E65656450726F63657373
+      4E616D65090001044E616D650607466F726D756C61094669656C644E616D6506
+      07466F726D756C610844617461547970650218084461746153697A6503FF0005
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650606
+      4C6F636B6564094669656C644E616D6506064C6F636B65640844617461547970
+      650205084461746153697A6502010549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D65060853657269616C4E6F094669656C644E616D
+      65060853657269616C4E6F0844617461547970650203084461746153697A6502
+      040549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060A507265446566696E6564094669656C644E616D65060A507265446566696E
+      65640844617461547970650205084461746153697A6502010549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D65060D4C6F636B656446
+      6F726D756C61094669656C644E616D65060D4C6F636B6564466F726D756C6108
+      44617461547970650205084461746153697A6502010549734B6579080F4E6565
+      6450726F636573734E616D65090000}
+  end
+  object sdvDealPayment: TsdDataView
+    Active = False
+    DataSet = sddDealPayment
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'SerialNo'
+      end
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'IsMinus'
+      end
+      item
+        FieldName = 'CurTotalPrice'
+        KeyFields = 'ID'
+        LookupDataSet = sddDealPayment
+        LookupKeyFields = 'ID'
+        LookupResultField = 'TotalPrice'
+      end
+      item
+        FieldName = 'TotalPrice'
+      end
+      item
+        FieldName = 'Locked'
+      end
+      item
+        FieldName = 'StartedPrice'
+      end
+      item
+        FieldName = 'RangePrice'
+      end>
+    OnGetText = sdvDealPaymentGetText
+    OnSetText = sdvDealPaymentSetText
+    OnNeedLookupRecord = sdvDealPaymentNeedLookupRecord
+    Left = 48
+    Top = 128
+  end
+end

+ 640 - 0
DataModules/DealPaymentDm.pas

@@ -0,0 +1,640 @@
+unit DealPaymentDm;
+
+interface
+
+uses
+  SysUtils, Classes, sdDB, sdProvider, ADODB, FormulaCalc, UtilMethods;
+
+type
+  TDealPaymentData = class(TDataModule)
+    sdpDealPayment: TsdADOProvider;
+    sddDealPayment: TsdDataSet;
+    sdvDealPayment: TsdDataView;
+    procedure sddDealPaymentAfterAddRecord(ARecord: TsdDataRecord);
+    procedure sdvDealPaymentGetText(var Text: String;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      DisplayText: Boolean);
+    procedure sdvDealPaymentNeedLookupRecord(ARecord: TsdDataRecord;
+      AColumn: TsdViewColumn; ANewText: String);
+    procedure sdvDealPaymentSetText(var Text: string;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      var Allow: Boolean);
+    procedure sddDealPaymentBeforeAddRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+    procedure sddDealPaymentAfterValueChanged(AValue: TsdValue);
+    procedure sddDealPaymentBeforeDeleteRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+  private
+    FProjectData: TObject;
+    FPayFormula: TPayFormula;
+
+    procedure InitPredefinedPayItems;
+    procedure RepairSerialNo;
+    procedure RepairLockedFormula;
+
+    function GetNewID: Integer;
+    function GetNewSerialNo: Integer;
+
+    function GetAddTotalPrice: Double;
+    function GetCutTotalPrice: Double;
+    function GetPaidTotalPrice: Double;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Close;
+    procedure Save;
+    procedure Init;
+
+    // 扣款项是否已达起扣金额
+    function CheckStartedPrice(AID: Integer): Boolean;
+    function GetAllowTotalPrice(AID: Integer; ATotalPrice: Double): Double;
+    procedure UpdateTotalPrice(AID: Integer; ATotalPrice: Double);
+
+    function GetStartedPrice(AID: Integer): Double;
+
+    procedure CalcStarted_RangePrice;
+
+    procedure ResetPhaseLink;
+    procedure LockedData;
+
+    property ProjectData: TObject read FProjectData;
+
+    // 扣款项,累计金额合计
+    property CutTotalPrice: Double read GetCutTotalPrice;
+    // 非扣款项,累计金额合计
+    property AddTotalPrice: Double read GetAddTotalPrice;
+    // 实付
+    property PaidTotalPrice: Double read GetPaidTotalPrice;
+  end;
+
+implementation
+
+uses
+  ProjectData, PhasePayDm, PhaseData, ZhAPI, BillsDm, Math;
+
+{$R *.dfm}
+
+{ TDealPaymentData }
+
+function TDealPaymentData.CheckStartedPrice(AID: Integer): Boolean;
+var
+  Rec: TsdDataRecord;
+begin
+  Rec := sddDealPayment.FindKey('idxID', AID);
+  with TProjectData(FProjectData).BillsData do
+    Result := Settlement[AddGatherIndex] >= Rec.ValueByName('StartedPrice').AsFloat;
+end;
+
+constructor TDealPaymentData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+  FPayFormula := TPayFormula.Create(FProjectData);
+end;
+
+destructor TDealPaymentData.Destroy;
+begin
+  FPayFormula.Free;
+  inherited;
+end;
+
+function TDealPaymentData.GetAllowTotalPrice(AID: Integer;
+  ATotalPrice: Double): Double;
+var
+  Rec: TsdDataRecord;
+  fAllowPrice: Double;
+begin
+  Result := ATotalPrice;
+  Rec := sddDealPayment.FindKey('idxID', AID);
+  if Rec.ValueByName('RangePrice').AsFloat = 0 then Exit;
+  fAllowPrice := Rec.ValueByName('RangePrice').AsFloat - Rec.ValueByName('TotalPrice').AsFloat;
+  Result := Min(fAllowPrice, ATotalPrice);
+end;
+
+function TDealPaymentData.GetNewID: Integer;
+var
+  idx: TsdIndex;
+begin
+  idx := sddDealPayment.FindIndex('idxID');
+  if idx.RecordCount > 0 then
+    Result := idx.Records[idx.RecordCount - 1].ValueByName('ID').AsInteger + 1
+  else
+    Result := 1;
+end;
+
+procedure TDealPaymentData.Init;
+begin
+  if sddDealPayment.RecordCount > 0 then Exit;
+  InitPredefinedPayItems;
+end;
+
+procedure TDealPaymentData.InitPredefinedPayItems;
+
+  procedure AddPredefinedPayItem(const AItem: string);
+  var
+    sgsItem: TStrings;
+    f: Double;
+    Rec: TsdDataRecord;
+  begin
+    sgsItem := TStringList.Create;
+    try
+      sgsItem.Delimiter := ';';
+      sgsItem.DelimitedText := AItem;
+      if sgsItem.Count < 7 then Exit;
+
+      Rec := sddDealPayment.Add;
+      Rec.ValueByName('Name').AsString := sgsItem[0];
+      Rec.ValueByName('CalcType').AsInteger := StrToIntDef(sgsItem[1], 0);
+      Rec.ValueByName('IsMinus').AsBoolean := sgsItem[2] = '1';
+      if TryStrToFloat(sgsItem[3], f) then
+        Rec.ValueByName('StartedPrice').AsFloat := f
+      else
+        Rec.ValueByName('SFormula').AsString := sgsItem[3];
+      if TryStrToFloat(sgsItem[4], f) then
+        Rec.ValueByName('RangePrice').AsFloat := f
+      else
+        Rec.ValueByName('RFormula').AsString := sgsItem[4];
+      Rec.ValueByName('Formula').AsString := sgsItem[5];
+      if SameText(sgsItem[5], 'bqwc') then
+        Rec.ValueByName('LockedFormula').AsBoolean := True;
+      Rec.ValueByName('PreDefined').AsBoolean := StrToBoolDef(sgsItem[6], False);
+    finally
+      sgsItem.Free;
+    end;
+  end;
+
+var
+  sgsItems: TStrings;
+  I: Integer;
+begin
+  sgsItems := TStringList.Create;
+  try
+    sgsItems.LoadFromFile(GetAppFilePath + 'DealPayment.txt');
+    for I := 0 to sgsItems.Count - 1 do
+      if sgsItems[I] <> '' then
+        AddPredefinedPayItem(sgsItems[I]);
+  finally
+    sgsItems.Free;
+  end;
+end;
+
+procedure TDealPaymentData.LockedData;
+var
+  iIndex: Integer;
+  Rec: TsdDataRecord;
+begin
+  for iIndex := 0 to sddDealPayment.RecordCount - 1 do
+  begin
+    Rec := sddDealPayment.Records[iIndex];
+    Rec.ValueByName('Locked').AsBoolean := True;
+    if Rec.ValueByName('Formula').AsString <> '' then
+      Rec.ValueByName('LockedFormula').AsBoolean := True;
+  end;
+end;
+
+procedure TDealPaymentData.Open(AConnection: TADOConnection);
+begin
+  sdpDealPayment.Connection := AConnection;
+  sddDealPayment.Open;
+  RepairSerialNo;
+  RepairLockedFormula;
+  if not Assigned(sddDealPayment.IndexList.FindByName('idxID')) then
+    sddDealPayment.AddIndex('idxID', 'ID');
+  if not Assigned(sddDealPayment.IndexList.FindByName('idxView')) then
+    sddDealPayment.AddIndex('idxView', 'SerialNo');
+  // 开始计量前,CutTotalPrice链接至TotalPrice,已解决无计量数据时无法输入问题
+  sddDealPayment.FieldByName('TotalPrice').ValidChars := sddDealPayment.FieldByName('TotalPrice').ValidChars + ArithmeticCharSet + ExprsBaseCharSet;
+  sddDealPayment.FieldByName('StartedPrice').ValidChars := sddDealPayment.FieldByName('StartedPrice').ValidChars + ArithmeticCharSet + ExprsExceptCharSet;
+  sddDealPayment.FieldByName('RangePrice').ValidChars := sddDealPayment.FieldByName('RangePrice').ValidChars + ArithmeticCharSet + ExprsExceptCharSet;
+  sdvDealPayment.Open;
+  sdvDealPayment.IndexName := 'idxView';
+end;
+
+procedure TDealPaymentData.ResetPhaseLink;
+begin
+  with TProjectData(FProjectData).PhaseData do
+  begin
+    sdvDealPayment.Columns.FindColumn('CurTotalPrice').LookupDataSet := PhasePayData.sddPhasePay;
+    sdvDealPayment.Columns.FindColumn('CurTotalPrice').LookupResultField := 'TotalPrice' + IntToStr(StageIndex);
+  end;
+end;
+
+procedure TDealPaymentData.Save;
+begin
+  sddDealPayment.Save;
+end;
+
+procedure TDealPaymentData.sddDealPaymentAfterAddRecord(
+  ARecord: TsdDataRecord);
+var
+  iSerialNo: Integer;
+begin
+  iSerialNo := GetNewSerialNo;
+  ARecord.ValueByName('ID').AsInteger := GetNewID;
+  ARecord.ValueByName('SerialNo').AsInteger := iSerialNo;
+  ARecord.ValueByName('CreatePhaseID').AsInteger := TProjectData(FProjectData).PhaseIndex;
+end;
+
+procedure TDealPaymentData.sdvDealPaymentGetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  DisplayText: Boolean);
+
+  procedure GetDisplayText;
+  begin
+    if not Assigned(AValue) or
+        ((Pos('Price', AValue.FieldName) > 0) and (AValue.AsFloat = 0)) then
+      Text := '';
+  end;
+
+  function GetFormulaField(const APriceField: string): string;
+  begin
+    if SameText(APriceField, 'StartedPrice') then
+      Result := 'SFormula'
+    else if SameText(APriceField, 'RangePrice') then
+      Result := 'RFormula'
+    else if SameText(APriceField, 'CurTotalPrice') then
+      Result := 'Formula'
+    else if Pos('TotalPrice', APriceField) = 1 then
+      Result := StringReplace(AValue.FieldName, 'TotalPrice', 'Formula', []);
+  end;
+
+  procedure GetStageEditText;
+  var
+    sField, sFormula: string;
+  begin
+    if Assigned(AValue) then
+    begin
+      Text := AValue.AsString;
+      sField := GetFormulaField(AValue.FieldName);
+      sFormula := AValue.Owner.ValueByName(sField).AsString;
+      if (sField <> '') and (sFormula <> '') then
+        Text:= sFormula;
+    end
+    else
+      Text := '';
+  end;
+
+  procedure GetMainEditText;
+  var
+    sField, sFormula: string;
+  begin
+    sField := GetFormulaField(AColumn.FieldName);
+    if (sField <> '') then
+    begin
+      sFormula := ARecord.ValueByName(sField).AsString;
+      if (sFormula <> '') then
+        Text := sFormula;
+    end
+    else
+      Text := '';
+  end;
+
+begin
+  if Pos('Price', AColumn.FieldName)> 0 then
+  begin
+    if DisplayText then
+      GetDisplayText
+    else if TProjectData(FProjectData).PhaseIndex > 0 then
+      GetStageEditText
+    else
+      GetMainEditText;
+  end;
+end;
+
+procedure TDealPaymentData.sdvDealPaymentNeedLookupRecord(
+  ARecord: TsdDataRecord; AColumn: TsdViewColumn; ANewText: String);
+
+  procedure SetNewRecData(APayRec: TsdDataRecord);
+  var
+    AID: Integer;
+    sTPField, sFField: string;
+    fTotalPrice: Double;
+  begin
+    sTPField := 'TotalPrice' + IntToStr(TProjectData(FProjectData).PhaseData.StageIndex);
+    sFField := 'Formula' + IntToStr(TProjectData(FProjectData).PhaseData.StageIndex);
+    if CheckNumeric(ANewText) then
+      APayRec.ValueByName(sTPField).AsString := ANewText
+    else
+    begin
+      AID := ARecord.ValueByName('ID').AsInteger;
+      APayRec.ValueByName(sFField).AsString := ANewText;
+      ARecord.ValueByName('Formula').AsString := ANewText;
+      fTotalPrice := FPayFormula.Calculate(ANewText);
+      if CheckStartedPrice(AID) then
+        APayRec.ValueByName(sTPField).AsFloat := GetAllowTotalPrice(AID, fTotalPrice);
+    end;
+  end;
+
+var
+  NewRec: TsdDataRecord;
+begin
+  if SameText(AColumn.FieldName, 'CurTotalPrice') then
+  begin
+    with TProjectData(FProjectData).PhaseData.PhasePayData do
+      NewRec := AddPayRecord(ARecord.ValueByName('ID').AsInteger);
+    SetNewRecData(NewRec);
+  end;
+end;
+
+procedure TDealPaymentData.sdvDealPaymentSetText(var Text: string;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  var Allow: Boolean);
+
+  procedure CheckLockedData;
+  var
+    Rec: TsdDataRecord;
+    sFormula: string;
+  begin
+    Rec := sddDealPayment.FindKey('idxID', ARecord.ValueByName('ID').AsInteger);
+    if Rec.ValueByName('CalcType').AsInteger = 1 then
+    begin
+      if SameText(AValue.FieldName, 'Name') or
+          SameText(AValue.FieldName, 'IsMinus') or
+          (Pos('TotalPrice', AValue.FieldName) > 0) or
+          SameText(AValue.FieldName, 'StartedPrice') or
+          SameText(AValue.FieldName, 'RangePrice') then
+        DataSetErrorMessage(Allow, '固定项不可修改!');
+    end;
+    if not Allow then Exit;
+
+    if Rec.ValueByName('LockedFormula').AsBoolean then
+    begin
+      if (Pos('TotalPrice', AValue.FieldName) = 1) and
+         (Rec.ValueByName('Formula').AsString <> '') then
+      begin
+        // 如果有公式计算,如果是纯数学计算式,则可设置,基数计算,则不可
+        sFormula := Rec.ValueByName('Formula').AsString;
+        if (Pos('bqwc', sFormula)>0) or (Pos('htj', sFormula)>0) or
+           (Pos('kgyfk', sFormula)>0) or (Pos('clyfk', sFormula)>0) then
+          DataSetErrorMessage(Allow, '该支付(扣款)项已设置基数计算公式且被锁定,不可修改!');
+      end;
+    end;
+    if not Allow then Exit;
+
+    if Rec.ValueByName('Locked').AsBoolean then
+    begin
+      if SameText(AValue.FieldName, 'StartedPrice') then
+        DataSetErrorMessage(Allow, '该支付(扣款)项的起扣金额被锁定,不可修改!')
+      else if SameText(AValue.FieldName, 'RangePrice') then
+        DataSetErrorMessage(Allow, '该支付(扣款)项的付(扣)款限额被锁定,不可修改!')
+      else if SameText(AValue.FieldName, 'Name') or SameText(AValue.FieldName, 'IsMinus') then
+        DataSetErrorMessage(Allow, '该项已被锁定,不可修改!');
+    end;
+  end;
+
+  procedure DoStartedPriceChanged;
+  begin
+    if AValue.Owner.ValueByName('TotalPrice').AsFloat <> 0 then
+      DataSetErrorMessage(Allow, '该付(扣)款金额已经计量,不可修改起扣金额!');
+    if not Allow then Exit;
+
+    if CheckStringNull(Text) or CheckNumeric(Text) then
+      AValue.Owner.ValueByName('SFormula').AsString := ''
+    else if Pos('bqwc', Text) = 0 then
+    begin
+      AValue.Owner.ValueByName('SFormula').AsString := Text;
+      Text := FloatToStr(FPayFormula.Calculate(Text));
+    end
+    else
+      DataSetErrorMessage(Allow, '起扣金额不可引用“本期计算价”进行计算!');
+  end;
+
+  procedure DoRangePriceChanged;
+  begin
+    if AValue.Owner.ValueByName('TotalPrice').AsFloat <> 0 then
+      DataSetErrorMessage(Allow, '该付(扣)款金额已经计量,不可修改付(扣)款限额!');
+    if not Allow then Exit;
+
+    if CheckStringNull(Text) or CheckNumeric(Text) then
+      AValue.Owner.ValueByName('RFormula').AsString := ''
+    else if Pos('bqwc', Text) = 0 then
+    begin
+      AValue.Owner.ValueByName('RFormula').AsString := Text;
+      Text := FloatToStr(FPayFormula.Calculate(Text));
+    end
+    else
+      DataSetErrorMessage(Allow, '付(扣)款限额不可引用“本期计算价”进行计算!');
+  end;
+
+  procedure DoCurTotalPriceChanged;
+  var
+    AID: Integer;
+    sFField: string;
+    fTotalPrice: Double;
+    Rec: TsdDataRecord;
+  begin
+    Rec := sddDealPayment.FindKey('idxID', ARecord.ValueByName('ID').AsInteger);
+    sFField := StringReplace(AValue.FieldName, 'TotalPrice', 'Formula', []);
+    if CheckStringNull(Text) or CheckNumeric(Text) then
+    begin
+      Rec.ValueByName('Formula').AsString := '';
+      AValue.Owner.ValueByName(sFField).AsString := '';
+    end
+    else
+    begin
+      Rec.ValueByName('Formula').AsString := Text;
+      AValue.Owner.ValueByName(sFField).AsString := Text;
+      AID := ARecord.ValueByName('ID').AsInteger;
+      fTotalPrice := FPayFormula.Calculate(Text) - AValue.AsFloat;
+      if CheckStartedPrice(AID) then
+        Text := FloatToStr(AValue.AsFloat + GetAllowTotalPrice(AID, fTotalPrice))
+      else
+        Text := '';
+    end;
+  end;
+
+  procedure DoLedgerFormulaChanged;
+  begin
+    if CheckStringNull(Text) or CheckNumeric(Text) then
+      ARecord.ValueByName('Formula').AsString := ''
+    else
+      ARecord.ValueByName('Formula').AsString := Text;
+    Text := '';
+  end;
+
+begin
+  if not Assigned(AValue) then Exit;
+  CheckLockedData;
+  if not Allow then Exit;
+  if SameText('StartedPrice', AValue.FieldName) then
+    DoStartedPriceChanged;
+  if SameText('RangePrice', AValue.FieldName) then
+    DoRangePriceChanged;
+  if Pos('TotalPrice', AValue.FieldName) = 1 then
+    if TProjectData(FProjectData).ProjProperties.PhaseCount > 0 then
+      DoCurTotalPriceChanged
+    else
+      DoLedgerFormulaChanged;
+end;
+
+procedure TDealPaymentData.UpdateTotalPrice(AID: Integer;
+  ATotalPrice: Double);
+var
+  Rec: TsdDataRecord;
+begin
+  Rec := sddDealPayment.FindKey('idxID', AID);
+  Rec.ValueByName('TotalPrice').AsFloat := Rec.ValueByName('TotalPrice').AsFloat + ATotalPrice;
+end;
+
+procedure TDealPaymentData.sddDealPaymentBeforeAddRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+begin
+{  if ARecord.ValueByName('Name').AsString = '' then
+    Allow := False;}
+end;
+
+procedure TDealPaymentData.CalcStarted_RangePrice;
+var
+  I: Integer;
+  Rec: TsdDataRecord;
+begin
+  if TProjectData(FProjectData).ProjProperties.PhaseCount > 0 then Exit;
+  for I := 0 to sddDealPayment.RecordCount - 1 do
+  begin
+    Rec := sddDealPayment.Records[I];
+    if Rec.ValueByName('CalcType').AsInteger <> 0 then Continue;
+    Rec.ValueByName('StartedPrice').AsFloat := FPayFormula.Calculate(Rec.ValueByName('SFormula').AsString);
+    Rec.ValueByName('RangePrice').AsFloat := FPayFormula.Calculate(Rec.ValueByName('RFormula').AsString);
+  end;
+end;
+
+procedure TDealPaymentData.sddDealPaymentAfterValueChanged(
+  AValue: TsdValue);
+begin
+  if SameText('IsMinus', AValue.FieldName) then
+    TProjectData(FProjectData).PhaseData.PhasePayData.CalculateCurPay;
+end;
+
+function TDealPaymentData.GetAddTotalPrice: Double;
+var
+  iIndex: Integer;
+  Rec: TsdDataRecord;
+begin
+  Result := 0;
+  for iIndex := 0 to sddDealPayment.RecordCount - 1 do
+  begin
+    Rec := sddDealPayment.Records[iIndex];
+    if (Rec.ValueByName('CalcType').AsInteger = 0) and not Rec.ValueByName('IsMinus').AsBoolean then
+      Result := Result + Rec.ValueByName('TotalPrice').AsFloat;
+  end;
+end;
+
+function TDealPaymentData.GetCutTotalPrice: Double;
+var
+  iIndex: Integer;
+  Rec: TsdDataRecord;
+begin
+  Result := 0;
+  for iIndex := 0 to sddDealPayment.RecordCount - 1 do
+  begin
+    Rec := sddDealPayment.Records[iIndex];
+    if (Rec.ValueByName('CalcType').AsInteger = 0) and Rec.ValueByName('IsMinus').AsBoolean then
+      Result := Result + Rec.ValueByName('TotalPrice').AsFloat;
+  end;
+end;
+
+function TDealPaymentData.GetPaidTotalPrice: Double;
+var
+  Rec: TsdDataRecord;
+begin
+  Rec := sddDealPayment.Locate('CalcType', 2);
+  if Assigned(Rec) then
+    Result := Rec.ValueByName('TotalPrice').AsFloat
+  else
+    Result := 0;
+end;
+
+procedure TDealPaymentData.sddDealPaymentBeforeDeleteRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+begin
+  if ARecord.ValueByName('Locked').AsBoolean then
+    DataSetErrorMessage(Allow, '该支付(扣款)项已锁定,不可删除!')
+  else if ARecord.ValueByName('PreDefined').AsBoolean then
+    DataSetErrorMessage(Allow, '此项为预定义项,不允许删除!')
+  else if ARecord.ValueByName('TotalPrice').AsFloat <> 0 then
+    DataSetErrorMessage(Allow, '该支付(扣款)项存在数据,如需删除请先清除本期金额!');
+    
+  if Allow and TProjectData(FProjectData).PhaseData.Active then
+    TProjectData(FProjectData).PhaseData.PhasePayData.Delete(ARecord.ValueByName('ID').AsInteger);
+end;
+
+procedure TDealPaymentData.Close;
+begin
+  sddDealPayment.Close;
+end;
+
+procedure TDealPaymentData.RepairSerialNo;
+var
+  Rec: TsdDataRecord;
+  iRec: Integer;
+begin
+  if sddDealPayment.RecordCount = 0 then Exit;
+  Rec := sddDealPayment.Records[0];
+  if Rec.ValueByName('SerialNo').AsString = '' then
+  begin
+    for iRec := 0 to sddDealPayment.RecordCount - 1 do
+    begin
+      Rec := sddDealPayment.Records[iRec];
+      Rec.ValueByName('SerialNo').AsInteger := iRec;
+    end;
+  end;
+end;
+
+function TDealPaymentData.GetNewSerialNo: Integer;
+var
+  idx: TsdIndex;
+begin
+  idx := sddDealPayment.FindIndex('idxView');
+  if idx.RecordCount > 0 then
+    Result := idx.Records[idx.RecordCount - 1].ValueByName('SerialNo').AsInteger + 1
+  else
+    Result := 1;
+end;
+
+procedure TDealPaymentData.RepairLockedFormula;
+
+  function CheckHasRepair: Boolean;
+  var
+    iRec: Integer;
+    Rec: TsdDataRecord;
+  begin
+    Result := True;
+    for iRec := 0 to sddDealPayment.RecordCount - 1 do
+    begin
+      Rec := sddDealPayment.Records[iRec];
+      if Rec.ValueByName('Locked').AsBoolean and
+        (Rec.ValueByName('Formula').AsString <> '') and (Rec.ValueByName('LockedFormula').AsBoolean) then
+      begin
+          Result := False;
+          Break;
+      end;
+    end;
+  end;
+
+var
+  iRec: Integer;
+  Rec: TsdDataRecord;
+begin
+  if sddDealPayment.RecordCount = 0 then Exit;
+  if CheckHasRepair then
+  begin
+    for iRec := 0 to sddDealPayment.RecordCount - 1 do
+    begin
+      Rec := sddDealPayment.Records[iRec];
+      if Rec.ValueByName('Locked').AsBoolean and (Rec.ValueByName('Formula').AsString <> '') then
+        Rec.ValueByName('LockedFormula').AsBoolean := True;
+    end;
+  end;
+end;
+
+function TDealPaymentData.GetStartedPrice(AID: Integer): Double;
+var
+  Rec: TsdDataRecord;
+begin
+  Rec := sddDealPayment.FindKey('idxID', AID);
+  Result := Rec.ValueByName('StartedPrice').AsFloat;
+end;
+
+end.

+ 67 - 0
DataModules/MainDataListDm.dfm

@@ -0,0 +1,67 @@
+object MainListData: TMainListData
+  OldCreateOrder = False
+  Left = 640
+  Top = 325
+  Height = 213
+  Width = 215
+  object sdpMainDataList: TsdADOProvider
+    TableName = 'MainDataList'
+    Left = 72
+    Top = 24
+  end
+  object sddMainDataList: TsdDataSet
+    Active = False
+    Provider = sdpMainDataList
+    Left = 72
+    Top = 88
+    FieldListData = {
+      0101044E616D65060750686173654944094669656C644E616D65060750686173
+      6549440844617461547970650203084461746153697A6502040549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D65060E4465616C546F
+      74616C5072696365094669656C644E616D65060E4465616C546F74616C507269
+      63650844617461547970650206084461746153697A6502080549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D65060C5163546F74616C
+      5072696365094669656C644E616D65060C5163546F74616C5072696365084461
+      7461547970650206084461746153697A6502080549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D65060C5063546F74616C5072696365
+      094669656C644E616D65060C5063546F74616C50726963650844617461547970
+      650206084461746153697A6502080549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D650610476174686572546F74616C507269636509
+      4669656C644E616D650610476174686572546F74616C50726963650844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D650611456E644465616C546F74616C5072
+      696365094669656C644E616D650611456E644465616C546F74616C5072696365
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D65060F456E645163546F7461
+      6C5072696365094669656C644E616D65060F456E645163546F74616C50726963
+      650844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D65060F456E645063546F74
+      616C5072696365094669656C644E616D65060F456E645063546F74616C507269
+      63650844617461547970650206084461746153697A6502080549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D650613456E6447617468
+      6572546F74616C5072696365094669656C644E616D650613456E644761746865
+      72546F74616C50726963650844617461547970650206084461746153697A6502
+      080549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      06115072654465616C546F74616C5072696365094669656C644E616D65061150
+      72654465616C546F74616C507269636508446174615479706502060844617461
+      53697A6502080549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D65060F5072655163546F74616C5072696365094669656C644E616D65
+      060F5072655163546F74616C5072696365084461746154797065020608446174
+      6153697A6502080549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060F5072655063546F74616C5072696365094669656C644E616D
+      65060F5072655063546F74616C50726963650844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D650613507265476174686572546F74616C507269636509466965
+      6C644E616D650613507265476174686572546F74616C50726963650844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D6506085068617365506179094669656C64
+      4E616D6506085068617365506179084461746154797065020608446174615369
+      7A6502080549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D65060B456E645068617365506179094669656C644E616D65060B456E6450
+      686173655061790844617461547970650206084461746153697A650208054973
+      4B6579080F4E65656450726F636573734E616D65090001044E616D65060B5072
+      655068617365506179094669656C644E616D65060B5072655068617365506179
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090000}
+  end
+end

+ 75 - 0
DataModules/MainDataListDm.pas

@@ -0,0 +1,75 @@
+unit MainDataListDm;
+// 各期主要数据一览表,与项目管理界面更新有关
+// 切换最新一期数据与其他各期数据时,保存最新一期数据
+// 保存时,如当前期为最新一期数据,保存最新一期数据
+// 往期数据只做历史数据备用,不做修改
+
+interface
+
+uses
+  SysUtils, Classes, sdDB, sdProvider, ADODB;
+
+type
+  TMainListData = class(TDataModule)
+    sdpMainDataList: TsdADOProvider;
+    sddMainDataList: TsdDataSet;
+  private
+    FProjectData: TObject;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Close;
+    procedure Save;
+
+    function GetPhaseMainRecord(APhaseIndex: Integer): TsdDataRecord;
+
+    property ProjectData: TObject read FProjectData;
+  end;
+
+implementation
+
+{$R *.dfm}
+
+{ TMainListData }
+
+procedure TMainListData.Close;
+begin
+  sddMainDataList.Close;
+end;
+
+constructor TMainListData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+end;
+
+destructor TMainListData.Destroy;
+begin
+  inherited;
+end;
+
+function TMainListData.GetPhaseMainRecord(
+  APhaseIndex: Integer): TsdDataRecord;
+begin
+  Result := sddMainDataList.Locate('PhaseID', APhaseIndex);
+  if not Assigned(Result) then
+  begin
+    Result := sddMainDataList.Add;
+    Result.ValueByName('PhaseID').AsInteger := APhaseIndex;
+  end;
+end;
+
+procedure TMainListData.Open(AConnection: TADOConnection);
+begin
+  sdpMainDataList.Connection := AConnection;
+  sddMainDataList.Open;
+end;
+
+procedure TMainListData.Save;
+begin
+  sddMainDataList.Save;
+end;
+
+end.

+ 25 - 0
DataModules/PHPWebDm.dfm

@@ -0,0 +1,25 @@
+object PHPWeb: TPHPWeb
+  OldCreateOrder = False
+  OnCreate = DataModuleCreate
+  Left = 771
+  Top = 216
+  Height = 226
+  Width = 281
+  object IdHTTP: TIdHTTP
+    MaxLineAction = maException
+    ReadTimeout = 0
+    AllowCookies = True
+    ProxyParams.BasicAuthentication = False
+    ProxyParams.ProxyPort = 0
+    Request.ContentLength = -1
+    Request.ContentRangeEnd = 0
+    Request.ContentRangeStart = 0
+    Request.ContentType = 'text/html'
+    Request.Accept = 'text/html, */*'
+    Request.BasicAuthentication = False
+    Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
+    HTTPOptions = [hoForceEncodeParams]
+    Left = 64
+    Top = 48
+  end
+end

+ 651 - 0
DataModules/PHPWebDm.pas

@@ -0,0 +1,651 @@
+{*******************************************************************************
+    单元名称: PHPWebDm.pas
+
+    单元说明: Delphi 同PHP web服务器通信接口。 计量的PHP比造价的PHP多了很多
+
+    作者时间: Chenshilong, 2012-5-13
+*******************************************************************************}
+
+
+unit PHPWebDm;
+
+interface
+
+uses
+  SysUtils, Classes, IdBaseComponent, IdComponent, IdTCPConnection,
+  IdTCPClient, IdHTTP, CslJson;
+
+type
+  // Web连接成功、Web连接失败、登录失败、旧用户需要升级、资料不全
+  TLoginType = (ltCon, ltDisCon, ltLoginFail, ltUpdate, ltIncomplete);
+
+  TPHPWeb = class(TDataModule)
+    IdHTTP: TIdHTTP;
+    procedure DataModuleCreate(Sender: TObject);
+  private
+    // 远程服务器上时间
+    FServerDateTime: TDateTime;
+    FUserID: Integer;
+    FAccount: string;
+    FRealName: string;
+    FUserFlag: Integer; // 用户标志位,用于区分出一部分用户进行特殊控制。
+    FMeasureURL: string;  // http://d.jl.smartcost.com.cn/api/client/
+    FLoginURL: string;
+    FLoginBannerURL: string;
+    FCheckOnLineURL: string;
+    FPassportURL: string;
+    FPwdURL: string;
+    FRegURL: string;
+    FWebLoginURL: string;
+    FServerDateTimeURL: string;
+    FWebSoftURL: string;
+    FLogoutURL: string;
+    FRole: string;
+    FCompany: string;
+    FUserImageURL: string;
+    FLoginCloudURL: string;
+
+    procedure SetUserID(const Value: Integer);
+    procedure SetAccount(const Value: string);
+    procedure SetRealName(const Value: string);
+
+{-------------------------------------------------------------------------------
+  方法:   CustomSearch()
+
+  描述:   通用的查询接口,集各种复杂情况之大成,宇宙级牛B综合算法,哦耶! ^__^
+
+          【函数返回值】
+            -1:           网络不通;
+             0:           网络通,但登录或查询出错、网页出错等,无法返回约定的
+                           Json格式,通常返回一篇乱码;
+             1:           成功(包括返回零记录)
+
+          【参数】
+             AURL:        请求的网址。
+             AInFields:   请求的键名字。
+             AInValues:   请求的键值。
+             AResultType: 返回值类型:0 返回一维数组;1 返回二维数组;2 两者都。
+             AOutStrs:    用于存储返回的零散值。需要赋字段名传入。
+             AOutRecords: 用于存储返回的多条记录、数据表。只需声明,无需定义大
+                           小和赋值,返回Json的数组,数组的值为'info'对象的值。
+
+          【要求】
+             ①返回的Json数据中必须有status、msg两个键名字(约定格式)。
+             ②AResults至少有一个元素,用来存储当返回值为0时查询出错的原因。
+
+
+  作者:   Chenshilong, 2014-07-13
+-------------------------------------------------------------------------------}
+    function CustomSearch(AURL: string; AInFields, AInValues: array of string;
+      AResultType: Integer; var AOutStrs: array of string;
+      var AOutRecords: TOVArr): Integer;
+  public
+    function SystemDateTime: TDateTime;
+    function Search(AURL: string; AInFields, AInValues: array of string; var AOutStrs: array of string): Integer; overload;
+    function Search(AURL: string; AInFields, AInValues: array of string; var AOutRecords: TOVArr): Integer; overload;
+    function Search(AURL: string; AInFields, AInValues: array of string; var AOutStrs: array of string ; var AOutRecords: TOVArr): Integer; overload;
+    function Search(AURL: string; AInFields, AInValues: array of string; AResultType: Integer; var AOutStrs: array of string ; var AOutRecords: TOVArr): Integer; overload;
+    function Login(AAccount, APW: string; var AInfo, ACheckCode: string): TLoginType;
+    function ConnectServer(AIP: string; var ACompanyName: string): Integer;  // 新装软件,先弹出设置IP窗口
+    function UpDataFile(AUserID, ATenderID, APhaseNo: Integer; AFile, AMD5_JL: string;
+      AIsSubmit: Boolean; var AResultStr: string; ACheckPassed: Boolean; ACheckerMemo: string): Boolean;
+    function UpAttachmentFile(AUperID, AWebID, ABillID: Integer; AFile,
+      ACategory, AMemo, APhaseName: string; var ANewFileName: string): Boolean;
+    function GetAttachmentFileList(AWebID: Integer; var vArr: TOVArr): Boolean;
+    function zip(AFileArr: array of string): string;
+    function TempName(ALength: Integer = 12): string;
+    function WebPath: string;
+    function UserPath: string;
+    // 下载文件:源文件网址;存储到本地的位置
+    function DownFile(ASourceURL: string; var ALocalFile: string): Boolean;
+    // 用于调试输出值,解决灵异现象(有些现象调试环境正常,运行环境时有时无)
+    procedure Debug(AFileName, AStr: string); overload;
+    procedure Debug(AFileName: string; AInFields, AInValues: array of string); overload;
+    function NetError(AMid: string): string;
+    function PageError(AMid: string): string;
+
+
+
+    property Account: string read FAccount write SetAccount;
+    property UserID: Integer read FUserID write SetUserID;
+    property RealName: string read FRealName write SetRealName;
+    property UserFlag: Integer read FUserFlag write FUserFlag;
+    property Company: string read FCompany write FCompany;
+    property Role: string read FRole write FRole;
+
+    property MeasureURL: string read FMeasureURL;
+    property WebSoftURL: string read FWebSoftURL;
+    property PassportURL: string read FPassportURL;
+    property LoginURL: string read FLoginURL;
+    property WebLoginURL: string read FWebLoginURL;
+    property LoginBannerURL: string read FLoginBannerURL;
+    property LogoutURL: string read FLogoutURL;
+    property RegURL: string read FRegURL;
+    property PwdURL: string read FPwdURL;
+    property CheckOnLineURL: string read FCheckOnLineURL;
+    property ServerDateTimeURL: string read FServerDateTimeURL;
+    property UserImageURL: string read FUserImageURL write FUserImageURL;
+    property LoginCloudURL: string read FLoginCloudURL write FLoginCloudURL;
+
+  end;
+
+
+function PHPWeb: TPHPWeb;
+// 全国  广东  标后预算 定额排版  港口水工  内河航运  疏浚 清单编制
+function ExeCategoryName: string;
+
+implementation
+
+uses
+  MD5Unit, IdMultipartFormData, VCLUnZip, VCLZip,
+  IniFiles, Forms, UtilMethods, Variants, ConstUnit{, Controls, Windows};
+
+var g_PHPWeb: TPHPWeb;
+
+{$R *.dfm}
+
+{ TPHPWeb }
+
+function PHPWeb: TPHPWeb;
+begin
+  if g_PHPWeb = nil then
+    g_PHPWeb := TPHPWeb.Create(nil);
+  Result := g_PHPWeb;
+end;
+
+function ExeCategoryName: string;
+begin
+  Result := 'JLZF';
+end;
+
+function TPHPWeb.Login(AAccount, APW: string; var AInfo, ACheckCode: string): TLoginType;
+var vArr: array of string;
+begin
+  vArr := VarArrayOf(['uid', 'name', 'email', 'ucompany', 'jobtitle', 'avatar', 'msg']);
+  case Search(FMeasureURL + 'signin', ['v3name', 'v3pass'], [AnsiToUtf8(AAccount), APW], vArr) of
+    -1: Result := ltDisCon;
+    0:
+    begin
+      AInfo := vArr[0];
+      Result := ltLoginFail;
+    end;
+    1:
+    begin
+      FUserID := StrToInt(vArr[0]);
+      FRealName := vArr[1];
+      FAccount := AAccount;  // vArr[2]
+      FCompany := vArr[3];
+      FRole := vArr[4];
+      FUserImageURL := vArr[5];
+      AInfo := vArr[6];
+      Result := ltCon;
+    end;
+  end;
+end;
+
+procedure TPHPWeb.SetUserID(const Value: Integer);
+begin
+  FUserID := Value;
+end;
+
+procedure TPHPWeb.SetAccount(const Value: string);
+begin
+  FAccount := Value;
+end;
+
+procedure TPHPWeb.DataModuleCreate(Sender: TObject);
+var ini: TIniFile;
+begin
+  FServerDateTime := -1;
+
+  ini := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'Cloud.ini');
+  try
+//    FMeasureURL := ini.ReadString('URL', 'MeasureURL', '');
+    FMeasureURL := 'http://' + ini.ReadString('URL', 'Server', '') +
+      ini.ReadString('URL', 'MeasureURL', '');
+    FWebSoftURL := ini.ReadString('URL', 'WebSoftURL', '');
+    FPassportURL := ini.ReadString('URL', 'PassportURL', '');
+    FLoginCloudURL := ini.ReadString('URL', 'LoginCloudURL', '');
+
+    FLoginURL := FWebSoftURL + ini.ReadString('URL', 'LoginURL', '');
+    FWebLoginURL := FWebSoftURL + ini.ReadString('URL', 'FWebLoginURL', '');
+    FLoginBannerURL := FWebSoftURL + ini.ReadString('URL', 'LoginBannerURL', '');
+    FLogoutURL := FWebSoftURL + ini.ReadString('URL', 'LogoutURL', '');
+    FRegURL := FPassportURL + ini.ReadString('URL', 'RegURL', '');
+    FPwdURL := FPassportURL + ini.ReadString('URL', 'PwdURL', '');
+    FCheckOnLineURL := FWebSoftURL + ini.ReadString('URL', 'CheckOnLineURL', '');
+    FServerDateTimeURL := FWebSoftURL + ini.ReadString('URL', 'ServerDateTimeURL', '');
+  finally
+    ini.Free;
+  end;
+end;
+
+procedure TPHPWeb.SetRealName(const Value: string);
+begin
+  FRealName := Value;
+end;
+
+function TPHPWeb.zip(AFileArr: array of string): string;
+var vZip: TVCLZip;
+  sAppFile, sZipFile: string;
+  i: Integer;
+begin
+  Result := 'Error';
+  sAppFile := AFileArr[Low(AFileArr)];
+  sZipFile := ExtractFilePath(sAppFile) + ExtractFileNameWithoutExt(sAppFile) + '.up';
+
+  if FileExists(sZipFile) then
+      DeleteFile(sZipFile);
+
+  vZip := TVCLZip.Create(nil);
+  try
+    for i := Low(AFileArr) to High(AFileArr) do
+    begin
+      if FileExists(AFileArr[i]) then
+        vZip.FilesList.Add(AFileArr[i]);
+    end;
+
+    vZip.ZipName := sZipFile;
+    // PHP不支持解压加密zip文件
+    //vZip.Password := 'jlzf.Sc.2014';
+    vZip.Recurse := True;
+    vZip.ZipComment := '纵横计量支付';
+    vZip.OverwriteMode := Always;
+    vZip.Zip;
+    Result := sZipFile;
+
+    for i := Low(AFileArr) to High(AFileArr) do
+      DeleteFile(AFileArr[i]);
+  finally
+    vZip.Free;
+  end;
+end;
+
+
+function TPHPWeb.UpDataFile(AUserID, ATenderID, APhaseNo: Integer; AFile, AMD5_JL: string;
+  AIsSubmit: Boolean; var AResultStr: string; ACheckPassed: Boolean; ACheckerMemo: string): Boolean;
+var
+  IdDataStream: TIdMultiPartFormDataStream;
+  sResult, sURL: string;
+  J: TCslJson;
+  sZipMD5: string;
+begin
+  Result := False;
+
+  if not FileExists(AFile) then Exit;
+
+  IdDataStream := TIdMultiPartFormDataStream.Create;
+  try
+    if ACheckPassed then   // 审核通过
+    begin
+      if AIsSubmit then
+      begin
+        sURL := Format('%speriod/%d/%d/%d/creat', [FMeasureURL, AUserID, ATenderID, APhaseNo])
+      end
+      else
+      begin
+        sURL := FMeasureURL + 'user/audit/measure';
+        IdDataStream.AddFormField('userid', IntToStr(AUserID));
+        IdDataStream.AddFormField('tenderid', IntToStr(ATenderID));
+        IdDataStream.AddFormField('phaseno', IntToStr(APhaseNo));
+        IdDataStream.AddFormField('CheckerMemo', ACheckerMemo);
+      end;
+    end
+    else  // 审核不通过
+    begin
+      sURL := Format('%suser/set/%d/%d/%d/checkno', [FMeasureURL, AUserID, ATenderID, APhaseNo]);
+      IdDataStream.AddFormField('CheckerMemo', ACheckerMemo);
+    end;
+
+    IdDataStream.AddFormField('upfile', AFile);
+//    IdDataStream.AddFormField('submit', 'submit');
+    IdDataStream.AddFormField('MD5_JL', AMD5_JL);
+    sZipMD5 := MD5_File(AFile);
+    IdDataStream.AddFormField('MD5_Zip', sZipMD5);
+    IdDataStream.AddFile('upfile', AFile, 'text/plain');
+    IdDataStream.Position := 0;
+    try
+      sResult := IdHTTP.Post(sURL, IdDataStream);
+    except
+      Abort;
+    end;
+  finally
+    IdDataStream.Free;
+    DeleteFile(AFile);
+  end;
+
+  J := TCslJson.Create;
+  try
+    J.Text := Utf8ToAnsi(sResult);
+    if SameText(J.Value['status'], 'true') then
+      Result := True
+    else
+    begin
+      Result := False;
+      AResultStr := J.Value['msg'];
+    end;
+  finally
+    J.Free;
+  end;
+end;
+
+function TPHPWeb.Search(AURL: string; AInFields, AInValues: array of string; var AOutStrs: array of string): Integer;
+var vA: TOVArr;
+begin
+  Result := CustomSearch(AURL, AInFields, AInValues, 0, AOutStrs, vA);
+end;
+
+function TPHPWeb.Search(AURL: string; AInFields, AInValues: array of string; var AOutRecords: TOVArr): Integer;
+var vA: array of string;
+begin
+  Result := CustomSearch(AURL, AInFields, AInValues, 1, vA, AOutRecords);
+end;
+
+function TPHPWeb.Search(AURL: string; AInFields, AInValues: array of string; var AOutStrs: array of string; var AOutRecords: TOVArr): Integer;
+begin
+  Result := CustomSearch(AURL, AInFields, AInValues, 2, AOutStrs, AOutRecords);
+end;
+
+function TPHPWeb.Search(AURL: string; AInFields, AInValues: array of string; AResultType: Integer; var AOutStrs: array of string; var AOutRecords: TOVArr): Integer;
+begin
+  Result := CustomSearch(AURL, AInFields, AInValues, 3, AOutStrs, AOutRecords);
+end;
+
+function TPHPWeb.TempName(ALength: Integer): string;
+const
+  CodedBuf: array[0..35] of Char = ('0', '1', '2', '3', '4', '5',
+  '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+  'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+  'W', 'X', 'Y', 'Z');
+begin
+  Result := '';
+  Randomize;
+  while Length(Result) < ALength do
+    Result := Result + CodedBuf[Random(36)];
+end;
+
+function TPHPWeb.WebPath: string;
+begin
+  Result := ExtractFilePath(Application.ExeName) + 'Web\';
+  if not DirectoryExists(Result) then
+    ForceDirectories(Result);
+end;
+
+function TPHPWeb.UserPath: string;
+begin
+  Result := ExtractFilePath(Application.ExeName) + 'Web\Users\' + IntToStr(FUserID) + '\';
+  if not DirectoryExists(Result) then
+    ForceDirectories(Result);
+end;
+
+function TPHPWeb.DownFile(ASourceURL: string; var ALocalFile: string): Boolean;
+var
+  vStream: TMemoryStream;
+  iFlag: Integer;
+  bOK: Boolean;
+
+  procedure SafeDownFile(ASourceURL: string; var ALocalFile: string);
+  begin
+    Inc(iFlag);
+    bOK := False;
+    try
+      IdHTTP.Get(ASourceURL, vStream);
+      vStream.SaveToFile(ALocalFile);
+      bOK := True;
+    except
+      bOK := False;
+    end;
+  end;
+begin
+  iFlag := 0;
+  bOK := False;
+  Result := False;
+
+  if Trim(ASourceURL) = '' then Exit;
+  if Trim(ALocalFile) = '' then Exit;
+
+  if (ExtractFileExt(ALocalFile) = '.rmf') and FileExists(ALocalFile) then
+    DeleteFile(ALocalFile);
+
+  vStream := TMemoryStream.Create;
+  try
+    while (not bOK) and (iFlag < 3) do   // 尝试3次
+      SafeDownFile(ASourceURL, ALocalFile);
+
+    Result := bOK;
+  finally
+    vStream.Free;
+  end;
+end;
+
+function TPHPWeb.CustomSearch(AURL: string; AInFields,
+  AInValues: array of string; AResultType: Integer;
+  var AOutStrs: array of string; var AOutRecords: TOVArr): Integer;
+var
+  i: Integer;
+  postList: TStrings;
+  ssResponse: TStringStream;
+  bDone: Boolean;
+  vJson: TCslJson;
+begin
+  Result := -1;
+  postList := TStringList.Create;
+  ssResponse := TStringStream.Create('');
+  try
+    try
+      for i := Low(AInFields) to High(AInFields) do
+        postList.Add(Format('%s=%s', [AInFields[i], AInValues[i]]));
+
+      IdHTTP.Post(AURL, postList, ssResponse);
+      bDone := True;
+    except
+      bDone := False;
+    end;
+
+    if (bDone) and (Pos('200 OK', IdHTTP.ResponseText) <> 0) then   // 网络已通
+    begin
+      vJson := TCslJson.Create;
+      try
+        vJson.Text := Utf8ToAnsi(ssResponse.DataString);
+
+        if SameText(vJson.Value['status'], 'true') then          // 数据读取成功
+        begin
+          case AResultType of
+            0:
+            begin
+              for i := Low(AOutStrs) to High(AOutStrs) do
+                AOutStrs[i] := vJson.Value[AOutStrs[i]];
+            end;
+            1:
+            begin
+              AOutRecords := vJson.ArrayValues('info');
+            end;
+            2:
+            begin
+              for i := Low(AOutStrs) to High(AOutStrs) do
+                AOutStrs[i] := vJson.Value[AOutStrs[i]];
+
+              AOutRecords := vJson.ArrayValues('info');
+            end;
+            3:
+            begin
+              vJson.ChildValues('info', AOutStrs);
+              AOutRecords := vJson.ArrayValues('auditinfo');
+            end;
+          end;
+          Result := 1;
+        end
+        else                                                     // 数据读取失败
+        begin
+          case AResultType of
+            0:
+            begin
+              AOutStrs[Low(AOutStrs)] := vJson.Value['msg'];
+            end;
+            1:
+            begin
+              SetLength(AOutRecords, 1, 1);
+              AOutRecords[0, 0] := vJson.Value['msg'];
+            end;
+            2, 3:
+            begin
+              AOutStrs[Low(AOutStrs)] := vJson.Value['msg'];
+
+              SetLength(AOutRecords, 1, 1);
+              AOutRecords[0, 0] := vJson.Value['msg'];
+            end;
+          end;
+          Result := 0;
+        end;
+      finally
+        vJson.Free;
+      end;
+    end;
+  finally
+    postList.Free;
+    ssResponse.Free;
+  end;
+end;
+
+function TPHPWeb.SystemDateTime: TDateTime;
+begin
+  Result := Now;
+end;
+
+function TPHPWeb.NetError(AMid: string): string;
+begin
+  Result := Format('当前网络状态较差(-1),%s,请重新尝试或重新登录后再尝试!', [AMid]);
+end;
+
+function TPHPWeb.PageError(AMid: string): string;
+begin
+  Result := Format('Web页返回错误(0),%s,请重新尝试或联系纵横客服。', [AMid]);
+end;
+
+procedure TPHPWeb.Debug(AFileName, AStr: string);
+var vSL: TStringList;
+  sAdd: string;
+begin
+  vSL := TStringList.Create;
+  try
+    sAdd := Format('%s%d %s %s', [#10#13#10#13#10#13#10#13#10#13,
+      UserID, RealName, Account]);
+
+    vSL.Add(AStr + sAdd);
+
+    if Pos('Debug_', AFileName) = 0 then
+      AFileName := 'Debug_' + AFileName;
+
+    vSL.SaveToFile(WebPath + AFileName + '.txt');
+  finally
+    vSL.Free;
+  end;
+end;
+
+procedure TPHPWeb.Debug(AFileName: string; AInFields, AInValues: array of string);
+var vSL: TStringList;
+  sAdd: string;
+  i: Integer;
+begin
+  if G_IsTest then
+  begin
+    vSL := TStringList.Create;
+    try
+      sAdd := Format('%s%d  %s  %s', [#10#13#10#13#10#13#10#13#10#13, UserID, RealName, Account]);
+
+      for i := Low(AInFields) to High(AInFields) do
+        vSL.Add(AInFields[i] + #9#9 + AInValues[i]);
+
+      vSL.Add(sAdd);
+
+      if Pos('Debug_', AFileName) = 0 then
+        AFileName := 'Debug_' + AFileName;
+
+      vSL.SaveToFile(WebPath + AFileName + '.txt');
+    finally
+      vSL.Free;
+    end;
+  end;
+end;
+
+function TPHPWeb.ConnectServer(AIP: string; var ACompanyName: string): Integer;
+var vArr: array of string;
+  sURL: string;
+begin
+  sURL := Format('http://%s/api/client/software/title', [AIP]);
+  vArr := VarArrayOf(['msg']);
+  Result := Search(sURL, [], [], vArr);
+  case Result of
+    -1: ACompanyName := '地址不存在';
+    0: ACompanyName := '服务器Web页错误';
+    1: ACompanyName := vArr[0];
+  end;
+end;
+
+function TPHPWeb.UpAttachmentFile(AUperID, AWebID, ABillID: Integer; AFile,
+  ACategory, AMemo, APhaseName: string; var ANewFileName: string): Boolean;
+var
+  vMPFDS: TIdMultiPartFormDataStream;
+  sResult, sURL: string;
+  J: TCslJson;
+  vArr: array of string;
+begin
+  Result := False;
+
+  if not FileExists(AFile) then
+  begin
+//    Application.MessageBox(PChar(AFile + ' 文件不存在!'), '错误', MB_OK + MB_ICONERROR);
+    Exit;
+  end;
+
+  vMPFDS := TIdMultiPartFormDataStream.Create;
+  try
+    sURL := Format('%stender/attachment/%d/%d/upload', [FMeasureURL, AWebID, AUperID]);
+    vMPFDS.AddFormField('itemid', IntToStr(ABillID));
+    vMPFDS.AddFormField('Category', ACategory);
+    vMPFDS.AddFormField('Memo', AMemo);
+    vMPFDS.AddFormField('PhaseName', APhaseName);
+    vMPFDS.AddFile('upitem', AFile, 'text/plain');
+    vMPFDS.Position := 0;
+    try
+      sResult := IdHTTP.Post(sURL, vMPFDS);
+    except
+      Abort;
+    end;
+  finally
+    vMPFDS.Free;
+  end;
+
+  J := TCslJson.Create;
+  try
+    J.Text := Utf8ToAnsi(sResult);
+    if SameText(J.Value['status'], 'true') then
+    begin
+      Result := True;
+      vArr := VarArrayOf(['onlinefilename']);
+      J.ChildValues('iteminfo', vArr);
+      ANewFileName := vArr[0];
+    end
+    else
+    begin
+      Result := False;
+    end;
+  finally
+    J.Free;
+  end;
+end;
+
+function TPHPWeb.GetAttachmentFileList(AWebID: Integer; var vArr: TOVArr): Boolean;
+var sURL: string;
+begin
+  sURL := Format('%stender/attachment/%d/list', [FMeasureURL, AWebID]);
+  Result := Search(sURL, [], [], vArr) = 1;
+end;
+
+initialization
+
+finalization
+  if g_PHPWeb <> nil then
+    g_PHPWeb.Free;
+
+end.

+ 39 - 0
DataModules/PhaseCompareDm.dfm

@@ -0,0 +1,39 @@
+object PhaseCompareData: TPhaseCompareData
+  OldCreateOrder = False
+  Left = 709
+  Top = 412
+  Height = 130
+  Width = 232
+  object sdvPhaseCompare: TsdDataView
+    Active = False
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'ParentID'
+      end
+      item
+        FieldName = 'NextSiblingID'
+      end
+      item
+        FieldName = 'Code'
+      end
+      item
+        FieldName = 'B_Code'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Units'
+      end
+      item
+        FieldName = 'CreatePhaseID'
+      end>
+    OnGetText = sdvPhaseCompareGetText
+    Left = 56
+    Top = 24
+  end
+end

+ 237 - 0
DataModules/PhaseCompareDm.pas

@@ -0,0 +1,237 @@
+unit PhaseCompareDm;
+
+
+interface
+
+uses
+  SysUtils, Classes, sdDB, sdIDTree, DB, DBClient, Provider, ADODB,
+  sdProvider;
+
+{const
+  PhaseSelect0 = 'Select R.BillsID, R.GatherQuantity As Quantity0, R.GatherTotalPrice As TotalPrice0' +
+                 '  From Refer As R';
+
+  PhaseSelect1 = 'Select A1.BillsID, A1.GatherQuantity As Quantity1, A1.GatherTotalPrice As TotalPrice1,' +
+                 '       R.GatherQuantity As Quantity0, R.GatherTotalPrice As TotalPrice0' +
+                 '  From Audit1 As A1 Left Join Refer As R on A1.BillsID = R.BillsID';
+
+  PhaseSelect2 = 'Select A2.BillsID, A2.GatherQuantity As Quantity2, A2.GatherTotalPrice As TotalPrice2,' +
+                 '       A1.GatherQuantity As Quantity1, A1.GatherTotalPrice As TotalPrice1' +
+                 '       R.GatherQuantity As Quantity0, R.GatherTotalPrice As TotalPrice0' +
+                 '  From' +
+                 '    (Audit2 As A2 Left Join Audit1 As A1 on A2.BillsID = A1.BillsID)'+
+                 '    Left Join Refer As R on A2.BillsID = R.BillsID';
+
+  PhaseSelect3 = 'Select A3.BillsID, A3.GatherQuantity As Quantity3, A3.GatherTotalPrice As TotalPrice3,' +
+                 '       A2.GatherQuantity As Quantity2, A2.GatherTotalPrice As TotalPrice2' +
+                 '       A1.GatherQuantity As Quantity1, A1.GatherTotalPrice As TotalPrice1' +
+                 '       R.GatherQuantity As Quantity0, R.GatherTotalPrice As TotalPrice0' +
+                 '  From' +
+                 '    ((Audit3 As A3 Left Join Audit2 As A2 on A3.BillsID = A2.BillsID)'+
+                 '     Left Join Audit1 As A1 on A3.BillsID = A1.BillsID)'+
+                 '    Left Join Refer As R on A3.BillsID = R.BillsID';
+
+  PhaseSelect4 = 'Select A4.BillsID, A4.GatherQuantity As Quantity4, A4.GatherTotalPrice As TotalPrice4,' +
+                 '       A3.GatherQuantity As Quantity3, A3.GatherTotalPrice As TotalPrice3' +
+                 '       A2.GatherQuantity As Quantity2, A2.GatherTotalPrice As TotalPrice2' +
+                 '       A1.GatherQuantity As Quantity1, A1.GatherTotalPrice As TotalPrice1' +
+                 '       R.GatherQuantity As Quantity0, R.GatherTotalPrice As TotalPrice0' +
+                 '  From' +
+                 '    (((Audit4 As A4 Left Join Audit3 As A3 on A4.BillsID = A3.BillsID)'+
+                 '      Left Join Audit2 As A2 on A4.BillsID = A2.BillsID)'+
+                 '     Left Join Audit1 As A1 on A4.BillsID = A1.BillsID)'+
+                 '    Left Join Refer As R on A4.BillsID = R.BillsID';
+
+  PhaseSelect14 = 'Select A14.BillsID, A14.GatherQuantity As Quantity14, A14.GatherTotalPrice As TotalPrice14,' +
+                  '       A13.GatherQuantity As Quantity13, A13.GatherTotalPrice As TotalPrice13' +
+                  '       A12.GatherQuantity As Quantity12, A12.GatherTotalPrice As TotalPrice12' +
+                  '       A11.GatherQuantity As Quantity11, A11.GatherTotalPrice As TotalPrice11' +
+                  '       A10.GatherQuantity As Quantity10, A10.GatherTotalPrice As TotalPrice10' +
+                  '       A9.GatherQuantity As Quantity9,   A9.GatherTotalPrice As TotalPrice9' +
+                  '       A8.GatherQuantity As Quantity8,   A8.GatherTotalPrice As TotalPrice8' +
+                  '       A7.GatherQuantity As Quantity7,   A7.GatherTotalPrice As TotalPrice7' +
+                  '       A6.GatherQuantity As Quantity6,   A6.GatherTotalPrice As TotalPrice6' +
+                  '       A5.GatherQuantity As Quantity5,   A5.GatherTotalPrice As TotalPrice5' +
+                  '       A4.GatherQuantity As Quantity4,   A4.GatherTotalPrice As TotalPrice4' +
+                  '       A3.GatherQuantity As Quantity3,   A3.GatherTotalPrice As TotalPrice3' +
+                  '       A2.GatherQuantity As Quantity2,   A2.GatherTotalPrice As TotalPrice2' +
+                  '       A1.GatherQuantity As Quantity1,   A1.GatherTotalPrice As TotalPrice1' +
+                  '       R.GatherQuantity As Quantity0,    R.GatherTotalPrice As TotalPrice0' +
+                  '  From' +
+                  '    (((((((((((((Audit14 As A14 Left Join Audit13 As A13 on A14.BillsID = A13.BillsID)'+
+                  '                Left Join Audit12 As A12 on A14.BillsID = A12.BillsID)'+
+                  '               Left Join Audit11 As A11 on A14.BillsID = A11.BillsID)'+
+                  '              Left Join Audit20 As A10 on A14.BillsID = A10.BillsID)'+
+                  '             Left Join Audit9 As A9 on A14.BillsID = A9.BillsID)'+
+                  '            Left Join Audit8 As A8 on A14.BillsID = A8.BillsID)'+
+                  '           Left Join Audit7 As A7 on A14.BillsID = A7.BillsID)'+
+                  '          Left Join Audit6 As A6 on A14.BillsID = A6.BillsID)'+
+                  '         Left Join Audit5 As A5 on A14.BillsID = A5.BillsID)'+
+                  '        Left Join Audit4 As A4 on A14.BillsID = A4.BillsID)'+
+                  '       Left Join Audit3 As A3 on A14.BillsID = A3.BillsID)'+
+                  '      Left Join Audit2 As A2 on A4.BillsID = A2.BillsID)'+
+                  '     Left Join Audit1 As A1 on A4.BillsID = A1.BillsID)'+
+                  '    Left Join Refer As R on A4.BillsID = R.BillsID'; }
+
+
+type
+  TPhaseCompareData = class(TDataModule)
+    sdvPhaseCompare: TsdDataView;
+    procedure sdvPhaseCompareGetText(var Text: String;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      DisplayText: Boolean);
+  private
+    FProjectData: TObject;
+    FCompareTree: TsdIDTree;
+    FStageCount: Integer;
+
+    procedure AddStageColumn(AStageIndex: Integer);
+    procedure ClearStageColumn;
+    procedure InitCompareColumns;
+
+    procedure CreateCompareTree;
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open;
+    procedure Close;
+
+    procedure ReConnectTree;
+
+    procedure ExpandNodeTo(ALevel: Integer);
+    procedure ExpandXmjNode;
+
+    property ProjectData: TObject read FProjectData;
+    property CompareTree: TsdIDTree read FCompareTree;
+  end;
+
+implementation
+
+uses
+  ProjectData, PhaseData, StageDm, StageCompareDm, UtilMethods;
+
+{$R *.dfm}
+
+{ TPhaseCompareData }
+
+procedure TPhaseCompareData.AddStageColumn(AStageIndex: Integer);
+var
+  vColumn: TsdViewColumn;
+begin
+  vColumn := sdvPhaseCompare.Columns.Add;
+  vColumn.FieldName := Format('Quantity%d', [AStageIndex]);
+  vColumn.KeyFields := 'ID';
+  vColumn.LookupKeyFields := 'BillsID';
+  vColumn.LookupResultField := Format('Quantity%d', [AStageIndex]);
+  vColumn.LookupDataSet := TProjectData(FProjectData).PhaseData.StageCompareData.sddStageCompare;
+
+  vColumn := sdvPhaseCompare.Columns.Add;
+  vColumn.FieldName := Format('TotalPrice%d', [AStageIndex]);
+  vColumn.KeyFields := 'ID';
+  vColumn.LookupKeyFields := 'BillsID';
+  vColumn.LookupResultField := Format('TotalPrice%d', [AStageIndex]);
+  vColumn.LookupDataSet := TProjectData(FProjectData).PhaseData.StageCompareData.sddStageCompare;
+end;
+
+procedure TPhaseCompareData.ClearStageColumn;
+var
+  iStage: Integer;
+  vCol: TsdViewColumn;
+begin
+  for iStage := 0 to FStageCount - 1 do
+  begin
+    vCol := sdvPhaseCompare.Columns.FindColumn('Quantity' + IntToStr(iStage));
+    if Assigned(vCol) then
+      sdvPhaseCompare.Columns.Delete(vCol.Index);
+    vCol := sdvPhaseCompare.Columns.FindColumn('TotalPrice' + IntToStr(iStage));
+    if Assigned(vCol) then
+      sdvPhaseCompare.Columns.Delete(vCol.Index);
+  end;
+end;
+
+procedure TPhaseCompareData.Close;
+begin
+  sdvPhaseCompare.Close;
+end;
+
+constructor TPhaseCompareData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+  FStageCount := 0;
+end;
+
+procedure TPhaseCompareData.CreateCompareTree;
+begin
+  FCompareTree := TsdIDTree.Create;
+  FCompareTree.KeyFieldName := 'ID';
+  FCompareTree.ParentFieldName := 'ParentID';
+  FCompareTree.NextSiblingFieldName := 'NextSiblingID';
+  FCompareTree.AutoExpand := True;
+  FCompareTree.DataView := sdvPhaseCompare;
+end;
+
+destructor TPhaseCompareData.Destroy;
+begin
+  FCompareTree.Free;
+  inherited;
+end;
+
+procedure TPhaseCompareData.ExpandNodeTo(ALevel: Integer);
+begin
+  CompareTree.ExpandLevel := ALevel;
+end;
+
+procedure TPhaseCompareData.ExpandXmjNode;
+var
+  iIndex: Integer;
+  stnNode: TsdIDTreeNode;
+begin
+  for iIndex := 0 to CompareTree.Count - 1 do
+  begin
+    stnNode := CompareTree.Items[iIndex];
+    if (stnNode.ParentID <> -1) then
+      stnNode.Parent.Expanded := stnNode.Rec.ValueByName('B_Code').AsString = '';
+  end;
+end;
+
+procedure TPhaseCompareData.InitCompareColumns;
+var
+  iStage: Integer;
+begin
+  ClearStageColumn;
+  if TProjectData(FProjectData).PhaseData.Active then
+    for iStage := 0 to TProjectData(FProjectData).PhaseData.AuditCount do
+      AddStageColumn(iStage);
+  FStageCount := TProjectData(FProjectData).PhaseData.StageCount;
+end;
+
+procedure TPhaseCompareData.Open;
+begin
+  sdvPhaseCompare.DataSet := TProjectData(FProjectData).BillsData.sddBills;
+  InitCompareColumns;
+  sdvPhaseCompare.Open;
+  CreateCompareTree;
+end;
+
+procedure TPhaseCompareData.ReConnectTree;
+begin
+  FCompareTree.DataView := nil;
+  FCompareTree.DataView := sdvPhaseCompare;
+  FCompareTree.Link(TProjectData(FProjectData).BillsCompileData.BillsCompileTree, True);
+end;
+
+procedure TPhaseCompareData.sdvPhaseCompareGetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  DisplayText: Boolean);
+begin
+  if (Pos('TotalPrice', AColumn.FieldName) > 0) or
+     (Pos('Quantity', AColumn.FieldName) > 0) then
+  begin
+    if Assigned(AValue) and (AValue.AsFloat = 0) then
+      Text := '';
+  end;
+end;
+
+end.

+ 195 - 0
DataModules/PhasePayDm.dfm

@@ -0,0 +1,195 @@
+object PhasePayData: TPhasePayData
+  OldCreateOrder = False
+  Left = 562
+  Top = 335
+  Height = 188
+  Width = 176
+  object sdpPhasePay: TsdADOProvider
+    TableName = 'PhasePay'
+    Left = 64
+    Top = 24
+  end
+  object sddPhasePay: TsdDataSet
+    Active = False
+    Provider = sdpPhasePay
+    BeforeValueChange = sddPhasePayBeforeValueChange
+    AfterValueChanged = sddPhasePayAfterValueChanged
+    Left = 64
+    Top = 88
+    FieldListData = {
+      0101044E616D6506024944094669656C644E616D650602494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D65060B546F74616C507269636530094669656C
+      644E616D65060B546F74616C5072696365300844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D650608466F726D756C6130094669656C644E616D650608466F72
+      6D756C61300844617461547970650218084461746153697A6503FF000549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060E456E64
+      546F74616C507269636530094669656C644E616D65060E456E64546F74616C50
+      72696365300844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060E50726554
+      6F74616C507269636530094669656C644E616D65060E507265546F74616C5072
+      696365300844617461547970650206084461746153697A6502080549734B6579
+      080F4E65656450726F636573734E616D65090001044E616D65060B546F74616C
+      507269636531094669656C644E616D65060B546F74616C507269636531084461
+      7461547970650206084461746153697A6502080549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D650608466F726D756C613109466965
+      6C644E616D650608466F726D756C613108446174615479706502180844617461
+      53697A6503FF000549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060E456E64546F74616C507269636531094669656C644E616D65
+      060E456E64546F74616C50726963653108446174615479706502060844617461
+      53697A6502080549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D65060E507265546F74616C507269636531094669656C644E616D6506
+      0E507265546F74616C5072696365310844617461547970650206084461746153
+      697A6502080549734B6579080F4E65656450726F636573734E616D6509000104
+      4E616D65060B546F74616C507269636532094669656C644E616D65060B546F74
+      616C5072696365320844617461547970650206084461746153697A6502080549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060846
+      6F726D756C6132094669656C644E616D650608466F726D756C61320844617461
+      547970650218084461746153697A6503FF000549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D65060E456E64546F74616C5072696365
+      32094669656C644E616D65060E456E64546F74616C5072696365320844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D65060E507265546F74616C507269636532
+      094669656C644E616D65060E507265546F74616C507269636532084461746154
+      7970650206084461746153697A6502080549734B6579080F4E65656450726F63
+      6573734E616D65090001044E616D65060B546F74616C50726963653309466965
+      6C644E616D65060B546F74616C50726963653308446174615479706502060844
+      61746153697A6502080549734B6579080F4E65656450726F636573734E616D65
+      090001044E616D650608466F726D756C6133094669656C644E616D650608466F
+      726D756C61330844617461547970650218084461746153697A6503FF00054973
+      4B6579080F4E65656450726F636573734E616D65090001044E616D65060E456E
+      64546F74616C507269636533094669656C644E616D65060E456E64546F74616C
+      5072696365330844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060E507265
+      546F74616C507269636533094669656C644E616D65060E507265546F74616C50
+      72696365330844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060B546F7461
+      6C507269636534094669656C644E616D65060B546F74616C5072696365340844
+      617461547970650206084461746153697A6502080549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D650608466F726D756C6134094669
+      656C644E616D650608466F726D756C6134084461746154797065021808446174
+      6153697A6503FF000549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D65060E456E64546F74616C507269636534094669656C644E616D
+      65060E456E64546F74616C507269636534084461746154797065020608446174
+      6153697A6502080549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060E507265546F74616C507269636534094669656C644E616D65
+      060E507265546F74616C50726963653408446174615479706502060844617461
+      53697A6502080549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D65060B546F74616C507269636535094669656C644E616D65060B546F
+      74616C5072696365350844617461547970650206084461746153697A65020805
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650608
+      466F726D756C6135094669656C644E616D650608466F726D756C613508446174
+      61547970650218084461746153697A6503FF000549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D65060E456E64546F74616C50726963
+      6535094669656C644E616D65060E456E64546F74616C50726963653508446174
+      61547970650206084461746153697A6502080549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D65060E507265546F74616C5072696365
+      35094669656C644E616D65060E507265546F74616C5072696365350844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D65060B546F74616C507269636536094669
+      656C644E616D65060B546F74616C507269636536084461746154797065020608
+      4461746153697A6502080549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D650608466F726D756C6136094669656C644E616D65060846
+      6F726D756C61360844617461547970650218084461746153697A6503FF000549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060E45
+      6E64546F74616C507269636536094669656C644E616D65060E456E64546F7461
+      6C5072696365360844617461547970650206084461746153697A650208054973
+      4B6579080F4E65656450726F636573734E616D65090001044E616D65060E5072
+      65546F74616C507269636536094669656C644E616D65060E507265546F74616C
+      5072696365360844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060B546F74
+      616C507269636537094669656C644E616D65060B546F74616C50726963653708
+      44617461547970650206084461746153697A6502080549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D650608466F726D756C61370946
+      69656C644E616D650608466F726D756C61370844617461547970650218084461
+      746153697A6503FF000549734B6579080F4E65656450726F636573734E616D65
+      090001044E616D65060E456E64546F74616C507269636537094669656C644E61
+      6D65060E456E64546F74616C5072696365370844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D65060E507265546F74616C507269636537094669656C644E616D
+      65060E507265546F74616C507269636537084461746154797065020608446174
+      6153697A6502080549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060B546F74616C507269636538094669656C644E616D65060B54
+      6F74616C5072696365380844617461547970650206084461746153697A650208
+      0549734B6579080F4E65656450726F636573734E616D65090001044E616D6506
+      08466F726D756C6138094669656C644E616D650608466F726D756C6138084461
+      7461547970650218084461746153697A6503FF000549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D65060E456E64546F74616C507269
+      636538094669656C644E616D65060E456E64546F74616C507269636538084461
+      7461547970650206084461746153697A6502080549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D65060E507265546F74616C50726963
+      6538094669656C644E616D65060E507265546F74616C50726963653808446174
+      61547970650206084461746153697A6502080549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D65060B546F74616C5072696365390946
+      69656C644E616D65060B546F74616C5072696365390844617461547970650206
+      084461746153697A6502080549734B6579080F4E65656450726F636573734E61
+      6D65090001044E616D650608466F726D756C6139094669656C644E616D650608
+      466F726D756C61390844617461547970650218084461746153697A6503FF0005
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D65060E
+      456E64546F74616C507269636539094669656C644E616D65060E456E64546F74
+      616C5072696365390844617461547970650206084461746153697A6502080549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060E50
+      7265546F74616C507269636539094669656C644E616D65060E507265546F7461
+      6C5072696365390844617461547970650206084461746153697A650208054973
+      4B6579080F4E65656450726F636573734E616D65090001044E616D65060C546F
+      74616C50726963653130094669656C644E616D65060C546F74616C5072696365
+      31300844617461547970650206084461746153697A6502080549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D650609466F726D756C61
+      3130094669656C644E616D650609466F726D756C613130084461746154797065
+      0218084461746153697A6503FF000549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D65060F456E64546F74616C507269636531300946
+      69656C644E616D65060F456E64546F74616C5072696365313008446174615479
+      70650206084461746153697A6502080549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D65060F507265546F74616C5072696365313009
+      4669656C644E616D65060F507265546F74616C50726963653130084461746154
+      7970650206084461746153697A6502080549734B6579080F4E65656450726F63
+      6573734E616D65090001044E616D65060C546F74616C50726963653131094669
+      656C644E616D65060C546F74616C507269636531310844617461547970650206
+      084461746153697A6502080549734B6579080F4E65656450726F636573734E61
+      6D65090001044E616D650609466F726D756C613131094669656C644E616D6506
+      09466F726D756C6131310844617461547970650218084461746153697A6503FF
+      000549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060F456E64546F74616C50726963653131094669656C644E616D65060F456E64
+      546F74616C507269636531310844617461547970650206084461746153697A65
+      02080549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      65060F507265546F74616C50726963653131094669656C644E616D65060F5072
+      65546F74616C507269636531310844617461547970650206084461746153697A
+      6502080549734B6579080F4E65656450726F636573734E616D65090001044E61
+      6D65060C546F74616C50726963653132094669656C644E616D65060C546F7461
+      6C507269636531320844617461547970650206084461746153697A6502080549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060946
+      6F726D756C613132094669656C644E616D650609466F726D756C613132084461
+      7461547970650218084461746153697A6503FF000549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D65060F456E64546F74616C507269
+      63653132094669656C644E616D65060F456E64546F74616C5072696365313208
+      44617461547970650206084461746153697A6502080549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D65060F507265546F74616C5072
+      6963653132094669656C644E616D65060F507265546F74616C50726963653132
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D65060C546F74616C50726963
+      653133094669656C644E616D65060C546F74616C507269636531330844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D650609466F726D756C613133094669656C
+      644E616D650609466F726D756C61313308446174615479706502180844617461
+      53697A6503FF000549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060F456E64546F74616C50726963653133094669656C644E616D
+      65060F456E64546F74616C507269636531330844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D65060F456E64546F74616C50726963653134094669656C644E61
+      6D65060F456E64546F74616C5072696365313408446174615479706502060844
+      61746153697A6502080549734B6579080F4E65656450726F636573734E616D65
+      090001044E616D65060C546F74616C50726963653134094669656C644E616D65
+      060C546F74616C50726963653134084461746154797065020608446174615369
+      7A6502080549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D650609466F726D756C613134094669656C644E616D650609466F726D756C
+      6131340844617461547970650218084461746153697A6503FF000549734B6579
+      080F4E65656450726F636573734E616D65090001044E616D65060F507265546F
+      74616C50726963653133094669656C644E616D65060F507265546F74616C5072
+      69636531330844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060F50726554
+      6F74616C50726963653134094669656C644E616D65060F507265546F74616C50
+      7269636531340844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090000}
+  end
+end

+ 362 - 0
DataModules/PhasePayDm.pas

@@ -0,0 +1,362 @@
+unit PhasePayDm;
+
+interface
+
+uses
+  SysUtils, Classes, sdDB, sdProvider, ADODB, FormulaCalc;
+
+type
+  TPhasePayData = class(TDataModule)
+    sdpPhasePay: TsdADOProvider;
+    sddPhasePay: TsdDataSet;
+    procedure sddPhasePayBeforeValueChange(AValue: TsdValue;
+      const NewValue: Variant; var Allow: Boolean);
+    procedure sddPhasePayAfterValueChanged(AValue: TsdValue);
+  private
+    FPhaseData: TObject;
+    FPayFormula: TPayFormula;
+
+    FBeforeChangeTotalPrice: Double;
+
+    function CheckMinus(AID: Integer): Boolean;
+    function GetFormula(AID: Integer): string;
+    function GetCalcType(AID: Integer): Integer;
+
+    function GetPayablePrice(AIndex: Integer): Double;
+
+    procedure BeforeBatchOperation;
+    procedure AfterBatchOperation;
+
+    function GetCurPayable: Double;
+    function GetLastestPhasePay(AType: Integer): Double;
+
+    procedure SetFieldValidChar;
+  public
+    constructor Create(APhaseData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Save;
+
+    function AddPayRecord(AID: Integer): TsdDataRecord;
+    function PayRecord(AID: Integer): TsdDataRecord;
+    procedure Delete(AID: Integer);
+
+    procedure CalculateAll;
+    procedure Calculate(AID: Integer);
+    procedure CalculateCurPay;
+
+    procedure UpdateDataForNewAudit;
+    procedure CopyPrePhasePayData;
+
+    property PayablePrice[AIndex: Integer]: Double read GetPayablePrice;
+    // 本期应付
+    property CurPayable: Double read GetCurPayable;
+    // AType表示不同类型,取值如下:
+    // 1: 本期数据  2: 截止本期数据  3: 截止上期数据
+    property LastestPhasePay[AType: Integer]: Double read GetLastestPhasePay;
+  end;
+
+implementation
+
+uses
+  PhaseData, ProjectData, DealPaymentDm, BillsDm, ConstUnit;
+
+{$R *.dfm}
+
+{ TPhasePayData }
+
+constructor TPhasePayData.Create(APhaseData: TObject);
+begin
+  inherited Create(nil);
+  FPhaseData := APhaseData;
+  FPayFormula := TPayFormula.Create(TPhaseData(FPhaseData).ProjectData);
+end;
+
+procedure TPhasePayData.Delete(AID: Integer);
+begin
+  sddPhasePay.Remove(sddPhasePay.FindKey('idxID', AID));
+end;
+
+destructor TPhasePayData.Destroy;
+begin
+  FPayFormula.Free;
+  inherited;
+end;
+
+procedure TPhasePayData.UpdateDataForNewAudit;
+var
+  iNewAudit, iIndex: Integer;
+  Rec: TsdDataRecord;
+begin
+  BeforeBatchOperation;
+  try
+    iNewAudit := TPhaseData(FPhaseData).PhaseProperty.AuditCount;
+    for iIndex := 0 to sddPhasePay.RecordCount - 1 do
+    begin
+      Rec := sddPhasePay.Records[iIndex];
+      Rec.ValueByName('TotalPrice' + IntToStr(iNewAudit)).AsString :=
+        Rec.ValueByName('TotalPrice' + IntToStr(iNewAudit - 1)).AsString;
+      Rec.ValueByName('Formula' + IntToStr(iNewAudit)).AsString :=
+        Rec.ValueByName('Formula' + IntToStr(iNewAudit - 1)).AsString;
+      Rec.ValueByName('EndTotalPrice' + IntToStr(iNewAudit)).AsString :=
+        Rec.ValueByName('EndTotalPrice' + IntToStr(iNewAudit - 1)).AsString;
+      Rec.ValueByName('PreTotalPrice' + IntToStr(iNewAudit)).AsString :=
+        Rec.ValueByName('PreTotalPrice' + IntToStr(iNewAudit - 1)).AsString;
+    end;
+  finally
+    AfterBatchOperation;
+  end;
+end;
+
+procedure TPhasePayData.Open(AConnection: TADOConnection);
+begin
+  sdpPhasePay.Connection := AConnection;
+  sddPhasePay.Open;
+  if not Assigned(sddPhasePay.IndexList.FindByName('idxID')) then
+    sddPhasePay.AddIndex('idxID', 'ID');
+  SetFieldValidChar;
+  // 为适应旧项目处不计算合同支付值所做修改。
+  if sddPhasePay.RecordCount = 0 then
+  begin
+    CopyPrePhasePayData;
+    CalculateAll;
+  end;
+end;
+
+procedure TPhasePayData.Save;
+begin
+  sddPhasePay.Save;
+end;
+
+function TPhasePayData.AddPayRecord(AID: Integer): TsdDataRecord;
+begin
+  Result := sddPhasePay.Add;
+  Result.ValueByName('ID').AsInteger := AID;
+end;
+
+procedure TPhasePayData.sddPhasePayBeforeValueChange(AValue: TsdValue;
+  const NewValue: Variant; var Allow: Boolean);
+begin
+  if not Assigned(AValue) then Exit;
+  if Pos('TotalPrice', AValue.FieldName) = 1 then
+    FBeforeChangeTotalPrice := AValue.AsFloat; 
+end;
+
+procedure TPhasePayData.sddPhasePayAfterValueChanged(AValue: TsdValue);
+begin
+  if Pos('TotalPrice', AValue.FieldName) = 1 then
+  begin
+    AValue.Owner.ValueByName('End' + AValue.FieldName).AsFloat := AValue.AsFloat
+        + AValue.Owner.ValueByName('Pre' + AValue.FieldName).AsFloat;
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do
+      UpdateTotalPrice(AValue.Owner.ValueByName('ID').AsInteger, AValue.AsFloat - FBeforeChangeTotalPrice);
+  end;
+  CalculateCurPay;      
+end;
+
+procedure TPhasePayData.CalculateAll;
+var
+  iIndex: Integer;
+begin
+  if TPhaseData(FPhaseData).StageDataReadOnly then Exit;
+  for iIndex := 0 to sddPhasePay.RecordCount - 1 do
+    Calculate(sddPhasePay.Records[iIndex].ValueByName('ID').AsInteger);
+  CalculateCurPay;
+end;
+
+procedure TPhasePayData.Calculate(AID: Integer);
+var
+  Rec: TsdDataRecord;
+  // 金额列名, 公式列名
+  sTPField, sFField: string;
+  iID: Integer;
+  fTotalPrice, fStartedPrice: Double;
+begin
+  Rec := sddPhasePay.FindKey('idxID', AID);
+  sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).StageIndex);
+  sFField := 'Formula' + IntToStr(TPhaseData(FPhaseData).StageIndex);
+  if Rec.ValueByName(sFField).AsString <> '' then
+  begin
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do
+    begin
+      iID := Rec.ValueByName('ID').AsInteger;
+      // 获取起扣金额
+      fStartedPrice :=  GetStartedPrice(iID);
+      // 初次达到起扣金额时,bqwc基数值取值为累计完成计量-起扣金额
+      if Rec.ValueByName('Pre'+sTPField).AsFloat = 0 then
+        fTotalPrice := FPayFormula.Calculate(Rec.ValueByName(sFField).AsString, fStartedPrice) - Rec.ValueByName(sTPField).AsFloat
+      else
+        fTotalPrice := FPayFormula.Calculate(Rec.ValueByName(sFField).AsString) - Rec.ValueByName(sTPField).AsFloat;
+      if CheckStartedPrice(iID) then
+        Rec.ValueByName(sTPField).AsFloat := Rec.ValueByName(sTPField).AsFloat + GetAllowTotalPrice(iID, fTotalPrice)
+      else
+        Rec.ValueByName(sTPField).AsFloat := 0;
+    end;
+  end;
+  // 计算截止数据
+  Rec.ValueByName('End' + sTPField).AsFloat := Rec.ValueByName(sTPField).AsFloat
+      + Rec.ValueByName('Pre' + sTPField).AsFloat;
+end;
+
+function TPhasePayData.GetPayablePrice(AIndex: Integer): Double;
+var
+  iIndex: Integer;
+  sTotalPriceField: string;
+  Rec: TsdDataRecord;
+begin
+  Result := 0;
+  // 阶段在0--14之间
+  if (AIndex < 0) or (AIndex > iMaxStageCount-1) then Exit;
+
+  sTotalPriceField := 'TotalPrice' + IntToStr(AIndex);
+  for iIndex := 0 to sddPhasePay.RecordCount - 1 do
+  begin
+    Rec := sddPhasePay.Records[iIndex];
+    if CheckMinus(Rec.ValueByName('ID').AsInteger) then
+      Result := Result - Rec.ValueByName(sTotalPriceField).AsFloat
+    else
+      Result := Result + Rec.ValueByName(sTotalPriceField).AsFloat;
+  end;
+end;
+
+function TPhasePayData.CheckMinus(AID: Integer): Boolean;
+begin
+  with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do
+    Result := sddDealPayment.FindKey('idxID', AID).ValueByName('IsMinus').AsBoolean;
+end;
+
+function TPhasePayData.GetFormula(AID: Integer): string;
+begin
+  with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do
+    Result := sddDealPayment.FindKey('idxID', AID).ValueByName('Formula').AsString;
+end;
+
+procedure TPhasePayData.AfterBatchOperation;
+begin
+  sddPhasePay.BeforeValueChange := sddPhasePayBeforeValueChange;
+  sddPhasePay.AfterValueChanged := sddPhasePayAfterValueChanged;
+end;
+
+procedure TPhasePayData.BeforeBatchOperation;
+begin
+  sddPhasePay.BeforeValueChange := nil;
+  sddPhasePay.AfterValueChanged := nil;
+end;
+
+procedure TPhasePayData.CalculateCurPay;
+var
+  Rec: TsdDataRecord;
+  sTPField: string;
+  I: Integer;
+begin
+  sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).StageIndex);
+  for I := 0 to sddPhasePay.RecordCount - 1 do
+  begin
+    Rec := sddPhasePay.Records[I];
+    if GetCalcType(Rec.ValueByName('ID').AsInteger) = 1 then
+    begin
+      Rec.ValueByName(sTPField).AsFloat := CurPayable;
+      Rec.ValueByName('End' + sTPField).AsFloat := Rec.ValueByName(sTPField).AsFloat
+          + Rec.ValueByName('Pre' + sTPField).AsFloat;
+      Break;
+    end;
+  end;
+end;
+
+function TPhasePayData.GetCurPayable: Double;
+var
+  Rec: TsdDataRecord;
+  sTPField: string;
+  i: Integer;
+begin
+  sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).StageIndex);
+  Result := 0;
+  for I := 0 to sddPhasePay.RecordCount - 1 do
+  begin
+    Rec := sddPhasePay.Records[I];
+    // 检查是否为一般项
+    if GetCalcType(Rec.ValueByName('ID').AsInteger) = 0 then
+      if CheckMinus(Rec.ValueByName('ID').AsInteger) then
+        Result := Result - Rec.ValueByName(sTPField).AsFloat
+      else
+        Result := Result + Rec.ValueByName(sTPField).AsFloat;
+  end;
+end;
+
+function TPhasePayData.GetCalcType(AID: Integer): Integer;
+var
+  Rec: TsdDataRecord;
+begin
+  Result := 0;
+  with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do
+    Rec := sddDealPayment.FindKey('idxID', AID);
+  if Assigned(Rec) then
+    Result := Rec.ValueByName('CalcType').AsInteger;
+end;
+
+function TPhasePayData.GetLastestPhasePay(AType: Integer): Double;
+var
+  Rec: TsdDataRecord;
+  sTPField: string;
+  i: Integer;
+begin
+  case AType of
+    1: sTPField := 'TotalPrice' + IntToStr(TPhaseData(FPhaseData).PhaseProperty.AuditCount);
+    2: sTPField := 'EndTotalPrice' + IntToStr(TPhaseData(FPhaseData).PhaseProperty.AuditCount);
+    3: sTPField := 'PreTotalPrice' + IntToStr(TPhaseData(FPhaseData).PhaseProperty.AuditCount);
+  end;
+  Result := 0;
+  for i := 0 to sddPhasePay.RecordCount - 1 do
+  begin
+    Rec := sddPhasePay.Records[i];
+    // 检查是否为一般项
+    if GetCalcType(Rec.ValueByName('ID').AsInteger) = 0 then
+      if CheckMinus(Rec.ValueByName('ID').AsInteger) then
+        Result := Result - Rec.ValueByName(sTPField).AsFloat
+      else
+        Result := Result + Rec.ValueByName(sTPField).AsFloat;
+  end;
+end;
+
+procedure TPhasePayData.CopyPrePhasePayData;
+var
+  iRecord: Integer;
+  Rec, NewRec: TsdDataRecord;
+begin
+  BeforeBatchOperation;
+  try
+    if sddPhasePay.RecordCount > 0 then Exit;
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).DealPaymentData do
+      for iRecord := 0 to sddDealPayment.RecordCount - 1 do
+      begin
+        Rec := sddDealPayment.Records[iRecord];
+        NewRec := sddPhasePay.Add;
+        NewRec.ValueByName('ID').AsInteger := Rec.ValueByName('ID').AsInteger;
+        NewRec.ValueByName('EndTotalPrice0').AsFloat := Rec.ValueByName('TotalPrice').AsFloat;
+        NewRec.ValueByName('PreTotalPrice0').AsFloat := Rec.ValueByName('TotalPrice').AsFloat;
+        NewRec.ValueByName('Formula0').AsString := Rec.ValueByName('Formula').AsString;
+      end;
+  finally
+    AfterBatchOperation;
+  end;
+end;
+
+procedure TPhasePayData.SetFieldValidChar;
+var
+  i: Integer;
+  sField: string;
+begin
+  for i := 0 to iMaxStageCount - 1 do
+  begin
+    sField := 'TotalPrice' + IntToStr(i);
+    sddPhasePay.FieldByName(sField).ValidChars := sddPhasePay.FieldByName(sField).ValidChars + ArithmeticCharSet + ExprsBaseCharSet;
+  end;
+end;
+
+function TPhasePayData.PayRecord(AID: Integer): TsdDataRecord;
+begin
+  Result := sddPhasePay.FindKey('idxID', AID);
+end;
+
+end.

+ 194 - 0
DataModules/ProjectManagerDm.dfm

@@ -0,0 +1,194 @@
+object ProjectManagerData: TProjectManagerData
+  OldCreateOrder = False
+  OnCreate = DataModuleCreate
+  Left = 713
+  Top = 241
+  Height = 223
+  Width = 227
+  object sdpProjectsInfo: TsdADOProvider
+    TableName = 'ProjectsInfo'
+    Left = 40
+    Top = 16
+  end
+  object sddProjectsInfo: TsdDataSet
+    Active = False
+    Provider = sdpProjectsInfo
+    Left = 40
+    Top = 72
+    FieldListData = {
+      0101044E616D6506024944094669656C644E616D650602494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D650608506172656E744944094669656C644E61
+      6D650608506172656E7449440844617461547970650203084461746153697A65
+      02040549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      65060D4E6578745369626C696E674944094669656C644E616D65060D4E657874
+      5369626C696E6749440844617461547970650203084461746153697A65020405
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650604
+      4E616D65094669656C644E616D6506044E616D65084461746154797065021808
+      4461746153697A6503FF000549734B6579080F4E65656450726F636573734E61
+      6D65090001044E616D65060454797065094669656C644E616D65060454797065
+      0844617461547970650203084461746153697A6502040549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D65060E4465616C546F74616C
+      5072696365094669656C644E616D65060E4465616C546F74616C507269636508
+      44617461547970650206084461746153697A6502080549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D65060F5068617365546F74616C
+      5072696365094669656C644E616D65060F5068617365546F74616C5072696365
+      0844617461547970650206084461746153697A6502080549734B6579080F4E65
+      656450726F636573734E616D65090001044E616D650611456E644465616C546F
+      74616C5072696365094669656C644E616D650611456E644465616C546F74616C
+      50726963650844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D650613456E6443
+      68616E6765546F74616C5072696365094669656C644E616D650613456E644368
+      616E6765546F74616C5072696365084461746154797065020608446174615369
+      7A6502080549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D65060D456E64546F74616C5072696365094669656C644E616D65060D456E
+      64546F74616C50726963650844617461547970650206084461746153697A6502
+      080549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060D507265546F74616C5072696365094669656C644E616D65060D507265546F
+      74616C50726963650844617461547970650206084461746153697A6502080549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060850
+      68617365506179094669656C644E616D65060850686173655061790844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D65060A5068617365436F756E7409466965
+      6C644E616D65060A5068617365436F756E740844617461547970650203084461
+      746153697A6502040549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D65060B4175646974537461747573094669656C644E616D65060B
+      41756469745374617475730844617461547970650203084461746153697A6502
+      040549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060846696C654E616D65094669656C644E616D65060846696C654E616D650844
+      617461547970650201084461746153697A6503FF000549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D65060A43726561746544617465
+      094669656C644E616D65060A4372656174654461746508446174615479706502
+      01084461746153697A6503FF000549734B6579080F4E65656450726F63657373
+      4E616D65090001044E616D65060C4261636B7570466F6C646572094669656C64
+      4E616D65060C4261636B7570466F6C6465720844617461547970650218084461
+      746153697A6502320549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D6506124465616C5F42474C546F74616C5072696365094669656C
+      644E616D6506124465616C5F42474C546F74616C507269636508446174615479
+      70650206084461746153697A6502080549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D6506055765624944094669656C644E616D6506
+      0557656249440844617461547970650203084461746153697A6502040549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060A576562
+      4F776E65724944094669656C644E616D65060A5765624F776E65724944084461
+      7461547970650203084461746153697A6502040549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D65060B576562417574686F72494409
+      4669656C644E616D65060B576562417574686F72494408446174615479706502
+      03084461746153697A6502040549734B6579080F4E65656450726F636573734E
+      616D65090001044E616D6506065765624D4435094669656C644E616D65060657
+      65624D44350844617461547970650201084461746153697A6503FF000549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D650609576562
+      557365724944094669656C644E616D6506095765625573657249440844617461
+      547970650203084461746153697A6502040549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D65060E576562466F6C6465724C6576656C
+      094669656C644E616D65060E576562466F6C6465724C6576656C084461746154
+      7970650203084461746153697A6502040549734B6579080F4E65656450726F63
+      6573734E616D65090001044E616D6506065765624B6579094669656C644E616D
+      6506065765624B65790844617461547970650201084461746153697A6503FF00
+      0549734B6579080F4E65656450726F636573734E616D65090000}
+  end
+  object sdvProjectsInfo: TsdDataView
+    Active = False
+    DataSet = sddProjectsInfo
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'ParentID'
+      end
+      item
+        FieldName = 'NextSiblingID'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Type'
+      end
+      item
+        FieldName = 'DealTotalPrice'
+      end
+      item
+        FieldName = 'PhaseTotalPrice'
+      end
+      item
+        FieldName = 'EndDealTotalPrice'
+      end
+      item
+        FieldName = 'EndChangeTotalPrice'
+      end
+      item
+        FieldName = 'EndTotalPrice'
+      end
+      item
+        FieldName = 'PreTotalPrice'
+      end
+      item
+        FieldName = 'PhasePay'
+      end
+      item
+        FieldName = 'PhaseCount'
+      end
+      item
+        FieldName = 'AuditStatus'
+      end
+      item
+        FieldName = 'FileName'
+      end
+      item
+        FieldName = 'CreateDate'
+      end
+      item
+        FieldName = 'BackupFolder'
+      end
+      item
+        FieldName = 'Deal_BGLTotalPrice'
+      end
+      item
+        FieldName = 'WebID'
+      end
+      item
+        FieldName = 'WebOwnerID'
+      end
+      item
+        FieldName = 'WebAuthorID'
+      end
+      item
+        FieldName = 'WebMD5'
+      end
+      item
+        FieldName = 'WebUserID'
+      end
+      item
+        FieldName = 'WebFolderLevel'
+      end
+      item
+        FieldName = 'WebKey'
+      end>
+    BeforeDeleteRecord = sdvProjectsInfoBeforeDeleteRecord
+    OnFilterRecord = sdvProjectsInfoFilterRecord
+    OnGetText = sdvProjectsInfoGetText
+    Left = 40
+    Top = 128
+  end
+  object sdpTenderProperty: TsdADOProvider
+    TableName = 'TenderProperty'
+    Left = 136
+    Top = 16
+  end
+  object sddTenderProperty: TsdDataSet
+    Active = False
+    Provider = sdpTenderProperty
+    Left = 136
+    Top = 72
+  end
+  object sdvTenderProperty: TsdDataView
+    Active = False
+    DataSet = sddTenderProperty
+    Filtered = False
+    Columns = <>
+    Left = 136
+    Top = 128
+  end
+end

+ 587 - 0
DataModules/ProjectManagerDm.pas

@@ -0,0 +1,587 @@
+unit ProjectManagerDm;
+
+interface
+
+uses
+  TenderBackupManager,
+  SysUtils, Classes, DB, DBClient, Provider, ADODB, Connections, ZhAPI,
+  sdDB, sdProvider, sdIDTree;
+
+type
+  TProjectManagerData = class(TDataModule)
+    sdpProjectsInfo: TsdADOProvider;
+    sddProjectsInfo: TsdDataSet;
+    sdvProjectsInfo: TsdDataView;
+    sdpTenderProperty: TsdADOProvider;
+    sddTenderProperty: TsdDataSet;
+    sdvTenderProperty: TsdDataView;
+    procedure sdvProjectsInfoGetText(var Text: String;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      DisplayText: Boolean);
+    procedure sdvProjectsInfoFilterRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+    procedure DataModuleCreate(Sender: TObject);
+    procedure sdvProjectsInfoBeforeDeleteRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+  private
+    FConnection: TEncryptConnection;
+    FProjectsTree: TsdIDTree;
+    FBackupManager: TBackupManager;
+
+    procedure UpdateManagerDataBase;
+
+    //procedure ReNameCurrentProject(const AName: string);
+    procedure CreateNewProjectFile(const AName: string);
+    procedure DeleteAllTenderFiles(ANode: TsdIDTreeNode);
+    procedure DeleteAttachmentFiles(ANode: TsdIDTreeNode);
+
+    function CreateBackupFolder(AProjectID: Integer): string;
+
+    procedure ExportTender(ARec: TsdDataRecord; AFileName: string);
+
+    function NewID: Integer;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    procedure Open;
+    procedure Save;
+
+    function HasProject: Boolean;
+    function ExistProject(const AName: string; ANode: TsdIDTreeNode): Boolean;
+    function ProjectID(const AName: string; ANode: TsdIDTreeNode): Integer;
+    // 云版要记下网络文件夹的ID和层次。
+    function InsertProject(const AName: string; APreNode: TsdIDTreeNode; AFolderID: Integer = -1; AFolderLevel: Integer = -1): TsdIDTreeNode;
+    function InsertSubProject(const AName: string; AParent: TsdIDTreeNode; AFolderID: Integer = -1; AFolderLevel: Integer = -1): TsdIDTreeNode;
+    function InsertTender(const AName: string; AParent: TsdIDTreeNode): TsdIDTreeNode;
+    procedure Delete;
+    procedure ReName(const AName: string; ANode: TsdIDTreeNode);
+    procedure RestoreTender(AID: Integer);
+    procedure RefreshSeedID;
+
+    function BackupPath(AProjectID: Integer): String;
+    procedure AddOpenTenderBackup(AProjectID: Integer);
+    procedure AddSaveTenderBackup(AProjectID: Integer);
+
+    property ProjectsTree: TsdIDTree read FProjectsTree;
+  end;
+
+implementation
+
+uses
+  UtilMethods, UpdateDataBase, ProjectCommands, PHPWebDm, ConstUnit;
+
+{$R *.dfm}
+
+{ TProjectManagerData }
+
+constructor TProjectManagerData.Create;
+begin
+  inherited Create(nil);
+  FConnection := TEncryptConnection.Create;
+  FProjectsTree := TsdIDTree.Create;
+  FProjectsTree.KeyFieldName := 'ID';
+  FProjectsTree.ParentFieldName := 'ParentID';
+  FProjectsTree.NextSiblingFieldName := 'NextSiblingID';
+  FProjectsTree.AutoCreateKeyID := True;
+  FProjectsTree.AutoExpand := True;
+  FProjectsTree.SeedID := 1;
+  FProjectsTree.DataView := sdvProjectsInfo;
+
+  FBackupManager := TBackupManager.Create;
+end;
+
+procedure TProjectManagerData.CreateNewProjectFile(const AName: string);
+var
+  TempFolder: string;
+begin
+  try
+    TempFolder := GenerateTempFolder(GetTempFilePath);
+    CopyFileOrFolder(GetEmptyDataBaseFileName, TempFolder + '\Main.dat');
+    ZipFolder(TempFolder, GetMyProjectsFilePath + AName);
+  finally
+    DeleteFileOrFolder(TempFolder);
+  end;
+end;
+
+procedure TProjectManagerData.Delete;
+begin
+  if HasProject then
+  begin
+    DeleteAttachmentFiles(FProjectsTree.Selected);
+    DeleteAllTenderFiles(FProjectsTree.Selected);
+    FProjectsTree.DeleteNode(FProjectsTree.Selected);
+    Save;
+  end;
+end;
+
+destructor TProjectManagerData.Destroy;
+begin
+  FBackupManager.Free;
+  FProjectsTree.Free;
+  FConnection.Free;
+  inherited;
+end;
+
+function TProjectManagerData.ExistProject(const AName: string;
+  ANode: TsdIDTreeNode): Boolean;
+var
+  vCur: TsdIDTreeNode;
+begin
+  Result := False;
+  if not Assigned(ANode) then Exit;
+  vCur := ANode.FirstChild;
+
+  while not Result and Assigned(vCur) do
+  begin
+    Result := vCur.Rec.ValueByName('Name').AsString = AName;
+    vCur := vCur.NextSibling;
+  end;
+end;
+
+function TProjectManagerData.HasProject: Boolean;
+begin
+  Result := sddProjectsInfo.RecordCount > 0;
+end;
+
+function TProjectManagerData.InsertProject(const AName: string;
+  APreNode: TsdIDTreeNode; AFolderID: Integer; AFolderLevel: Integer): TsdIDTreeNode;
+var
+  vNew: TsdIDTreeNode;
+  bOnLine, bCanCreate: Boolean;
+begin
+  // 云版判断是否已存在的标准是服务端传来的ID,不是单机版所使用的名称。
+  // 判断条件写在这里面不合适,因为云版调用不正确,应该写到方法外面。
+  // 现在已经这样了,改起来麻烦,先补丁的方式用着。
+  if G_IsCloud then
+    bCanCreate := True
+  else if (not G_IsCloud) and (not Assigned(APreNode)
+    or not ExistProject(AName, APreNode.Parent)) then
+    bCanCreate := True
+  else
+    bCanCreate := False;
+
+  if bCanCreate then
+  begin
+    RefreshSeedID;
+    if Assigned(APreNode) then
+      vNew := FProjectsTree.Add(APreNode.ParentID, APreNode.NextSiblingID)
+    else
+      vNew := FProjectsTree.Add(-1, -1);
+    vNew.Rec.BeginUpdate;
+    vNew.Rec.ValueByName('Type').AsInteger := 0;
+    vNew.Rec.ValueByName('Name').AsString := AName;
+
+    {---------------------------------------------------------------------------
+     恼火的问题:直接写成下面这样,则第二句编译不进:
+      if G_IsOnLine then
+        vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
+     这里用局部变量bOnLine转接一下,能解决问题。
+    ---------------------------------------------------------------------------}
+    bOnLine := G_IsCloud;
+    if bOnLine then
+    begin
+      vNew.Rec.ValueByName('WebID').AsInteger := AFolderID;
+      vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
+      vNew.Rec.ValueByName('WebFolderLevel').AsInteger := AFolderLevel;
+    end;
+
+
+    vNew.Rec.EndUpdate;
+    Result := vNew;
+    Save;
+  end
+  else
+    raise Exception.Create('存在同名类别!');
+end;
+
+function TProjectManagerData.InsertSubProject(const AName: string;
+  AParent: TsdIDTreeNode; AFolderID: Integer; AFolderLevel: Integer): TsdIDTreeNode;
+var
+  vNew: TsdIDTreeNode;
+  bOnLine, bCanCreate: Boolean;
+begin
+  if G_IsCloud then
+    bCanCreate := True
+  else if (not G_IsCloud) and (not ExistProject(AName, AParent)) then
+    bCanCreate := True
+  else
+    bCanCreate := False;
+
+  if bCanCreate then
+  begin
+    RefreshSeedID;
+    vNew := FProjectsTree.Add(AParent.ID, -1);
+    vNew.Rec.ValueByName('Type').AsInteger := 0;
+    vNew.Rec.ValueByName('Name').AsString := AName;
+
+    {---------------------------------------------------------------------------
+     恼火的问题:直接写成下面这样,则第二句编译不进:
+      if G_IsOnLine then
+        vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
+     这里用局部变量bOnLine转接一下,能解决问题。
+    ---------------------------------------------------------------------------}
+    bOnLine := G_IsCloud;
+    if bOnLine then
+    begin
+      vNew.Rec.ValueByName('WebID').AsInteger := AFolderID;
+      vNew.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
+      vNew.Rec.ValueByName('WebFolderLevel').AsInteger := AFolderLevel;
+    end;
+
+    Result := vNew;
+    Save;
+  end
+  else
+    raise Exception.Create('存在同名类别!');
+end;
+
+function TProjectManagerData.InsertTender(const AName: string;
+  AParent: TsdIDTreeNode): TsdIDTreeNode;
+var bOnLine: Boolean;
+begin
+  if not ExistProject(AName, AParent) then
+  begin
+    RefreshSeedID;
+    Result := FProjectsTree.Add(AParent.ID, -1);
+
+    {---------------------------------------------------------------------------
+     恼火的问题:直接写成下面这样,则第二句编译不进:
+      if G_IsOnLine then
+        Result.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
+     这里用局部变量bOnLine转接一下,能解决问题。
+    ---------------------------------------------------------------------------}
+
+//    if G_IsOnLine then
+//      Result.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;  // 编译不进
+
+    bOnLine := G_IsCloud;
+    if bOnLine then
+      Result.Rec.ValueByName('WebUserID').AsInteger := PHPWeb.UserID;
+      
+    Result.Rec.ValueByName('Type').AsInteger := 1;
+    Result.Rec.ValueByName('Name').AsString := AName;
+    Result.Rec.ValueByName('PhaseCount').AsInteger := 0;
+    Result.Rec.ValueByName('AuditStatus').AsInteger := 0;
+    Result.Rec.ValueByName('FileName').AsString :=
+      ExtractSimpleFileName(GetNewGUIDFileName(GetMyProjectsFilePath));
+    Result.Rec.ValueByName('CreateDate').AsString := FormatDateTime('yyyy-mm-dd', Date);
+    CreateNewProjectFile(Result.Rec.ValueByName('FileName').AsString);
+    Save;
+  end
+  else
+    raise Exception.Create('存在同名标段!');
+end;
+
+procedure TProjectManagerData.Open;
+var
+  FQuery: TADOQuery;
+begin
+  FConnection.Open(GetAppFilePath + 'Data\ProjectManager.dat');
+
+  UpdateManagerDataBase;
+  sdpProjectsInfo.Connection := FConnection.Connection;
+  sddProjectsInfo.Open;
+  sdvProjectsInfo.Open;
+  sddProjectsInfo.AddIndex('idxID', 'ID');
+  sdvProjectsInfo.IndexName := 'idxID';
+  sdpTenderProperty.Connection := FConnection.Connection;
+  sddTenderProperty.Open;
+  sdvTenderProperty.Open;
+end;
+
+procedure TProjectManagerData.Save;
+begin
+  sddTenderProperty.Save;
+  sddProjectsInfo.Save;
+  FConnection.Save;
+end;
+
+procedure TProjectManagerData.UpdateManagerDataBase;
+var
+  vUpdator: TUpdateManagerDB;
+begin
+  vUpdator := TUpdateManagerDB.Create;
+  try
+    vUpdator.Update(FConnection);
+  finally
+    vUpdator.Free;
+  end;
+end;
+
+procedure TProjectManagerData.sdvProjectsInfoGetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  DisplayText: Boolean);
+
+  function NumToAuditStatus(AValue: Integer): string;
+  begin
+    case AValue of
+      -1:
+        if ARecord.ValueByName('PhaseCount').AsInteger = 0 then
+          Result := '原报'
+        else
+          Result := '批复';
+      0:
+        Result := '原报';
+    else
+      Result := Format('%d 审', [AValue]);
+    end;
+  end;
+
+begin
+  if not Assigned(ARecord) then Exit;
+  if SameText(AColumn.FieldName, 'AuditStatus') then
+    if ARecord.ValueByName('Type').AsInteger = 1 then
+      Text := NumToAuditStatus(AValue.AsInteger)
+    else
+      Text := '';
+end;
+
+procedure TProjectManagerData.DeleteAllTenderFiles(ANode: TsdIDTreeNode);
+var
+  iChild: Integer;
+begin
+  if ANode.HasChildren then
+    for iChild := 0 to ANode.ChildCount - 1 do
+      DeleteAllTenderFiles(ANode.ChildNodes[iChild])
+  else if ANode.Rec.ValueByName('Type').AsInteger = 1 then
+    DeleteFile(GetMyProjectsFilePath + ANode.Rec.ValueByName('FileName').AsString);
+end;
+
+procedure TProjectManagerData.ReName(const AName: string;
+  ANode: TsdIDTreeNode);
+begin
+  ANode.Rec.ValueByName('Name').AsString := AName;
+  Save;
+end;
+
+procedure TProjectManagerData.RestoreTender(AID: Integer);
+var
+  vNode: TsdIDTreeNode;
+  sRestoreFile: string;
+  Exportor: TTenderExport;
+begin
+  vNode := FProjectsTree.FindNode(AID);
+  if not FileExists(GetMyProjectsFilePath + vNode.Rec.ValueByName('FileName').AsString) then Exit;
+
+  sRestoreFile := GetBackUpFilePath + vNode.Rec.ValueByName('Name').AsString
+      + '[' + FormatDateTime('yyyy-mm-dd hh,nn,ss', Now) + '].mtf';
+  Exportor := TTenderExport.Create(vNode.Rec, sRestoreFile);
+  try
+    Exportor.Execute;
+  finally
+    Exportor.Free;
+  end;
+end;
+
+procedure TProjectManagerData.sdvProjectsInfoFilterRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+begin
+  if G_IsCloud then
+  begin
+    if ARecord.ValueByName('WebUserID').AsInteger = PHPWeb.UserID then
+      Allow := True
+    else
+      Allow := False;
+  end
+  else
+  begin
+    if ARecord.ValueByName('WebUserID').AsInteger = 0 then
+      Allow := True
+    else
+      Allow := False;
+  end;
+end;
+
+procedure TProjectManagerData.DataModuleCreate(Sender: TObject);
+begin
+  // 单机版也要过滤:防止单机版程序能显示所有用户的项目。
+//  if G_IsOnLine then
+    sdvProjectsInfo.Filtered := True;
+end;
+
+function TProjectManagerData.NewID: Integer;
+var
+  idxID: TsdIndex;
+begin
+  idxID := sddProjectsInfo.FindIndex('idxID');
+  Result := idxID.Records[idxID.RecordCount - 1].ValueByName('ID').AsInteger + 1;
+end;
+
+procedure TProjectManagerData.RefreshSeedID;
+begin
+  FProjectsTree.SeedID := NewID;
+end;
+
+function TProjectManagerData.BackupPath(AProjectID: Integer): String;
+var
+  Rec: TsdDataRecord;
+begin
+  Result := GetAppFilePath + 'FileBackup\TenderBackup';
+  Rec := ProjectsTree.FindNode(AProjectID).Rec;
+  if Rec.ValueByName('BackupFolder').AsString = '' then
+    Rec.ValueByName('BackupFolder').AsString := CreateBackupFolder(AProjectID);
+  Result := Result + '\' + Rec.ValueByName('BackupFolder').AsString + '\';
+end;
+
+function TProjectManagerData.CreateBackupFolder(
+  AProjectID: Integer): string;
+
+  function GetParentNames(ANode: TsdIDTreeNode): string;
+  var
+    stnParent: TsdIDTreeNode;
+  begin
+    Result := '';
+    stnParent := ANode.Parent;
+    while Assigned(stnParent) do
+    begin
+      if Result <> '' then
+        Result := stnParent.Rec.ValueByName('Name').AsString + '--' + Result
+      else
+        Result := stnParent.Rec.ValueByName('Name').AsString;
+      stnParent := stnParent.Parent;
+    end;
+  end;
+
+var
+  stnNode: TsdIDTreeNode;
+  sGUID, sPath: string;
+  sgs: TStringList;
+begin
+  stnNode := ProjectsTree.FindNode(AProjectID);
+  Result := stnNode.Rec.ValueByName('BackupFolder').AsString;
+  if Result <> '' then Exit;
+
+  sPath := GetAppFilePath + 'FileBackup\TenderBackup\';
+  sGUID := GetNewGUIDFileName(sPath);
+  if FileExists(sGUID) then DeleteFile(sGUID);
+  CreateDirectoryInDeep(sGUID);
+  sgs := TStringList.Create;
+  try
+    sgs.Add('项目备份文件夹');
+    sgs.Add(Format('项目名称:%s', [stnNode.Rec.ValueByName('Name').AsString]));
+    sgs.Add(Format('所属项目:%s', [GetParentNames(stnNode)]));
+    sgs.Add(Format('创建时间:%s', [DateTimeToStr(Now)]));
+  finally
+    sgs.SaveToFile(sGUID + '\说明.txt');
+    sgs.Free;
+  end;
+  Result := ExtractSimpleFileName(sGUID)
+end;
+
+procedure TProjectManagerData.sdvProjectsInfoBeforeDeleteRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+var
+  sOrgFolder, sNewFolder: string;
+begin
+  if ARecord.ValueByName('BackupFolder').AsString <> '' then
+  begin
+    sOrgFolder := GetAppFilePath + 'FileBackup\TenderBackup\'
+                + ARecord.ValueByName('BackupFolder').AsString;
+    sNewFolder := GetAppFilePath + 'FileBackup\RecycleBackup\'
+                + ARecord.ValueByName('BackupFolder').AsString;
+    CopyFileOrFolder(sOrgFolder, sNewFolder);
+    DeleteFileOrFolder(sOrgFolder);
+  end;
+end;
+
+procedure TProjectManagerData.AddOpenTenderBackup(AProjectID: Integer);
+var
+  BackupRec, Rec: TsdDataRecord;
+  sBackupFile: string;
+begin
+  Rec := sddProjectsInfo.FindKey('idxID', AProjectID);
+  if not Assigned(Rec) then Exit;
+
+  FBackupManager.LoadBackupFile(BackupPath(AProjectID));
+  if FBackupManager.LastestOpenBackupIsToday then Exit;
+  sBackupFile := FBackupManager.OpenBackupFile;
+  if FileExists(sBackupFile) then DeleteFile(sBackupFile);
+  ExportTender(Rec, sBackupFile);
+end;
+
+procedure TProjectManagerData.AddSaveTenderBackup(AProjectID: Integer);
+var
+  BackupRec, Rec: TsdDataRecord;
+  sBackupFile: string;
+begin
+  Rec := sddProjectsInfo.FindKey('idxID', AProjectID);
+  if not Assigned(Rec) then Exit;
+
+  FBackupManager.LoadBackupFile(BackupPath(AProjectID));
+  sBackupFile := FBackupManager.SaveBackupFile;
+  if FileExists(sBackupFile) then DeleteFile(sBackupFile);
+  ExportTender(Rec, sBackupFile);
+end;
+
+procedure TProjectManagerData.ExportTender(ARec: TsdDataRecord;
+  AFileName: string);
+var
+  Exportor : TTenderExport;
+begin
+  Exportor := TTenderExport.Create(ARec, AFileName);
+  try
+    Exportor.Execute;
+  finally
+    Exportor.Free;
+  end;
+end;
+
+function TProjectManagerData.ProjectID(const AName: string;
+  ANode: TsdIDTreeNode): Integer;
+var
+  vCur: TsdIDTreeNode;
+begin
+  Result := -1;
+  if not Assigned(ANode) then Exit;
+  vCur := ANode.FirstChild;
+
+  while (Result = -1) and Assigned(vCur) do
+  begin
+    if vCur.Rec.ValueByName('Name').AsString = AName then
+      Result := vCur.ID;
+    vCur := vCur.NextSibling;
+  end;
+end;
+
+procedure TProjectManagerData.DeleteAttachmentFiles(ANode: TsdIDTreeNode);
+var sDir: string;
+
+  procedure DeleteAtch(ANode: TsdIDTreeNode);
+  begin
+    // 如果文件名为空,删除时会删除整个附件文件夹,危险!
+    if ANode.Rec.ValueByName('FileName').AsString = '' then Exit;
+    sDir := GetMyProjectsFilePath + 'Attachment\' + ANode.Rec.ValueByName('FileName').AsString;
+    DeleteFolder(sDir);
+  end;
+
+  procedure DeleteNodes(ANode: TsdIDTreeNode);
+  begin
+    if ANode = nil then Exit; 
+
+    if ANode.FirstChild <> nil then
+      DeleteNodes(ANode.FirstChild);
+
+    if ANode.Rec.ValueByName('Type').AsInteger = 1 then
+      DeleteAtch(ANode);
+
+    if ANode.NextSibling <> nil then
+      DeleteNodes(ANode.NextSibling);
+  end;
+
+begin
+  if not G_IsCloud then
+  begin
+    if not Assigned(ANode) then Exit;
+
+    if ANode.Rec.ValueByName('Type').AsInteger = 0 then
+    begin
+      if Assigned(ANode.FirstChild) then
+        DeleteNodes(ANode.FirstChild);
+    end
+    else
+      DeleteAtch(ANode);
+  end;
+end;
+
+end.

+ 50 - 0
DataModules/ReportMemoryDm/rmBGLExecutionDm.dfm

@@ -0,0 +1,50 @@
+object rmBGLExecutionData: TrmBGLExecutionData
+  OldCreateOrder = False
+  Left = 447
+  Top = 333
+  Height = 150
+  Width = 215
+  object cdsBGLExecution: TClientDataSet
+    Active = True
+    Aggregates = <>
+    Params = <>
+    Left = 64
+    Top = 32
+    Data = {
+      CF0000009619E0BD010000001800000008000000000003000000CF000742474C
+      436F646501004A000000010005574944544802000200640004436F6465010049
+      000000010005574944544802000200320006425F436F64650100490000000100
+      055749445448020002003200044E616D6501004A000000010005574944544802
+      000200C80005556E69747301004A000000010005574944544802000200280005
+      50726963650800040000000000085175616E7469747908000400000000000A54
+      6F74616C507269636508000400000000000000}
+    object cdsBGLExecutionBGLCode: TWideStringField
+      FieldName = 'BGLCode'
+      Size = 50
+    end
+    object cdsBGLExecutionCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsBGLExecutionB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBGLExecutionName: TWideStringField
+      FieldName = 'Name'
+      Size = 100
+    end
+    object cdsBGLExecutionUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBGLExecutionPrice: TFloatField
+      FieldName = 'Price'
+    end
+    object cdsBGLExecutionQuantity: TFloatField
+      FieldName = 'Quantity'
+    end
+    object cdsBGLExecutionTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+  end
+end

+ 361 - 0
DataModules/ReportMemoryDm/rmBGLExecutionDm.pas

@@ -0,0 +1,361 @@
+unit rmBGLExecutionDm;
+
+interface
+
+uses
+  SysUtils, Classes, ProjectData, DB, DBClient, sdIDTree, sdDB;
+
+type
+  TGclNode = class
+  private
+    FQuantity: Double;
+    FTotalPrice: Double;
+    FPrice: Double;
+    FUnits: string;
+    FName: string;
+    FB_Code: string;
+  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;
+  end;
+
+  TXmjNode = class
+  private
+    FCode: string;
+    FName: string;
+    FUnits: string;
+    FGclList: TList;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AddGclNode(AB_Code: string): TGclNode;
+
+    property Code: string read FCode write FCode;
+    property Name: string read FName write FName;
+    property Units: string read FUnits write FUnits;
+    property GclList: TList read FGclList;
+  end;
+
+  TBGLNode = class
+  private
+    FBGLCode: string;
+    FXmjList: TList;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function FindXmjNode(ACode: string): TXmjNode;
+    function AddXmjNode(ACode: string): TXmjNode;
+
+    property BGLCode: string read FBGLCode write FBGLCode;
+    property XmjList: TList read FXmjList;
+  end;
+
+  TrmBGLExecutionData = class(TDataModule)
+    cdsBGLExecution: TClientDataSet;
+    cdsBGLExecutionBGLCode: TWideStringField;
+    cdsBGLExecutionCode: TStringField;
+    cdsBGLExecutionB_Code: TStringField;
+    cdsBGLExecutionName: TWideStringField;
+    cdsBGLExecutionUnits: TWideStringField;
+    cdsBGLExecutionPrice: TFloatField;
+    cdsBGLExecutionQuantity: TFloatField;
+    cdsBGLExecutionTotalPrice: TFloatField;
+  private
+    FProjectData: TProjectData;
+    FBGLList: TList;
+
+    function FindBGLNode(ABGLCode: string): TBGLNode;
+    function AddBGLNode(ABGLCode: string): TBGLNode;
+
+    procedure FilterGclBills(ANode: TsdIDTreeNode);
+    procedure FilterBills(ANode: TsdIDTreeNode);
+
+    procedure WriteData;
+  public
+    function AssignData(AProjectData: TProjectData): TDataSet;
+  end;
+
+implementation
+
+uses
+  ZhAPI, UtilMethods, PhaseData, BillsCompileDm;
+
+{$R *.dfm}
+
+{ TrmBGLExecutionData }
+
+function TrmBGLExecutionData.AddBGLNode(ABGLCode: string): TBGLNode;
+var
+  Node: TBGLNode;
+  i, iIndex: Integer;
+begin
+  // 新增
+  Result := TBGLNode.Create;
+  Result.BGLCode := ABGLCode;
+  // List中根据顺序新增
+  iIndex := FBGLList.Count;
+  for i := 0 to FBGLList.Count - 1 do
+  begin
+    Node := TBGLNode(FBGLList.Items[i]);
+    if ABGLCode < Node.BGLCode then
+    begin
+      iIndex := i;
+      Break;
+    end;
+  end;
+  FBGLList.Insert(iIndex, Result);
+end;
+
+function TrmBGLExecutionData.AssignData(
+  AProjectData: TProjectData): TDataSet;
+begin
+  cdsBGLExecution.DisableControls;
+  cdsBGLExecution.Active := True;
+  cdsBGLExecution.EmptyDataSet;
+  FBGLList := TList.Create;
+  try
+    FProjectData := AProjectData;
+    FilterBills(AProjectData.BillsMeasureData.BillsMeasureTree.FirstNode);
+    WriteData;
+    Result := cdsBGLExecution;
+  finally
+    ClearObjects(FBGLList);
+    FBGLList.Free;
+    cdsBGLExecution.EnableControls;
+  end;
+end;
+
+procedure TrmBGLExecutionData.FilterBills(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if not ANode.HasChildren then
+    FilterGclBills(ANode);
+  FilterBills(ANode.FirstChild);
+  FilterBills(ANode.NextSibling);
+end;
+
+procedure TrmBGLExecutionData.FilterGclBills(ANode: TsdIDTreeNode);
+
+  procedure AddBGLData(ABGLCode, ABGLNum: string);
+  var
+    BGLNode: TBGLNode;
+    XmjNode: TXmjNode;
+    GclNode: TGclNode;
+    LeafXmjParent: TsdIDTreeNode;
+  begin
+    // BGL
+    BGLNode := FindBGLNode(ABGLCode);
+    if not Assigned(BGLNode) then
+      BGLNode := AddBGLNode(ABGLCode);
+    // Xmj
+    with FProjectData.BillsCompileData do
+      LeafXmjParent := BillsCompileTree.FindNode(GetLeafXmjParentID(ANode.ID));
+    XmjNode := BGLNode.FindXmjNode(LeafXmjParent.Rec.ValueByName('Code').AsString);
+    if not Assigned(XmjNode) then
+      XmjNode := BGLNode.AddXmjNode(LeafXmjParent.Rec.ValueByName('Code').AsString);
+    XmjNode.Name := LeafXmjParent.Rec.ValueByName('Name').AsString;
+    XmjNode.Units := LeafXmjParent.Rec.ValueByName('Units').AsString;    
+    // Gcl
+    GclNode := XmjNode.AddGclNode(ANode.Rec.ValueByName('B_Code').AsString);
+    GclNode.Name := ANode.Rec.ValueByName('Name').AsString;
+    GclNode.FUnits := ANode.Rec.ValueByName('Units').AsString;
+    GclNode.Price := ANode.Rec.ValueByName('Price').AsFloat;
+    GclNode.Quantity := StrToFloatDef(ABGLNum, 0);
+    GclNode.TotalPrice := GclNode.Quantity * GclNode.Price;
+  end;
+
+var
+  StageRec: TsdDataRecord;
+  sgsCode, sgsNum: TStringList;
+  i: Integer;
+begin
+  StageRec := FProjectData.PhaseData.StageData.StageRecord(ANode.ID);
+  if (ANode.Rec.ValueByName('B_Code').AsString = '') or
+      (not Assigned(StageRec)) or
+      (StageRec.ValueByName('QcBGLCode').AsString = '') then Exit;
+  sgsCode := TStringList.Create;
+  sgsNum := TStringList.Create;
+  try
+    sgsCode.Delimiter := ';';
+    sgsCode.DelimitedText := StageRec.ValueByName('QcBGLCode').AsString;
+    sgsNum.Delimiter := ';';
+    sgsNum.DelimitedText := StageRec.ValueByName('QcBGLNum').AsString;
+    for i := 0 to sgsCode.Count - 1 do
+      AddBGLData(sgsCode[i], sgsNum[i]);
+  finally
+    sgsNum.Free;
+    sgsCode.Free;
+  end;
+end;
+
+function TrmBGLExecutionData.FindBGLNode(ABGLCode: string): TBGLNode;
+var
+  iBGL: Integer;
+  BGLNode: TBGLNode;
+begin
+  Result := nil;
+  for iBGL := 0 to FBGLList.Count - 1 do
+  begin
+    BGLNode := TBGLNode(FBGLList.Items[iBGL]);
+    if SameText(BGLNode.BGLCode, ABGLCode) then
+    begin
+      Result := BGLNode;
+      Break;
+    end;
+  end;
+end;
+
+procedure TrmBGLExecutionData.WriteData;
+
+  procedure WriteGclData(AXmjNode: TXmjNode);
+  var
+    iGcl: Integer;
+    GclNode: TGclNode;
+  begin
+    for iGcl := 0 to AXmjNode.GclList.Count - 1 do
+    begin
+      GclNode := TGclNode(AXmjNode.GclList.Items[iGcl]);
+      cdsBGLExecution.Append;
+      cdsBGLExecutionB_Code.AsString := GclNode.B_Code;
+      cdsBGLExecutionName.AsString := GclNode.Name;
+      cdsBGLExecutionUnits.AsString := GclNode.Units;
+      cdsBGLExecutionPrice.AsFloat := GclNode.Price;
+      cdsBGLExecutionQuantity.AsFloat := GclNode.Quantity;
+      cdsBGLExecutionTotalPrice.AsFloat := GclNode.TotalPrice;
+      cdsBGLExecution.Post;
+    end;
+  end;
+
+  procedure WriteXmjData(ABGLNode: TBGLNode);
+  var
+    iXmj: Integer;
+    XmjNode: TXmjNode;
+  begin
+    for iXmj := 0 to ABGLNode.XmjList.Count - 1 do
+    begin
+      XmjNode := TXmjNode(ABGLNode.XmjList.Items[iXmj]);
+      cdsBGLExecution.Append;
+      cdsBGLExecutionCode.AsString := XmjNode.Code;
+      cdsBGLExecutionName.AsString := XmjNode.Name;
+      cdsBGLExecutionUnits.AsString := XmjNode.Units;
+      cdsBGLExecution.Post;
+      WriteGclData(XmjNode);
+    end;
+  end;
+
+var
+  iBGL: Integer;
+  BGLNode: TBGLNode;
+begin
+  for iBGL := 0 to FBGLList.Count - 1 do
+  begin
+    BGLNode := TBGLNode(FBGLList.Items[iBGL]);
+    cdsBGLExecution.Append;
+    cdsBGLExecutionBGLCode.AsString := BGLNode.BGLCode;
+    cdsBGLExecution.Post;
+    WriteXmjData(BGLNode);
+  end;
+end;
+
+{ TXmjNode }
+
+function TXmjNode.AddGclNode(AB_Code: string): TGclNode;
+var
+  Node: TGclNode;
+  i, iIndex: Integer;
+  sB_Code1, sB_Code2: string;
+begin
+  // 新增
+  Result := TGclNode.Create;
+  Result.B_Code := AB_Code;
+  // List中根据顺序新增
+  iIndex := FGclList.Count;
+  sB_Code1 := B_CodeToIndexCode(AB_Code);
+  for i := 0 to FGclList.Count - 1 do
+  begin
+    Node := TGclNode(FGclList.Items[i]);
+    sB_Code2 := B_CodeToIndexCode(Node.B_Code);
+    if sB_Code1 < sB_Code2 then
+    begin
+      iIndex := i;
+      Break;
+    end;
+  end;
+  FGclList.Insert(iIndex, Result);
+end;
+
+constructor TXmjNode.Create;
+begin
+  FGclList := TList.Create;
+end;
+
+destructor TXmjNode.Destroy;
+begin
+  ClearObjects(FGclList);
+  FGclList.Free;
+  inherited;
+end;
+
+{ TBGLNode }
+
+function TBGLNode.AddXmjNode(ACode: string): TXmjNode;
+var
+  Node: TXmjNode;
+  i, iIndex: Integer;
+  sCode1, sCode2: string;
+begin
+  // 新增
+  Result := TXmjNode.Create;
+  Result.Code := ACode;
+  // List中根据顺序新增
+  iIndex := FXmjList.Count;
+  sCode1 := ConvertDigitCode(ACode, 3);
+  for i := 0 to FXmjList.Count - 1 do
+  begin
+    Node := TXmjNode(FXmjList.Items[i]);
+    sCode2 := ConvertDigitCode(Node.Code, 3);
+    if sCode1 < sCode2 then
+    begin
+      iIndex := i;
+      Break;
+    end;
+  end;
+  FXmjList.Insert(iIndex, Result);
+end;
+
+constructor TBGLNode.Create;
+begin
+  FXmjList := TList.Create;
+end;
+
+destructor TBGLNode.Destroy;
+begin
+  ClearObjects(FXmjList);
+  FXmjList.Free;
+  inherited;
+end;
+
+function TBGLNode.FindXmjNode(ACode: string): TXmjNode;
+var
+  iXmj: Integer;
+  XmjNode: TXmjNode;
+begin
+  Result := nil;
+  for iXmj := 0 to FXmjList.Count - 1 do
+  begin
+    XmjNode := TXmjNode(FXmjList.Items[iXmj]);
+    if SameText(XmjNode.Code, ACode) then
+    begin
+      Result := XmjNode;
+      Break;
+    end;
+  end;
+end;
+
+end.

文件差异内容过多而无法显示
+ 1410 - 0
DataModules/ReportMemoryDm/rmBillsGatherDm.dfm


文件差异内容过多而无法显示
+ 1303 - 0
DataModules/ReportMemoryDm/rmBillsGatherDm.pas


+ 323 - 0
DataModules/ReportMemoryDm/rmCacheData.pas

@@ -0,0 +1,323 @@
+unit rmCacheData;
+// Report Memory Cache Data
+
+interface
+
+uses
+  Classes, CacheTree, sdIDTree, sdDB;
+
+type
+  TDoubleArray = array of Double;
+  TStringArray = array of string;
+
+  TGclGatherNode = class
+  private
+    FB_Code: string;
+    FIndexCode: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+
+    FQuantity: Double;
+    FTotalPrice: Double;
+
+    FAddDealQuantity: Double;
+    FAddDealTotalPrice: Double;
+    FAddQcQuantity: Double;
+    FAddQcTotalPrice: Double;
+    FAddPcQuantity: Double;
+    FAddPcTotalPrice: Double;
+
+    FP_Price: TDoubleArray;
+    FP_Quantity: TDoubleArray;
+    FP_TotalPrice: TDoubleArray;
+    FP_AddGatherQuantity: TDoubleArray;
+    FP_AddGatherTotalPrice: TDoubleArray;
+
+    procedure SetB_Code(const Value: string);
+  public
+    constructor Create(AProjectCount: Integer);
+
+    property B_Code: string read FB_Code write SetB_Code;
+    property IndexCode: string read FIndexCode;
+    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;
+
+    property AddDealQuantity: Double read FAddDealQuantity write FAddDealQuantity;
+    property AddDealTotalPrice: Double read FAddDealTotalPrice write FAddDealTotalPrice;
+    property AddQcQuantity: Double read FAddQcQuantity write FAddQcQuantity;
+    property AddQcTotalPrice: Double read FAddQcTotalPrice write FAddQcTotalPrice;
+    property AddPcQuantity: Double read FAddPcQuantity write FAddPcQuantity;
+    property AddPcTotalPrice: Double read FAddPcTotalPrice write FAddPcTotalPrice;
+
+    property P_Price: TDoubleArray read FP_Price write FP_Price;
+    property P_Quantity: TDoubleArray read FP_Quantity write FP_Quantity;
+    property P_TotalPrice: TDoubleArray read FP_TotalPrice write FP_TotalPrice;
+    property P_AddGatherQuantity: TDoubleArray read FP_AddGatherQuantity write FP_AddGatherQuantity;
+    property P_AddGatherTotalPrice: TDoubleArray read FP_AddGatherTotalPrice write FP_AddGatherTotalPrice;
+  end;
+
+  TGclGatherList = class
+  private
+    FList: TList;
+    FComparePrice: Boolean;
+    FProjectName: TStringArray;
+    FProjectCount: Integer;
+    FGatherNode: TGclGatherNode;
+
+    function SameGclNode(AGclNode: TGclGatherNode; ARec: TsdDataRecord): Boolean;
+
+    function FindGclNode(ARec: TsdDataRecord): TGclGatherNode;
+    function AddGclNode(ARec: TsdDataRecord): TGclGatherNode;
+
+    function GetCount: Integer;
+    function GetNode(AIndex: Integer): TGclGatherNode;
+  public
+    constructor Create(AProjectCount: Integer; AComparePrice: Boolean = True);
+    destructor Destroy; override;
+
+    function GetGclGatherNode(ARec: TsdDataRecord): TGclGatherNode;
+    procedure ReCalcualteGatherNode;
+
+    property ProjectCount: Integer read FProjectCount;
+    property Count: Integer read GetCount;
+    property Node[AIndex: Integer]: TGclGatherNode read GetNode;
+    property GatherNode: TGclGatherNode read FGatherNode;
+    property ProjectName: TStringArray read FProjectName write FProjectName;
+  end;
+
+  TFixedIDBillsNode = class
+  private
+    FFixedID: Integer;
+    FName: string;
+    FTotalPrice: Double;
+    FP_TotalPrice: TDoubleArray;
+    FAddGatherTotalPrice: Double;
+    FP_AddGatherTotalPrice: TDoubleArray;
+  public
+    constructor Create(AProjectCount: Integer);
+
+    property FixedID: Integer read FFixedID write FFixedID;
+    property Name: string read FName write FName;
+    property TotalPrice: Double read FTotalPrice write FTotalPrice;
+    property P_TotalPrice: TDoubleArray read FP_TotalPrice write FP_TotalPrice;
+    property AddGatherTotalPrice: Double read FAddGatherTotalPrice write FAddGatherTotalPrice;
+    property P_AddGatherTotalPrice: TDoubleArray read FP_AddGatherTotalPrice write FP_AddGatherTotalPrice;
+  end;
+
+  TFixedIDBillsList = class
+  private
+    FList: TList;
+    FProjectName: TStringArray;
+    FProjectCount: Integer;
+
+    function AddNode(AFixedID: Integer): TFixedIDBillsNode;
+
+    function GetCount: Integer;
+    function GetNode(AIndex: Integer): TFixedIDBillsNode;
+  public
+    constructor Create(AProjectCount: Integer);
+    destructor Destroy; override;
+
+    function GetFixedIDBillsNode(AFixedID: Integer): TFixedIDBillsNode;
+    function FixedIDBillsNode(AFixedID: Integer): TFixedIDBillsNode;
+
+    property ProjectCount: Integer read FProjectCount;
+    property Count: Integer read GetCount;
+    property Node[AIndex: Integer]: TFixedIDBillsNode read GetNode;
+    property ProjectName: TStringArray read FProjectName write FProjectName;
+  end;
+
+implementation
+
+uses
+  ZhAPI, DateUtils, SysUtils, UtilMethods;
+
+{ TGclGatherNode }
+
+constructor TGclGatherNode.Create(AProjectCount: Integer);
+begin
+  SetLength(FP_Price, AProjectCount);
+  SetLength(FP_Quantity, AProjectCount);
+  SetLength(FP_TotalPrice, AProjectCount);
+  SetLength(FP_AddGatherQuantity, AProjectCount);
+  SetLength(FP_AddGatherTotalPrice, AProjectCount);
+end;
+
+procedure TGclGatherNode.SetB_Code(const Value: string);
+begin
+  FB_Code := Value;
+  FIndexCode := B_CodeToIndexCode(FB_Code);
+end;
+
+{ TGclGatherList }
+
+constructor TGclGatherList.Create(AProjectCount: Integer;
+  AComparePrice: Boolean = True);
+begin
+  FProjectCount := AProjectCount;
+  FList := TList.Create;
+  FComparePrice := AComparePrice;
+  SetLength(FProjectName, FProjectCount);
+  FGatherNode := TGclGatherNode.Create(FProjectCount);
+end;
+
+destructor TGclGatherList.Destroy;
+begin
+  FGatherNode.Free;
+  ClearObjects(FList);
+  FList.Free;
+  inherited;
+end;
+
+function TGclGatherList.FindGclNode(ARec: TsdDataRecord): TGclGatherNode;
+var
+  i: Integer;
+  GclNode: TGclGatherNode;
+begin
+  Result := nil;
+  for i := 0 to FList.Count - 1 do
+  begin
+    GclNode := TGclGatherNode(FList.Items[i]);
+    if SameGclNode(GclNode, ARec) then
+    begin
+      Result := GclNode;
+      Break;
+    end;
+  end;
+end;
+
+function TGclGatherList.GetCount: Integer;
+begin
+  Result := FList.Count;
+end;
+
+function TGclGatherList.GetNode(AIndex: Integer): TGclGatherNode;
+begin
+  Result := TGclGatherNode(FList.Items[AIndex]);
+end;
+
+function TGclGatherList.GetGclGatherNode(ARec: TsdDataRecord): TGclGatherNode;
+begin
+  Result := FindGclNode(ARec);
+  if not Assigned(Result) then
+    Result := AddGclNode(ARec);
+end;
+
+function TGclGatherList.AddGclNode(ARec: TsdDataRecord): TGclGatherNode;
+begin
+  Result := TGclGatherNode.Create(FProjectCount);
+  FList.Add(Result);
+  Result.B_Code := ARec.ValueByName('B_Code').AsString;
+  Result.Name := ARec.ValueByName('Name').AsString;
+  Result.Units := ARec.ValueByName('Units').AsString;
+  Result.Price := ARec.ValueByName('Price').AsFloat;
+end;
+
+procedure TGclGatherList.ReCalcualteGatherNode;
+var
+  iNode, iP: Integer;
+  GclNode: TGclGatherNode;
+begin
+  for iNode := 0 to FList.Count - 1 do
+  begin
+    GclNode := TGclGatherNode(FList.Items[iNode]);
+    FGatherNode.Quantity := FGatherNode.Quantity + GclNode.Quantity;
+    FGatherNode.TotalPrice := FGatherNode.TotalPrice + GclNode.TotalPrice;
+
+    FGatherNode.AddDealQuantity := FGatherNode.AddDealQuantity + GclNode.AddDealQuantity;
+    FGatherNode.AddDealTotalPrice := FGatherNode.AddDealTotalPrice + GclNode.AddDealTotalPrice;
+    FGatherNode.AddQcQuantity := FGatherNode.AddQcQuantity + GclNode.AddQcQuantity;
+    FGatherNode.AddQcTotalPrice := FGatherNode.AddQcTotalPrice + GclNode.AddQcTotalPrice;
+    FGatherNode.AddPcQuantity := FGatherNode.AddPcQuantity + GclNode.AddPcQuantity;
+    FGatherNode.AddPcTotalPrice := FGatherNode.AddPcTotalPrice + GclNode.AddPcTotalPrice;
+
+    for iP := 0 to FProjectCount - 1 do
+    begin
+      FGatherNode.P_Quantity[iP] := FGatherNode.P_Quantity[iP] + GclNode.P_Quantity[iP];
+      FGatherNode.P_TotalPrice[iP] := FGatherNode.P_TotalPrice[iP] + GclNode.P_TotalPrice[iP];
+      FGatherNode.P_AddGatherQuantity[iP] := FGatherNode.P_AddGatherQuantity[iP] + GclNode.P_AddGatherQuantity[iP];
+      FGatherNode.P_AddGatherTotalPrice[iP] := FGatherNode.P_AddGatherTotalPrice[iP] + GclNode.P_AddGatherTotalPrice[iP];
+    end;
+  end;
+end;
+
+function TGclGatherList.SameGclNode(AGclNode: TGclGatherNode; ARec: TsdDataRecord): Boolean;
+begin
+  Result := SameText(AGclNode.B_Code, ARec.ValueByName('B_Code').AsString) and
+            SameText(AGclNode.Name, ARec.ValueByName('Name').AsString) and
+            SameText(AGclNode.Units, ARec.ValueByName('Units').AsString);
+  if FComparePrice then
+    Result := Result and (AGclNode.Price = ARec.ValueByName('Price').AsFloat);
+end;
+
+{ TFixedIDBillsNode }
+
+constructor TFixedIDBillsNode.Create(AProjectCount: Integer);
+begin
+  SetLength(FP_TotalPrice, AProjectCount);
+  SetLength(FP_AddGatherTotalPrice, AProjectCount);
+end;
+
+{ TFixedIDBillsList }
+
+function TFixedIDBillsList.AddNode(AFixedID: Integer): TFixedIDBillsNode;
+begin
+  Result := TFixedIDBillsNode.Create(FProjectCount);
+  FList.Add(Result);
+  Result.FixedID := AFixedID;
+end;
+
+constructor TFixedIDBillsList.Create(AProjectCount: Integer);
+begin
+  FProjectCount := AProjectCount;
+  FList := TList.Create;
+  SetLength(FProjectName, FProjectCount);
+end;
+
+destructor TFixedIDBillsList.Destroy;
+begin
+  ClearObjects(FList);
+  FList.Free;
+  inherited;
+end;
+
+function TFixedIDBillsList.FixedIDBillsNode(
+  AFixedID: Integer): TFixedIDBillsNode;
+var
+  i: Integer;
+begin
+  Result := nil;
+  for i := 0 to FList.Count - 1 do
+  begin
+    if TFixedIDBillsNode(FList.Items[i]).FixedID = AFixedID then
+    begin
+      Result := TFixedIDBillsNode(FList.Items[i]);
+      Break;
+    end;
+  end;
+end;
+
+function TFixedIDBillsList.GetCount: Integer;
+begin
+  Result := FList.Count;
+end;
+
+function TFixedIDBillsList.GetFixedIDBillsNode(
+  AFixedID: Integer): TFixedIDBillsNode;
+begin
+  Result := FixedIDBillsNode(AFixedID);
+  if not Assigned(Result) then
+    Result := AddNode(AFixedID);
+end;
+
+function TFixedIDBillsList.GetNode(AIndex: Integer): TFixedIDBillsNode;
+begin
+  Result := TFixedIDBillsNode(FList.Items[AIndex]);
+end;
+
+end.

+ 51 - 0
DataModules/ReportMemoryDm/rmCustomized2Dm.dfm

@@ -0,0 +1,51 @@
+object rmCustomized2Data: TrmCustomized2Data
+  OldCreateOrder = False
+  Left = 652
+  Top = 548
+  Height = 150
+  Width = 215
+  object cdsCustom: TClientDataSet
+    Active = True
+    Aggregates = <>
+    Params = <>
+    Left = 56
+    Top = 40
+    Data = {
+      E80000009619E0BD010000001800000009000000000003000000E80008536572
+      69616C4E6F0400010000000000044E616D6502004A0000000100055749445448
+      0200020090010A546F74616C507269636508000400000000000E456E6443546F
+      74616C5072696365080004000000000013456E64476174686572546F74616C50
+      726963650800040000000000114375724465616C546F74616C50726963650800
+      040000000000115072654465616C546F74616C50726963650800040000000000
+      11456E644465616C546F74616C50726963650800040000000000075072656365
+      6E7408000400000000000000}
+    object cdsCustomSerialNo: TIntegerField
+      FieldName = 'SerialNo'
+    end
+    object cdsCustomName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsCustomTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsCustomEndCTotalPrice: TFloatField
+      FieldName = 'EndCTotalPrice'
+    end
+    object cdsCustomEndGatherTotalPrice: TFloatField
+      FieldName = 'EndGatherTotalPrice'
+    end
+    object cdsCustomCurDealTotalPrice: TFloatField
+      FieldName = 'CurDealTotalPrice'
+    end
+    object cdsCustomPreDealTotalPrice: TFloatField
+      FieldName = 'PreDealTotalPrice'
+    end
+    object cdsCustomEndDealTotalPrice: TFloatField
+      FieldName = 'EndDealTotalPrice'
+    end
+    object cdsCustomPrecent: TFloatField
+      FieldName = 'Precent'
+    end
+  end
+end

+ 468 - 0
DataModules/ReportMemoryDm/rmCustomized2Dm.pas

@@ -0,0 +1,468 @@
+unit rmCustomized2Dm;
+// 广东肇庆定制 -- 汇总表(计量汇总表)
+// 严禁任何其他项目使用该单元
+
+interface
+
+uses
+  SysUtils, Classes, ZhAPI, DB, ProjectData, DBClient,
+  rmSelectProjectFrm, sdDB;
+
+type
+  TTenderBaseData = class
+  private
+    FTenderName: string;
+    FTotalPrice: Double;
+    FEndCTotalPrice: Double;
+    FCurDealTotalPrice: Double;
+    FPreDealTotalPrice: Double;
+    FEndDealTotalPrice: Double;
+    function GetEndGatherTotalPrice: Double;
+    function GetPrecent: Double;
+  public
+    constructor Create(const ATenderName: string);
+
+    property TenderName: string read FTenderName;
+    property TotalPrice: Double read FTotalPrice write FTotalPrice;
+    property EndCTotalPrice: Double read FEndCTotalPrice write FEndCTotalPrice;
+    property EndGatherTotalPrice: Double read GetEndGatherTotalPrice;
+
+    property CurDealTotalPrice: Double read FCurDealTotalPrice write FCurDealTotalPrice;
+    property PreDealTotalPrice: Double read FPreDealTotalPrice write FPreDealTotalPrice;
+    property EndDealTotalPrice: Double read FEndDealTotalPrice write FEndDealTotalPrice;
+
+    property Precent: Double read GetPrecent;
+  end;
+
+  TDealPayData = class
+  private
+    FName: string;
+    FCurTotalPrice: Double;
+    FPreTotalPrice: Double;
+    FEndTotalPrice: Double;
+  public
+    constructor Create(const AName: string);
+
+    property Name: string read FName;
+
+    property CurTotalPrice: Double read FCurTotalPrice write FCurTotalPrice;
+    property PreTotalPrice: Double read FPreTotalPrice write FPreTotalPrice;
+    property EndTotalPrice: Double read FEndTotalPrice write FEndTotalPrice;
+  end;
+
+  TGatherData = class
+  private
+    FTenders: TList;
+    FTenderGather: TTenderBaseData;
+    FDealPays: TList;
+    FPayGather: TDealPayData;
+
+    function FindDealPay(const AName: string): TDealPayData;
+
+    function GetTenderCount: Integer;
+    function GetTenders(AIndex: Integer): TTenderBaseData;
+    function GetDealPay(AIndex: Integer): TDealPayData;
+    function GetDealPayCount: Integer;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AddTender(const ATenderName: string): TTenderBaseData;
+    procedure GatherTender;
+    function AddDealPay(const AName: string): TDealPayData;
+
+    property TenderCount: Integer read GetTenderCount;
+    property Tenders[AIndex: Integer]: TTenderBaseData read GetTenders;
+    property TenderGather: TTenderBaseData read FTenderGather;
+    property DealPayCount: Integer read GetDealPayCount;
+    property DealPay[AIndex: Integer]: TDealPayData read GetDealPay;
+    property PayGather: TDealPayData read FPayGather;
+  end;
+
+  TrmCustomized2Data = class(TDataModule)
+    cdsCustom: TClientDataSet;
+    cdsCustomSerialNo: TIntegerField;
+    cdsCustomName: TWideStringField;
+    cdsCustomTotalPrice: TFloatField;
+    cdsCustomEndCTotalPrice: TFloatField;
+    cdsCustomEndGatherTotalPrice: TFloatField;
+    cdsCustomCurDealTotalPrice: TFloatField;
+    cdsCustomPreDealTotalPrice: TFloatField;
+    cdsCustomEndDealTotalPrice: TFloatField;
+    cdsCustomPrecent: TFloatField;
+  private
+    FProjectData: TProjectData;
+    FProjectName: string;
+    FGatherData: TGatherData;
+    FSerialNo: Integer;
+
+    procedure BeforeGather;
+    procedure AfterGather;
+
+    procedure OpenProjectData(AProject: TSelectProject);
+    procedure FreeProjectData;
+
+    procedure GatherProject(AProject: TSelectProject);
+
+    procedure WriteData;
+  public
+    function AssignData(AProjects: TList): TDataSet;
+  end;
+
+implementation
+
+uses
+  DealPaymentDm, PhasePayDm, Globals, UtilMethods;
+
+{$R *.dfm}
+
+{ TTenderBaseData }
+
+constructor TTenderBaseData.Create(const ATenderName: string);
+begin
+  FTenderName := ATenderName;
+  FTotalPrice := 0;
+  FEndCTotalPrice := 0;
+  FCurDealTotalPrice := 0;
+  FPreDealTotalPrice := 0;
+  FEndDealTotalPrice := 0;
+end;
+
+function TTenderBaseData.GetEndGatherTotalPrice: Double;
+begin
+  Result := TotalPrice + EndCTotalPrice;
+end;
+
+function TTenderBaseData.GetPrecent: Double;
+begin
+  if EndGatherTotalPrice <> 0 then
+    Result := EndDealTotalPrice/EndGatherTotalPrice*100
+  else
+    Result := 0;
+end;
+
+{ TGatherData }
+
+function TGatherData.AddDealPay(const AName: string): TDealPayData;
+begin
+  Result := FindDealPay(AName);
+  if not Assigned(Result) then
+  begin
+    Result := TDealPayData.Create(AName);
+    FDealPays.Add(Result);
+  end;
+end;
+
+function TGatherData.AddTender(const ATenderName: string): TTenderBaseData;
+begin
+  Result := TTenderBaseData.Create(ATenderName);
+  FTenders.Add(Result);
+end;
+
+constructor TGatherData.Create;
+begin
+  FTenders := TList.Create;
+  FTenderGather := TTenderBaseData.Create('合计');
+  FDealPays := TList.Create;
+  FPayGather := TDealPayData.Create('支付');
+end;
+
+destructor TGatherData.Destroy;
+begin
+  FPayGather.Free;
+  ClearObjects(FDealPays);
+  FDealPays.Free;
+  FTenderGather.Free;
+  ClearObjects(FTenders);
+  FTenders.Free;
+  inherited;
+end;
+
+function TGatherData.FindDealPay(const AName: string): TDealPayData;
+var
+  iIndex: Integer;
+begin
+  Result := nil;
+  for iIndex := 0 to DealPayCount - 1 do
+  begin
+    if SameText(AName, DealPay[iIndex].Name) then
+    begin
+      Result := DealPay[iIndex];
+      Break;
+    end;
+  end;
+end;
+
+procedure TGatherData.GatherTender;
+var
+  iIndex: Integer;
+  Tender: TTenderBaseData;
+begin
+  FTenderGather.TotalPrice := 0;
+  FTenderGather.EndCTotalPrice := 0;
+  FTenderGather.CurDealTotalPrice := 0;
+  FTenderGather.PreDealTotalPrice := 0;
+  FTenderGather.EndDealTotalPrice := 0;
+
+  for iIndex := 0 to FTenders.Count - 1 do
+  begin
+    Tender := Tenders[iIndex];
+    FTenderGather.TotalPrice := FTenderGather.TotalPrice + Tender.TotalPrice;
+    FTenderGather.EndCTotalPrice := FTenderGather.EndCTotalPrice + Tender.FEndCTotalPrice;
+    FTenderGather.CurDealTotalPrice := FTenderGather.CurDealTotalPrice + Tender.CurDealTotalPrice;
+    FTenderGather.PreDealTotalPrice := FTenderGather.PreDealTotalPrice + Tender.PreDealTotalPrice;
+    FTenderGather.EndDealTotalPrice := FTenderGather.EndDealTotalPrice + Tender.EndDealTotalPrice;
+  end;
+end;
+
+function TGatherData.GetDealPay(AIndex: Integer): TDealPayData;
+begin
+  Result := TDealPayData(FDealPays.Items[AIndex]);
+end;
+
+function TGatherData.GetDealPayCount: Integer;
+begin
+  Result := FDealPays.Count;
+end;
+
+function TGatherData.GetTenderCount: Integer;
+begin
+  Result := FTenders.Count;
+end;
+
+function TGatherData.GetTenders(AIndex: Integer): TTenderBaseData;
+begin
+  Result := TTenderBaseData(FTenders.Items[AIndex]);
+end;
+
+{ TDealPayData }
+
+constructor TDealPayData.Create(const AName: string);
+begin
+  FName := AName;
+  FCurTotalPrice := 0;
+  FPreTotalPrice := 0;
+  FEndTotalPrice := 0;
+end;
+
+{ TrmCustomized2Data }
+
+procedure TrmCustomized2Data.AfterGather;
+begin
+  FGatherData.Free;
+end;
+
+function TrmCustomized2Data.AssignData(AProjects: TList): TDataSet;
+var
+  iProject: Integer;
+begin
+  BeforeGather;
+  try
+    for iProject := 0 to AProjects.Count - 1 do
+      GatherProject(TSelectProject(AProjects.Items[iProject]));
+    FGatherData.GatherTender;
+    WriteData;
+  finally
+    Result := cdsCustom;
+    AfterGather;
+  end;
+end;
+
+procedure TrmCustomized2Data.BeforeGather;
+begin
+  cdsCustom.Active := True;
+  cdsCustom.EmptyDataSet;
+  FGatherData := TGatherData.Create;
+end;
+
+procedure TrmCustomized2Data.FreeProjectData;
+begin
+  if not Assigned(OpenProjectManager.FindProjectData(FProjectData.ProjectID)) then
+    FProjectData.Free;
+end;
+
+procedure TrmCustomized2Data.GatherProject(AProject: TSelectProject);
+var
+  sCurField, sPreField, sEndField: string;
+
+  function DealPayRecord(const AName: string): TsdDataRecord;
+  var
+    iRec: Integer;
+    Rec: TsdDataRecord;
+  begin
+    Result := nil;
+    with FProjectData.DealPaymentData do
+    begin
+      for iRec := 0 to sddDealPayment.RecordCount - 1 do
+      begin
+        Rec := sddDealPayment.Records[iRec];
+        if SameText(AName, Rec.ValueByName('Name').AsString) then
+        begin
+          Result := Rec;
+          Break;
+        end;
+      end;
+    end;
+  end;
+
+  procedure GatherBaseData;
+  var
+    TenderBase: TTenderBaseData;
+    Rec, StageRec: TsdDataRecord;
+  begin
+    TenderBase := FGatherData.AddTender(FProjectName);
+    TenderBase.TotalPrice := FProjectData.BillsData.Settlement[0];
+    TenderBase.EndCTotalPrice := FProjectData.BillsData.Settlement[2];
+    Rec := DealPayRecord('本期完成计量');
+    StageRec := FProjectData.PhaseData.PhasePayData.PayRecord(Rec.ValueByName('ID').AsInteger);
+    TenderBase.CurDealTotalPrice := StageRec.ValueByName(sCurField).AsFloat;
+    TenderBase.PreDealTotalPrice := StageRec.ValueByName(sPreField).AsFloat;
+    TenderBase.EndDealTotalPrice := StageRec.ValueByName(sEndField).AsFloat;
+  end;
+
+  procedure GatherCommonDealPayData;
+  var
+    iRec: Integer;
+    Rec, StageRec: TsdDataRecord;
+    DealPay: TDealPayData;
+  begin
+    with FProjectData.DealPaymentData do
+    begin
+      for iRec := 0 to sddDealPayment.RecordCount - 1 do
+      begin
+        Rec := sddDealPayment.Records[iRec];
+        if SameText(Rec.ValueByName('Name').AsString, '本期完成计量') or
+           SameText(Rec.ValueByName('Name').AsString, '本期应付') or
+           SameText(Rec.ValueByName('Name').AsString, '本期实付') then
+          Continue;
+        StageRec := FProjectData.PhaseData.PhasePayData.PayRecord(Rec.ValueByName('ID').AsInteger);
+        if StageRec.ValueByName(sEndField).AsFloat = 0 then
+          Continue;
+        DealPay := FGatherData.AddDealPay(Rec.ValueByName('Name').AsString);
+        DealPay.CurTotalPrice := DealPay.CurTotalPrice + StageRec.ValueByName(sCurField).AsFloat;
+        DealPay.PreTotalPrice := DealPay.PreTotalPrice + StageRec.ValueByName(sPreField).AsFloat;
+        DealPay.EndTotalPrice := DealPay.EndTotalPrice + StageRec.ValueByName(sEndField).AsFloat;
+      end;
+    end;
+  end;
+
+  procedure GatherPayData;
+  var
+    Rec, StageRec: TsdDataRecord;
+  begin
+    Rec := DealPayRecord('本期应付');
+    StageRec := FProjectData.PhaseData.PhasePayData.PayRecord(Rec.ValueByName('ID').AsInteger);
+    with FGatherData.PayGather do
+    begin
+      CurTotalPrice := CurTotalPrice + StageRec.ValueByName(sCurField).AsFloat;
+      PreTotalPrice := PreTotalPrice + StageRec.ValueByName(sPreField).AsFloat;
+      EndTotalPrice := EndTotalPrice + StageRec.ValueByName(sEndField).AsFloat;
+    end;
+  end;
+
+begin
+  OpenProjectData(AProject);
+  try
+    sCurField := 'TotalPrice' + IntToStr(FProjectData.PhaseData.AuditCount);
+    sPreField := 'PreTotalPrice' + IntToStr(FProjectData.PhaseData.AuditCount);
+    sEndField := 'EndTotalPrice' + IntToStr(FProjectData.PhaseData.AuditCount);
+    GatherBaseData;
+    GatherCommonDealPayData;
+    GatherPayData;
+  finally
+    FreeProjectData;
+  end;
+end;
+
+procedure TrmCustomized2Data.OpenProjectData(AProject: TSelectProject);
+var
+  Rec: TsdDataRecord;
+begin
+  FProjectData := OpenProjectManager.FindProjectData(AProject.ProjectID);
+  Rec := ProjectManager.sddProjectsInfo.FindKey('idxID', AProject.ProjectID);
+  if not Assigned(FProjectData) then
+  begin
+    FProjectData := TProjectData.Create;
+    FProjectData.OpenForReport2(GetMyProjectsFilePath + Rec.ValueByName('FileName').AsString);
+  end;
+  FProjectName := Rec.ValueByName('Name').AsString;
+end;
+
+procedure TrmCustomized2Data.WriteData;
+
+  procedure WriteProjectData;
+  var
+    i: Integer;
+    Tender: TTenderBaseData;
+  begin
+    for i := 0 to FGatherData.TenderCount - 1 do
+    begin
+      Tender := FGatherData.Tenders[i];
+      cdsCustom.Append;
+      cdsCustomSerialNo.AsInteger := FSerialNo;
+      cdsCustomName.AsString := Tender.TenderName;
+      cdsCustomTotalPrice.AsFloat := Tender.TotalPrice;
+      cdsCustomEndCTotalPrice.AsFloat := Tender.EndCTotalPrice;
+      cdsCustomEndGatherTotalPrice.AsFloat := Tender.EndGatherTotalPrice;
+      cdsCustomCurDealTotalPrice.AsFloat := Tender.CurDealTotalPrice;
+      cdsCustomPreDealTotalPrice.AsFloat := Tender.PreDealTotalPrice;
+      cdsCustomEndDealTotalPrice.AsFloat := Tender.EndDealTotalPrice;
+      cdsCustomPrecent.AsFloat := Tender.Precent;
+      cdsCustom.Post;
+      Inc(FSerialNo);
+    end;
+  end;
+
+  procedure WriteProjectGather;
+  begin
+    cdsCustom.Append;
+    cdsCustomName.AsString := FGatherData.TenderGather.TenderName;
+    cdsCustomTotalPrice.AsFloat := FGatherData.TenderGather.TotalPrice;
+    cdsCustomEndCTotalPrice.AsFloat := FGatherData.TenderGather.EndCTotalPrice;
+    cdsCustomEndGatherTotalPrice.AsFloat := FGatherData.TenderGather.EndGatherTotalPrice;
+    cdsCustomCurDealTotalPrice.AsFloat := FGatherData.TenderGather.CurDealTotalPrice;
+    cdsCustomPreDealTotalPrice.AsFloat := FGatherData.TenderGather.PreDealTotalPrice;
+    cdsCustomEndDealTotalPrice.AsFloat := FGatherData.TenderGather.EndDealTotalPrice;
+    cdsCustomPrecent.AsFloat := FGatherData.TenderGather.Precent;
+    cdsCustom.Post;
+  end;
+
+  procedure WriteDealPays;
+  var
+    i: Integer;
+    DealPay: TDealPayData;
+  begin
+    for i := 0 to FGatherData.DealPayCount - 1 do
+    begin
+      DealPay := FGatherData.DealPay[i];
+      cdsCustom.Append;
+      cdsCustomSerialNo.AsInteger := FSerialNo;
+      cdsCustomName.AsString := DealPay.Name;
+      cdsCustomCurDealTotalPrice.AsFloat := DealPay.CurTotalPrice;
+      cdsCustomPreDealTotalPrice.AsFloat := DealPay.PreTotalPrice;
+      cdsCustomEndDealTotalPrice.AsFloat := DealPay.EndTotalPrice;
+      cdsCustom.Post;
+      Inc(FSerialNo);
+    end;
+  end;
+
+  procedure WriteGatherPay;
+  begin
+    cdsCustom.Append;
+    cdsCustomSerialNo.AsInteger := FSerialNo;
+    cdsCustomName.AsString := FGatherData.PayGather.Name;
+    cdsCustomCurDealTotalPrice.AsFloat := FGatherData.PayGather.CurTotalPrice;
+    cdsCustomPreDealTotalPrice.AsFloat := FGatherData.PayGather.PreTotalPrice;
+    cdsCustomEndDealTotalPrice.AsFloat := FGatherData.PayGather.EndTotalPrice;
+    cdsCustom.Post;
+  end;
+
+begin
+  FSerialNo := 1;
+  WriteProjectData;
+  WriteProjectGather;
+  WriteDealPays;
+  WriteGatherPay;
+end;
+
+end.

+ 140 - 0
DataModules/ReportMemoryDm/rmDealInfosDm.dfm

@@ -0,0 +1,140 @@
+object rmDealInfosData: TrmDealInfosData
+  OldCreateOrder = False
+  Left = 667
+  Top = 347
+  Height = 150
+  Width = 214
+  object cdsDealInfos: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'DealType'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'DealCode'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'BalanceCode'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'DealName'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'DealCompany'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'DealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'FinalTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CutTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'PayTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'PaidTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'PayingTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'PayPercent'
+        DataType = ftFloat
+      end
+      item
+        Name = 'MemoStr'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'ContractPrice'
+        DataType = ftFloat
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 64
+    Top = 40
+    Data = {
+      810100009619E0BD01000000180000000E000000000003000000810108446561
+      6C5479706501004A0000000100055749445448020002002800084465616C436F
+      646501004A00000001000557494454480200020064000B42616C616E6365436F
+      646501004A0000000100055749445448020002006400084465616C4E616D6501
+      004A00000001000557494454480200020064000B4465616C436F6D70616E7901
+      004A00000001000557494454480200020064000E4465616C546F74616C507269
+      636508000400000000000F46696E616C546F74616C5072696365080004000000
+      00000D437574546F74616C507269636508000400000000000D506179546F7461
+      6C507269636508000400000000000E50616964546F74616C5072696365080004
+      000000000010506179696E67546F74616C507269636508000400000000000A50
+      617950657263656E740800040000000000074D656D6F53747201004A00000001
+      000557494454480200020064000D436F6E747261637450726963650800040000
+      0000000000}
+    object cdsDealInfosDealType: TWideStringField
+      FieldName = 'DealType'
+    end
+    object cdsDealInfosDealCode: TWideStringField
+      FieldName = 'DealCode'
+      Size = 50
+    end
+    object cdsDealInfosBalanceCode: TWideStringField
+      FieldName = 'BalanceCode'
+      Size = 50
+    end
+    object cdsDealInfosDealName: TWideStringField
+      FieldName = 'DealName'
+      Size = 50
+    end
+    object cdsDealInfosDealCompany: TWideStringField
+      FieldName = 'DealCompany'
+      Size = 50
+    end
+    object cdsDealInfosDealTotalPrice: TFloatField
+      FieldName = 'DealTotalPrice'
+    end
+    object cdsDealInfosFinalTotalPrice: TFloatField
+      FieldName = 'FinalTotalPrice'
+    end
+    object cdsDealInfosCutTotalPrice: TFloatField
+      FieldName = 'CutTotalPrice'
+    end
+    object cdsDealInfosPayTotalPrice: TFloatField
+      FieldName = 'PayTotalPrice'
+    end
+    object cdsDealInfosPaidTotalPrice: TFloatField
+      FieldName = 'PaidTotalPrice'
+    end
+    object cdsDealInfosPayingTotalPrice: TFloatField
+      FieldName = 'PayingTotalPrice'
+    end
+    object cdsDealInfosPayPercent: TFloatField
+      FieldName = 'PayPercent'
+    end
+    object cdsDealInfosMemoStr: TWideStringField
+      FieldName = 'MemoStr'
+      Size = 50
+    end
+    object cdsDealInfosContractPrice: TFloatField
+      FieldName = 'ContractPrice'
+    end
+  end
+end

+ 269 - 0
DataModules/ReportMemoryDm/rmDealInfosDm.pas

@@ -0,0 +1,269 @@
+unit rmDealInfosDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, rmSelectProjectFrm, ProjectData,
+  ZhAPI, sdDB, sdIDTree;
+
+type
+  TInfoNode = class
+  private
+    // 合同类别
+    FDealType: string;
+    // 合同编号
+    FDealCode: string;
+    // 结算书编号
+    FBalanceCode: string;
+    // 合同名称
+    FDealName: string;
+    // 签订单位
+    FDealCompany: string;
+    // 合同金额
+    FDealTotalPrice: Double;
+    // 结算金额
+    FFinalTotalPrice: Double;
+    // 累计应扣款
+    FCutTotalPrice: Double;
+    // 累计已支付
+    FPaidTotalPrice: Double;
+    // 签约合同价 (单合同:取项目属性签约合同价,多合同:取0号台账合同)
+    FContractPrice: Double;
+  public
+    constructor Create;
+  end;
+
+  TrmDealInfosData = class(TDataModule)
+    cdsDealInfos: TClientDataSet;
+    cdsDealInfosDealType: TWideStringField;
+    cdsDealInfosDealCode: TWideStringField;
+    cdsDealInfosDealCompany: TWideStringField;
+    cdsDealInfosDealTotalPrice: TFloatField;
+    cdsDealInfosFinalTotalPrice: TFloatField;
+    cdsDealInfosCutTotalPrice: TFloatField;
+    cdsDealInfosPayTotalPrice: TFloatField;
+    cdsDealInfosPaidTotalPrice: TFloatField;
+    cdsDealInfosPayingTotalPrice: TFloatField;
+    cdsDealInfosMemoStr: TWideStringField;
+    cdsDealInfosBalanceCode: TWideStringField;
+    cdsDealInfosDealName: TWideStringField;
+    cdsDealInfosPayPercent: TFloatField;
+    cdsDealInfosContractPrice: TFloatField;
+  private
+    FDealInfos: TList;
+    FTotalDealInfo: TInfoNode;
+    FProjectData: TProjectData;
+
+    procedure BeforeGather;
+    procedure AfterGather;
+
+    procedure OpenProjectData(AProjectID: Integer);
+    procedure FreeProjectData;
+
+    procedure AddBillsDealInfo(ANode: TsdIDTreeNode);
+    procedure AddBillsDeal(ANode: TsdIDTreeNode);
+
+    // 标段为合同
+    procedure AddDealProjectInfo(AProjectID: Integer);
+    // 标段内含多个合同
+    procedure AddProjectDealInfos(AProjectID: Integer);
+    procedure AddDealInfo(AProject: TSelectProject);
+
+    procedure GatherTotalDealInfo;
+
+    procedure WriteDealInfoData;
+  public
+    function AssignData(AProjects: TList): TDataSet;
+  end;
+
+implementation
+
+uses ProjectProperty, Globals, UtilMethods;
+
+{$R *.dfm}
+
+{ TrmDealInfosData }
+
+procedure TrmDealInfosData.AddBillsDeal(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.Rec.ValueByName('DealCode').AsString <> '' then
+    AddBillsDealInfo(ANode);
+  AddBillsDeal(ANode.FirstChild);
+  AddBillsDeal(ANode.NextSibling);
+end;
+
+procedure TrmDealInfosData.AddBillsDealInfo(ANode: TsdIDTreeNode);
+var
+  DealInfo: TInfoNode;
+begin
+  DealInfo := TInfoNode.Create;
+  FDealInfos.Add(DealInfo);
+
+  DealInfo.FDealType := ANode.Rec.ValueByName('DealType').AsString;
+  DealInfo.FDealCode := ANode.Rec.ValueByName('DealCode').AsString;
+  DealInfo.FDealName := ANode.Rec.ValueByName('Name').AsString;
+  DealInfo.FDealCompany := ANode.Rec.ValueByName('DealCompany').AsString;
+  DealInfo.FDealTotalPrice := ANode.Rec.ValueByName('TotalPrice').AsFloat;
+  DealInfo.FFinalTotalPrice := ANode.Rec.ValueByName('AddGatherTotalPrice').AsFloat;
+  DealInfo.FCutTotalPrice := ANode.Rec.ValueByName('AddCutTotalPrice').AsFloat;
+  DealInfo.FPaidTotalPrice := ANode.Rec.ValueByName('AddPayTotalPrice').AsFloat;
+  DealInfo.FContractPrice := ANode.Rec.ValueByName('TotalPrice').AsFloat;
+end;
+
+procedure TrmDealInfosData.AddDealInfo(AProject: TSelectProject);
+begin
+  if AProject.IsDeal then
+    AddProjectDealInfos(AProject.ProjectID)
+  else
+    AddDealProjectInfo(AProject.ProjectID);
+end;
+
+procedure TrmDealInfosData.AddDealProjectInfo(AProjectID: Integer);
+var
+  DealInfo: TInfoNode;
+begin
+  OpenProjectData(AProjectID);
+  try
+    DealInfo := TInfoNode.Create;
+    FDealInfos.Add(DealInfo);
+
+    DealInfo.FDealType := FProjectData.ProjProperties.DealType;
+    DealInfo.FDealCode := FProjectData.ProjProperties.DealIndex;
+    DealInfo.FDealName := FProjectData.ProjProperties.DealName;
+    DealInfo.FDealCompany := FProjectData.ProjProperties.CName;
+    // Bug #674 要求修改为取项目属性界面签约合同价
+    DealInfo.FDealTotalPrice := FProjectData.BillsData.Settlement[0];
+    DealInfo.FFinalTotalPrice := FProjectData.DealPaymentData.AddTotalPrice;
+    DealInfo.FCutTotalPrice := FProjectData.DealPaymentData.CutTotalPrice;
+    DealInfo.FPaidTotalPrice := FProjectData.DealPaymentData.PaidTotalPrice;
+    DealInfo.FContractPrice := FProjectData.ProjProperties.ContractPrice;
+  finally
+    FreeProjectData;
+  end;
+end;
+
+procedure TrmDealInfosData.AddProjectDealInfos(AProjectID: Integer);
+begin
+  OpenProjectData(AProjectID);
+  try
+    AddBillsDeal(FProjectData.BillsCompileData.BillsCompileTree.FirstNode);
+  finally
+    FreeProjectData;
+  end;
+end;
+
+procedure TrmDealInfosData.AfterGather;
+begin
+  FTotalDealInfo.Free;
+  ClearObjects(FDealInfos);
+  FDealInfos.Free;
+
+  cdsDealInfos.EnableControls;
+end;
+
+function TrmDealInfosData.AssignData(AProjects: TList): TDataSet;
+var
+  iProject: Integer;
+begin
+  BeforeGather;
+  try
+    for iProject := 0 to AProjects.Count - 1 do
+      AddDealInfo(TSelectProject(AProjects.Items[iProject]));
+    GatherTotalDealInfo;
+    WriteDealInfoData;
+  finally
+    AfterGather;
+    Result := cdsDealInfos;
+  end;
+end;
+
+procedure TrmDealInfosData.BeforeGather;
+begin
+  cdsDealInfos.DisableControls;
+  cdsDealInfos.Active := True;
+  cdsDealInfos.EmptyDataSet;
+
+  FDealInfos := TList.Create;
+  FTotalDealInfo := TInfoNode.Create;
+  FTotalDealInfo.FDealType := '合计';
+end;
+
+procedure TrmDealInfosData.FreeProjectData;
+begin
+  if not Assigned(OpenProjectManager.FindProjectData(FProjectData.ProjectID)) then
+    FProjectData.Free;
+end;
+
+procedure TrmDealInfosData.GatherTotalDealInfo;
+var
+  i: Integer;
+  DealInfo: TInfoNode;
+begin
+  for i := 0 to FDealInfos.Count - 1 do
+  begin
+    DealInfo := TInfoNode(FDealInfos.Items[i]);
+    FTotalDealInfo.FDealTotalPrice := FTotalDealInfo.FDealTotalPrice + DealInfo.FDealTotalPrice;
+    FTotalDealInfo.FFinalTotalPrice := FTotalDealInfo.FFinalTotalPrice + DealInfo.FFinalTotalPrice;
+    FTotalDealInfo.FCutTotalPrice := FTotalDealInfo.FCutTotalPrice + DealInfo.FCutTotalPrice;
+    FTotalDealInfo.FPaidTotalPrice := FTotalDealInfo.FPaidTotalPrice + DealInfo.FPaidTotalPrice;
+    FTotalDealInfo.FContractPrice := FTotalDealInfo.FContractPrice + DealInfo.FContractPrice;
+  end;
+end;
+
+procedure TrmDealInfosData.OpenProjectData(AProjectID: Integer);
+var
+  Rec: TsdDataRecord;
+begin
+  FProjectData := OpenProjectManager.FindProjectData(AProjectID);
+  Rec := ProjectManager.sddProjectsInfo.FindKey('idxID', AProjectID);
+  if not Assigned(FProjectData) then
+  begin
+    FProjectData := TProjectData.Create;
+    FProjectData.OpenForReport(GetMyProjectsFilePath + Rec.ValueByName('FileName').AsString);
+  end;
+end;
+
+procedure TrmDealInfosData.WriteDealInfoData;
+
+  procedure WriteInfoNodeData(AInfo: TInfoNode);
+  begin
+    cdsDealInfos.Append;
+    cdsDealInfosDealType.AsString := AInfo.FDealType;
+    cdsDealInfosDealCode.AsString := AInfo.FDealCode;
+    cdsDealInfosBalanceCode.AsString := AInfo.FBalanceCode;
+    cdsDealInfosDealName.AsString := AInfo.FDealName;
+    cdsDealInfosDealCompany.AsString := AInfo.FDealCompany;
+    cdsDealInfosDealTotalPrice.AsFloat := AInfo.FDealTotalPrice;
+    cdsDealInfosFinalTotalPrice.AsFloat := AInfo.FFinalTotalPrice;
+    cdsDealInfosCutTotalPrice.AsFloat := AInfo.FCutTotalPrice;
+    cdsDealInfosPayTotalPrice.AsFloat := AInfo.FFinalTotalPrice - AInfo.FCutTotalPrice;
+    cdsDealInfosPaidTotalPrice.AsFloat := AInfo.FPaidTotalPrice;
+    cdsDealInfosPayingTotalPrice.AsFloat := AInfo.FFinalTotalPrice - AInfo.FCutTotalPrice - AInfo.FPaidTotalPrice;
+    if cdsDealInfosPayTotalPrice.AsFloat <> 0 then
+      cdsDealInfosPayPercent.AsFloat := AdvRoundTo(
+          cdsDealInfosPaidTotalPrice.AsFloat/cdsDealInfosPayTotalPrice.AsFloat*100);
+    cdsDealInfosContractPrice.AsFloat := AInfo.FContractPrice;
+    cdsDealInfos.Post;
+  end;
+
+var
+  i: Integer;
+begin
+  for i := 0 to FDealInfos.Count - 1 do
+    WriteInfoNodeData(TInfoNode(FDealInfos.Items[i]));
+  WriteInfoNodeData(FTotalDealInfo);
+end;
+
+{ TInfoNode }
+
+constructor TInfoNode.Create;
+begin
+  FDealTotalPrice := 0;
+  FFinalTotalPrice := 0;
+  FCutTotalPrice := 0;
+  FPaidTotalPrice := 0;
+  FContractPrice := 0;
+end;
+
+end.

+ 852 - 0
DataModules/ReportMemoryDm/rmFxBillsAddDm.dfm

@@ -0,0 +1,852 @@
+object rmFxBillsAddData: TrmFxBillsAddData
+  OldCreateOrder = False
+  Left = 191
+  Top = 114
+  Height = 150
+  Width = 215
+  object cdsBills: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 100
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'Price'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity1'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice1'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity2'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice2'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity3'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice3'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity4'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice4'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity5'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice5'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity6'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice6'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity7'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice7'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity8'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice8'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity9'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice9'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity10'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice10'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity11'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice11'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity12'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice12'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity13'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice13'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity14'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice14'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity15'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice15'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity16'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice16'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity17'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice17'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity18'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice18'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity19'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice19'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity20'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice20'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity21'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice21'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity22'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice22'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity23'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice23'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity24'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice24'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity25'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice25'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity26'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice26'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity27'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice27'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity28'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice28'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity29'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice29'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity30'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice30'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity31'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice31'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity32'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice32'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity33'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice33'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity34'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice34'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity35'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice35'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity36'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice36'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity37'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice37'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity38'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice38'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity39'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice39'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity40'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice40'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity41'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice41'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity42'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice42'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity43'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice43'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity44'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice44'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity45'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice45'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity46'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice46'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity47'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice47'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity48'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice48'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity49'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice49'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity50'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice50'
+        DataType = ftFloat
+      end
+      item
+        Name = 'MemoStr'
+        DataType = ftWideString
+        Size = 100
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 56
+    Top = 40
+    Data = {
+      8D0800009619E0BD01000000180000006C0000000000030000008D0804436F64
+      65010049000000010005574944544802000200320006425F436F646501004900
+      00000100055749445448020002003200044E616D6501004A0000000100055749
+      44544802000200C80005556E69747301004A0000000100055749445448020002
+      0028000550726963650800040000000000085175616E74697479080004000000
+      00000A546F74616C50726963650800040000000000095175616E746974793108
+      000400000000000B546F74616C5072696365310800040000000000095175616E
+      746974793208000400000000000B546F74616C50726963653208000400000000
+      00095175616E746974793308000400000000000B546F74616C50726963653308
+      00040000000000095175616E746974793408000400000000000B546F74616C50
+      72696365340800040000000000095175616E746974793508000400000000000B
+      546F74616C5072696365350800040000000000095175616E7469747936080004
+      00000000000B546F74616C5072696365360800040000000000095175616E7469
+      74793708000400000000000B546F74616C507269636537080004000000000009
+      5175616E746974793808000400000000000B546F74616C507269636538080004
+      0000000000095175616E746974793908000400000000000B546F74616C507269
+      63653908000400000000000A5175616E74697479313008000400000000000C54
+      6F74616C5072696365313008000400000000000A5175616E7469747931310800
+      0400000000000C546F74616C5072696365313108000400000000000A5175616E
+      74697479313208000400000000000C546F74616C507269636531320800040000
+      0000000A5175616E74697479313308000400000000000C546F74616C50726963
+      65313308000400000000000A5175616E74697479313408000400000000000C54
+      6F74616C5072696365313408000400000000000A5175616E7469747931350800
+      0400000000000C546F74616C5072696365313508000400000000000A5175616E
+      74697479313608000400000000000C546F74616C507269636531360800040000
+      0000000A5175616E74697479313708000400000000000C546F74616C50726963
+      65313708000400000000000A5175616E74697479313808000400000000000C54
+      6F74616C5072696365313808000400000000000A5175616E7469747931390800
+      0400000000000C546F74616C5072696365313908000400000000000A5175616E
+      74697479323008000400000000000C546F74616C507269636532300800040000
+      0000000A5175616E74697479323108000400000000000C546F74616C50726963
+      65323108000400000000000A5175616E74697479323208000400000000000C54
+      6F74616C5072696365323208000400000000000A5175616E7469747932330800
+      0400000000000C546F74616C5072696365323308000400000000000A5175616E
+      74697479323408000400000000000C546F74616C507269636532340800040000
+      0000000A5175616E74697479323508000400000000000C546F74616C50726963
+      65323508000400000000000A5175616E74697479323608000400000000000C54
+      6F74616C5072696365323608000400000000000A5175616E7469747932370800
+      0400000000000C546F74616C5072696365323708000400000000000A5175616E
+      74697479323808000400000000000C546F74616C507269636532380800040000
+      0000000A5175616E74697479323908000400000000000C546F74616C50726963
+      65323908000400000000000A5175616E74697479333008000400000000000C54
+      6F74616C5072696365333008000400000000000A5175616E7469747933310800
+      0400000000000C546F74616C5072696365333108000400000000000A5175616E
+      74697479333208000400000000000C546F74616C507269636533320800040000
+      0000000A5175616E74697479333308000400000000000C546F74616C50726963
+      65333308000400000000000A5175616E74697479333408000400000000000C54
+      6F74616C5072696365333408000400000000000A5175616E7469747933350800
+      0400000000000C546F74616C5072696365333508000400000000000A5175616E
+      74697479333608000400000000000C546F74616C507269636533360800040000
+      0000000A5175616E74697479333708000400000000000C546F74616C50726963
+      65333708000400000000000A5175616E74697479333808000400000000000C54
+      6F74616C5072696365333808000400000000000A5175616E7469747933390800
+      0400000000000C546F74616C5072696365333908000400000000000A5175616E
+      74697479343008000400000000000C546F74616C507269636534300800040000
+      0000000A5175616E74697479343108000400000000000C546F74616C50726963
+      65343108000400000000000A5175616E74697479343208000400000000000C54
+      6F74616C5072696365343208000400000000000A5175616E7469747934330800
+      0400000000000C546F74616C5072696365343308000400000000000A5175616E
+      74697479343408000400000000000C546F74616C507269636534340800040000
+      0000000A5175616E74697479343508000400000000000C546F74616C50726963
+      65343508000400000000000A5175616E74697479343608000400000000000C54
+      6F74616C5072696365343608000400000000000A5175616E7469747934370800
+      0400000000000C546F74616C5072696365343708000400000000000A5175616E
+      74697479343808000400000000000C546F74616C507269636534380800040000
+      0000000A5175616E74697479343908000400000000000C546F74616C50726963
+      65343908000400000000000A5175616E74697479353008000400000000000C54
+      6F74616C507269636535300800040000000000074D656D6F53747201004A0000
+      00010005574944544802000200C8000000}
+    object cdsBillsCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsBillsB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBillsName: TWideStringField
+      FieldName = 'Name'
+      Size = 100
+    end
+    object cdsBillsUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBillsPrice: TFloatField
+      FieldName = 'Price'
+    end
+    object cdsBillsQuantity: TFloatField
+      FieldName = 'Quantity'
+    end
+    object cdsBillsTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsBillsQuantity1: TFloatField
+      FieldName = 'Quantity1'
+    end
+    object cdsBillsTotalPrice1: TFloatField
+      FieldName = 'TotalPrice1'
+    end
+    object cdsBillsQuantity2: TFloatField
+      FieldName = 'Quantity2'
+    end
+    object cdsBillsTotalPrice2: TFloatField
+      FieldName = 'TotalPrice2'
+    end
+    object cdsBillsQuantity3: TFloatField
+      FieldName = 'Quantity3'
+    end
+    object cdsBillsTotalPrice3: TFloatField
+      FieldName = 'TotalPrice3'
+    end
+    object cdsBillsQuantity4: TFloatField
+      FieldName = 'Quantity4'
+    end
+    object cdsBillsTotalPrice4: TFloatField
+      FieldName = 'TotalPrice4'
+    end
+    object cdsBillsQuantity5: TFloatField
+      FieldName = 'Quantity5'
+    end
+    object cdsBillsTotalPrice5: TFloatField
+      FieldName = 'TotalPrice5'
+    end
+    object cdsBillsQuantity6: TFloatField
+      FieldName = 'Quantity6'
+    end
+    object cdsBillsTotalPrice6: TFloatField
+      FieldName = 'TotalPrice6'
+    end
+    object cdsBillsQuantity7: TFloatField
+      FieldName = 'Quantity7'
+    end
+    object cdsBillsTotalPrice7: TFloatField
+      FieldName = 'TotalPrice7'
+    end
+    object cdsBillsQuantity8: TFloatField
+      FieldName = 'Quantity8'
+    end
+    object cdsBillsTotalPrice8: TFloatField
+      FieldName = 'TotalPrice8'
+    end
+    object cdsBillsQuantity9: TFloatField
+      FieldName = 'Quantity9'
+    end
+    object cdsBillsTotalPrice9: TFloatField
+      FieldName = 'TotalPrice9'
+    end
+    object cdsBillsQuantity10: TFloatField
+      FieldName = 'Quantity10'
+    end
+    object cdsBillsTotalPrice10: TFloatField
+      FieldName = 'TotalPrice10'
+    end
+    object cdsBillsQuantity11: TFloatField
+      FieldName = 'Quantity11'
+    end
+    object cdsBillsTotalPrice11: TFloatField
+      FieldName = 'TotalPrice11'
+    end
+    object cdsBillsQuantity12: TFloatField
+      FieldName = 'Quantity12'
+    end
+    object cdsBillsTotalPrice12: TFloatField
+      FieldName = 'TotalPrice12'
+    end
+    object cdsBillsQuantity13: TFloatField
+      FieldName = 'Quantity13'
+    end
+    object cdsBillsTotalPrice13: TFloatField
+      FieldName = 'TotalPrice13'
+    end
+    object cdsBillsQuantity14: TFloatField
+      FieldName = 'Quantity14'
+    end
+    object cdsBillsTotalPrice14: TFloatField
+      FieldName = 'TotalPrice14'
+    end
+    object cdsBillsQuantity15: TFloatField
+      FieldName = 'Quantity15'
+    end
+    object cdsBillsTotalPrice15: TFloatField
+      FieldName = 'TotalPrice15'
+    end
+    object cdsBillsQuantity16: TFloatField
+      FieldName = 'Quantity16'
+    end
+    object cdsBillsTotalPrice16: TFloatField
+      FieldName = 'TotalPrice16'
+    end
+    object cdsBillsQuantity17: TFloatField
+      FieldName = 'Quantity17'
+    end
+    object cdsBillsTotalPrice17: TFloatField
+      FieldName = 'TotalPrice17'
+    end
+    object cdsBillsQuantity18: TFloatField
+      FieldName = 'Quantity18'
+    end
+    object cdsBillsTotalPrice18: TFloatField
+      FieldName = 'TotalPrice18'
+    end
+    object cdsBillsQuantity19: TFloatField
+      FieldName = 'Quantity19'
+    end
+    object cdsBillsTotalPrice19: TFloatField
+      FieldName = 'TotalPrice19'
+    end
+    object cdsBillsQuantity20: TFloatField
+      FieldName = 'Quantity20'
+    end
+    object cdsBillsTotalPrice20: TFloatField
+      FieldName = 'TotalPrice20'
+    end
+    object cdsBillsQuantity21: TFloatField
+      FieldName = 'Quantity21'
+    end
+    object cdsBillsTotalPrice21: TFloatField
+      FieldName = 'TotalPrice21'
+    end
+    object cdsBillsQuantity22: TFloatField
+      FieldName = 'Quantity22'
+    end
+    object cdsBillsTotalPrice22: TFloatField
+      FieldName = 'TotalPrice22'
+    end
+    object cdsBillsQuantity23: TFloatField
+      FieldName = 'Quantity23'
+    end
+    object cdsBillsTotalPrice23: TFloatField
+      FieldName = 'TotalPrice23'
+    end
+    object cdsBillsQuantity24: TFloatField
+      FieldName = 'Quantity24'
+    end
+    object cdsBillsTotalPrice24: TFloatField
+      FieldName = 'TotalPrice24'
+    end
+    object cdsBillsQuantity25: TFloatField
+      FieldName = 'Quantity25'
+    end
+    object cdsBillsTotalPrice25: TFloatField
+      FieldName = 'TotalPrice25'
+    end
+    object cdsBillsQuantity26: TFloatField
+      FieldName = 'Quantity26'
+    end
+    object cdsBillsTotalPrice26: TFloatField
+      FieldName = 'TotalPrice26'
+    end
+    object cdsBillsQuantity27: TFloatField
+      FieldName = 'Quantity27'
+    end
+    object cdsBillsTotalPrice27: TFloatField
+      FieldName = 'TotalPrice27'
+    end
+    object cdsBillsQuantity28: TFloatField
+      FieldName = 'Quantity28'
+    end
+    object cdsBillsTotalPrice28: TFloatField
+      FieldName = 'TotalPrice28'
+    end
+    object cdsBillsQuantity29: TFloatField
+      FieldName = 'Quantity29'
+    end
+    object cdsBillsTotalPrice29: TFloatField
+      FieldName = 'TotalPrice29'
+    end
+    object cdsBillsQuantity30: TFloatField
+      FieldName = 'Quantity30'
+    end
+    object cdsBillsTotalPrice30: TFloatField
+      FieldName = 'TotalPrice30'
+    end
+    object cdsBillsQuantity31: TFloatField
+      FieldName = 'Quantity31'
+    end
+    object cdsBillsTotalPrice31: TFloatField
+      FieldName = 'TotalPrice31'
+    end
+    object cdsBillsQuantity32: TFloatField
+      FieldName = 'Quantity32'
+    end
+    object cdsBillsTotalPrice32: TFloatField
+      FieldName = 'TotalPrice32'
+    end
+    object cdsBillsQuantity33: TFloatField
+      FieldName = 'Quantity33'
+    end
+    object cdsBillsTotalPrice33: TFloatField
+      FieldName = 'TotalPrice33'
+    end
+    object cdsBillsQuantity34: TFloatField
+      FieldName = 'Quantity34'
+    end
+    object cdsBillsTotalPrice34: TFloatField
+      FieldName = 'TotalPrice34'
+    end
+    object cdsBillsQuantity35: TFloatField
+      FieldName = 'Quantity35'
+    end
+    object cdsBillsTotalPrice35: TFloatField
+      FieldName = 'TotalPrice35'
+    end
+    object cdsBillsQuantity36: TFloatField
+      FieldName = 'Quantity36'
+    end
+    object cdsBillsTotalPrice36: TFloatField
+      FieldName = 'TotalPrice36'
+    end
+    object cdsBillsQuantity37: TFloatField
+      FieldName = 'Quantity37'
+    end
+    object cdsBillsTotalPrice37: TFloatField
+      FieldName = 'TotalPrice37'
+    end
+    object cdsBillsQuantity38: TFloatField
+      FieldName = 'Quantity38'
+    end
+    object cdsBillsTotalPrice38: TFloatField
+      FieldName = 'TotalPrice38'
+    end
+    object cdsBillsQuantity39: TFloatField
+      FieldName = 'Quantity39'
+    end
+    object cdsBillsTotalPrice39: TFloatField
+      FieldName = 'TotalPrice39'
+    end
+    object cdsBillsQuantity40: TFloatField
+      FieldName = 'Quantity40'
+    end
+    object cdsBillsTotalPrice40: TFloatField
+      FieldName = 'TotalPrice40'
+    end
+    object cdsBillsQuantity41: TFloatField
+      FieldName = 'Quantity41'
+    end
+    object cdsBillsTotalPrice41: TFloatField
+      FieldName = 'TotalPrice41'
+    end
+    object cdsBillsQuantity42: TFloatField
+      FieldName = 'Quantity42'
+    end
+    object cdsBillsTotalPrice42: TFloatField
+      FieldName = 'TotalPrice42'
+    end
+    object cdsBillsQuantity43: TFloatField
+      FieldName = 'Quantity43'
+    end
+    object cdsBillsTotalPrice43: TFloatField
+      FieldName = 'TotalPrice43'
+    end
+    object cdsBillsQuantity44: TFloatField
+      FieldName = 'Quantity44'
+    end
+    object cdsBillsTotalPrice44: TFloatField
+      FieldName = 'TotalPrice44'
+    end
+    object cdsBillsQuantity45: TFloatField
+      FieldName = 'Quantity45'
+    end
+    object cdsBillsTotalPrice45: TFloatField
+      FieldName = 'TotalPrice45'
+    end
+    object cdsBillsQuantity46: TFloatField
+      FieldName = 'Quantity46'
+    end
+    object cdsBillsTotalPrice46: TFloatField
+      FieldName = 'TotalPrice46'
+    end
+    object cdsBillsQuantity47: TFloatField
+      FieldName = 'Quantity47'
+    end
+    object cdsBillsTotalPrice47: TFloatField
+      FieldName = 'TotalPrice47'
+    end
+    object cdsBillsQuantity48: TFloatField
+      FieldName = 'Quantity48'
+    end
+    object cdsBillsTotalPrice48: TFloatField
+      FieldName = 'TotalPrice48'
+    end
+    object cdsBillsQuantity49: TFloatField
+      FieldName = 'Quantity49'
+    end
+    object cdsBillsTotalPrice49: TFloatField
+      FieldName = 'TotalPrice49'
+    end
+    object cdsBillsQuantity50: TFloatField
+      FieldName = 'Quantity50'
+    end
+    object cdsBillsTotalPrice50: TFloatField
+      FieldName = 'TotalPrice50'
+    end
+    object cdsBillsMemoStr: TWideStringField
+      FieldName = 'MemoStr'
+      Size = 100
+    end
+  end
+end

+ 344 - 0
DataModules/ReportMemoryDm/rmFxBillsAddDm.pas

@@ -0,0 +1,344 @@
+unit rmFxBillsAddDm;
+
+interface
+
+uses
+  SysUtils, Classes, ProjectData, PhaseData, StageDm, DB, DBClient,
+  MCacheTree, sdIDTree, sdDB;
+
+type
+  TrmFxBillsAddData = class(TDataModule)
+    cdsBills: TClientDataSet;
+    cdsBillsB_Code: TStringField;
+    cdsBillsCode: TStringField;
+    cdsBillsName: TWideStringField;
+    cdsBillsUnits: TWideStringField;
+    cdsBillsPrice: TFloatField;
+    cdsBillsQuantity: TFloatField;
+    cdsBillsTotalPrice: TFloatField;
+    cdsBillsQuantity1: TFloatField;
+    cdsBillsTotalPrice1: TFloatField;
+    cdsBillsQuantity2: TFloatField;
+    cdsBillsTotalPrice2: TFloatField;
+    cdsBillsQuantity3: TFloatField;
+    cdsBillsTotalPrice3: TFloatField;
+    cdsBillsQuantity4: TFloatField;
+    cdsBillsTotalPrice4: TFloatField;
+    cdsBillsQuantity5: TFloatField;
+    cdsBillsTotalPrice5: TFloatField;
+    cdsBillsQuantity6: TFloatField;
+    cdsBillsTotalPrice6: TFloatField;
+    cdsBillsQuantity7: TFloatField;
+    cdsBillsTotalPrice7: TFloatField;
+    cdsBillsQuantity8: TFloatField;
+    cdsBillsTotalPrice8: TFloatField;
+    cdsBillsQuantity9: TFloatField;
+    cdsBillsTotalPrice9: TFloatField;
+    cdsBillsQuantity10: TFloatField;
+    cdsBillsTotalPrice10: TFloatField;
+    cdsBillsQuantity11: TFloatField;
+    cdsBillsTotalPrice11: TFloatField;
+    cdsBillsQuantity12: TFloatField;
+    cdsBillsTotalPrice12: TFloatField;
+    cdsBillsQuantity13: TFloatField;
+    cdsBillsTotalPrice13: TFloatField;
+    cdsBillsQuantity14: TFloatField;
+    cdsBillsTotalPrice14: TFloatField;
+    cdsBillsQuantity15: TFloatField;
+    cdsBillsTotalPrice15: TFloatField;
+    cdsBillsQuantity16: TFloatField;
+    cdsBillsTotalPrice16: TFloatField;
+    cdsBillsQuantity17: TFloatField;
+    cdsBillsTotalPrice17: TFloatField;
+    cdsBillsQuantity18: TFloatField;
+    cdsBillsTotalPrice18: TFloatField;
+    cdsBillsQuantity19: TFloatField;
+    cdsBillsTotalPrice19: TFloatField;
+    cdsBillsQuantity20: TFloatField;
+    cdsBillsTotalPrice20: TFloatField;
+    cdsBillsQuantity21: TFloatField;
+    cdsBillsTotalPrice21: TFloatField;
+    cdsBillsQuantity22: TFloatField;
+    cdsBillsTotalPrice22: TFloatField;
+    cdsBillsQuantity23: TFloatField;
+    cdsBillsTotalPrice23: TFloatField;
+    cdsBillsQuantity24: TFloatField;
+    cdsBillsTotalPrice24: TFloatField;
+    cdsBillsQuantity25: TFloatField;
+    cdsBillsTotalPrice25: TFloatField;
+    cdsBillsQuantity26: TFloatField;
+    cdsBillsTotalPrice26: TFloatField;
+    cdsBillsQuantity27: TFloatField;
+    cdsBillsTotalPrice27: TFloatField;
+    cdsBillsQuantity28: TFloatField;
+    cdsBillsTotalPrice28: TFloatField;
+    cdsBillsQuantity29: TFloatField;
+    cdsBillsTotalPrice29: TFloatField;
+    cdsBillsQuantity30: TFloatField;
+    cdsBillsTotalPrice30: TFloatField;
+    cdsBillsQuantity31: TFloatField;
+    cdsBillsTotalPrice31: TFloatField;
+    cdsBillsQuantity32: TFloatField;
+    cdsBillsTotalPrice32: TFloatField;
+    cdsBillsQuantity33: TFloatField;
+    cdsBillsTotalPrice33: TFloatField;
+    cdsBillsQuantity34: TFloatField;
+    cdsBillsTotalPrice34: TFloatField;
+    cdsBillsQuantity35: TFloatField;
+    cdsBillsTotalPrice35: TFloatField;
+    cdsBillsQuantity36: TFloatField;
+    cdsBillsTotalPrice36: TFloatField;
+    cdsBillsQuantity37: TFloatField;
+    cdsBillsTotalPrice37: TFloatField;
+    cdsBillsQuantity38: TFloatField;
+    cdsBillsTotalPrice38: TFloatField;
+    cdsBillsQuantity39: TFloatField;
+    cdsBillsTotalPrice39: TFloatField;
+    cdsBillsQuantity40: TFloatField;
+    cdsBillsTotalPrice40: TFloatField;
+    cdsBillsQuantity41: TFloatField;
+    cdsBillsTotalPrice41: TFloatField;
+    cdsBillsQuantity42: TFloatField;
+    cdsBillsTotalPrice42: TFloatField;
+    cdsBillsQuantity43: TFloatField;
+    cdsBillsTotalPrice43: TFloatField;
+    cdsBillsQuantity44: TFloatField;
+    cdsBillsTotalPrice44: TFloatField;
+    cdsBillsQuantity45: TFloatField;
+    cdsBillsTotalPrice45: TFloatField;
+    cdsBillsQuantity46: TFloatField;
+    cdsBillsTotalPrice46: TFloatField;
+    cdsBillsQuantity47: TFloatField;
+    cdsBillsTotalPrice47: TFloatField;
+    cdsBillsQuantity48: TFloatField;
+    cdsBillsTotalPrice48: TFloatField;
+    cdsBillsQuantity49: TFloatField;
+    cdsBillsTotalPrice49: TFloatField;
+    cdsBillsQuantity50: TFloatField;
+    cdsBillsTotalPrice50: TFloatField;
+    cdsBillsMemoStr: TWideStringField;
+  private
+    FProjectData: TProjectData;
+    FAllPhaseCacheTree: TAllPhaseCacheTree;
+
+    function AddBills(ANode: TsdIDTreeNode; AParent: TAllPhaseCacheNode): TAllPhaseCacheNode;
+
+    procedure LoadStageData(AStageData: TStageData; APhaseIndex: Integer);
+    procedure LoadPhaseData(APhaseIndex: Integer);
+
+    procedure WriteBills(ANode: TAllPhaseCacheNode);
+  public
+    function AssignData(AProjectData: TProjectData): TDataSet;
+  end;
+
+implementation
+
+uses CacheTree;
+
+{$R *.dfm}
+
+{ TrmFxBillsAddData }
+
+function TrmFxBillsAddData.AddBills(ANode: TsdIDTreeNode;
+  AParent: TAllPhaseCacheNode): TAllPhaseCacheNode;
+begin
+  if not Assigned(ANode) then Exit;
+  Result := FAllPhaseCacheTree.AddNode(ANode.ID, AParent, nil);
+  Result.Code := ANode.Rec.ValueByName('Code').AsString;
+  Result.B_Code := ANode.Rec.ValueByName('B_Code').AsString;
+  Result.Name := ANode.Rec.ValueByName('Name').AsString;
+  Result.Units := ANode.Rec.ValueByName('Units').AsString;
+  Result.Price := ANode.Rec.ValueByName('Price').AsFloat;
+  Result.Quantity := ANode.Rec.ValueByName('Quantity').AsFloat;
+  Result.TotalPrice := ANode.Rec.ValueByName('TotalPrice').AsFloat;  
+  AddBills(ANode.FirstChild, Result);
+  AddBills(ANode.NextSibling, AParent);
+end;
+
+function TrmFxBillsAddData.AssignData(
+  AProjectData: TProjectData): TDataSet;
+var
+  iPhase: Integer;
+begin
+  FProjectData := AProjectData;
+  cdsBills.DisableControls;
+  cdsBills.Active := True;
+  cdsBills.EmptyDataSet;
+  FAllPhaseCacheTree := TAllPhaseCacheTree.Create;
+  try
+    AddBills(FProjectData.BillsCompileData.BillsCompileTree.FirstNode, nil);
+    for iPhase := 1 to FProjectData.ProjProperties.PhaseCount do
+      LoadPhaseData(iPhase);
+    WriteBills(TAllPhaseCacheNode(FAllPhaseCacheTree.FirstNode));
+  finally
+    Result := cdsBills;
+    FAllPhaseCacheTree.Free;
+    cdsBills.EnableControls;
+  end;
+end;
+
+procedure TrmFxBillsAddData.LoadPhaseData(APhaseIndex: Integer);
+var
+  PhaseData: TPhaseData;
+  StageData: TStageData;
+begin
+  PhaseData := TPhaseData.Create(nil);
+  try
+    PhaseData.SimpleOpen(Format('%s\Phase%d.dat', [FProjectData.TempPath, APhaseIndex]));
+    if PhaseData.IsLastStage then
+      LoadStageData(PhaseData.StageData, APhaseIndex)
+    else
+    begin
+      try
+        StageData := TStageData.Create(PhaseData);
+        StageData.TableName := PhaseData.StageTableName[PhaseData.AuditCount];
+        StageData.Open(PhaseData.ADOConnection);
+        LoadStageData(StageData, APhaseIndex);
+      finally
+        StageData.Free;
+      end;
+    end;
+  finally
+    PhaseData.Free;
+  end;
+end;
+
+procedure TrmFxBillsAddData.LoadStageData(AStageData: TStageData;
+  APhaseIndex: Integer);
+var
+  i: Integer;
+  StageRec: TsdDataRecord;
+  stnNode: TsdIDTreeNode;
+  Node: TAllPhaseCacheNode;
+begin
+  for i := 0 to AStageData.sddStage.RecordCount - 1 do
+  begin
+    StageRec := AStageData.sddStage.Records[i];
+    with FProjectData.BillsCompileData.BillsCompileTree do
+      stnNode := FindNode(StageRec.ValueByName('BillsID').AsInteger);
+    Node := FAllPhaseCacheTree.FindNode(StageRec.ValueByName('BillsID').AsInteger);
+    if Assigned(Node) then
+    begin
+      Node.FP_Quantity[APhaseIndex] := StageRec.ValueByName('GatherQuantity').AsFloat;
+      Node.FP_TotalPrice[APhaseIndex] := StageRec.ValueByName('GatherTotalPrice').AsFloat;
+    end;
+  end;
+end;
+
+procedure TrmFxBillsAddData.WriteBills(ANode: TAllPhaseCacheNode);
+begin
+  if not Assigned(ANode) then Exit;
+  cdsBills.Append;
+  cdsBillsCode.AsString := ANode.Code;
+  cdsBillsB_Code.AsString := ANode.B_Code;
+  cdsBillsName.AsString := ANode.Name;
+  cdsBillsUnits.AsString := ANode.Units;
+  cdsBillsPrice.AsFloat := ANode.Price;
+  cdsBillsQuantity.AsFloat := ANode.Quantity;
+  cdsBillsTotalPrice.AsFloat := ANode.TotalPrice;
+  cdsBillsQuantity1.AsFloat := ANode.FP_Quantity[1];
+  cdsBillsTotalPrice1.AsFloat := ANode.FP_TotalPrice[1];
+  cdsBillsQuantity2.AsFloat := ANode.FP_Quantity[2];
+  cdsBillsTotalPrice2.AsFloat := ANode.FP_TotalPrice[2];
+  cdsBillsQuantity3.AsFloat := ANode.FP_Quantity[3];
+  cdsBillsTotalPrice3.AsFloat := ANode.FP_TotalPrice[3];
+  cdsBillsQuantity4.AsFloat := ANode.FP_Quantity[4];
+  cdsBillsTotalPrice4.AsFloat := ANode.FP_TotalPrice[4];
+  cdsBillsQuantity5.AsFloat := ANode.FP_Quantity[5];
+  cdsBillsTotalPrice5.AsFloat := ANode.FP_TotalPrice[5];
+  cdsBillsQuantity6.AsFloat := ANode.FP_Quantity[6];
+  cdsBillsTotalPrice6.AsFloat := ANode.FP_TotalPrice[6];
+  cdsBillsQuantity7.AsFloat := ANode.FP_Quantity[7];
+  cdsBillsTotalPrice7.AsFloat := ANode.FP_TotalPrice[7];
+  cdsBillsQuantity8.AsFloat := ANode.FP_Quantity[8];
+  cdsBillsTotalPrice8.AsFloat := ANode.FP_TotalPrice[8];
+  cdsBillsQuantity9.AsFloat := ANode.FP_Quantity[9];
+  cdsBillsTotalPrice9.AsFloat := ANode.FP_TotalPrice[9];
+  cdsBillsQuantity10.AsFloat := ANode.FP_Quantity[10];
+  cdsBillsTotalPrice10.AsFloat := ANode.FP_TotalPrice[10];
+  cdsBillsQuantity11.AsFloat := ANode.FP_Quantity[11];
+  cdsBillsTotalPrice11.AsFloat := ANode.FP_TotalPrice[11];
+  cdsBillsQuantity12.AsFloat := ANode.FP_Quantity[12];
+  cdsBillsTotalPrice12.AsFloat := ANode.FP_TotalPrice[12];
+  cdsBillsQuantity13.AsFloat := ANode.FP_Quantity[13];
+  cdsBillsTotalPrice13.AsFloat := ANode.FP_TotalPrice[13];
+  cdsBillsQuantity14.AsFloat := ANode.FP_Quantity[14];
+  cdsBillsTotalPrice14.AsFloat := ANode.FP_TotalPrice[14];
+  cdsBillsQuantity15.AsFloat := ANode.FP_Quantity[15];
+  cdsBillsTotalPrice15.AsFloat := ANode.FP_TotalPrice[15];
+  cdsBillsQuantity16.AsFloat := ANode.FP_Quantity[16];
+  cdsBillsTotalPrice16.AsFloat := ANode.FP_TotalPrice[16];
+  cdsBillsQuantity17.AsFloat := ANode.FP_Quantity[17];
+  cdsBillsTotalPrice17.AsFloat := ANode.FP_TotalPrice[17];
+  cdsBillsQuantity18.AsFloat := ANode.FP_Quantity[18];
+  cdsBillsTotalPrice18.AsFloat := ANode.FP_TotalPrice[18];
+  cdsBillsQuantity19.AsFloat := ANode.FP_Quantity[19];
+  cdsBillsTotalPrice19.AsFloat := ANode.FP_TotalPrice[19];
+  cdsBillsQuantity20.AsFloat := ANode.FP_Quantity[20];
+  cdsBillsTotalPrice20.AsFloat := ANode.FP_TotalPrice[20];
+  cdsBillsQuantity21.AsFloat := ANode.FP_Quantity[21];
+  cdsBillsTotalPrice21.AsFloat := ANode.FP_TotalPrice[21];
+  cdsBillsQuantity22.AsFloat := ANode.FP_Quantity[22];
+  cdsBillsTotalPrice22.AsFloat := ANode.FP_TotalPrice[22];
+  cdsBillsQuantity23.AsFloat := ANode.FP_Quantity[23];
+  cdsBillsTotalPrice23.AsFloat := ANode.FP_TotalPrice[23];
+  cdsBillsQuantity24.AsFloat := ANode.FP_Quantity[24];
+  cdsBillsTotalPrice24.AsFloat := ANode.FP_TotalPrice[24];
+  cdsBillsQuantity25.AsFloat := ANode.FP_Quantity[25];
+  cdsBillsTotalPrice25.AsFloat := ANode.FP_TotalPrice[25];
+  cdsBillsQuantity26.AsFloat := ANode.FP_Quantity[26];
+  cdsBillsTotalPrice26.AsFloat := ANode.FP_TotalPrice[26];
+  cdsBillsQuantity27.AsFloat := ANode.FP_Quantity[27];
+  cdsBillsTotalPrice27.AsFloat := ANode.FP_TotalPrice[27];
+  cdsBillsQuantity28.AsFloat := ANode.FP_Quantity[28];
+  cdsBillsTotalPrice28.AsFloat := ANode.FP_TotalPrice[28];
+  cdsBillsQuantity29.AsFloat := ANode.FP_Quantity[29];
+  cdsBillsTotalPrice29.AsFloat := ANode.FP_TotalPrice[29];
+  cdsBillsQuantity30.AsFloat := ANode.FP_Quantity[30];
+  cdsBillsTotalPrice30.AsFloat := ANode.FP_TotalPrice[30];
+  cdsBillsQuantity31.AsFloat := ANode.FP_Quantity[31];
+  cdsBillsTotalPrice31.AsFloat := ANode.FP_TotalPrice[31];
+  cdsBillsQuantity32.AsFloat := ANode.FP_Quantity[32];
+  cdsBillsTotalPrice32.AsFloat := ANode.FP_TotalPrice[32];
+  cdsBillsQuantity33.AsFloat := ANode.FP_Quantity[33];
+  cdsBillsTotalPrice33.AsFloat := ANode.FP_TotalPrice[33];
+  cdsBillsQuantity34.AsFloat := ANode.FP_Quantity[34];
+  cdsBillsTotalPrice34.AsFloat := ANode.FP_TotalPrice[34];
+  cdsBillsQuantity35.AsFloat := ANode.FP_Quantity[35];
+  cdsBillsTotalPrice35.AsFloat := ANode.FP_TotalPrice[35];
+  cdsBillsQuantity36.AsFloat := ANode.FP_Quantity[36];
+  cdsBillsTotalPrice36.AsFloat := ANode.FP_TotalPrice[36];
+  cdsBillsQuantity37.AsFloat := ANode.FP_Quantity[37];
+  cdsBillsTotalPrice37.AsFloat := ANode.FP_TotalPrice[37];
+  cdsBillsQuantity38.AsFloat := ANode.FP_Quantity[38];
+  cdsBillsTotalPrice38.AsFloat := ANode.FP_TotalPrice[38];
+  cdsBillsQuantity39.AsFloat := ANode.FP_Quantity[39];
+  cdsBillsTotalPrice39.AsFloat := ANode.FP_TotalPrice[39];
+  cdsBillsQuantity40.AsFloat := ANode.FP_Quantity[40];
+  cdsBillsTotalPrice40.AsFloat := ANode.FP_TotalPrice[40];
+  cdsBillsQuantity41.AsFloat := ANode.FP_Quantity[41];
+  cdsBillsTotalPrice41.AsFloat := ANode.FP_TotalPrice[41];
+  cdsBillsQuantity42.AsFloat := ANode.FP_Quantity[42];
+  cdsBillsTotalPrice42.AsFloat := ANode.FP_TotalPrice[42];
+  cdsBillsQuantity43.AsFloat := ANode.FP_Quantity[43];
+  cdsBillsTotalPrice43.AsFloat := ANode.FP_TotalPrice[43];
+  cdsBillsQuantity44.AsFloat := ANode.FP_Quantity[44];
+  cdsBillsTotalPrice44.AsFloat := ANode.FP_TotalPrice[44];
+  cdsBillsQuantity45.AsFloat := ANode.FP_Quantity[45];
+  cdsBillsTotalPrice45.AsFloat := ANode.FP_TotalPrice[45];
+  cdsBillsQuantity46.AsFloat := ANode.FP_Quantity[46];
+  cdsBillsTotalPrice46.AsFloat := ANode.FP_TotalPrice[46];
+  cdsBillsQuantity47.AsFloat := ANode.FP_Quantity[47];
+  cdsBillsTotalPrice47.AsFloat := ANode.FP_TotalPrice[47];
+  cdsBillsQuantity48.AsFloat := ANode.FP_Quantity[48];
+  cdsBillsTotalPrice48.AsFloat := ANode.FP_TotalPrice[48];
+  cdsBillsQuantity49.AsFloat := ANode.FP_Quantity[49];
+  cdsBillsTotalPrice49.AsFloat := ANode.FP_TotalPrice[49];
+  cdsBillsQuantity50.AsFloat := ANode.FP_Quantity[50];
+  cdsBillsTotalPrice50.AsFloat := ANode.FP_TotalPrice[50];
+  cdsBills.Post;
+  WriteBills(TAllPhaseCacheNode(ANode.FirstChild));
+  WriteBills(TAllPhaseCacheNode(ANode.NextSibling));
+end;
+
+end.

+ 247 - 0
DataModules/ReportMemoryDm/rmFxBillsCompareDm.dfm

@@ -0,0 +1,247 @@
+object rmFxBillsCompareData: TrmFxBillsCompareData
+  OldCreateOrder = False
+  Left = 567
+  Top = 304
+  Height = 150
+  Width = 215
+  object cdsBills: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 100
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'SQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'SPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'STotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'MemoStr'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'SDgnQuantity1'
+        DataType = ftFloat
+      end
+      item
+        Name = 'SDgnQuantity2'
+        DataType = ftFloat
+      end
+      item
+        Name = 'SDgnQuantity'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'CDgnQuantity1'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CDgnQuantity2'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CDgnQuantity'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'DDgnQuantity1'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DDgnQuantity2'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DDgnQuantity'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'XiangCode'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'MuCode'
+        DataType = ftString
+        Size = 20
+      end
+      item
+        Name = 'JieCode'
+        DataType = ftString
+        Size = 20
+      end
+      item
+        Name = 'XiMuCode'
+        DataType = ftString
+        Size = 20
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 48
+    Top = 40
+    Data = {
+      950200009619E0BD01000000180000001B000000000003000000950204436F64
+      65010049000000010005574944544802000200320006425F436F646501004900
+      00000100055749445448020002003200044E616D6501004A0000000100055749
+      44544802000200C80005556E69747301004A0000000100055749445448020002
+      00280009535175616E7469747908000400000000000653507269636508000400
+      000000000B53546F74616C5072696365080004000000000009435175616E7469
+      747908000400000000000643507269636508000400000000000B43546F74616C
+      5072696365080004000000000009445175616E74697479080004000000000006
+      44507269636508000400000000000B44546F74616C5072696365080004000000
+      0000074D656D6F53747201004900000001000557494454480200020032000D53
+      44676E5175616E746974793108000400000000000D5344676E5175616E746974
+      793208000400000000000C5344676E5175616E74697479010049000000010005
+      57494454480200020032000D4344676E5175616E746974793108000400000000
+      000D4344676E5175616E746974793208000400000000000C4344676E5175616E
+      7469747901004900000001000557494454480200020032000D4444676E517561
+      6E746974793108000400000000000D4444676E5175616E746974793208000400
+      000000000C4444676E5175616E74697479010049000000010005574944544802
+      0002003200095869616E67436F646501004A0000000100055749445448020002
+      002800064D75436F64650100490000000100055749445448020002001400074A
+      6965436F646501004900000001000557494454480200020014000858694D7543
+      6F646501004900000001000557494454480200020014000000}
+    object cdsBillsCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsBillsB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBillsName: TWideStringField
+      FieldName = 'Name'
+      Size = 100
+    end
+    object cdsBillsUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBillsSQuantity: TFloatField
+      FieldName = 'SQuantity'
+    end
+    object cdsBillsSPrice: TFloatField
+      FieldName = 'SPrice'
+    end
+    object cdsBillsSTotalPrice: TFloatField
+      FieldName = 'STotalPrice'
+    end
+    object cdsBillsCQuantity: TFloatField
+      FieldName = 'CQuantity'
+    end
+    object cdsBillsCPrice: TFloatField
+      FieldName = 'CPrice'
+    end
+    object cdsBillsCTotalPrice: TFloatField
+      FieldName = 'CTotalPrice'
+    end
+    object cdsBillsDQuantity: TFloatField
+      FieldName = 'DQuantity'
+    end
+    object cdsBillsDPrice: TFloatField
+      FieldName = 'DPrice'
+    end
+    object cdsBillsDTotalPrice: TFloatField
+      FieldName = 'DTotalPrice'
+    end
+    object cdsBillsMemoStr: TStringField
+      FieldName = 'MemoStr'
+      Size = 50
+    end
+    object cdsBillsSDgnQuantity1: TFloatField
+      FieldName = 'SDgnQuantity1'
+    end
+    object cdsBillsSDgnQuantity2: TFloatField
+      FieldName = 'SDgnQuantity2'
+    end
+    object cdsBillsSDgnQuantity: TStringField
+      FieldName = 'SDgnQuantity'
+      Size = 50
+    end
+    object cdsBillsCDgnQuantity1: TFloatField
+      FieldName = 'CDgnQuantity1'
+    end
+    object cdsBillsCDgnQuantity2: TFloatField
+      FieldName = 'CDgnQuantity2'
+    end
+    object cdsBillsCDgnQuantity: TStringField
+      FieldName = 'CDgnQuantity'
+      Size = 50
+    end
+    object cdsBillsDDgnQuantity1: TFloatField
+      FieldName = 'DDgnQuantity1'
+    end
+    object cdsBillsDDgnQuantity2: TFloatField
+      FieldName = 'DDgnQuantity2'
+    end
+    object cdsBillsDDgnQuantity: TStringField
+      FieldName = 'DDgnQuantity'
+      Size = 50
+    end
+    object cdsBillsXiangCode: TWideStringField
+      FieldName = 'XiangCode'
+    end
+    object cdsBillsMuCode: TStringField
+      FieldName = 'MuCode'
+    end
+    object cdsBillsJieCode: TStringField
+      FieldName = 'JieCode'
+    end
+    object cdsBillsXiMuCode: TStringField
+      FieldName = 'XiMuCode'
+    end
+  end
+end

+ 252 - 0
DataModules/ReportMemoryDm/rmFxBillsCompareDm.pas

@@ -0,0 +1,252 @@
+unit rmFxBillsCompareDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, ProjectData, sdIDTree, MCacheTree;
+
+type
+  {------------------------------------
+    fctCommon: 常规的分项清单审核比较模式。
+    fctG07: 广东标准表-台账07表,在fctCommon的基础上加一行公路基本造价汇总行。
+            需求有标明: 只需汇总项目节。此处不做特别处理,根据报表设置中的选项决定。
+  ------------------------------------}
+  TFxCompareType = (fctCommon, fctG07);
+
+  TrmFxBillsCompareData = class(TDataModule)
+    cdsBills: TClientDataSet;
+    cdsBillsCode: TStringField;
+    cdsBillsB_Code: TStringField;
+    cdsBillsName: TWideStringField;
+    cdsBillsUnits: TWideStringField;
+    cdsBillsSQuantity: TFloatField;
+    cdsBillsSPrice: TFloatField;
+    cdsBillsSTotalPrice: TFloatField;
+    cdsBillsCQuantity: TFloatField;
+    cdsBillsCPrice: TFloatField;
+    cdsBillsCTotalPrice: TFloatField;
+    cdsBillsDQuantity: TFloatField;
+    cdsBillsDPrice: TFloatField;
+    cdsBillsDTotalPrice: TFloatField;
+    cdsBillsMemoStr: TStringField;
+    cdsBillsSDgnQuantity1: TFloatField;
+    cdsBillsSDgnQuantity2: TFloatField;
+    cdsBillsSDgnQuantity: TStringField;
+    cdsBillsCDgnQuantity1: TFloatField;
+    cdsBillsCDgnQuantity2: TFloatField;
+    cdsBillsCDgnQuantity: TStringField;
+    cdsBillsDDgnQuantity1: TFloatField;
+    cdsBillsDDgnQuantity2: TFloatField;
+    cdsBillsDDgnQuantity: TStringField;
+    cdsBillsXiangCode: TWideStringField;
+    cdsBillsMuCode: TStringField;
+    cdsBillsJieCode: TStringField;
+    cdsBillsXiMuCode: TStringField;
+  private
+    FCacheTree: TReportCacheTree;
+    FCompareType: TFxCompareType;
+
+    function GetDgnQuantity(ANum1, ANum2: Double): string;
+
+    function FilterBillsNode(ANode: TsdIDTreeNode; AParent: TReportCacheNode;
+      AIsSource: Boolean): TReportCacheNode;
+    procedure FilterBills(ANode: TsdIDTreeNode; AParent: TReportCacheNode;
+      AIsSource: Boolean);
+
+    procedure WriteNode(ANode: TReportCacheNode);
+    procedure WriteGatherNodeData(const AName: string);
+    procedure WriteBills;
+  public
+    function AssignData(ASProjectData, ACProjectData: TProjectData): TDataSet;
+
+    property CompareType: TFxCompareType read FCompareType write FCompareType;
+  end;
+
+implementation
+
+uses
+  CacheTree, Globals;
+
+{$R *.dfm}
+
+{ TrmFxBillsCompareData }
+
+function TrmFxBillsCompareData.AssignData(ASProjectData,
+  ACProjectData: TProjectData): TDataSet;
+begin
+  cdsBills.DisableControls;
+  cdsBills.Active := True;
+  cdsBills.EmptyDataSet;
+  FCacheTree := TReportCacheTree.Create(2);
+  try
+    FilterBills(ASProjectData.BillsCompileData.BillsCompileTree.FirstNode, nil, True);
+    FilterBills(ACProjectData.BillsCompileData.BillsCompileTree.FirstNode, nil, False);
+    if CompareType = fctG07 then
+      FCacheTree.ReCalcGatherData;
+    WriteBills;
+    Result := cdsBills;
+  finally
+    FCacheTree.Free;
+    cdsBills.EnableControls;
+  end;
+end;
+
+procedure TrmFxBillsCompareData.FilterBills(ANode: TsdIDTreeNode;
+  AParent: TReportCacheNode; AIsSource: Boolean);
+var
+  ACur: TReportCacheNode;
+begin
+  if not Assigned(ANode) then Exit;
+  // (Level从0开始取值)
+  case ReportConfig.GatherLevel of
+    // 项
+    0: if ANode.Level > 1 then Exit;
+    // 目
+    1: if ANode.Level > 2 then Exit;
+    // 节
+    2: if ANode.Level > 3 then Exit;
+    // 细目
+    3: if ANode.Level > 4 then Exit;
+    // 项目节
+    4: if ANode.Rec.ValueByName('B_Code').AsString <> '' then Exit;
+  end;
+  ACur := FilterBillsNode(ANode, AParent, AIsSource);
+  FilterBills(ANode.FirstChild, ACur, AIsSource);
+  FilterBills(ANode.NextSibling, AParent, AIsSource);
+end;
+
+function TrmFxBillsCompareData.FilterBillsNode(ANode: TsdIDTreeNode;
+  AParent: TReportCacheNode; AIsSource: Boolean): TReportCacheNode;
+var
+  iGatherCompare: Integer;
+  ANextSibling: TReportCacheNode;
+begin
+  with ANode.Rec do
+  begin
+    if ANode.Rec.ValueByName('B_Code').AsString <> '' then
+      iGatherCompare := ReportConfig.GclCompare
+    else
+      iGatherCompare := ReportConfig.XmjCompare;
+    case iGatherCompare of
+      // 按编号
+      0: if (ValueByName('Code').asString <> '') or (ValueByName('B_Code').asString <> '') then
+           Result := FCacheTree.FindNode(AParent,
+               ValueByName('Code').AsString, ValueByName('B_Code').AsString)
+         else
+           Result := FCacheTree.FindNode(AParent, ValueByName('Code').AsString,
+             ValueByName('B_Code').AsString, ValueByName('Name').AsString);
+      // 按名称
+      1: Result := FCacheTree.FindNode(AParent, ValueByName('Name').AsString);
+      // 按编号+名称
+      2: Result := FCacheTree.FindNode(AParent, ValueByName('Code').AsString,
+             ValueByName('B_Code').AsString, ValueByName('Name').AsString);
+    end;
+
+    if not Assigned(Result) then
+    begin
+      ANextSibling := FCacheTree.FindNextSibling(AParent,
+          ValueByName('Code').AsString, ValueByName('B_Code').AsString);
+      Result := FCacheTree.AddNode(AParent, ANextSibling);
+      Result.Code := ValueByName('Code').AsString;
+      Result.B_Code := ValueByName('B_Code').AsString;
+      Result.Name := ValueByName('Name').AsString;
+      Result.Units := ValueByName('Units').AsString;
+    end;
+    
+    if AIsSource then
+    begin
+      Result.P_Quantity[0] := ValueByName('Quantity').AsFloat;
+      Result.P_Price[0] := ValueByName('Price').AsFloat;
+      Result.P_TotalPrice[0] := ValueByName('TotalPrice').AsFloat;
+
+      Result.P_DgnQuantity1[0] := ValueByName('DgnQuantity1').AsFloat;
+      Result.P_DgnQuantity2[0] := ValueByName('DgnQuantity2').AsFloat;
+    end
+    else
+    begin
+      Result.P_Quantity[1] := ValueByName('Quantity').AsFloat;
+      Result.P_Price[1] := ValueByName('Price').AsFloat;
+      Result.P_TotalPrice[1] := ValueByName('TotalPrice').AsFloat;
+
+      Result.P_DgnQuantity1[1] := ValueByName('DgnQuantity1').AsFloat;
+      Result.P_DgnQuantity2[1] := ValueByName('DgnQuantity2').AsFloat;
+    end;
+  end;
+end;
+
+function TrmFxBillsCompareData.GetDgnQuantity(ANum1,
+  ANum2: Double): string;
+begin
+  Result := '';
+  if ANum1 <> 0 then
+  begin
+    Result := FloatToStr(ANum1);
+    if ANum2 <> 0 then
+      Result := Result + '/' + FloatToStr(ANum2);
+  end;
+end;
+
+procedure TrmFxBillsCompareData.WriteBills;
+begin
+  WriteNode(TReportCacheNode(FCacheTree.FirstNode));
+  WriteGatherNodeData('公路基本造价');
+end;
+
+procedure TrmFxBillsCompareData.WriteGatherNodeData(const AName: string);
+begin
+  cdsBills.Append;
+  cdsBillsName.AsString := AName;
+  with FCacheTree.GatherCacheNode do
+  begin
+    cdsBillsSTotalPrice.AsFloat := P_TotalPrice[0];
+    cdsBillsCTotalPrice.AsFloat := P_TotalPrice[1];
+    cdsBillsDTotalPrice.AsFloat := P_TotalPrice[1] - P_TotalPrice[0];
+  end;
+  cdsBills.Post;
+end;
+
+procedure TrmFxBillsCompareData.WriteNode(ANode: TReportCacheNode);
+begin
+  if not Assigned(ANode) then Exit;
+
+  cdsBills.Append;
+  cdsBillsCode.AsString := ANode.Code;
+  cdsBillsB_Code.AsString := ANode.B_Code;
+  cdsBillsName.AsString := ANode.Name;
+  cdsBillsUnits.AsString := ANode.Units;
+
+  cdsBillsSQuantity.AsFloat := ANode.P_Quantity[0];
+  cdsBillsSPrice.AsFloat := ANode.P_Price[0];
+  cdsBillsSTotalPrice.AsFloat := ANode.P_TotalPrice[0];
+  cdsBillsSDgnQuantity1.AsFloat := ANode.P_DgnQuantity1[0];
+  cdsBillsSDgnQuantity2.AsFloat := ANode.P_DgnQuantity2[0];
+  cdsBillsSDgnQuantity.AsString := GetDgnQuantity(cdsBillsSDgnQuantity1.AsFloat,
+      cdsBillsSDgnQuantity2.AsFloat);
+
+  cdsBillsCQuantity.AsFloat := ANode.P_Quantity[1];
+  cdsBillsCPrice.AsFloat := ANode.P_Price[1];
+  cdsBillsCTotalPrice.AsFloat := ANode.P_TotalPrice[1];
+  cdsBillsCDgnQuantity1.AsFloat := ANode.P_DgnQuantity1[1];
+  cdsBillsCDgnQuantity2.AsFloat := ANode.P_DgnQuantity2[1];
+  cdsBillsCDgnQuantity.AsString := GetDgnQuantity(cdsBillsCDgnQuantity1.AsFloat,
+      cdsBillsCDgnQuantity2.AsFloat);
+
+  cdsBillsDQuantity.AsFloat := ANode.P_Quantity[1] - ANode.P_Quantity[0];
+  cdsBillsDPrice.AsFloat := ANode.P_Price[1] - ANode.P_Price[0];
+  cdsBillsDTotalPrice.AsFloat := ANode.P_TotalPrice[1] - ANode.P_TotalPrice[0];
+  cdsBillsDDgnQuantity1.AsFloat := ANode.P_DgnQuantity1[1] - ANode.P_DgnQuantity1[0];
+  cdsBillsDDgnQuantity2.AsFloat := ANode.P_DgnQuantity2[1] - ANode.P_DgnQuantity2[0];
+  cdsBillsDDgnQuantity.AsString := GetDgnQuantity(cdsBillsDDgnQuantity1.AsFloat,
+      cdsBillsDDgnQuantity2.AsFloat);
+
+  cdsBillsXiangCode.AsString := ANode.XiangCode;
+  cdsBillsMuCode.AsString := ANode.MuCode;
+  cdsBillsJieCode.AsString := ANode.JieCode;
+  cdsBillsXiMuCode.AsString := ANode.XiMuCode;
+  cdsBills.Post;
+
+  WriteNode(TReportCacheNode(ANode.FirstChild));
+  WriteNode(TReportCacheNode(ANode.NextSibling));
+end;
+
+end.

+ 416 - 0
DataModules/ReportMemoryDm/rmGclBillsAddDm.dfm

@@ -0,0 +1,416 @@
+object rmGclBillsAddData: TrmGclBillsAddData
+  OldCreateOrder = False
+  Left = 745
+  Top = 306
+  Height = 150
+  Width = 215
+  object cdsBills: TClientDataSet
+    Active = True
+    Aggregates = <>
+    IndexFieldNames = 'IndexCode'
+    Params = <>
+    Left = 56
+    Top = 40
+    Data = {
+      A20800009619E0BD01000000180000006D000000000003000000A20806425F43
+      6F6465010049000000010005574944544802000200320009496E646578436F64
+      650100490000000100055749445448020002003200044E616D6501004A000000
+      010005574944544802000200C80005556E69747301004A000000010005574944
+      544802000200280005507269636508000400000000000C4465616C5175616E74
+      69747908000400000000000E4465616C546F74616C5072696365080004000000
+      0000085175616E7469747908000400000000000A546F74616C50726963650800
+      040000000000095175616E746974793108000400000000000B546F74616C5072
+      696365310800040000000000095175616E746974793208000400000000000B54
+      6F74616C5072696365320800040000000000095175616E746974793308000400
+      000000000B546F74616C5072696365330800040000000000095175616E746974
+      793408000400000000000B546F74616C50726963653408000400000000000951
+      75616E746974793508000400000000000B546F74616C50726963653508000400
+      00000000095175616E746974793608000400000000000B546F74616C50726963
+      65360800040000000000095175616E746974793708000400000000000B546F74
+      616C5072696365370800040000000000095175616E7469747938080004000000
+      00000B546F74616C5072696365380800040000000000095175616E7469747939
+      08000400000000000B546F74616C50726963653908000400000000000A517561
+      6E74697479313008000400000000000C546F74616C5072696365313008000400
+      000000000A5175616E74697479313108000400000000000C546F74616C507269
+      6365313108000400000000000A5175616E74697479313208000400000000000C
+      546F74616C5072696365313208000400000000000A5175616E74697479313308
+      000400000000000C546F74616C5072696365313308000400000000000A517561
+      6E74697479313408000400000000000C546F74616C5072696365313408000400
+      000000000A5175616E74697479313508000400000000000C546F74616C507269
+      6365313508000400000000000A5175616E74697479313608000400000000000C
+      546F74616C5072696365313608000400000000000A5175616E74697479313708
+      000400000000000C546F74616C5072696365313708000400000000000A517561
+      6E74697479313808000400000000000C546F74616C5072696365313808000400
+      000000000A5175616E74697479313908000400000000000C546F74616C507269
+      6365313908000400000000000A5175616E74697479323008000400000000000C
+      546F74616C5072696365323008000400000000000A5175616E74697479323108
+      000400000000000C546F74616C5072696365323108000400000000000A517561
+      6E74697479323208000400000000000C546F74616C5072696365323208000400
+      000000000A5175616E74697479323308000400000000000C546F74616C507269
+      6365323308000400000000000A5175616E74697479323408000400000000000C
+      546F74616C5072696365323408000400000000000A5175616E74697479323508
+      000400000000000C546F74616C5072696365323508000400000000000A517561
+      6E74697479323608000400000000000C546F74616C5072696365323608000400
+      000000000A5175616E74697479323708000400000000000C546F74616C507269
+      6365323708000400000000000A5175616E74697479323808000400000000000C
+      546F74616C5072696365323808000400000000000A5175616E74697479323908
+      000400000000000C546F74616C5072696365323908000400000000000A517561
+      6E74697479333008000400000000000C546F74616C5072696365333008000400
+      000000000A5175616E74697479333108000400000000000C546F74616C507269
+      6365333108000400000000000A5175616E74697479333208000400000000000C
+      546F74616C5072696365333208000400000000000A5175616E74697479333308
+      000400000000000C546F74616C5072696365333308000400000000000A517561
+      6E74697479333408000400000000000C546F74616C5072696365333408000400
+      000000000A5175616E74697479333508000400000000000C546F74616C507269
+      6365333508000400000000000A5175616E74697479333608000400000000000C
+      546F74616C5072696365333608000400000000000A5175616E74697479333708
+      000400000000000C546F74616C5072696365333708000400000000000A517561
+      6E74697479333808000400000000000C546F74616C5072696365333808000400
+      000000000A5175616E74697479333908000400000000000C546F74616C507269
+      6365333908000400000000000A5175616E74697479343008000400000000000C
+      546F74616C5072696365343008000400000000000A5175616E74697479343108
+      000400000000000C546F74616C5072696365343108000400000000000A517561
+      6E74697479343208000400000000000C546F74616C5072696365343208000400
+      000000000A5175616E74697479343308000400000000000C546F74616C507269
+      6365343308000400000000000A5175616E74697479343408000400000000000C
+      546F74616C5072696365343408000400000000000A5175616E74697479343508
+      000400000000000C546F74616C5072696365343508000400000000000A517561
+      6E74697479343608000400000000000C546F74616C5072696365343608000400
+      000000000A5175616E74697479343708000400000000000C546F74616C507269
+      6365343708000400000000000A5175616E74697479343808000400000000000C
+      546F74616C5072696365343808000400000000000A5175616E74697479343908
+      000400000000000C546F74616C5072696365343908000400000000000A517561
+      6E74697479353008000400000000000C546F74616C5072696365353008000400
+      000000000000}
+    object cdsBillsB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBillsIndexCode: TStringField
+      FieldName = 'IndexCode'
+      Size = 50
+    end
+    object cdsBillsName: TWideStringField
+      FieldName = 'Name'
+      Size = 100
+    end
+    object cdsBillsUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBillsPrice: TFloatField
+      FieldName = 'Price'
+    end
+    object cdsBillsDealQuantity: TFloatField
+      FieldName = 'DealQuantity'
+    end
+    object cdsBillsDealTotalPrice: TFloatField
+      FieldName = 'DealTotalPrice'
+    end
+    object cdsBillsQuantity: TFloatField
+      FieldName = 'Quantity'
+    end
+    object cdsBillsTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsBillsQuantity1: TFloatField
+      FieldName = 'Quantity1'
+    end
+    object cdsBillsTotalPrice1: TFloatField
+      FieldName = 'TotalPrice1'
+    end
+    object cdsBillsQuantity2: TFloatField
+      FieldName = 'Quantity2'
+    end
+    object cdsBillsTotalPrice2: TFloatField
+      FieldName = 'TotalPrice2'
+    end
+    object cdsBillsQuantity3: TFloatField
+      FieldName = 'Quantity3'
+    end
+    object cdsBillsTotalPrice3: TFloatField
+      FieldName = 'TotalPrice3'
+    end
+    object cdsBillsQuantity4: TFloatField
+      FieldName = 'Quantity4'
+    end
+    object cdsBillsTotalPrice4: TFloatField
+      FieldName = 'TotalPrice4'
+    end
+    object cdsBillsQuantity5: TFloatField
+      FieldName = 'Quantity5'
+    end
+    object cdsBillsTotalPrice5: TFloatField
+      FieldName = 'TotalPrice5'
+    end
+    object cdsBillsQuantity6: TFloatField
+      FieldName = 'Quantity6'
+    end
+    object cdsBillsTotalPrice6: TFloatField
+      FieldName = 'TotalPrice6'
+    end
+    object cdsBillsQuantity7: TFloatField
+      FieldName = 'Quantity7'
+    end
+    object cdsBillsTotalPrice7: TFloatField
+      FieldName = 'TotalPrice7'
+    end
+    object cdsBillsQuantity8: TFloatField
+      FieldName = 'Quantity8'
+    end
+    object cdsBillsTotalPrice8: TFloatField
+      FieldName = 'TotalPrice8'
+    end
+    object cdsBillsQuantity9: TFloatField
+      FieldName = 'Quantity9'
+    end
+    object cdsBillsTotalPrice9: TFloatField
+      FieldName = 'TotalPrice9'
+    end
+    object cdsBillsQuantity10: TFloatField
+      FieldName = 'Quantity10'
+    end
+    object cdsBillsTotalPrice10: TFloatField
+      FieldName = 'TotalPrice10'
+    end
+    object cdsBillsQuantity11: TFloatField
+      FieldName = 'Quantity11'
+    end
+    object cdsBillsTotalPrice11: TFloatField
+      FieldName = 'TotalPrice11'
+    end
+    object cdsBillsQuantity12: TFloatField
+      FieldName = 'Quantity12'
+    end
+    object cdsBillsTotalPrice12: TFloatField
+      FieldName = 'TotalPrice12'
+    end
+    object cdsBillsQuantity13: TFloatField
+      FieldName = 'Quantity13'
+    end
+    object cdsBillsTotalPrice13: TFloatField
+      FieldName = 'TotalPrice13'
+    end
+    object cdsBillsQuantity14: TFloatField
+      FieldName = 'Quantity14'
+    end
+    object cdsBillsTotalPrice14: TFloatField
+      FieldName = 'TotalPrice14'
+    end
+    object cdsBillsQuantity15: TFloatField
+      FieldName = 'Quantity15'
+    end
+    object cdsBillsTotalPrice15: TFloatField
+      FieldName = 'TotalPrice15'
+    end
+    object cdsBillsQuantity16: TFloatField
+      FieldName = 'Quantity16'
+    end
+    object cdsBillsTotalPrice16: TFloatField
+      FieldName = 'TotalPrice16'
+    end
+    object cdsBillsQuantity17: TFloatField
+      FieldName = 'Quantity17'
+    end
+    object cdsBillsTotalPrice17: TFloatField
+      FieldName = 'TotalPrice17'
+    end
+    object cdsBillsQuantity18: TFloatField
+      FieldName = 'Quantity18'
+    end
+    object cdsBillsTotalPrice18: TFloatField
+      FieldName = 'TotalPrice18'
+    end
+    object cdsBillsQuantity19: TFloatField
+      FieldName = 'Quantity19'
+    end
+    object cdsBillsTotalPrice19: TFloatField
+      FieldName = 'TotalPrice19'
+    end
+    object cdsBillsQuantity20: TFloatField
+      FieldName = 'Quantity20'
+    end
+    object cdsBillsTotalPrice20: TFloatField
+      FieldName = 'TotalPrice20'
+    end
+    object cdsBillsQuantity21: TFloatField
+      FieldName = 'Quantity21'
+    end
+    object cdsBillsTotalPrice21: TFloatField
+      FieldName = 'TotalPrice21'
+    end
+    object cdsBillsQuantity22: TFloatField
+      FieldName = 'Quantity22'
+    end
+    object cdsBillsTotalPrice22: TFloatField
+      FieldName = 'TotalPrice22'
+    end
+    object cdsBillsQuantity23: TFloatField
+      FieldName = 'Quantity23'
+    end
+    object cdsBillsTotalPrice23: TFloatField
+      FieldName = 'TotalPrice23'
+    end
+    object cdsBillsQuantity24: TFloatField
+      FieldName = 'Quantity24'
+    end
+    object cdsBillsTotalPrice24: TFloatField
+      FieldName = 'TotalPrice24'
+    end
+    object cdsBillsQuantity25: TFloatField
+      FieldName = 'Quantity25'
+    end
+    object cdsBillsTotalPrice25: TFloatField
+      FieldName = 'TotalPrice25'
+    end
+    object cdsBillsQuantity26: TFloatField
+      FieldName = 'Quantity26'
+    end
+    object cdsBillsTotalPrice26: TFloatField
+      FieldName = 'TotalPrice26'
+    end
+    object cdsBillsQuantity27: TFloatField
+      FieldName = 'Quantity27'
+    end
+    object cdsBillsTotalPrice27: TFloatField
+      FieldName = 'TotalPrice27'
+    end
+    object cdsBillsQuantity28: TFloatField
+      FieldName = 'Quantity28'
+    end
+    object cdsBillsTotalPrice28: TFloatField
+      FieldName = 'TotalPrice28'
+    end
+    object cdsBillsQuantity29: TFloatField
+      FieldName = 'Quantity29'
+    end
+    object cdsBillsTotalPrice29: TFloatField
+      FieldName = 'TotalPrice29'
+    end
+    object cdsBillsQuantity30: TFloatField
+      FieldName = 'Quantity30'
+    end
+    object cdsBillsTotalPrice30: TFloatField
+      FieldName = 'TotalPrice30'
+    end
+    object cdsBillsQuantity31: TFloatField
+      FieldName = 'Quantity31'
+    end
+    object cdsBillsTotalPrice31: TFloatField
+      FieldName = 'TotalPrice31'
+    end
+    object cdsBillsQuantity32: TFloatField
+      FieldName = 'Quantity32'
+    end
+    object cdsBillsTotalPrice32: TFloatField
+      FieldName = 'TotalPrice32'
+    end
+    object cdsBillsQuantity33: TFloatField
+      FieldName = 'Quantity33'
+    end
+    object cdsBillsTotalPrice33: TFloatField
+      FieldName = 'TotalPrice33'
+    end
+    object cdsBillsQuantity34: TFloatField
+      FieldName = 'Quantity34'
+    end
+    object cdsBillsTotalPrice34: TFloatField
+      FieldName = 'TotalPrice34'
+    end
+    object cdsBillsQuantity35: TFloatField
+      FieldName = 'Quantity35'
+    end
+    object cdsBillsTotalPrice35: TFloatField
+      FieldName = 'TotalPrice35'
+    end
+    object cdsBillsQuantity36: TFloatField
+      FieldName = 'Quantity36'
+    end
+    object cdsBillsTotalPrice36: TFloatField
+      FieldName = 'TotalPrice36'
+    end
+    object cdsBillsQuantity37: TFloatField
+      FieldName = 'Quantity37'
+    end
+    object cdsBillsTotalPrice37: TFloatField
+      FieldName = 'TotalPrice37'
+    end
+    object cdsBillsQuantity38: TFloatField
+      FieldName = 'Quantity38'
+    end
+    object cdsBillsTotalPrice38: TFloatField
+      FieldName = 'TotalPrice38'
+    end
+    object cdsBillsQuantity39: TFloatField
+      FieldName = 'Quantity39'
+    end
+    object cdsBillsTotalPrice39: TFloatField
+      FieldName = 'TotalPrice39'
+    end
+    object cdsBillsQuantity40: TFloatField
+      FieldName = 'Quantity40'
+    end
+    object cdsBillsTotalPrice40: TFloatField
+      FieldName = 'TotalPrice40'
+    end
+    object cdsBillsQuantity41: TFloatField
+      FieldName = 'Quantity41'
+    end
+    object cdsBillsTotalPrice41: TFloatField
+      FieldName = 'TotalPrice41'
+    end
+    object cdsBillsQuantity42: TFloatField
+      FieldName = 'Quantity42'
+    end
+    object cdsBillsTotalPrice42: TFloatField
+      FieldName = 'TotalPrice42'
+    end
+    object cdsBillsQuantity43: TFloatField
+      FieldName = 'Quantity43'
+    end
+    object cdsBillsTotalPrice43: TFloatField
+      FieldName = 'TotalPrice43'
+    end
+    object cdsBillsQuantity44: TFloatField
+      FieldName = 'Quantity44'
+    end
+    object cdsBillsTotalPrice44: TFloatField
+      FieldName = 'TotalPrice44'
+    end
+    object cdsBillsQuantity45: TFloatField
+      FieldName = 'Quantity45'
+    end
+    object cdsBillsTotalPrice45: TFloatField
+      FieldName = 'TotalPrice45'
+    end
+    object cdsBillsQuantity46: TFloatField
+      FieldName = 'Quantity46'
+    end
+    object cdsBillsTotalPrice46: TFloatField
+      FieldName = 'TotalPrice46'
+    end
+    object cdsBillsQuantity47: TFloatField
+      FieldName = 'Quantity47'
+    end
+    object cdsBillsTotalPrice47: TFloatField
+      FieldName = 'TotalPrice47'
+    end
+    object cdsBillsQuantity48: TFloatField
+      FieldName = 'Quantity48'
+    end
+    object cdsBillsTotalPrice48: TFloatField
+      FieldName = 'TotalPrice48'
+    end
+    object cdsBillsQuantity49: TFloatField
+      FieldName = 'Quantity49'
+    end
+    object cdsBillsTotalPrice49: TFloatField
+      FieldName = 'TotalPrice49'
+    end
+    object cdsBillsQuantity50: TFloatField
+      FieldName = 'Quantity50'
+    end
+    object cdsBillsTotalPrice50: TFloatField
+      FieldName = 'TotalPrice50'
+    end
+  end
+end

+ 431 - 0
DataModules/ReportMemoryDm/rmGclBillsAddDm.pas

@@ -0,0 +1,431 @@
+unit rmGclBillsAddDm;
+
+interface
+
+uses
+  SysUtils, Classes, ProjectData, DB, DBClient, sdIDTree,
+  PhaseData, sdDB, StageDm;
+
+type
+  TP_DoubleArray = array [1..50] of Double;
+
+  TGclAddNode = class
+    FB_Code: string;
+    FIndexCode: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+    FDealQuantity: Double;
+    FDealTotalPrice: Double;
+    FQuantity: Double;
+    FTotalPrice: Double;
+    FP_Quantity: TP_DoubleArray;
+    FP_TotalPrice: TP_DoubleArray;
+  end;
+
+  TrmGclBillsAddData = class(TDataModule)
+    cdsBills: TClientDataSet;
+    cdsBillsB_Code: TStringField;
+    cdsBillsIndexCode: TStringField;
+    cdsBillsName: TWideStringField;
+    cdsBillsUnits: TWideStringField;
+    cdsBillsPrice: TFloatField;
+    cdsBillsDealQuantity: TFloatField;
+    cdsBillsDealTotalPrice: TFloatField;
+    cdsBillsQuantity: TFloatField;
+    cdsBillsTotalPrice: TFloatField;
+    cdsBillsQuantity1: TFloatField;
+    cdsBillsTotalPrice1: TFloatField;
+    cdsBillsQuantity2: TFloatField;
+    cdsBillsTotalPrice2: TFloatField;
+    cdsBillsQuantity3: TFloatField;
+    cdsBillsTotalPrice3: TFloatField;
+    cdsBillsQuantity4: TFloatField;
+    cdsBillsTotalPrice4: TFloatField;
+    cdsBillsQuantity5: TFloatField;
+    cdsBillsTotalPrice5: TFloatField;
+    cdsBillsQuantity6: TFloatField;
+    cdsBillsTotalPrice6: TFloatField;
+    cdsBillsQuantity7: TFloatField;
+    cdsBillsTotalPrice7: TFloatField;
+    cdsBillsQuantity8: TFloatField;
+    cdsBillsTotalPrice8: TFloatField;
+    cdsBillsQuantity9: TFloatField;
+    cdsBillsTotalPrice9: TFloatField;
+    cdsBillsQuantity10: TFloatField;
+    cdsBillsTotalPrice10: TFloatField;
+    cdsBillsQuantity11: TFloatField;
+    cdsBillsTotalPrice11: TFloatField;
+    cdsBillsQuantity12: TFloatField;
+    cdsBillsTotalPrice12: TFloatField;
+    cdsBillsQuantity13: TFloatField;
+    cdsBillsTotalPrice13: TFloatField;
+    cdsBillsQuantity14: TFloatField;
+    cdsBillsTotalPrice14: TFloatField;
+    cdsBillsQuantity15: TFloatField;
+    cdsBillsTotalPrice15: TFloatField;
+    cdsBillsQuantity16: TFloatField;
+    cdsBillsTotalPrice16: TFloatField;
+    cdsBillsQuantity17: TFloatField;
+    cdsBillsTotalPrice17: TFloatField;
+    cdsBillsQuantity18: TFloatField;
+    cdsBillsTotalPrice18: TFloatField;
+    cdsBillsQuantity19: TFloatField;
+    cdsBillsTotalPrice19: TFloatField;
+    cdsBillsQuantity20: TFloatField;
+    cdsBillsTotalPrice20: TFloatField;
+    cdsBillsQuantity21: TFloatField;
+    cdsBillsTotalPrice21: TFloatField;
+    cdsBillsQuantity22: TFloatField;
+    cdsBillsTotalPrice22: TFloatField;
+    cdsBillsQuantity23: TFloatField;
+    cdsBillsTotalPrice23: TFloatField;
+    cdsBillsQuantity24: TFloatField;
+    cdsBillsTotalPrice24: TFloatField;
+    cdsBillsQuantity25: TFloatField;
+    cdsBillsTotalPrice25: TFloatField;
+    cdsBillsQuantity26: TFloatField;
+    cdsBillsTotalPrice26: TFloatField;
+    cdsBillsQuantity27: TFloatField;
+    cdsBillsTotalPrice27: TFloatField;
+    cdsBillsQuantity28: TFloatField;
+    cdsBillsTotalPrice28: TFloatField;
+    cdsBillsQuantity29: TFloatField;
+    cdsBillsTotalPrice29: TFloatField;
+    cdsBillsQuantity30: TFloatField;
+    cdsBillsTotalPrice30: TFloatField;
+    cdsBillsQuantity31: TFloatField;
+    cdsBillsTotalPrice31: TFloatField;
+    cdsBillsQuantity32: TFloatField;
+    cdsBillsTotalPrice32: TFloatField;
+    cdsBillsQuantity33: TFloatField;
+    cdsBillsTotalPrice33: TFloatField;
+    cdsBillsQuantity34: TFloatField;
+    cdsBillsTotalPrice34: TFloatField;
+    cdsBillsQuantity35: TFloatField;
+    cdsBillsTotalPrice35: TFloatField;
+    cdsBillsQuantity36: TFloatField;
+    cdsBillsTotalPrice36: TFloatField;
+    cdsBillsQuantity37: TFloatField;
+    cdsBillsTotalPrice37: TFloatField;
+    cdsBillsQuantity38: TFloatField;
+    cdsBillsTotalPrice38: TFloatField;
+    cdsBillsQuantity39: TFloatField;
+    cdsBillsTotalPrice39: TFloatField;
+    cdsBillsQuantity40: TFloatField;
+    cdsBillsTotalPrice40: TFloatField;
+    cdsBillsQuantity41: TFloatField;
+    cdsBillsTotalPrice41: TFloatField;
+    cdsBillsQuantity42: TFloatField;
+    cdsBillsTotalPrice42: TFloatField;
+    cdsBillsQuantity43: TFloatField;
+    cdsBillsTotalPrice43: TFloatField;
+    cdsBillsQuantity44: TFloatField;
+    cdsBillsTotalPrice44: TFloatField;
+    cdsBillsQuantity45: TFloatField;
+    cdsBillsTotalPrice45: TFloatField;
+    cdsBillsQuantity46: TFloatField;
+    cdsBillsTotalPrice46: TFloatField;
+    cdsBillsQuantity47: TFloatField;
+    cdsBillsTotalPrice47: TFloatField;
+    cdsBillsQuantity48: TFloatField;
+    cdsBillsTotalPrice48: TFloatField;
+    cdsBillsQuantity49: TFloatField;
+    cdsBillsTotalPrice49: TFloatField;
+    cdsBillsQuantity50: TFloatField;
+    cdsBillsTotalPrice50: TFloatField;
+  private
+    FProjectData: TProjectData;
+    FGclAddList: TList;
+
+    function FindGclNode(ARec: TsdDataRecord): TGclAddNode;
+    procedure FilterGclBills(ANode: TsdIDTreeNode);
+    procedure FilterBills(ANode: TsdIDTreeNode);
+
+    procedure LoadStageData(StageData: TStageData; APhaseIndex: Integer);
+    procedure LoadPhaseData(APhaseIndex: Integer);
+
+    procedure WriteBills;
+  public
+    function AssignData(AProjectData: TProjectData): TDataSet;
+  end;
+
+implementation
+
+uses
+  ZhAPI, UtilMethods;
+
+{$R *.dfm}
+
+{ TrmGclBillsAddData }
+
+function TrmGclBillsAddData.AssignData(AProjectData: TProjectData): TDataSet;
+var
+  iPhase: Integer;
+begin
+  FProjectData := AProjectData;
+  FGclAddList := TList.Create;
+  cdsBills.DisableControls;
+  cdsBills.Active := True;
+  cdsBills.EmptyDataSet;
+  try
+    FilterBills(FProjectData.BillsCompileData.BillsCompileTree.FirstNode);
+    for iPhase := 1 to FProjectData.ProjProperties.PhaseCount do
+      LoadPhaseData(iPhase);
+    WriteBills;
+  finally
+    Result := cdsBills;
+    cdsBills.EnableControls;
+    ClearObjects(FGclAddList);
+    FGclAddList.Free;
+  end;
+end;
+
+procedure TrmGclBillsAddData.FilterBills(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    FilterBills(ANode.FirstChild)
+  else
+    FilterGclBills(ANode);
+  FilterBills(ANode.NextSibling);
+end;
+
+procedure TrmGclBillsAddData.FilterGclBills(ANode: TsdIDTreeNode);
+
+  function CreateGclNode(ARec: TsdDataRecord): TGclAddNode;
+  begin
+    Result := TGclAddNode.Create;
+    FGclAddList.Add(Result);
+    Result.FB_Code := ARec.ValueByName('B_Code').AsString;
+    Result.FIndexCode := B_CodeToIndexCode(ARec.ValueByName('B_Code').AsString);
+    Result.FName := ARec.ValueByName('Name').AsString;
+    Result.FUnits := ARec.ValueByName('Units').AsString;
+    Result.FPrice := ARec.ValueByName('Price').AsFloat;
+  end;
+
+  function GetGclNode(ARec: TsdDataRecord): TGclAddNode;
+  begin
+    Result := FindGclNode(ARec);
+    if not Assigned(Result) then
+      Result := CreateGclNode(ARec);
+  end;
+
+  procedure LoadDealData(AGclNode: TGclAddNode; AB_Code: string);
+  var
+    DealRec: TsdDataRecord;
+  begin
+    DealRec := TProjectData(FProjectData).DealBillsData.DealRecord(AB_Code);
+    if Assigned(DealRec) then
+    begin
+      AGclNode.FDealQuantity := DealRec.ValueByName('Quantity').AsFloat;
+      AGclNode.FDealTotalPrice := DealRec.ValueByName('TotalPrice').AsFloat;
+    end;
+  end;
+
+var
+  Rec, StageRec: TsdDataRecord;
+  GclNode: TGclAddNode;
+begin
+  if not Assigned(ANode) then Exit;
+  Rec := ANode.Rec;
+  if Rec.ValueByName('B_Code').AsString = '' then Exit;
+  GclNode := GetGclNode(Rec);
+  LoadDealData(GclNode, Rec.ValueByName('B_Code').AsString);
+  GclNode.FQuantity := GclNode.FQuantity + Rec.ValueByName('Quantity').AsFloat;
+  GclNode.FTotalPrice := GclNode.FTotalPrice + Rec.ValueByName('TotalPrice').AsFloat;
+end;
+
+function TrmGclBillsAddData.FindGclNode(ARec: TsdDataRecord): TGclAddNode;
+var
+  I: Integer;
+  GclNode: TGclAddNode;
+begin
+  Result := nil;
+  for I := 0 to FGclAddList.Count - 1 do
+  begin
+    GclNode := TGclAddNode(FGclAddList.Items[I]);
+    if SameText(GclNode.FB_Code, ARec.ValueByName('B_Code').AsString) and
+        SameText(GclNode.FName, ARec.ValueByName('Name').AsString) and
+        SameText(GclNode.FUnits, ARec.ValueByName('Units').AsString) and
+        (GclNode.FPrice = ARec.ValueByName('Price').AsFloat) then
+    begin
+      Result := GclNode;
+      Break;
+    end;
+  end;
+end;
+
+procedure TrmGclBillsAddData.LoadPhaseData(APhaseIndex: Integer);
+var
+  PhaseData: TPhaseData;
+  StageData: TStageData;
+begin
+  PhaseData := TPhaseData.Create(nil);
+  try
+    PhaseData.SimpleOpen(Format('%s\Phase%d.dat', [FProjectData.TempPath, APhaseIndex]));
+    if PhaseData.IsLastStage then
+      LoadStageData(PhaseData.StageData, APhaseIndex)
+    else
+    begin
+      try
+        StageData := TStageData.Create(PhaseData);
+        StageData.TableName := PhaseData.StageTableName[PhaseData.AuditCount];
+        StageData.Open(PhaseData.ADOConnection);
+        LoadStageData(StageData, APhaseIndex);
+      finally
+        StageData.Free;
+      end;
+    end;
+  finally
+    PhaseData.Free;
+  end;
+end;
+
+procedure TrmGclBillsAddData.LoadStageData(
+  StageData: TStageData; APhaseIndex: Integer);
+var
+  i: Integer;
+  StageRec: TsdDataRecord;
+  stnNode: TsdIDTreeNode;
+  GclNode: TGclAddNode;
+begin
+  for i := 0 to StageData.sddStage.RecordCount - 1 do
+  begin
+    StageRec := StageData.sddStage.Records[i];
+    with FProjectData.BillsCompileData.BillsCompileTree do
+      stnNode := FindNode(StageRec.ValueByName('BillsID').AsInteger);
+    // 非最底层工程量清单不添加数据
+    if stnNode.HasChildren or (stnNode.Rec.ValueByName('B_Code').AsString = '') then Continue;
+    GclNode := FindGclNode(stnNode.Rec);
+    if Assigned(GclNode) then
+    begin
+      GclNode.FP_Quantity[APhaseIndex] := StageRec.ValueByName('GatherQuantity').AsFloat;
+      GclNode.FP_TotalPrice[APhaseIndex] := StageRec.ValueByName('GatherTotalPrice').AsFloat;
+    end;
+  end;
+end;
+
+procedure TrmGclBillsAddData.WriteBills;
+var
+  iGcl: Integer;
+  GclAddNode: TGclAddNode;
+begin
+  for iGcl := 0 to FGclAddList.Count - 1 do
+  begin
+    GclAddNode := TGclAddNode(FGclAddList.Items[iGcl]);
+    cdsBills.Append;
+    cdsBillsB_Code.AsString := GclAddNode.FB_Code;
+    cdsBillsIndexCode.AsString := GclAddNode.FIndexCode;
+    cdsBillsName.AsString := GclAddNode.FName;
+    cdsBillsUnits.AsString := GclAddNode.FUnits;
+    cdsBillsPrice.AsFloat := GclAddNode.FPrice;
+    cdsBillsDealQuantity.AsFloat := GclAddNode.FDealQuantity;
+    cdsBillsDealTotalPrice.AsFloat := GclAddNode.FDealTotalPrice;
+    cdsBillsQuantity.AsFloat := GclAddNode.FQuantity;
+    cdsBillsTotalPrice.AsFloat := GclAddNode.FTotalPrice;
+    cdsBillsQuantity1.AsFloat := GclAddNode.FP_Quantity[1];
+    cdsBillsTotalPrice1.AsFloat := GclAddNode.FP_TotalPrice[1];
+    cdsBillsQuantity2.AsFloat := GclAddNode.FP_Quantity[2];
+    cdsBillsTotalPrice2.AsFloat := GclAddNode.FP_TotalPrice[2];
+    cdsBillsQuantity3.AsFloat := GclAddNode.FP_Quantity[3];
+    cdsBillsTotalPrice3.AsFloat := GclAddNode.FP_TotalPrice[3];
+    cdsBillsQuantity4.AsFloat := GclAddNode.FP_Quantity[4];
+    cdsBillsTotalPrice4.AsFloat := GclAddNode.FP_TotalPrice[4];
+    cdsBillsQuantity5.AsFloat := GclAddNode.FP_Quantity[5];
+    cdsBillsTotalPrice5.AsFloat := GclAddNode.FP_TotalPrice[5];
+    cdsBillsQuantity6.AsFloat := GclAddNode.FP_Quantity[6];
+    cdsBillsTotalPrice6.AsFloat := GclAddNode.FP_TotalPrice[6];
+    cdsBillsQuantity7.AsFloat := GclAddNode.FP_Quantity[7];
+    cdsBillsTotalPrice7.AsFloat := GclAddNode.FP_TotalPrice[7];
+    cdsBillsQuantity8.AsFloat := GclAddNode.FP_Quantity[8];
+    cdsBillsTotalPrice8.AsFloat := GclAddNode.FP_TotalPrice[8];
+    cdsBillsQuantity9.AsFloat := GclAddNode.FP_Quantity[9];
+    cdsBillsTotalPrice9.AsFloat := GclAddNode.FP_TotalPrice[9];
+    cdsBillsQuantity10.AsFloat := GclAddNode.FP_Quantity[10];
+    cdsBillsTotalPrice10.AsFloat := GclAddNode.FP_TotalPrice[10];
+    cdsBillsQuantity11.AsFloat := GclAddNode.FP_Quantity[11];
+    cdsBillsTotalPrice11.AsFloat := GclAddNode.FP_TotalPrice[11];
+    cdsBillsQuantity12.AsFloat := GclAddNode.FP_Quantity[12];
+    cdsBillsTotalPrice12.AsFloat := GclAddNode.FP_TotalPrice[12];
+    cdsBillsQuantity13.AsFloat := GclAddNode.FP_Quantity[13];
+    cdsBillsTotalPrice13.AsFloat := GclAddNode.FP_TotalPrice[13];
+    cdsBillsQuantity14.AsFloat := GclAddNode.FP_Quantity[14];
+    cdsBillsTotalPrice14.AsFloat := GclAddNode.FP_TotalPrice[14];
+    cdsBillsQuantity15.AsFloat := GclAddNode.FP_Quantity[15];
+    cdsBillsTotalPrice15.AsFloat := GclAddNode.FP_TotalPrice[15];
+    cdsBillsQuantity16.AsFloat := GclAddNode.FP_Quantity[16];
+    cdsBillsTotalPrice16.AsFloat := GclAddNode.FP_TotalPrice[16];
+    cdsBillsQuantity17.AsFloat := GclAddNode.FP_Quantity[17];
+    cdsBillsTotalPrice17.AsFloat := GclAddNode.FP_TotalPrice[17];
+    cdsBillsQuantity18.AsFloat := GclAddNode.FP_Quantity[18];
+    cdsBillsTotalPrice18.AsFloat := GclAddNode.FP_TotalPrice[18];
+    cdsBillsQuantity19.AsFloat := GclAddNode.FP_Quantity[19];
+    cdsBillsTotalPrice19.AsFloat := GclAddNode.FP_TotalPrice[19];
+    cdsBillsQuantity20.AsFloat := GclAddNode.FP_Quantity[20];
+    cdsBillsTotalPrice20.AsFloat := GclAddNode.FP_TotalPrice[20];
+    cdsBillsQuantity21.AsFloat := GclAddNode.FP_Quantity[21];
+    cdsBillsTotalPrice21.AsFloat := GclAddNode.FP_TotalPrice[21];
+    cdsBillsQuantity22.AsFloat := GclAddNode.FP_Quantity[22];
+    cdsBillsTotalPrice22.AsFloat := GclAddNode.FP_TotalPrice[22];
+    cdsBillsQuantity23.AsFloat := GclAddNode.FP_Quantity[23];
+    cdsBillsTotalPrice23.AsFloat := GclAddNode.FP_TotalPrice[23];
+    cdsBillsQuantity24.AsFloat := GclAddNode.FP_Quantity[24];
+    cdsBillsTotalPrice24.AsFloat := GclAddNode.FP_TotalPrice[24];
+    cdsBillsQuantity25.AsFloat := GclAddNode.FP_Quantity[25];
+    cdsBillsTotalPrice25.AsFloat := GclAddNode.FP_TotalPrice[25];
+    cdsBillsQuantity26.AsFloat := GclAddNode.FP_Quantity[26];
+    cdsBillsTotalPrice26.AsFloat := GclAddNode.FP_TotalPrice[26];
+    cdsBillsQuantity27.AsFloat := GclAddNode.FP_Quantity[27];
+    cdsBillsTotalPrice27.AsFloat := GclAddNode.FP_TotalPrice[27];
+    cdsBillsQuantity28.AsFloat := GclAddNode.FP_Quantity[28];
+    cdsBillsTotalPrice28.AsFloat := GclAddNode.FP_TotalPrice[28];
+    cdsBillsQuantity29.AsFloat := GclAddNode.FP_Quantity[29];
+    cdsBillsTotalPrice29.AsFloat := GclAddNode.FP_TotalPrice[29];
+    cdsBillsQuantity30.AsFloat := GclAddNode.FP_Quantity[30];
+    cdsBillsTotalPrice30.AsFloat := GclAddNode.FP_TotalPrice[30];
+    cdsBillsQuantity31.AsFloat := GclAddNode.FP_Quantity[31];
+    cdsBillsTotalPrice31.AsFloat := GclAddNode.FP_TotalPrice[31];
+    cdsBillsQuantity32.AsFloat := GclAddNode.FP_Quantity[32];
+    cdsBillsTotalPrice32.AsFloat := GclAddNode.FP_TotalPrice[32];
+    cdsBillsQuantity33.AsFloat := GclAddNode.FP_Quantity[33];
+    cdsBillsTotalPrice33.AsFloat := GclAddNode.FP_TotalPrice[33];
+    cdsBillsQuantity34.AsFloat := GclAddNode.FP_Quantity[34];
+    cdsBillsTotalPrice34.AsFloat := GclAddNode.FP_TotalPrice[34];
+    cdsBillsQuantity35.AsFloat := GclAddNode.FP_Quantity[35];
+    cdsBillsTotalPrice35.AsFloat := GclAddNode.FP_TotalPrice[35];
+    cdsBillsQuantity36.AsFloat := GclAddNode.FP_Quantity[36];
+    cdsBillsTotalPrice36.AsFloat := GclAddNode.FP_TotalPrice[36];
+    cdsBillsQuantity37.AsFloat := GclAddNode.FP_Quantity[37];
+    cdsBillsTotalPrice37.AsFloat := GclAddNode.FP_TotalPrice[37];
+    cdsBillsQuantity38.AsFloat := GclAddNode.FP_Quantity[38];
+    cdsBillsTotalPrice38.AsFloat := GclAddNode.FP_TotalPrice[38];
+    cdsBillsQuantity39.AsFloat := GclAddNode.FP_Quantity[39];
+    cdsBillsTotalPrice39.AsFloat := GclAddNode.FP_TotalPrice[39];
+    cdsBillsQuantity40.AsFloat := GclAddNode.FP_Quantity[40];
+    cdsBillsTotalPrice40.AsFloat := GclAddNode.FP_TotalPrice[40];
+    cdsBillsQuantity41.AsFloat := GclAddNode.FP_Quantity[41];
+    cdsBillsTotalPrice41.AsFloat := GclAddNode.FP_TotalPrice[41];
+    cdsBillsQuantity42.AsFloat := GclAddNode.FP_Quantity[42];
+    cdsBillsTotalPrice42.AsFloat := GclAddNode.FP_TotalPrice[42];
+    cdsBillsQuantity43.AsFloat := GclAddNode.FP_Quantity[43];
+    cdsBillsTotalPrice43.AsFloat := GclAddNode.FP_TotalPrice[43];
+    cdsBillsQuantity44.AsFloat := GclAddNode.FP_Quantity[44];
+    cdsBillsTotalPrice44.AsFloat := GclAddNode.FP_TotalPrice[44];
+    cdsBillsQuantity45.AsFloat := GclAddNode.FP_Quantity[45];
+    cdsBillsTotalPrice45.AsFloat := GclAddNode.FP_TotalPrice[45];
+    cdsBillsQuantity46.AsFloat := GclAddNode.FP_Quantity[46];
+    cdsBillsTotalPrice46.AsFloat := GclAddNode.FP_TotalPrice[46];
+    cdsBillsQuantity47.AsFloat := GclAddNode.FP_Quantity[47];
+    cdsBillsTotalPrice47.AsFloat := GclAddNode.FP_TotalPrice[47];
+    cdsBillsQuantity48.AsFloat := GclAddNode.FP_Quantity[48];
+    cdsBillsTotalPrice48.AsFloat := GclAddNode.FP_TotalPrice[48];
+    cdsBillsQuantity49.AsFloat := GclAddNode.FP_Quantity[49];
+    cdsBillsTotalPrice49.AsFloat := GclAddNode.FP_TotalPrice[49];
+    cdsBillsQuantity50.AsFloat := GclAddNode.FP_Quantity[50];
+    cdsBillsTotalPrice50.AsFloat := GclAddNode.FP_TotalPrice[50];
+    cdsBills.Post;
+  end;
+end;
+
+end.

+ 247 - 0
DataModules/ReportMemoryDm/rmGclBillsAuditCompareDm.dfm

@@ -0,0 +1,247 @@
+object rmGclBillsAuditCompareData: TrmGclBillsAuditCompareData
+  OldCreateOrder = False
+  Left = 191
+  Top = 114
+  Height = 150
+  Width = 215
+  object cdsBills: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'IndexCode'
+        DataType = ftString
+        Size = 20
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'Price'
+        DataType = ftFloat
+      end
+      item
+        Name = 'NewPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurQcBGLCode'
+        DataType = ftWideString
+        Size = 100
+      end
+      item
+        Name = 'ReferCurPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurPcBGLCode'
+        DataType = ftWideString
+        Size = 100
+      end
+      item
+        Name = 'ReferCurGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReferCurGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurQcBGLCode'
+        DataType = ftWideString
+        Size = 100
+      end
+      item
+        Name = 'ReplyCurPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurPcBGLCode'
+        DataType = ftWideString
+        Size = 100
+      end
+      item
+        Name = 'ReplyCurGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'ReplyCurGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'FlowIndex'
+        DataType = ftInteger
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 64
+    Top = 32
+    Data = {
+      270300009619E0BD01000000180000001B000000000003000000270306425F43
+      6F6465010049000000010005574944544802000200320009496E646578436F64
+      650100490000000100055749445448020002001400044E616D6502004A000000
+      010005574944544802000200900105556E69747301004A000000010005574944
+      54480200020028000550726963650800040000000000084E6577507269636508
+      000400000000001452656665724375724465616C5175616E7469747908000400
+      000000001652656665724375724465616C546F74616C50726963650800040000
+      00000012526566657243757251635175616E7469747908000400000000001452
+      656665724375725163546F74616C507269636508000400000000001152656665
+      72437572516342474C436F646501004A000000010005574944544802000200C8
+      0012526566657243757250635175616E74697479080004000000000014526566
+      65724375725063546F74616C5072696365080004000000000011526566657243
+      7572506342474C436F646501004A000000010005574944544802000200C80016
+      52656665724375724761746865725175616E7469747908000400000000001852
+      65666572437572476174686572546F74616C5072696365080004000000000014
+      5265706C794375724465616C5175616E74697479080004000000000016526570
+      6C794375724465616C546F74616C50726963650800040000000000125265706C
+      7943757251635175616E746974790800040000000000145265706C7943757251
+      63546F74616C50726963650800040000000000115265706C7943757251634247
+      4C436F646501004A000000010005574944544802000200C800125265706C7943
+      757250635175616E746974790800040000000000145265706C79437572506354
+      6F74616C50726963650800040000000000115265706C79437572506342474C43
+      6F646501004A000000010005574944544802000200C800165265706C79437572
+      4761746865725175616E746974790800040000000000185265706C7943757247
+      6174686572546F74616C5072696365080004000000000009466C6F77496E6465
+      7804000100000000000000}
+    object cdsBillsB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBillsIndexCode: TStringField
+      FieldName = 'IndexCode'
+    end
+    object cdsBillsName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsBillsUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBillsPrice: TFloatField
+      FieldName = 'Price'
+    end
+    object cdsBillsNewPrice: TFloatField
+      FieldName = 'NewPrice'
+    end
+    object cdsBillsReferCurDealQuantity: TFloatField
+      FieldName = 'ReferCurDealQuantity'
+    end
+    object cdsBillsReferCurDealTotalPrice: TFloatField
+      FieldName = 'ReferCurDealTotalPrice'
+    end
+    object cdsBillsReferCurQcQuantity: TFloatField
+      FieldName = 'ReferCurQcQuantity'
+    end
+    object cdsBillsReferCurQcTotalPrice: TFloatField
+      FieldName = 'ReferCurQcTotalPrice'
+    end
+    object cdsBillsReferCurQcBGLCode: TWideStringField
+      FieldName = 'ReferCurQcBGLCode'
+      Size = 100
+    end
+    object cdsBillsReferCurPcQuantity: TFloatField
+      FieldName = 'ReferCurPcQuantity'
+    end
+    object cdsBillsReferCurPcTotalPrice: TFloatField
+      FieldName = 'ReferCurPcTotalPrice'
+    end
+    object cdsBillsReferCurPcBGLCode: TWideStringField
+      FieldName = 'ReferCurPcBGLCode'
+      Size = 100
+    end
+    object cdsBillsReferCurGatherQuantity: TFloatField
+      FieldName = 'ReferCurGatherQuantity'
+    end
+    object cdsBillsReferCurGatherTotalPrice: TFloatField
+      FieldName = 'ReferCurGatherTotalPrice'
+    end
+    object cdsBillsReplyCurDealQuantity: TFloatField
+      FieldName = 'ReplyCurDealQuantity'
+    end
+    object cdsBillsReplyCurDealTotalPrice: TFloatField
+      FieldName = 'ReplyCurDealTotalPrice'
+    end
+    object cdsBillsReplyCurQcQuantity: TFloatField
+      FieldName = 'ReplyCurQcQuantity'
+    end
+    object cdsBillsReplyCurQcTotalPrice: TFloatField
+      FieldName = 'ReplyCurQcTotalPrice'
+    end
+    object cdsBillsReplyCurQcBGLCode: TWideStringField
+      FieldName = 'ReplyCurQcBGLCode'
+      Size = 100
+    end
+    object cdsBillsReplyCurPcQuantity: TFloatField
+      FieldName = 'ReplyCurPcQuantity'
+    end
+    object cdsBillsReplyCurPcTotalPrice: TFloatField
+      FieldName = 'ReplyCurPcTotalPrice'
+    end
+    object cdsBillsReplyCurPcBGLCode: TWideStringField
+      FieldName = 'ReplyCurPcBGLCode'
+      Size = 100
+    end
+    object cdsBillsReplyCurGatherQuantity: TFloatField
+      FieldName = 'ReplyCurGatherQuantity'
+    end
+    object cdsBillsReplyCurGatherTotalPrice: TFloatField
+      FieldName = 'ReplyCurGatherTotalPrice'
+    end
+    object cdsBillsFlowIndex: TIntegerField
+      FieldName = 'FlowIndex'
+    end
+  end
+end

+ 293 - 0
DataModules/ReportMemoryDm/rmGclBillsAuditCompareDm.pas

@@ -0,0 +1,293 @@
+unit rmGclBillsAuditCompareDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, ProjectData, sdIDTree, sdDB;
+
+type
+  TrmFilterType = (rmftPhaseDeal, rmftPhaseQc, rmftPhasePc, rmftPhaseGather);
+  TDataType = (atRefer, atReply);
+
+  TGclNode = class
+  private
+    FB_Code: string;
+    FIndexCode: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+    FNewPrice: Double;
+
+    FReferCurDealQuantity: Double;
+    FReferCurDealTotalPrice: Double;
+    FReferCurQcQuantity: Double;
+    FReferCurQcTotalPrice: Double;
+    FReferCurQcBGLCode: string;
+    FReferCurPcQuantity: Double;
+    FReferCurPcTotalPrice: Double;
+    FReferCurPcBGLCode: string;
+    FReferCurGatherQuantity: Double;
+    FReferCurGatherTotalPrice: Double;
+
+    FReplyCurDealQuantity: Double;
+    FReplyCurDealTotalPrice: Double;
+    FReplyCurQcQuantity: Double;
+    FReplyCurQcTotalPrice: Double;
+    FReplyCurQcBGLCode: string;
+    FReplyCurPcQuantity: Double;
+    FReplyCurPcTotalPrice: Double;
+    FReplyCurPcBGLCode: string;
+    FReplyCurGatherQuantity: Double;
+    FReplyCurGatherTotalPrice: Double;
+  end;
+
+  TrmGclBillsAuditCompareData = class(TDataModule)
+    cdsBills: TClientDataSet;
+    cdsBillsB_Code: TStringField;
+    cdsBillsIndexCode: TStringField;
+    cdsBillsName: TWideStringField;
+    cdsBillsUnits: TWideStringField;
+    cdsBillsPrice: TFloatField;
+    cdsBillsNewPrice: TFloatField;
+    cdsBillsReferCurDealQuantity: TFloatField;
+    cdsBillsReferCurDealTotalPrice: TFloatField;
+    cdsBillsReferCurQcQuantity: TFloatField;
+    cdsBillsReferCurQcTotalPrice: TFloatField;
+    cdsBillsReferCurQcBGLCode: TWideStringField;
+    cdsBillsReferCurPcQuantity: TFloatField;
+    cdsBillsReferCurPcTotalPrice: TFloatField;
+    cdsBillsReferCurPcBGLCode: TWideStringField;
+    cdsBillsReferCurGatherQuantity: TFloatField;
+    cdsBillsReferCurGatherTotalPrice: TFloatField;
+    cdsBillsReplyCurDealQuantity: TFloatField;
+    cdsBillsReplyCurDealTotalPrice: TFloatField;
+    cdsBillsReplyCurQcQuantity: TFloatField;
+    cdsBillsReplyCurQcTotalPrice: TFloatField;
+    cdsBillsReplyCurQcBGLCode: TWideStringField;
+    cdsBillsReplyCurPcQuantity: TFloatField;
+    cdsBillsReplyCurPcTotalPrice: TFloatField;
+    cdsBillsReplyCurPcBGLCode: TWideStringField;
+    cdsBillsReplyCurGatherQuantity: TFloatField;
+    cdsBillsReplyCurGatherTotalPrice: TFloatField;
+    cdsBillsFlowIndex: TIntegerField;
+  private
+    FProjectData: TProjectData;
+    FrmFilterType: TrmFilterType;
+    FGclList: TList;
+
+    procedure FilterGclBills(ANode: TsdIDTreeNode; ADataType: TDataType);
+    procedure FilterBills(ANode: TsdIDTreeNode; ADataType: TDataType);
+    procedure WriteBills;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AssignData(AProjectData: TProjectData;
+      ArmFilterType: TrmFilterType): TDataSet;
+  end;
+
+implementation
+
+uses
+  ZhAPI, UtilMethods, PhaseData;
+
+{$R *.dfm}
+
+{ TrmGclBillsAuditCompareData }
+
+function TrmGclBillsAuditCompareData.AssignData(AProjectData: TProjectData;
+  ArmFilterType: TrmFilterType): TDataSet;
+var
+  iStageMark: Integer;
+begin
+  FProjectData := AProjectData;
+  FrmFilterType := ArmFilterType;
+  cdsBills.Active := True;
+  cdsBills.DisableControls;
+  try
+    cdsBills.EmptyDataSet;
+    if FProjectData.PhaseData.Active then
+      with FProjectData.BillsMeasureData.BillsMeasureTree do
+      begin
+        iStageMark := FProjectData.PhaseData.StageIndex;
+
+        FProjectData.PhaseData.StageIndex := 0;
+        FilterBills(FirstNode, atRefer);
+
+        if FProjectData.PhaseData.StageCount > 1 then
+        begin
+          FProjectData.PhaseData.StageIndex := FProjectData.PhaseData.AuditCount;
+          FilterBills(FirstNode, atReply);
+        end;
+      end;
+    WriteBills;
+  finally
+    FProjectData.PhaseData.StageIndex := iStageMark;
+    ClearObjects(FGclList);
+    cdsBills.EnableControls;
+    Result := cdsBills;
+  end;
+end;
+
+constructor TrmGclBillsAuditCompareData.Create;
+begin
+  inherited Create(nil);
+  FGclList := TList.Create;
+  cdsBills.IndexFieldNames := 'IndexCode';
+end;
+
+destructor TrmGclBillsAuditCompareData.Destroy;
+begin
+  ClearObjects(FGclList);
+  FGclList.Free;
+  inherited;
+end;
+
+procedure TrmGclBillsAuditCompareData.FilterBills(ANode: TsdIDTreeNode;
+  ADataType: TDataType);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    FilterBills(ANode.FirstChild, ADataType)
+  else
+    FilterGclBills(ANode, ADataType);
+  FilterBills(ANode.NextSibling, ADataType);
+end;
+
+procedure TrmGclBillsAuditCompareData.FilterGclBills(ANode: TsdIDTreeNode;
+  ADataType: TDataType);
+
+  function CreateGclNode(ARec: TsdDataRecord): TGclNode;
+  begin
+    Result := TGclNode.Create;
+    FGclList.Add(Result);
+    Result.FB_Code := ARec.ValueByName('B_Code').AsString;
+    Result.FIndexCode := B_CodeToIndexCode(ARec.ValueByName('B_Code').AsString);
+    Result.FName := ARec.ValueByName('Name').AsString;
+    Result.FUnits := ARec.ValueByName('Units').AsString;
+    Result.FPrice := ARec.ValueByName('Price').AsFloat;
+    Result.FNewPrice := ARec.ValueByName('NewPrice').AsFloat;
+  end;
+
+  function GetGclNode(ARec: TsdDataRecord): TGclNode;
+  var
+    I: Integer;
+    GclNode: TGclNode;
+  begin
+    Result := nil;
+    for I := 0 to FGclList.Count - 1 do
+    begin
+      GclNode := TGclNode(FGclList.Items[I]);
+      if SameText(GclNode.FB_Code, ARec.ValueByName('B_Code').AsString) and
+          SameText(GclNode.FName, ARec.ValueByName('Name').AsString) and
+          SameText(GclNode.FUnits, ARec.ValueByName('Units').AsString) and
+          (GclNode.FPrice = ARec.ValueByName('Price').AsFloat) then
+      begin
+        Result := GclNode;
+        Break;
+      end;
+    end;
+    if not Assigned(Result) then
+      Result := CreateGclNode(ARec);
+  end;
+
+  procedure LoadReferData(AGclNode: TGclNode; ARec: TsdDataRecord);
+  begin
+    AGclNode.FReferCurDealQuantity := AGclNode.FReferCurDealQuantity + ARec.ValueByName('DealQuantity').AsFloat;
+    AGclNode.FReferCurDealTotalPrice := AGclNode.FReferCurDealTotalPrice + ARec.ValueByName('DealTotalPrice').AsFloat;
+    AGclNode.FReferCurQcQuantity := AGclNode.FReferCurQcQuantity + ARec.ValueByName('QcQuantity').AsFloat;
+    AGclNode.FReferCurQcTotalPrice := AGclNode.FReferCurQcTotalPrice + ARec.ValueByName('QcTotalPrice').AsFloat;
+    AGclNode.FReferCurQcBGLCode := MergeRelaBGL(AGclNode.FReferCurQcBGLCode, ARec.ValueByName('QcBGLCode').AsString);
+    AGclNode.FReferCurPcQuantity := AGclNode.FReferCurPcQuantity + ARec.ValueByName('PcQuantity').AsFloat;
+    AGclNode.FReferCurPcTotalPrice := AGclNode.FReferCurPcTotalPrice + ARec.ValueByName('PcTotalPrice').AsFloat;
+    AGclNode.FReferCurPcBGLCode := MergeRelaBGL(AGclNode.FReferCurPcBGLCode, ARec.ValueByName('PcBGLCode').AsString);
+    AGclNode.FReferCurGatherQuantity := AGclNode.FReferCurGatherQuantity + ARec.ValueByName('GatherQuantity').AsFloat;
+    AGclNode.FReferCurGatherTotalPrice := AGclNode.FReferCurGatherTotalPrice + ARec.ValueByName('GatherTotalPrice').AsFloat;
+  end;
+
+  procedure LoadReplyData(AGclNode: TGclNode; ARec: TsdDataRecord);
+  begin
+    AGclNode.FReplyCurDealQuantity := AGclNode.FReplyCurDealQuantity + ARec.ValueByName('DealQuantity').AsFloat;
+    AGclNode.FReplyCurDealTotalPrice := AGclNode.FReplyCurDealTotalPrice + ARec.ValueByName('DealTotalPrice').AsFloat;
+    AGclNode.FReplyCurQcQuantity := AGclNode.FReplyCurQcQuantity + ARec.ValueByName('QcQuantity').AsFloat;
+    AGclNode.FReplyCurQcTotalPrice := AGclNode.FReplyCurQcTotalPrice + ARec.ValueByName('QcTotalPrice').AsFloat;
+    AGclNode.FReplyCurQcBGLCode := MergeRelaBGL(AGclNode.FReplyCurQcBGLCode, ARec.ValueByName('QcBGLCode').AsString);
+    AGclNode.FReplyCurPcQuantity := AGclNode.FReplyCurPcQuantity + ARec.ValueByName('PcQuantity').AsFloat;
+    AGclNode.FReplyCurPcTotalPrice := AGclNode.FReplyCurPcTotalPrice + ARec.ValueByName('PcTotalPrice').AsFloat;
+    AGclNode.FReplyCurPcBGLCode := MergeRelaBGL(AGclNode.FReplyCurPcBGLCode, ARec.ValueByName('PcBGLCode').AsString);
+    AGclNode.FReplyCurGatherQuantity := AGclNode.FReplyCurGatherQuantity + ARec.ValueByName('GatherQuantity').AsFloat;
+    AGclNode.FReplyCurGatherTotalPrice := AGclNode.FReplyCurGatherTotalPrice + ARec.ValueByName('GatherTotalPrice').AsFloat;
+  end;
+
+var
+  Rec, StageRec: TsdDataRecord;
+  GclNode: TGclNode;
+begin
+  if not Assigned(ANode) then Exit;
+  Rec := ANode.Rec;
+  if Rec.ValueByName('B_Code').AsString = '' then Exit;
+  StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ANode.ID);
+  {case ADataType of
+    atRefer: StageRec := TProjectData(FProjectData).PhaseData.ReferData.StageRecord(ANode.ID);
+    atReply: StageRec := TProjectData(FProjectData).PhaseData.LastStageData.StageRecord(ANode.ID);
+  end;}
+  if not Assigned(StageRec) then Exit;
+
+  case FrmFilterType of
+    rmftPhaseDeal: if StageRec.ValueByName('DealTotalPrice').AsFloat = 0 then Exit;
+    rmftPhaseQc: if StageRec.ValueByName('QcTotalPrice').AsFloat = 0 then Exit;
+    rmftPhasePc: if StageRec.ValueByName('PcTotalPrice').AsFloat = 0 then Exit;
+    rmftPhaseGather: if StageRec.ValueByName('GatherTotalPrice').AsFloat = 0 then Exit;
+  end;
+
+  GclNode := GetGclNode(Rec);
+  case ADataType of
+    atRefer: LoadReferData(GclNode, StageRec);
+    atReply: LoadReplyData(GclNode, StageRec);
+  end;
+end;
+
+procedure TrmGclBillsAuditCompareData.WriteBills;
+var
+  I: Integer;
+  GclNode: TGclNode;
+begin
+  for I := 0 to FGclList.Count - 1 do
+  begin
+    GclNode := TGclNode(FGclList.Items[I]);
+    cdsBills.Append;
+    cdsBillsB_Code.AsString := GclNode.FB_Code;
+    cdsBillsIndexCode.AsString := GclNode.FIndexCode;
+    cdsBillsName.AsString := GclNode.FName;
+    cdsBillsUnits.AsString := GclNode.FUnits;
+    cdsBillsPrice.AsFloat := GclNode.FPrice;
+    cdsBillsNewPrice.AsFloat := GclNode.FNewPrice;
+
+    cdsBillsReferCurDealQuantity.AsFloat := GclNode.FReferCurDealQuantity;
+    cdsBillsReferCurDealTotalPrice.AsFloat := GclNode.FReferCurDealTotalPrice;
+    cdsBillsReferCurQcQuantity.AsFloat := GclNode.FReferCurQcQuantity;
+    cdsBillsReferCurQcTotalPrice.AsFloat := GclNode.FReferCurQcTotalPrice;
+    cdsBillsReferCurQcBGLCode.AsString := GclNode.FReferCurQcBGLCode;
+    cdsBillsReferCurPcQuantity.AsFloat := GclNode.FReferCurPcQuantity;
+    cdsBillsReferCurPcTotalPrice.AsFloat := GclNode.FReferCurPcTotalPrice;
+    cdsBillsReferCurPcBGLCode.AsString := GclNode.FReferCurPcBGLCode;
+    cdsBillsReferCurGatherQuantity.AsFloat := GclNode.FReferCurGatherQuantity;
+    cdsBillsReferCurGatherTotalPrice.AsFloat := GclNode.FReferCurGatherTotalPrice;
+
+    cdsBillsReplyCurDealQuantity.AsFloat := GclNode.FReplyCurDealQuantity;
+    cdsBillsReplyCurDealTotalPrice.AsFloat := GclNode.FReplyCurDealTotalPrice;
+    cdsBillsReplyCurQcQuantity.AsFloat := GclNode.FReplyCurQcQuantity;
+    cdsBillsReplyCurQcTotalPrice.AsFloat := GclNode.FReplyCurQcTotalPrice;
+    cdsBillsReplyCurQcBGLCode.AsString := GclNode.FReplyCurQcBGLCode;
+    cdsBillsReplyCurPcQuantity.AsFloat := GclNode.FReplyCurPcQuantity;
+    cdsBillsReplyCurPcTotalPrice.AsFloat := GclNode.FReplyCurPcTotalPrice;
+    cdsBillsReplyCurPcBGLCode.AsString := GclNode.FReplyCurPcBGLCode;
+    cdsBillsReplyCurGatherQuantity.AsFloat := GclNode.FReplyCurGatherQuantity;
+    cdsBillsReplyCurGatherTotalPrice.AsFloat := GclNode.FReplyCurGatherTotalPrice;
+
+    cdsBillsFlowIndex.AsInteger := 0;
+    cdsBills.Post;
+  end;
+end;
+
+end.

+ 356 - 0
DataModules/ReportMemoryDm/rmGclBillsBGDm.dfm

@@ -0,0 +1,356 @@
+object rmGclBillsBGData: TrmGclBillsBGData
+  OldCreateOrder = False
+  Left = 554
+  Top = 307
+  Height = 150
+  Width = 215
+  object cdsBills: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'IndexCode'
+        DataType = ftString
+        Size = 20
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'Price'
+        DataType = ftFloat
+      end
+      item
+        Name = 'NewPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurQcBGLCode'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'CurPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurPcBGLCode'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'CurGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndQcBGLCode'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'EndPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndPcBGLCode'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'EndGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddDealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddQcBGLCode'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'AddPcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddPcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddPcBGLCode'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'AddGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'SerialNo'
+        DataType = ftInteger
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 64
+    Top = 32
+    Data = {
+      180400009619E0BD010000001800000029000000000003000000180406425F43
+      6F6465010049000000010005574944544802000200320009496E646578436F64
+      650100490000000100055749445448020002001400044E616D6502004A000000
+      010005574944544802000200900105556E69747301004A000000010005574944
+      54480200020028000550726963650800040000000000084E6577507269636508
+      000400000000000C4465616C5175616E7469747908000400000000000E446561
+      6C546F74616C50726963650800040000000000085175616E7469747908000400
+      000000000A546F74616C507269636508000400000000000F4375724465616C51
+      75616E746974790800040000000000114375724465616C546F74616C50726963
+      6508000400000000000D43757251635175616E7469747908000400000000000F
+      4375725163546F74616C507269636508000400000000000C437572516342474C
+      436F646502004A00000001000557494454480200020090010D43757250635175
+      616E7469747908000400000000000F4375725063546F74616C50726963650800
+      0400000000000C437572506342474C436F646502004A00000001000557494454
+      48020002009001114375724761746865725175616E7469747908000400000000
+      0013437572476174686572546F74616C507269636508000400000000000F456E
+      644465616C5175616E74697479080004000000000011456E644465616C546F74
+      616C507269636508000400000000000D456E6451635175616E74697479080004
+      00000000000F456E645163546F74616C507269636508000400000000000C456E
+      64516342474C436F646502004A00000001000557494454480200020090010D45
+      6E6450635175616E7469747908000400000000000F456E645063546F74616C50
+      7269636508000400000000000C456E64506342474C436F646502004A00000001
+      0005574944544802000200900111456E644761746865725175616E7469747908
+      0004000000000013456E64476174686572546F74616C50726963650800040000
+      0000000F4164644465616C5175616E7469747908000400000000001141646444
+      65616C546F74616C507269636508000400000000000D41646451635175616E74
+      69747908000400000000000F4164645163546F74616C50726963650800040000
+      0000000C416464516342474C436F646502004A00000001000557494454480200
+      020090010D41646450635175616E7469747908000400000000000F4164645063
+      546F74616C507269636508000400000000000C416464506342474C436F646502
+      004A000000010005574944544802000200900111416464476174686572517561
+      6E74697479080004000000000013416464476174686572546F74616C50726963
+      6508000400000000000853657269616C4E6F04000100000000000000}
+    object cdsBillsB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBillsIndexCode: TStringField
+      FieldName = 'IndexCode'
+    end
+    object cdsBillsName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsBillsUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBillsPrice: TFloatField
+      FieldName = 'Price'
+    end
+    object cdsBillsNewPrice: TFloatField
+      FieldName = 'NewPrice'
+    end
+    object cdsBillsDealQuantity: TFloatField
+      FieldName = 'DealQuantity'
+    end
+    object cdsBillsDealTotalPrice: TFloatField
+      FieldName = 'DealTotalPrice'
+    end
+    object cdsBillsQuantity: TFloatField
+      FieldName = 'Quantity'
+    end
+    object cdsBillsTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsBillsCurDealQuantity: TFloatField
+      FieldName = 'CurDealQuantity'
+    end
+    object cdsBillsCurDealTotalPrice: TFloatField
+      FieldName = 'CurDealTotalPrice'
+    end
+    object cdsBillsCurQcQuantity: TFloatField
+      FieldName = 'CurQcQuantity'
+    end
+    object cdsBillsCurQcTotalPrice: TFloatField
+      FieldName = 'CurQcTotalPrice'
+    end
+    object cdsBillsCurQcBGLCode: TWideStringField
+      FieldName = 'CurQcBGLCode'
+      Size = 200
+    end
+    object cdsBillsCurPcQuantity: TFloatField
+      FieldName = 'CurPcQuantity'
+    end
+    object cdsBillsCurPcTotalPrice: TFloatField
+      FieldName = 'CurPcTotalPrice'
+    end
+    object cdsBillsCurPcBGLCode: TWideStringField
+      FieldName = 'CurPcBGLCode'
+      Size = 200
+    end
+    object cdsBillsCurGatherQuantity: TFloatField
+      FieldName = 'CurGatherQuantity'
+    end
+    object cdsBillsCurGatherTotalPrice: TFloatField
+      FieldName = 'CurGatherTotalPrice'
+    end
+    object cdsBillsEndDealQuantity: TFloatField
+      FieldName = 'EndDealQuantity'
+    end
+    object cdsBillsEndDealTotalPrice: TFloatField
+      FieldName = 'EndDealTotalPrice'
+    end
+    object cdsBillsEndQcQuantity: TFloatField
+      FieldName = 'EndQcQuantity'
+    end
+    object cdsBillsEndQcTotalPrice: TFloatField
+      FieldName = 'EndQcTotalPrice'
+    end
+    object cdsBillsEndQcBGLCode: TWideStringField
+      FieldName = 'EndQcBGLCode'
+      Size = 200
+    end
+    object cdsBillsEndPcQuantity: TFloatField
+      FieldName = 'EndPcQuantity'
+    end
+    object cdsBillsEndPcTotalPrice: TFloatField
+      FieldName = 'EndPcTotalPrice'
+    end
+    object cdsBillsEndPcBGLCode: TWideStringField
+      FieldName = 'EndPcBGLCode'
+      Size = 200
+    end
+    object cdsBillsEndGatherQuantity: TFloatField
+      FieldName = 'EndGatherQuantity'
+    end
+    object cdsBillsEndGatherTotalPrice: TFloatField
+      FieldName = 'EndGatherTotalPrice'
+    end
+    object cdsBillsAddDealQuantity: TFloatField
+      FieldName = 'AddDealQuantity'
+    end
+    object cdsBillsAddDealTotalPrice: TFloatField
+      FieldName = 'AddDealTotalPrice'
+    end
+    object cdsBillsAddQcQuantity: TFloatField
+      FieldName = 'AddQcQuantity'
+    end
+    object cdsBillsAddQcTotalPrice: TFloatField
+      FieldName = 'AddQcTotalPrice'
+    end
+    object cdsBillsAddQcBGLCode: TWideStringField
+      FieldName = 'AddQcBGLCode'
+      Size = 200
+    end
+    object cdsBillsAddPcQuantity: TFloatField
+      FieldName = 'AddPcQuantity'
+    end
+    object cdsBillsAddPcTotalPrice: TFloatField
+      FieldName = 'AddPcTotalPrice'
+    end
+    object cdsBillsAddPcBGLCode: TWideStringField
+      FieldName = 'AddPcBGLCode'
+      Size = 200
+    end
+    object cdsBillsAddGatherQuantity: TFloatField
+      FieldName = 'AddGatherQuantity'
+    end
+    object cdsBillsAddGatherTotalPrice: TFloatField
+      FieldName = 'AddGatherTotalPrice'
+    end
+    object cdsBillsSerialNo: TIntegerField
+      FieldName = 'SerialNo'
+    end
+  end
+end

+ 475 - 0
DataModules/ReportMemoryDm/rmGclBillsBGDm.pas

@@ -0,0 +1,475 @@
+unit rmGclBillsBGDm;
+// Report Memory Gcl Bills BianGeng DataModule
+// For 連깊05 헌데긴뫘寧응깊
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, ProjectData, sdIDTree, sdDB,
+  PhaseData;
+
+type
+  TGclNode = class
+  private
+    FB_Code: string;
+    FIndexCode: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+    FNewPrice: Double;
+    FDealQuantity: Double;
+    FDealTotalPrice: Double;
+    FQuantity: Double;
+    FTotalPrice: Double;
+    FCurDealQuantity: Double;
+    FCurDealTotalPrice: Double;
+    FCurQcQuantity: Double;
+    FCurQcTotalPrice: Double;
+    FCurQcBGLCode: string;
+    FCurPcQuantity: Double;
+    FCurPcTotalPrice: Double;
+    FCurPcBGLCode: string;
+    FCurGatherQuantity: Double;
+    FCurGatherTotalPrice: Double;
+    FEndDealQuantity: Double;
+    FEndDealTotalPrice: Double;
+    FEndQcQuantity: Double;
+    FEndQcTotalPrice: Double;
+    FEndQcBGLCode: string;
+    FEndPcQuantity: Double;
+    FEndPcTotalPrice: Double;
+    FEndPcBGLCode: string;
+    FEndGatherQuantity: Double;
+    FEndGatherTotalPrice: Double;
+    FAddDealQuantity: Double;
+    FAddDealTotalPrice: Double;
+    FAddQcQuantity: Double;
+    FAddQcTotalPrice: Double;
+    FAddQcBGLCode: string;
+    FAddPcQuantity: Double;
+    FAddPcTotalPrice: Double;
+    FAddPcBGLCode: string;
+    FAddGatherQuantity: Double;
+    FAddGatherTotalPrice: Double;
+  end;
+
+  TrmType = (rmtPhaseDeal, rmtPhaseQc, rmtPhasePc, rmtPhaseGather,
+      rmtEndDeal, rmtEndQc, rmtEndPc, rmtEndGather);
+  TrmGatherType = (rmgtGather, rmgtFlow);
+
+  TrmGclBillsBGData = class(TDataModule)
+    cdsBills: TClientDataSet;
+    cdsBillsB_Code: TStringField;
+    cdsBillsIndexCode: TStringField;
+    cdsBillsName: TWideStringField;
+    cdsBillsUnits: TWideStringField;
+    cdsBillsPrice: TFloatField;
+    cdsBillsNewPrice: TFloatField;
+    cdsBillsDealQuantity: TFloatField;
+    cdsBillsDealTotalPrice: TFloatField;
+    cdsBillsQuantity: TFloatField;
+    cdsBillsTotalPrice: TFloatField;
+    cdsBillsCurDealQuantity: TFloatField;
+    cdsBillsCurDealTotalPrice: TFloatField;
+    cdsBillsCurQcQuantity: TFloatField;
+    cdsBillsCurQcTotalPrice: TFloatField;
+    cdsBillsCurQcBGLCode: TWideStringField;
+    cdsBillsCurPcQuantity: TFloatField;
+    cdsBillsCurPcTotalPrice: TFloatField;
+    cdsBillsCurPcBGLCode: TWideStringField;
+    cdsBillsCurGatherQuantity: TFloatField;
+    cdsBillsCurGatherTotalPrice: TFloatField;
+    cdsBillsEndDealQuantity: TFloatField;
+    cdsBillsEndDealTotalPrice: TFloatField;
+    cdsBillsEndQcQuantity: TFloatField;
+    cdsBillsEndQcTotalPrice: TFloatField;
+    cdsBillsEndPcQuantity: TFloatField;
+    cdsBillsEndPcTotalPrice: TFloatField;
+    cdsBillsEndGatherQuantity: TFloatField;
+    cdsBillsEndGatherTotalPrice: TFloatField;
+    cdsBillsAddDealQuantity: TFloatField;
+    cdsBillsAddDealTotalPrice: TFloatField;
+    cdsBillsAddQcQuantity: TFloatField;
+    cdsBillsAddQcTotalPrice: TFloatField;
+    cdsBillsAddPcQuantity: TFloatField;
+    cdsBillsAddPcTotalPrice: TFloatField;
+    cdsBillsAddGatherQuantity: TFloatField;
+    cdsBillsAddGatherTotalPrice: TFloatField;
+    cdsBillsEndQcBGLCode: TWideStringField;
+    cdsBillsEndPcBGLCode: TWideStringField;
+    cdsBillsAddQcBGLCode: TWideStringField;
+    cdsBillsAddPcBGLCode: TWideStringField;
+    cdsBillsSerialNo: TIntegerField;
+  private
+    FProjectData: TProjectData;
+    FrmType: TrmType;
+    FrmGatherType: TrmGatherType;
+    FGclList: TList;
+
+    procedure FilterGclBills(ANode: TsdIDTreeNode);
+    procedure FilterBills(ANode: TsdIDTreeNode);
+    procedure WriteBills;
+
+    procedure WriteGclBills(APhaseData: TPhaseData; ANode: TsdIDTreeNode;
+      APhaseIndex: Integer);
+    procedure WritePhaseBills(APhaseData: TPhaseData; ANode: TsdIDTreeNode;
+      APhaseIndex: Integer);
+    procedure WritePhaseFlowBills(APhaseIndex: Integer);
+    procedure WriteFlowBills;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AssignData(AProjectData: TProjectData;
+      ArmType: TrmType; ArmGatherType: TrmGatherType): TDataSet;
+  end;
+
+implementation
+
+uses
+  ZhAPI, UtilMethods;
+
+{$R *.dfm}
+
+{ TrmGclBillsBGData }
+
+function TrmGclBillsBGData.AssignData(AProjectData: TProjectData;
+  ArmType: TrmType; ArmGatherType: TrmGatherType): TDataSet;
+begin
+  FProjectData := AProjectData;
+  FrmType := ArmType;
+  FrmGatherType := ArmGatherType;
+  cdsBills.Active := True;
+  cdsBills.DisableControls;
+  try
+    cdsBills.EmptyDataSet;
+    if FrmGatherType = rmgtGather then
+    begin
+      FilterBills(FProjectData.BillsMeasureData.BillsMeasureTree.FirstNode);
+      WriteBills;
+    end
+    else if FrmGatherType = rmgtFlow then
+      WriteFlowBills;
+  finally
+    ClearObjects(FGclList);
+    cdsBills.EnableControls;
+    Result := cdsBills;
+  end;
+end;
+
+constructor TrmGclBillsBGData.Create;
+begin
+  inherited Create(nil);
+  FGclList := TList.Create;
+  cdsBills.IndexFieldNames := 'IndexCode';
+end;
+
+destructor TrmGclBillsBGData.Destroy;
+begin
+  ClearObjects(FGclList);
+  FGclList.Free;
+  inherited;
+end;
+
+procedure TrmGclBillsBGData.FilterBills(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    FilterBills(ANode.FirstChild)
+  else
+    FilterGclBills(ANode);
+  FilterBills(ANode.NextSibling);
+end;
+
+procedure TrmGclBillsBGData.FilterGclBills(ANode: TsdIDTreeNode);
+
+  function CreateGclNode(ARec: TsdDataRecord): TGclNode;
+  begin
+    Result := TGclNode.Create;
+    FGclList.Add(Result);
+    Result.FB_Code := ARec.ValueByName('B_Code').AsString;
+    Result.FIndexCode := B_CodeToIndexCode(ARec.ValueByName('B_Code').AsString);
+    Result.FName := ARec.ValueByName('Name').AsString;
+    Result.FUnits := ARec.ValueByName('Units').AsString;
+    Result.FPrice := ARec.ValueByName('Price').AsFloat;
+    Result.FNewPrice := ARec.ValueByName('NewPrice').AsFloat;
+  end;
+
+  function GetGclNode(ARec: TsdDataRecord): TGclNode;
+  var
+    I: Integer;
+    GclNode: TGclNode;
+  begin
+    Result := nil;
+    for I := 0 to FGclList.Count - 1 do
+    begin
+      GclNode := TGclNode(FGclList.Items[I]);
+      if SameText(GclNode.FB_Code, ARec.ValueByName('B_Code').AsString) and
+          SameText(GclNode.FName, ARec.ValueByName('Name').AsString) and
+          SameText(GclNode.FUnits, ARec.ValueByName('Units').AsString) and
+          (GclNode.FPrice = ARec.ValueByName('Price').AsFloat) then
+      begin
+        Result := GclNode;
+        Break;
+      end;
+    end;
+    if not Assigned(Result) then
+      Result := CreateGclNode(ARec);
+  end;
+
+  procedure LoadPhaseData(AGclNode: TGclNode; AID: Integer);
+  var
+    Rec: TsdDataRecord;
+  begin
+    Rec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(AID);
+    if not Assigned(Rec) then Exit;
+    AGclNode.FCurDealQuantity := AGclNode.FCurDealQuantity + Rec.ValueByName('DealQuantity').AsFloat;
+    AGclNode.FCurDealTotalPrice := AGclNode.FCurDealTotalPrice + Rec.ValueByName('DealTotalPrice').AsFloat;
+    AGclNode.FCurQcQuantity := AGclNode.FCurQcQuantity + Rec.ValueByName('QcQuantity').AsFloat;
+    AGclNode.FCurQcTotalPrice := AGclNode.FCurQcTotalPrice + Rec.ValueByName('QcTotalPrice').AsFloat;
+    AGclNode.FCurQcBGLCode := MergeRelaBGL(AGclNode.FCurQcBGLCode, Rec.ValueByName('QcBGLCode').AsString);
+    AGclNode.FCurPcQuantity := AGclNode.FCurPcQuantity + Rec.ValueByName('PcQuantity').AsFloat;
+    AGclNode.FCurPcTotalPrice := AGclNode.FCurPcTotalPrice + Rec.ValueByName('PcTotalPrice').AsFloat;
+    AGclNode.FCurPcBGLCode := MergeRelaBGL(AGclNode.FCurPcBGLCode, Rec.ValueByName('PcBGLCode').AsString);
+    AGclNode.FCurGatherQuantity := AGclNode.FCurGatherQuantity + Rec.ValueByName('GatherQuantity').AsFloat;
+    AGclNode.FCurGatherTotalPrice := AGclNode.FCurGatherTotalPrice + Rec.ValueByName('GatherTotalPrice').AsFloat;
+
+    AGclNode.FEndDealQuantity := AGclNode.FEndDealQuantity + Rec.ValueByName('EndDealQuantity').AsFloat;
+    AGclNode.FEndDealTotalPrice := AGclNode.FEndDealTotalPrice + Rec.ValueByName('EndDealTotalPrice').AsFloat;
+    AGclNode.FEndQcQuantity := AGclNode.FEndQcQuantity + Rec.ValueByName('EndQcQuantity').AsFloat;
+    AGclNode.FEndQcTotalPrice := AGclNode.FEndQcTotalPrice + Rec.ValueByName('EndQcTotalPrice').AsFloat;
+    AGclNode.FEndQcBGLCode := MergeRelaBGL(AGclNode.FEndQcBGLCode, Rec.ValueByName('EndQcBGLCode').AsString);
+    AGclNode.FEndPcQuantity := AGclNode.FEndPcQuantity + Rec.ValueByName('EndPcQuantity').AsFloat;
+    AGclNode.FEndPcTotalPrice := AGclNode.FEndPcTotalPrice + Rec.ValueByName('EndPcTotalPrice').AsFloat;
+    AGclNode.FEndPcBGLCode := MergeRelaBGL(AGclNode.FEndPcBGLCode, Rec.ValueByName('EndPcBGLCode').AsString);
+    AGclNode.FEndGatherQuantity := AGclNode.FEndGatherQuantity + Rec.ValueByName('EndGatherQuantity').AsFloat;
+    AGclNode.FEndGatherTotalPrice := AGclNode.FEndGatherTotalPrice + Rec.ValueByName('EndGatherTotalPrice').AsFloat;
+  end;
+
+  procedure LoadMeasureData(AGclNode: TGclNode; ARec: TsdDataRecord);
+  begin
+    AGclNode.FQuantity := AGclNode.FQuantity + ARec.ValueByName('Quantity').AsFloat;
+    AGclNode.FTotalPrice := AGclNode.FTotalPrice + ARec.ValueByName('TotalPrice').AsFloat;
+    if TProjectData(FProjectData).ProjProperties.PhaseCount = 0 then Exit;
+    LoadPhaseData(AGclNode, ARec.ValueByName('ID').AsInteger);
+    AGclNode.FAddDealQuantity := AGclNode.FAddDealQuantity + ARec.ValueByName('AddDealQuantity').AsFloat;
+    AGclNode.FAddDealTotalPrice := AGclNode.FAddDealTotalPrice + ARec.ValueByName('AddDealTotalPrice').AsFloat;
+    AGclNode.FAddQcQuantity := AGclNode.FAddQcQuantity + ARec.ValueByName('AddQcQuantity').AsFloat;
+    AGclNode.FAddQcTotalPrice := AGclNode.FAddQcTotalPrice + ARec.ValueByName('AddQcTotalPrice').AsFloat;
+    AGclNode.FAddQcBGLCode := MergeRelaBGL(AGclNode.FAddQcBGLCode, ARec.ValueByName('AddQcBGLCode').AsString);
+    AGclNode.FAddPcQuantity := AGclNode.FAddPcQuantity + ARec.ValueByName('AddPcQuantity').AsFloat;
+    AGclNode.FAddPcTotalPrice := AGclNode.FAddPcTotalPrice + ARec.ValueByName('AddPcTotalPrice').AsFloat;
+    AGclNode.FAddPcBGLCode := MergeRelaBGL(AGclNode.FAddPcBGLCode, ARec.ValueByName('AddPcBGLCode').AsString);
+    AGclNode.FAddGatherQuantity := AGclNode.FAddGatherQuantity + ARec.ValueByName('AddGatherQuantity').AsFloat;
+    AGclNode.FAddGatherTotalPrice := AGclNode.FAddGatherTotalPrice + ARec.ValueByName('AddGatherTotalPrice').AsFloat;
+  end;
+
+  procedure LoadDealData(AGclNode: TGclNode; AB_Code: string);
+  var
+    DealRec: TsdDataRecord;
+  begin
+    DealRec := TProjectData(FProjectData).DealBillsData.DealRecord(AB_Code);
+    if Assigned(DealRec) then
+    begin
+      AGclNode.FDealQuantity := DealRec.ValueByName('Quantity').AsFloat;
+      AGclNode.FDealTotalPrice := DealRec.ValueByName('TotalPrice').AsFloat;
+    end;
+  end;
+
+var
+  Rec, StageRec: TsdDataRecord;
+  GclNode: TGclNode;
+begin
+  if not Assigned(ANode) then Exit;
+  Rec := ANode.Rec;
+  if Rec.ValueByName('B_Code').AsString = '' then Exit;
+  StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ANode.ID);
+  if not Assigned(StageRec) then Exit;
+
+  case FrmType of
+    rmtPhaseDeal: if StageRec.ValueByName('DealTotalPrice').AsFloat = 0 then Exit;
+    rmtPhaseQc: if StageRec.ValueByName('QcTotalPrice').AsFloat = 0 then Exit;
+    rmtPhasePc: if StageRec.ValueByName('PcTotalPrice').AsFloat = 0 then Exit;
+    rmtPhaseGather: if StageRec.ValueByName('GatherTotalPrice').AsFloat = 0 then Exit;
+    rmtEndDeal: if StageRec.ValueByName('EndDealTotalPrice').AsFloat = 0 then Exit;
+    rmtEndQc: if StageRec.ValueByName('EndQcTotalPrice').AsFloat = 0 then Exit;
+    rmtEndPc: if StageRec.ValueByName('EndPcTotalPrice').AsFloat = 0 then Exit;
+    rmtEndGather: if StageRec.ValueByName('EndGatherTotalPrice').AsFloat = 0 then Exit;
+  end;
+
+  GclNode := GetGclNode(Rec);
+  LoadDealData(GclNode, Rec.ValueByName('B_Code').AsString);
+  LoadMeasureData(GclNode, Rec);
+end;
+
+procedure TrmGclBillsBGData.WriteBills;
+var
+  I: Integer;
+  GclNode: TGclNode;
+begin
+  for I := 0 to FGclList.Count - 1 do
+  begin
+    GclNode := TGclNode(FGclList.Items[I]);
+    cdsBills.Append;
+    cdsBillsB_Code.AsString := GclNode.FB_Code;
+    cdsBillsIndexCode.AsString := GclNode.FIndexCode;
+    cdsBillsName.AsString := GclNode.FName;
+    cdsBillsUnits.AsString := GclNode.FUnits;
+    cdsBillsPrice.AsFloat := GclNode.FPrice;
+    cdsBillsNewPrice.AsFloat := GclNode.FNewPrice;
+
+    cdsBillsDealQuantity.AsFloat := GclNode.FDealQuantity;
+    cdsBillsDealTotalPrice.AsFloat := GclNode.FDealTotalPrice;
+
+    cdsBillsQuantity.AsFloat := GclNode.FQuantity;
+    cdsBillsTotalPrice.AsFloat := GclNode.FTotalPrice;
+
+    cdsBillsCurDealQuantity.AsFloat := GclNode.FCurDealQuantity;
+    cdsBillsCurDealTotalPrice.AsFloat := GclNode.FCurDealTotalPrice;
+    cdsBillsCurQcQuantity.AsFloat := GclNode.FCurQcQuantity;
+    cdsBillsCurQcTotalPrice.AsFloat := GclNode.FCurQcTotalPrice;
+    cdsBillsCurQcBGLCode.AsString := GclNode.FCurQcBGLCode;
+    cdsBillsCurPcQuantity.AsFloat := GclNode.FCurPcQuantity;
+    cdsBillsCurPcTotalPrice.AsFloat := GclNode.FCurPcTotalPrice;
+    cdsBillsCurPcBGLCode.AsString := GclNode.FCurPcBGLCode;
+    cdsBillsCurGatherQuantity.AsFloat := GclNode.FCurGatherQuantity;
+    cdsBillsCurGatherTotalPrice.AsFloat := GclNode.FCurGatherTotalPrice;
+
+    cdsBillsEndDealQuantity.AsFloat := GclNode.FEndDealQuantity;
+    cdsBillsEndDealTotalPrice.AsFloat := GclNode.FEndDealTotalPrice;
+    cdsBillsEndQcQuantity.AsFloat := GclNode.FEndQcQuantity;
+    cdsBillsEndQcTotalPrice.AsFloat := GclNode.FEndQcTotalPrice;
+    cdsBillsEndQcBGLCode.AsString := GclNode.FEndQcBGLCode;
+    cdsBillsEndPcQuantity.AsFloat := GclNode.FEndPcQuantity;
+    cdsBillsEndPcTotalPrice.AsFloat := GclNode.FEndPcTotalPrice;
+    cdsBillsEndPcBGLCode.AsString := GclNode.FEndPcBGLCode;
+    cdsBillsEndGatherQuantity.AsFloat := GclNode.FEndGatherQuantity;
+    cdsBillsEndGatherTotalPrice.AsFloat := GclNode.FEndGatherTotalPrice;
+
+    cdsBillsAddDealQuantity.AsFloat := GclNode.FAddDealQuantity;
+    cdsBillsAddDealTotalPrice.AsFloat := GclNode.FAddDealTotalPrice;
+    cdsBillsAddQcQuantity.AsFloat := GclNode.FAddQcQuantity;
+    cdsBillsAddQcTotalPrice.AsFloat := GclNode.FAddQcTotalPrice;
+    cdsBillsAddQcBGLCode.AsString := GclNode.FAddQcBGLCode;
+    cdsBillsAddPcQuantity.AsFloat := GclNode.FAddPcQuantity;
+    cdsBillsAddPcTotalPrice.AsFloat := GclNode.FAddPcTotalPrice;
+    cdsBillsAddPcBGLCode.AsString := GclNode.FAddPcBGLCode;    
+    cdsBillsAddGatherQuantity.AsFloat := GclNode.FAddGatherQuantity;
+    cdsBillsAddGatherTotalPrice.AsFloat := GclNode.FAddGatherTotalPrice;
+    cdsBills.Post;
+  end;
+end;
+
+procedure TrmGclBillsBGData.WriteFlowBills;
+var
+  iPhase: Integer;
+begin
+  for iPhase := 1 to FProjectData.PhaseIndex do
+    WritePhaseFlowBills(iPhase);
+end;
+
+procedure TrmGclBillsBGData.WriteGclBills(APhaseData: TPhaseData;
+  ANode: TsdIDTreeNode; APhaseIndex: Integer);
+
+  procedure WriteGclBillsData(ARec, AStageRec: TsdDataRecord);
+  begin
+    cdsBills.Append;
+    cdsBillsB_Code.AsString := ARec.ValueByName('B_Code').AsString;
+    cdsBillsIndexCode.AsString := B_CodeToIndexCode(ARec.ValueByName('B_Code').AsString);
+    cdsBillsName.AsString := ARec.ValueByName('Name').AsString;
+    cdsBillsUnits.AsString := ARec.ValueByName('Units').AsString;
+    cdsBillsPrice.AsFloat := ARec.ValueByName('Price').AsFloat;
+    cdsBillsNewPrice.AsFloat := ARec.ValueByName('NewPrice').AsFloat;
+
+    cdsBillsQuantity.AsFloat := ARec.ValueByName('Quantity').AsFloat;
+    cdsBillsTotalPrice.AsFloat := ARec.ValueByName('TotalPrice').AsFloat;
+
+    cdsBillsCurDealQuantity.AsFloat := AStageRec.ValueByName('DealQuantity').AsFloat;
+    cdsBillsCurDealTotalPrice.AsFloat := AStageRec.ValueByName('DealTotalPrice').AsFloat;
+    cdsBillsCurQcQuantity.AsFloat := AStageRec.ValueByName('QcQuantity').AsFloat;
+    cdsBillsCurQcTotalPrice.AsFloat := AStageRec.ValueByName('QcTotalPrice').AsFloat;
+    cdsBillsCurQcBGLCode.AsString := AStageRec.ValueByName('QcBGLCode').AsString;
+    cdsBillsCurPcQuantity.AsFloat := AStageRec.ValueByName('PcQuantity').AsFloat;
+    cdsBillsCurPcTotalPrice.AsFloat := AStageRec.ValueByName('PcTotalPrice').AsFloat;
+    cdsBillsCurPcBGLCode.AsString := AStageRec.ValueByName('PcBGLCode').AsString;
+    cdsBillsCurGatherQuantity.AsFloat := AStageRec.ValueByName('GatherQuantity').AsFloat;
+    cdsBillsCurGatherTotalPrice.AsFloat := AStageRec.ValueByName('GatherTotalPrice').AsFloat;
+
+    cdsBillsEndDealQuantity.AsFloat := AStageRec.ValueByName('EndDealQuantity').AsFloat;
+    cdsBillsEndDealTotalPrice.AsFloat := AStageRec.ValueByName('EndDealTotalPrice').AsFloat;
+    cdsBillsEndQcQuantity.AsFloat := AStageRec.ValueByName('EndQcQuantity').AsFloat;
+    cdsBillsEndQcTotalPrice.AsFloat := AStageRec.ValueByName('EndQcTotalPrice').AsFloat;
+    cdsBillsEndQcBGLCode.AsString := AStageRec.ValueByName('EndQcBGLCode').AsString;
+    cdsBillsEndPcQuantity.AsFloat := AStageRec.ValueByName('EndPcQuantity').AsFloat;
+    cdsBillsEndPcTotalPrice.AsFloat := AStageRec.ValueByName('EndPcTotalPrice').AsFloat;
+    cdsBillsEndPcBGLCode.AsString := AStageRec.ValueByName('EndPcBGLCode').AsString;
+    cdsBillsEndGatherQuantity.AsFloat := AStageRec.ValueByName('EndGatherQuantity').AsFloat;
+    cdsBillsEndGatherTotalPrice.AsFloat := AStageRec.ValueByName('EndGatherTotalPrice').AsFloat;
+
+    cdsBillsAddDealQuantity.AsFloat := ARec.ValueByName('AddDealQuantity').AsFloat;
+    cdsBillsAddDealTotalPrice.AsFloat := ARec.ValueByName('AddDealTotalPrice').AsFloat;
+    cdsBillsAddQcQuantity.AsFloat := ARec.ValueByName('AddQcQuantity').AsFloat;
+    cdsBillsAddQcTotalPrice.AsFloat := ARec.ValueByName('AddQcTotalPrice').AsFloat;
+    cdsBillsAddQcBGLCode.AsString := ARec.ValueByName('AddQcBGLCode').AsString;
+    cdsBillsAddPcQuantity.AsFloat := ARec.ValueByName('AddPcQuantity').AsFloat;
+    cdsBillsAddPcTotalPrice.AsFloat := ARec.ValueByName('AddPcTotalPrice').AsFloat;
+    cdsBillsAddPcBGLCode.AsString := ARec.ValueByName('AddPcBGLCode').AsString;
+    cdsBillsAddGatherQuantity.AsFloat := ARec.ValueByName('AddGatherQuantity').AsFloat;
+    cdsBillsAddGatherTotalPrice.AsFloat := ARec.ValueByName('AddGatherTotalPrice').AsFloat;
+
+    cdsBillsSerialNo.AsInteger := APhaseIndex;
+    cdsBills.Post;
+  end;
+
+var
+  Rec, StageRec: TsdDataRecord;
+begin
+  if not Assigned(ANode) then Exit;
+  Rec := ANode.Rec;
+  if Rec.ValueByName('B_Code').AsString = '' then Exit;
+  StageRec := APhaseData.StageData.StageRecord(ANode.ID);
+  if not Assigned(StageRec) then Exit;
+
+  case FrmType of
+    rmtPhaseDeal: if StageRec.ValueByName('DealTotalPrice').AsFloat = 0 then Exit;
+    rmtPhaseQc: if StageRec.ValueByName('QcTotalPrice').AsFloat = 0 then Exit;
+    rmtPhasePc: if StageRec.ValueByName('PcTotalPrice').AsFloat = 0 then Exit;
+    rmtPhaseGather: if StageRec.ValueByName('GatherTotalPrice').AsFloat = 0 then Exit;
+    rmtEndDeal: if StageRec.ValueByName('EndDealTotalPrice').AsFloat = 0 then Exit;
+    rmtEndQc: if StageRec.ValueByName('EndQcTotalPrice').AsFloat = 0 then Exit;
+    rmtEndPc: if StageRec.ValueByName('EndPcTotalPrice').AsFloat = 0 then Exit;
+    rmtEndGather: if StageRec.ValueByName('EndGatherTotalPrice').AsFloat = 0 then Exit;
+  end;
+
+  WriteGclBillsData(Rec, StageRec);
+end;
+
+procedure TrmGclBillsBGData.WritePhaseBills(APhaseData: TPhaseData;
+  ANode: TsdIDTreeNode; APhaseIndex: Integer);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    WritePhaseBills(APhaseData, ANode.FirstChild, APhaseIndex)
+  else
+    WriteGclBills(APhaseData, ANode, APhaseIndex);
+  WritePhaseBills(APhaseData, ANode.NextSibling, APhaseIndex);
+end;
+
+procedure TrmGclBillsBGData.WritePhaseFlowBills(APhaseIndex: Integer);
+var
+  PhaseData: TPhaseData;
+begin
+  PhaseData := TPhaseData.Create(FProjectData);
+  try
+    PhaseData.SimpleOpen(Format('%s\Phase%d.dat', [FProjectData.TempPath, APhaseIndex]));
+    cdsBills.Append;
+    cdsBillsName.AsString := Format('뒤 %d 퍅', [APhaseIndex]);
+    cdsBillsSerialNo.AsInteger := APhaseIndex;
+    cdsBills.Post;
+    WritePhaseBills(PhaseData, FProjectData.BillsCompileData.BillsCompileTree.FirstNode, APhaseIndex);
+  finally
+    PhaseData.Free;
+  end;
+end;
+
+end.

+ 136 - 0
DataModules/ReportMemoryDm/rmGclBillsCompareDm.dfm

@@ -0,0 +1,136 @@
+object rmGclBillsCompareData: TrmGclBillsCompareData
+  OldCreateOrder = False
+  Left = 577
+  Top = 287
+  Height = 150
+  Width = 215
+  object cdsBills: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'CodeIndex'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'SQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'SPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'STotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'MemoStr'
+        DataType = ftWideString
+        Size = 50
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 56
+    Top = 40
+    Data = {
+      410100009619E0BD01000000180000000E000000000003000000410106425F43
+      6F6465010049000000010005574944544802000200320009436F6465496E6465
+      780100490000000100055749445448020002003200044E616D6502004A000000
+      010005574944544802000200900105556E69747301004A000000010005574944
+      544802000200280009535175616E746974790800040000000000065350726963
+      6508000400000000000B53546F74616C50726963650800040000000000094351
+      75616E7469747908000400000000000643507269636508000400000000000B43
+      546F74616C5072696365080004000000000009445175616E7469747908000400
+      000000000644507269636508000400000000000B44546F74616C507269636508
+      00040000000000074D656D6F53747201004A0000000100055749445448020002
+      0064000000}
+    object cdsBillsB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsBillsCodeIndex: TStringField
+      FieldName = 'CodeIndex'
+      Size = 50
+    end
+    object cdsBillsName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsBillsUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsBillsSQuantity: TFloatField
+      FieldName = 'SQuantity'
+    end
+    object cdsBillsSPrice: TFloatField
+      FieldName = 'SPrice'
+    end
+    object cdsBillsSTotalPrice: TFloatField
+      FieldName = 'STotalPrice'
+    end
+    object cdsBillsCQuantity: TFloatField
+      FieldName = 'CQuantity'
+    end
+    object cdsBillsCPrice: TFloatField
+      FieldName = 'CPrice'
+    end
+    object cdsBillsCTotalPrice: TFloatField
+      FieldName = 'CTotalPrice'
+    end
+    object cdsBillsDQuantity: TFloatField
+      FieldName = 'DQuantity'
+    end
+    object cdsBillsDPrice: TFloatField
+      FieldName = 'DPrice'
+    end
+    object cdsBillsDTotalPrice: TFloatField
+      FieldName = 'DTotalPrice'
+    end
+    object cdsBillsMemoStr: TWideStringField
+      FieldName = 'MemoStr'
+      Size = 50
+    end
+  end
+end

+ 240 - 0
DataModules/ReportMemoryDm/rmGclBillsCompareDm.pas

@@ -0,0 +1,240 @@
+unit rmGclBillsCompareDm;
+// Report Memory Gcl Bills Compare DataModule
+// For [05.�뵙궐싹깊] 連깊01 묏넋좆헌데�뵙궐싹깊(0뵀憩瑯)
+
+interface
+
+uses
+  SysUtils, Classes, ProjectData, sdDB, DB, DBClient, sdIDTree;
+
+type
+  TCompareGclNode = class
+  private
+    FB_Code: string;
+    FIndexCode: string;
+    FName: string;
+    FUnits: string;
+    FSQuantity: Double;
+    FSPrice: Double;
+    FSTotalPrice: Double;
+    FCQuantity: Double;
+    FCPrice: Double;
+    FCTotalPrice: Double;
+    FMemoStr: string;
+    function GetDPrice: Double;
+    function GetDQuantity: Double;
+    function GetDTotalPrice: Double;
+  public
+    property B_Code: string read FB_Code write FB_Code;
+    property IndexCode: string read FIndexCode write FIndexCode;
+    property Name: string read FName write FName;
+    property Units: string read FUnits write FUnits;
+    // 覩괩
+    property SQuantity: Double read FSQuantity write FSQuantity;
+    property SPrice: Double read FSPrice write FSPrice;
+    property STotalPrice: Double read FSTotalPrice write FSTotalPrice;
+    // �뵙
+    property CQuantity: Double read FCQuantity write FCQuantity;
+    property CPrice: Double read FCPrice write FCPrice;
+    property CTotalPrice: Double read FCTotalPrice write FCTotalPrice;
+    // �뵙 - 覩괩
+    property DQuantity: Double read GetDQuantity;
+    property DPrice: Double read GetDPrice;
+    property DTotalPrice: Double read GetDTotalPrice;
+    property MemoStr: string read FMemoStr;
+  end;
+
+  TrmGclBillsCompareData = class(TDataModule)
+    cdsBills: TClientDataSet;
+    cdsBillsB_Code: TStringField;
+    cdsBillsCodeIndex: TStringField;
+    cdsBillsName: TWideStringField;
+    cdsBillsUnits: TWideStringField;
+    cdsBillsSQuantity: TFloatField;
+    cdsBillsSPrice: TFloatField;
+    cdsBillsSTotalPrice: TFloatField;
+    cdsBillsCQuantity: TFloatField;
+    cdsBillsCPrice: TFloatField;
+    cdsBillsCTotalPrice: TFloatField;
+    cdsBillsDQuantity: TFloatField;
+    cdsBillsDPrice: TFloatField;
+    cdsBillsDTotalPrice: TFloatField;
+    cdsBillsMemoStr: TWideStringField;
+  private
+    FNodeList: TList;
+
+    procedure LoadGclNodeData(AGclNode: TCompareGclNode; ARec: TsdDataRecord; AIsSource: Boolean);
+    procedure FilterGclBills(ANode: TsdIDTreeNode; AIsSource: Boolean);
+    procedure FilterBills(ANode: TsdIDTreeNode; AIsSource: Boolean);
+
+    procedure WriteBills;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AssignData(ASProjectData, ACProjectData: TProjectData): TDataSet;
+  end;
+
+implementation
+
+uses
+  Globals, UtilMethods, ZhAPI;
+
+{$R *.dfm}
+
+{ TCompareGclNode }
+
+function TCompareGclNode.GetDPrice: Double;
+begin
+  {Result := FCPrice;
+  if Result = 0 then
+    Result := FSPrice;}
+  Result := CPrice - SPrice;
+end;
+
+function TCompareGclNode.GetDQuantity: Double;
+begin
+  Result := CQuantity - SQuantity;
+end;
+
+function TCompareGclNode.GetDTotalPrice: Double;
+begin
+  Result := CTotalPrice - STotalPrice;
+end;
+
+{ TGclBillsCompareData }
+
+function TrmGclBillsCompareData.AssignData(
+  ASProjectData, ACProjectData: TProjectData): TDataSet;
+begin
+  cdsBills.Active := True;
+  cdsBills.EmptyDataSet;
+  ClearObjects(FNodeList);
+  try
+    FilterBills(ASProjectData.BillsCompileData.BillsCompileTree.FirstNode, True);
+    FilterBills(ACProjectData.BillsCompileData.BillsCompileTree.FirstNode, False);
+    WriteBills;
+  finally
+    Result := cdsBills;
+  end;
+end;
+
+constructor TrmGclBillsCompareData.Create;
+begin
+  inherited Create(nil);
+  FNodeList := TList.Create;
+  cdsBills.IndexFieldNames := 'CodeIndex';
+end;
+
+destructor TrmGclBillsCompareData.Destroy;
+begin
+  ClearObjects(FNodeList);
+  FNodeList.Free;
+  inherited;
+end;
+
+procedure TrmGclBillsCompareData.FilterBills(ANode: TsdIDTreeNode;
+  AIsSource: Boolean);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    FilterBills(ANode.FirstChild, AIsSource)
+  else
+    FilterGclBills(ANode, AIsSource);
+  FilterBills(ANode.NextSibling, AIsSource);
+end;
+
+procedure TrmGclBillsCompareData.FilterGclBills(ANode: TsdIDTreeNode;
+  AIsSource: Boolean);
+
+  function CreateGclNode(ARec: TsdDataRecord): TCompareGclNode;
+  begin
+    Result := TCompareGclNode.Create;
+    FNodeList.Add(Result);
+    Result.FB_Code := ARec.ValueByName('B_Code').AsString;
+    Result.FIndexCode := B_CodeToIndexCode(ARec.ValueByName('B_Code').AsString);
+    Result.FName := ARec.ValueByName('Name').AsString;
+    Result.FUnits := ARec.ValueByName('Units').AsString;
+  end;
+
+  function GetGclNode(ARec: TsdDataRecord): TCompareGclNode;
+  var
+    I: Integer;
+    GclNode: TCompareGclNode;
+  begin
+    Result := nil;
+    for I := 0 to FNodeList.Count - 1 do
+    begin
+      GclNode := TCompareGclNode(FNodeList.Items[I]);
+      if SameText(GclNode.FB_Code, ARec.ValueByName('B_Code').AsString) and
+          SameText(GclNode.FName, ARec.ValueByName('Name').AsString) and
+          SameText(GclNode.FUnits, ARec.ValueByName('Units').AsString) then
+      begin
+        Result := GclNode;
+        Break;
+      end;
+    end;
+    if not Assigned(Result) then
+      Result := CreateGclNode(ARec);
+  end;
+
+var
+  Rec: TsdDataRecord;
+  GclNode: TCompareGclNode;
+begin
+  if not Assigned(ANode) then Exit;
+  Rec := ANode.Rec;
+  if Rec.ValueByName('B_Code').AsString = '' then Exit;
+  GclNode := GetGclNode(Rec);
+  LoadGclNodeData(GclNode, Rec, AIsSource);
+end;
+
+procedure TrmGclBillsCompareData.LoadGclNodeData(AGclNode: TCompareGclNode;
+  ARec: TsdDataRecord; AIsSource: Boolean);
+begin
+  if AIsSource then
+  begin
+    AGclNode.FSQuantity := AGclNode.FSQuantity + ARec.ValueByName('Quantity').AsFloat;
+    AGclNode.FSPrice := ARec.ValueByName('Price').AsFloat;
+    AGclNode.FSTotalPrice := AGclNode.FSTotalPrice + ARec.ValueByName('TotalPrice').AsFloat;
+  end
+  else
+  begin
+    AGclNode.FCQuantity := AGclNode.FCQuantity + ARec.ValueByName('Quantity').AsFloat;
+    AGclNode.FCPrice := ARec.ValueByName('Price').AsFloat;
+    AGclNode.FCTotalPrice := AGclNode.FCTotalPrice + ARec.ValueByName('TotalPrice').AsFloat;
+  end;
+end;
+
+procedure TrmGclBillsCompareData.WriteBills;
+var
+  I: Integer;
+  GclNode: TCompareGclNode;
+begin
+  for I := 0 to FNodeList.Count - 1 do
+  begin
+    GclNode := TCompareGclNode(FNodeList.Items[I]);
+    cdsBills.Append;
+    cdsBillsB_Code.AsString := GclNode.B_Code;
+    cdsBillsCodeIndex.AsString := GclNode.IndexCode;
+    cdsBillsName.AsString := GclNode.Name;
+    cdsBillsUnits.AsString := GclNode.Units;
+
+    cdsBillsSQuantity.AsFloat := GclNode.SQuantity;
+    cdsBillsSPrice.AsFloat := GclNode.SPrice;
+    cdsBillsSTotalPrice.AsFloat := GclNode.STotalPrice;
+
+    cdsBillsCQuantity.AsFloat := GclNode.CQuantity;
+    cdsBillsCPrice.AsFloat := GclNode.CPrice;
+    cdsBillsCTotalPrice.AsFloat := GclNode.CTotalPrice;
+
+    cdsBillsDQuantity.AsFloat := GclNode.DQuantity;
+    cdsBillsDPrice.AsFloat := GclNode.DPrice;
+    cdsBillsDTotalPrice.AsFloat := GclNode.DTotalPrice;
+
+    cdsBillsMemoStr.AsString := GclNode.MemoStr;
+    cdsBills.Post;
+  end;
+end;
+
+end.

+ 81 - 0
DataModules/ReportMemoryDm/rmGclBillsPlaneDm.dfm

@@ -0,0 +1,81 @@
+object rmGclBillsPlaneData: TrmGclBillsPlaneData
+  OldCreateOrder = False
+  Left = 192
+  Top = 110
+  Height = 150
+  Width = 215
+  object cdsGclBillsPlane: TClientDataSet
+    Active = True
+    Aggregates = <>
+    Params = <>
+    Left = 64
+    Top = 40
+    Data = {
+      920100009619E0BD01000000180000000E000000000003000000920107507265
+      436F64650100490000000100055749445448020002003200084C617374436F64
+      650100490000000100055749445448020002000A0004436F6465010049000000
+      010005574944544802000200320007586D6A4E616D6502004A00000001000557
+      4944544802000200900108586D6A556E69747301004A00000001000557494454
+      480200020028000350656701004A000000010005574944544802000200640008
+      426567696E50656701004A000000010005574944544802000200640006456E64
+      50656701004A0000000100055749445448020002006400094E616D6542755765
+      6902004A00000001000557494454480200020090010B44726177696E67436F64
+      6501004A000000010005574944544802000200640006425F436F646501004900
+      00000100055749445448020002003200044E616D6502004A0000000100055749
+      44544802000200900105556E69747301004A0000000100055749445448020002
+      002800085175616E7469747908000400000000000000}
+    object cdsGclBillsPlanePreCode: TStringField
+      FieldName = 'PreCode'
+      Size = 50
+    end
+    object cdsGclBillsPlaneLastCode: TStringField
+      FieldName = 'LastCode'
+      Size = 10
+    end
+    object cdsGclBillsPlaneCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsGclBillsPlaneXmjName: TWideStringField
+      FieldName = 'XmjName'
+      Size = 200
+    end
+    object cdsGclBillsPlaneXmjUnits: TWideStringField
+      FieldName = 'XmjUnits'
+    end
+    object cdsGclBillsPlanePeg: TWideStringField
+      FieldName = 'Peg'
+      Size = 50
+    end
+    object cdsGclBillsPlaneBeginPeg: TWideStringField
+      FieldName = 'BeginPeg'
+      Size = 50
+    end
+    object cdsGclBillsPlaneEndPeg: TWideStringField
+      FieldName = 'EndPeg'
+      Size = 50
+    end
+    object cdsGclBillsPlaneNameBuWei: TWideStringField
+      FieldName = 'NameBuWei'
+      Size = 200
+    end
+    object cdsGclBillsPlaneDrawingCode: TWideStringField
+      FieldName = 'DrawingCode'
+      Size = 50
+    end
+    object cdsGclBillsPlaneB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsGclBillsPlaneName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsGclBillsPlaneUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsGclBillsPlaneQuantity: TFloatField
+      FieldName = 'Quantity'
+    end
+  end
+end

+ 302 - 0
DataModules/ReportMemoryDm/rmGclBillsPlaneDm.pas

@@ -0,0 +1,302 @@
+unit rmGclBillsPlaneDm;
+
+// 0号台账平面表
+
+interface
+
+uses
+  SysUtils, Classes, ProjectData, DB, DBClient, sdIDTree;
+
+type
+  TGclBillNode = class
+  private
+    FB_Code: string;
+    FName: string;
+    FUnits: string;
+    FQuantity: 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 Quantity: Double read FQuantity write FQuantity;
+  end;
+
+  TLastXmjNode = class
+  private
+    FGclBills: TList;
+
+    FCode: string;
+    FName: string;
+    FUnits: string;
+
+    FPeg: string;
+    FParentName: string;
+    FDrawingCode: string;
+    function GetBeginPeg: string;
+    function GetEndPeg: string;
+    function GetLastCode: string;
+    function GetPreCode: string;
+    procedure SetPeg(const Value: string);
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AddGclBillNode: TGclBillNode;
+
+    property Code: string read FCode write FCode;
+    property PreCode: string read GetPreCode;
+    property LastCode: string read GetLastCode;
+
+    property Name: string read FName write FName;
+    property Units: string read FUnits write FUnits;
+
+    property Peg: string read FPeg write SetPeg;
+    property BeginPeg: string read GetBeginPeg;
+    property EndPeg: string read GetEndPeg;
+
+    property ParentName: string read FParentName write FParentName;
+    property DrawingCode: string read FDrawingCode write FDrawingCode;
+  end;
+
+  TrmGclBillsPlaneData = class(TDataModule)
+    cdsGclBillsPlane: TClientDataSet;
+    cdsGclBillsPlanePreCode: TStringField;
+    cdsGclBillsPlaneLastCode: TStringField;
+    cdsGclBillsPlaneCode: TStringField;
+    cdsGclBillsPlaneXmjName: TWideStringField;
+    cdsGclBillsPlaneXmjUnits: TWideStringField;
+    cdsGclBillsPlanePeg: TWideStringField;
+    cdsGclBillsPlaneBeginPeg: TWideStringField;
+    cdsGclBillsPlaneEndPeg: TWideStringField;
+    cdsGclBillsPlaneNameBuWei: TWideStringField;
+    cdsGclBillsPlaneB_Code: TStringField;
+    cdsGclBillsPlaneName: TWideStringField;
+    cdsGclBillsPlaneUnits: TWideStringField;
+    cdsGclBillsPlaneQuantity: TFloatField;
+    cdsGclBillsPlaneDrawingCode: TWideStringField;
+  private
+    FLastXmjs: TList;
+    FProjectData: TProjectData;
+
+    procedure AddGclBill(ANode: TsdIDTreeNode; ALastXmj: TLastXmjNode);
+    procedure AddGclBills(ANode:TsdIDTreeNode; ALastXmj: TLastXmjNode);
+
+    function GetPegNode(ANode: TsdIDTreeNode): TsdIDTreeNode;
+    function CheckLastXmj(ANode: TsdIDTreeNode): Boolean;
+    procedure AddLastXmj(ANode: TsdIDTreeNode);
+    procedure FilterBills(ANode: TsdIDTreeNode);
+
+    procedure WriteLastXmj(ALastXmj: TLastXmjNode);
+    procedure WriteData;
+  public
+    function AssignData(AProjectData: TProjectData): TDataSet;
+  end;
+
+implementation
+
+uses
+  ZhAPI, UtilMethods, sdDB;
+
+{$R *.dfm}
+
+{ TLastXmjNode }
+
+function TLastXmjNode.AddGclBillNode: TGclBillNode;
+begin
+  Result := TGclBillNode.Create;
+  FGclBills.Add(Result);
+end;
+
+constructor TLastXmjNode.Create;
+begin
+  FGclBills := TList.Create;
+end;
+
+destructor TLastXmjNode.Destroy;
+begin
+  ClearObjects(FGclBills);
+  FGclBills.Free;
+  inherited;
+end;
+
+function TLastXmjNode.GetBeginPeg: string;
+var
+  iPos: Integer;
+begin
+  iPos := Pos('~', FPeg);
+  Result := Copy(FPeg, 1, iPos-1);
+end;
+
+function TLastXmjNode.GetEndPeg: string;
+var
+  iPos: Integer;
+begin
+  iPos := Pos('~', FPeg);
+  Result := Copy(FPeg, iPos + 1, Length(FPeg) - iPos);
+end;
+
+function TLastXmjNode.GetLastCode: string;
+begin
+  Result := GetLastSetmentOfCode(FCode);
+end;
+
+function TLastXmjNode.GetPreCode: string;
+begin
+  Result := GetPrefixOfCode(FCode);
+end;
+
+procedure TLastXmjNode.SetPeg(const Value: string);
+begin
+  FPeg := StringReplace(Value, '~', '~', [rfReplaceAll]);
+end;
+
+{ TrmGclBillsPlaneData }
+
+procedure TrmGclBillsPlaneData.AddGclBill(ANode: TsdIDTreeNode;
+  ALastXmj: TLastXmjNode);
+var
+  GclBill: TGclBillNode;
+begin
+  if ANode.Rec.ValueByName('B_Code').AsString = '' then Exit;
+  GclBill := ALastXmj.AddGclBillNode;
+  GclBill.B_Code := ANode.Rec.ValueByName('B_Code').AsString;
+  GclBill.Name := ANode.Rec.ValueByName('Name').AsString;
+  GclBill.Units := ANode.Rec.ValueByName('Units').AsString;
+  GclBill.Quantity := ANode.Rec.ValueByName('Quantity').AsFloat;
+end;
+
+procedure TrmGclBillsPlaneData.AddGclBills(ANode: TsdIDTreeNode;
+  ALastXmj: TLastXmjNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if not ANode.HasChildren then
+    AddGclBill(ANode, ALastXmj);
+  AddGclBills(ANode.FirstChild, ALastXmj);
+  AddGclBills(ANode.NextSibling, ALastXmj);
+end;
+
+procedure TrmGclBillsPlaneData.AddLastXmj(ANode: TsdIDTreeNode);
+var
+  LastXmj: TLastXmjNode;
+  vPeg: TsdIDTreeNode;
+begin
+  if not Assigned(ANode) then Exit;
+  LastXmj := TLastXmjNode.Create;
+  FLastXmjs.Add(LastXmj);
+
+  LastXmj.Code := ANode.Rec.ValueByName('Code').AsString;
+  LastXmj.Name := ANode.Rec.ValueByName('Name').AsString;
+  LastXmj.Units := ANode.Rec.ValueByName('Units').AsString;
+  vPeg := GetPegNode(ANode);
+  if Assigned(vPeg) then
+    LastXmj.Peg := vPeg.Rec.ValueByName('Name').AsString;
+  if Assigned(ANode.Parent) then
+    LastXmj.ParentName := ANode.Parent.Rec.ValueByName('Name').AsString;
+  LastXmj.DrawingCode := ANode.Rec.ValueByName('DrawingCode').AsString;
+  AddGclBills(ANode.FirstChild, LastXmj);
+end;
+
+function TrmGclBillsPlaneData.AssignData(
+  AProjectData: TProjectData): TDataSet;
+begin
+  FLastXmjs := TList.Create;
+  cdsGclBillsPlane.Active := True;
+  cdsGclBillsPlane.EmptyDataSet;
+  try
+    FProjectData := AProjectData;
+    FilterBills(FProjectData.BillsCompileData.BillsCompileTree.FirstNode);
+    WriteData;
+  finally
+    ClearObjects(FLastXmjs);
+    FLastXmjs.Free;
+    Result := cdsGclBillsPlane;
+  end;
+end;
+
+function TrmGclBillsPlaneData.CheckLastXmj(ANode: TsdIDTreeNode): Boolean;
+
+  function IsXmj: Boolean;
+  begin
+    Result := ANode.Rec.ValueByName('Code').AsString <> '';
+  end;
+
+  function HasGcl: Boolean;
+  var
+    vChild: TsdIDTreeNode;
+  begin
+    Result := False;
+    vChild := ANode.FirstChild;
+    while not Result and Assigned(vChild) do
+    begin
+      if (vChild.Rec.ValueByName('Code').AsString = '') and
+         (vChild.Rec.ValueByName('B_Code').AsString <> '') then
+        Result := True;
+      vChild := vChild.NextSibling;
+    end;
+  end;
+
+begin
+  // 报表数据的主体应是工程量清单,故最底层项目节的判断为,其下含有工程量清单则为项目节
+  Result := IsXmj and HasGcl;
+end;
+
+procedure TrmGclBillsPlaneData.FilterBills(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if CheckLastXmj(ANode) then
+    AddLastXmj(ANode);
+  FilterBills(ANode.FirstChild);
+  FilterBills(ANode.NextSibling);
+end;
+
+function TrmGclBillsPlaneData.GetPegNode(
+  ANode: TsdIDTreeNode): TsdIDTreeNode;
+begin
+  Result := nil;
+  if not Assigned(ANode) then Exit;
+  if CheckPeg(ANode.Rec.ValueByName('Name').AsString) then
+    Result := ANode
+  else
+    Result := GetPegNode(ANode.Parent);
+end;
+
+procedure TrmGclBillsPlaneData.WriteData;
+var
+  i: Integer;
+begin
+  for i := 0 to FLastXmjs.Count - 1 do
+    WriteLastXmj(TLastXmjNode(FLastXmjs.Items[i]));
+end;
+
+procedure TrmGclBillsPlaneData.WriteLastXmj(ALastXmj: TLastXmjNode);
+var
+  i: Integer;
+  GclBill: TGclBillNode;
+begin
+  for i := 0 to ALastXmj.FGclBills.Count - 1 do
+  begin
+    GclBill := TGclBillNode(ALastXmj.FGclBills.Items[i]);
+    cdsGclBillsPlane.Append;
+    cdsGclBillsPlanePreCode.AsString := ALastXmj.PreCode;
+    cdsGclBillsPlaneLastCode.AsString := ALastXmj.LastCode;
+
+    cdsGclBillsPlaneCode.AsString := ALastXmj.Code;
+    cdsGclBillsPlaneXmjName.AsString := ALastXmj.Name;
+    cdsGclBillsPlaneXmjUnits.AsString := ALastXmj.Units;
+
+    cdsGclBillsPlanePeg.AsString := ALastXmj.Peg;
+    cdsGclBillsPlaneBeginPeg.AsString := ALastXmj.BeginPeg;
+    cdsGclBillsPlaneEndPeg.AsString := ALastXmj.EndPeg;
+    
+    cdsGclBillsPlaneNameBuWei.AsString := ALastXmj.ParentName;
+    cdsGclBillsPlaneDrawingCode.AsString := ALastXmj.DrawingCode;
+
+    cdsGclBillsPlaneB_Code.AsString := GclBill.B_Code;
+    cdsGclBillsPlaneName.AsString := GclBill.Name;
+    cdsGclBillsPlaneUnits.AsString := GclBill.Units;
+    cdsGclBillsPlaneQuantity.AsFloat := GclBill.Quantity;
+    cdsGclBillsPlane.Post;
+  end;
+end;
+
+end.

+ 251 - 0
DataModules/ReportMemoryDm/rmGcl_XmjBillsDm.dfm

@@ -0,0 +1,251 @@
+object rmGcl_XmjBillsData: TrmGcl_XmjBillsData
+  OldCreateOrder = False
+  Left = 795
+  Top = 218
+  Height = 150
+  Width = 215
+  object cdsGcl: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'IndexCode'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'IndexID'
+        DataType = ftInteger
+      end
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Peg'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'NameDanWei'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'NameFenBu'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'NameFenXiang'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'NameUnit'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'DrawingCode'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'Price'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DealQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DifferQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DifferTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'NewPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Position'
+        DataType = ftWideString
+        Size = 255
+      end
+      item
+        Name = 'OrgQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'OrgTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'MisQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'MisTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'OthQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'OthTotalPrice'
+        DataType = ftFloat
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 56
+    Top = 48
+    Data = {
+      9C0200009619E0BD01000000180000001B0000000000030000009C0209496E64
+      6578436F6465010049000000010005574944544802000200320007496E646578
+      4944040001000000000006425F436F6465010049000000010005574944544802
+      0002003200044E616D6502004A00000001000557494454480200020090010443
+      6F646501004900000001000557494454480200020032000350656701004A0000
+      0001000557494454480200020064000A4E616D6544616E57656902004A000000
+      0100055749445448020002009001094E616D6546656E427502004A0000000100
+      0557494454480200020090010C4E616D6546656E5869616E6702004A00000001
+      00055749445448020002009001084E616D65556E697402004A00000001000557
+      494454480200020090010B44726177696E67436F646501004A00000001000557
+      494454480200020064000550726963650800040000000000085175616E746974
+      7908000400000000000A546F74616C507269636508000400000000000C446561
+      6C5175616E7469747908000400000000000E4465616C546F74616C5072696365
+      08000400000000000E4469666665725175616E74697479080004000000000010
+      446966666572546F74616C5072696365080004000000000005556E6974730100
+      4A0000000100055749445448020002002800084E657750726963650800040000
+      00000008506F736974696F6E02004A000000010005574944544802000200FE01
+      0B4F72675175616E7469747908000400000000000D4F7267546F74616C507269
+      636508000400000000000B4D69735175616E7469747908000400000000000D4D
+      6973546F74616C507269636508000400000000000B4F74685175616E74697479
+      08000400000000000D4F7468546F74616C507269636508000400000000000000}
+    object cdsGclIndexCode: TStringField
+      FieldName = 'IndexCode'
+      Size = 50
+    end
+    object cdsGclIndexID: TIntegerField
+      FieldName = 'IndexID'
+    end
+    object cdsGclB_Code: TStringField
+      FieldName = 'B_Code'
+      Size = 50
+    end
+    object cdsGclName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsGclCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsGclPeg: TWideStringField
+      FieldName = 'Peg'
+      Size = 50
+    end
+    object cdsGclNameDanWei: TWideStringField
+      FieldName = 'NameDanWei'
+      Size = 200
+    end
+    object cdsGclNameFenBu: TWideStringField
+      FieldName = 'NameFenBu'
+      Size = 200
+    end
+    object cdsGclNameFenXiang: TWideStringField
+      FieldName = 'NameFenXiang'
+      Size = 200
+    end
+    object cdsGclNameUnit: TWideStringField
+      FieldName = 'NameUnit'
+      Size = 200
+    end
+    object cdsGclDrawingCode: TWideStringField
+      FieldName = 'DrawingCode'
+      Size = 50
+    end
+    object cdsGclPrice: TFloatField
+      FieldName = 'Price'
+    end
+    object cdsGclQuantity: TFloatField
+      FieldName = 'Quantity'
+    end
+    object cdsGclTotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsGclDealQuantity: TFloatField
+      FieldName = 'DealQuantity'
+    end
+    object cdsGclDealTotalPrice: TFloatField
+      FieldName = 'DealTotalPrice'
+    end
+    object cdsGclDifferQuantity: TFloatField
+      FieldName = 'DifferQuantity'
+    end
+    object cdsGclDifferTotalPrice: TFloatField
+      FieldName = 'DifferTotalPrice'
+    end
+    object cdsGclUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsGclNewPrice: TFloatField
+      FieldName = 'NewPrice'
+    end
+    object cdsGclPosition: TWideStringField
+      FieldName = 'Position'
+      Size = 255
+    end
+    object cdsGclOrgQuantity: TFloatField
+      FieldName = 'OrgQuantity'
+    end
+    object cdsGclOrgTotalPrice: TFloatField
+      FieldName = 'OrgTotalPrice'
+    end
+    object cdsGclMisQuantity: TFloatField
+      FieldName = 'MisQuantity'
+    end
+    object cdsGclMisTotalPrice: TFloatField
+      FieldName = 'MisTotalPrice'
+    end
+    object cdsGclOthQuantity: TFloatField
+      FieldName = 'OthQuantity'
+    end
+    object cdsGclOthTotalPrice: TFloatField
+      FieldName = 'OthTotalPrice'
+    end
+  end
+end

+ 614 - 0
DataModules/ReportMemoryDm/rmGcl_XmjBillsDm.pas

@@ -0,0 +1,614 @@
+unit rmGcl_XmjBillsDm;
+
+interface
+
+uses
+  SysUtils, Classes, ProjectData, DB, DBClient, sdIDTree, sdDB;
+
+type
+  {-----------------------------
+    gxtTopGcl: 汇总方式默认,写入方式:工程量清单1&其所属全部项目节, 工程量清单2&其所属全部项目节, ...;
+      示例: 202-1       456
+                   1-1  123
+                   1-2  333
+            203-1       222
+                   1-1  120
+                   1-2  102
+    gxtFlowGcl: 汇总方式默认,写入方式:工程量清单1所属全部项目节, 工程量清单2所属全部项目节, ...;
+      示例: 202-1  1-1  123
+            202-1  1-2  333
+            203-1  1-1  120
+            203-1  1-1  102
+    gxtWithoutXmj: 同gxtTopGcl,完成后过滤所有清单编号为空的节点
+      示例: 202-1       456
+            203-1       222
+  -----------------------------}
+  TGXType = (gxtTopGcl, gxtFlowGcl, gxtWithoutXmj);
+
+  TXmjNode = class
+  private
+    FCode: string;
+    FName: string;
+    FUnits: string;
+
+    FOrgQuantity: Double;
+    FOrgTotalPrice: Double;
+    FMisQuantity: Double;
+    FMisTotalPrice: Double;
+    FOthQuantity: Double;
+    FOthTotalPrice: Double;
+
+    FQuantity: Double;
+    FTotalPrice: Double;
+
+    FDrawingCode: string;
+    FPeg: string;
+    FNameDanWei: string;
+    FNameFenBu: string;
+    FNameFenXiang: string;
+    FNameUnit: string;
+    FPosition: string;
+  end;
+
+  TGclNode = class
+  private
+    FB_Code: string;
+    FIndexCode: string;
+    FName: string;
+    FUnits: string;
+    FPrice: Double;
+    FNewPrice: Double;
+
+    FDealQuantity: Double;
+    FDealTotalPrice: Double;
+
+    FOrgQuantity: Double;
+    FOrgTotalPrice: Double;
+    FMisQuantity: Double;
+    FMisTotalPrice: Double;
+    FOthQuantity: Double;
+    FOthTotalPrice: Double;
+
+    FQuantity: Double;
+    FTotalPrice: Double;
+
+    FXmjList: TList;
+
+    function FindXmjNode(ANode: TsdIDTreeNode): TXmjNode;
+    function NewXmjNode(ANode, APeg: TsdIDTreeNode): TXmjNode;
+
+    function GetXmjCount: Integer;
+    function GetXmjNode(AIndex: Integer): TXmjNode;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AddXmjNode(ANode, APeg: TsdIDTreeNode): TXmjNode;
+
+    property XmjCount: Integer read GetXmjCount;
+    property XmjNode[AIndex: Integer]: TXmjNode read GetXmjNode;
+  end;
+
+  TrmGcl_XmjBillsData = class(TDataModule)
+    cdsGcl: TClientDataSet;
+    cdsGclIndexCode: TStringField;
+    cdsGclIndexID: TIntegerField;
+    cdsGclB_Code: TStringField;
+    cdsGclName: TWideStringField;
+    cdsGclCode: TStringField;
+    cdsGclPeg: TWideStringField;
+    cdsGclNameDanWei: TWideStringField;
+    cdsGclNameFenBu: TWideStringField;
+    cdsGclNameFenXiang: TWideStringField;
+    cdsGclNameUnit: TWideStringField;
+    cdsGclDrawingCode: TWideStringField;
+    cdsGclPrice: TFloatField;
+    cdsGclQuantity: TFloatField;
+    cdsGclTotalPrice: TFloatField;
+    cdsGclDealQuantity: TFloatField;
+    cdsGclDealTotalPrice: TFloatField;
+    cdsGclDifferQuantity: TFloatField;
+    cdsGclDifferTotalPrice: TFloatField;
+    cdsGclUnits: TWideStringField;
+    cdsGclNewPrice: TFloatField;
+    cdsGclPosition: TWideStringField;
+    cdsGclOrgQuantity: TFloatField;
+    cdsGclOrgTotalPrice: TFloatField;
+    cdsGclMisQuantity: TFloatField;
+    cdsGclMisTotalPrice: TFloatField;
+    cdsGclOthQuantity: TFloatField;
+    cdsGclOthTotalPrice: TFloatField;
+  private
+    FProjectData: TProjectData;
+    FGclList: TList;
+    FIndex: Integer;
+    FGXType: TGXType;
+
+    procedure BeforeOperation;
+    procedure AfterOperation;
+
+    procedure AddRelaLeafXmj(AGclNode: TGclNode; ARec: TsdDataRecord);
+    function GetGclNode(ARec: TsdDataRecord): TGclNode;
+    procedure FilterGclBills(ANode: TsdIDTreeNode);
+    procedure FilterBills(ANode: TsdIDTreeNode);
+    procedure FilterDealBills;
+
+    procedure WriteXmjNode(AGclNode: TGclNode);
+    procedure WriteGclNode(AGclNode: TGclNode);
+    procedure WriteTopGclTypeData;
+
+    procedure WriteFlowGclNode(AGclNode: TGclNode);
+    procedure WriteFlowGclTypeData;
+
+    procedure WriteData;
+  public
+    function AssignData(AProjectData: TProjectData; AGXType: TGXType): TDataSet;
+  end;
+
+implementation
+
+uses
+  ZhAPI, UtilMethods;
+
+{$R *.dfm}
+
+{ TGclNode }
+
+constructor TGclNode.Create;
+begin
+  FXmjList := TList.Create;
+end;
+
+destructor TGclNode.Destroy;
+begin
+  ClearObjects(FXmjList);
+  FXmjList.Free;
+  inherited;
+end;
+
+function TGclNode.FindXmjNode(ANode: TsdIDTreeNode): TXmjNode;
+var
+  i: Integer;
+begin
+  Result := nil;
+  for i := 0 to XmjCount - 1 do
+  begin
+    if SameText(XmjNode[i].FCode, ANode.Rec.ValueByName('Code').AsString) and
+       SameText(XmjNode[i].FName, ANode.Rec.ValueByName('Name').AsString) and
+       SameText(XmjNode[i].FUnits, ANode.Rec.ValueByName('Units').AsString) then
+    begin
+      Result := XmjNode[i];
+      Break;
+    end;
+  end;
+end;
+
+function TGclNode.AddXmjNode(
+  ANode, APeg: TsdIDTreeNode): TXmjNode;
+begin
+  Result := FindXmjNode(ANode);
+  if not Assigned(Result) then
+    Result := NewXmjNode(ANode, APeg);
+end;
+
+function TGclNode.GetXmjCount: Integer;
+begin
+  Result := FXmjList.Count;
+end;
+
+function TGclNode.GetXmjNode(AIndex: Integer): TXmjNode;
+begin
+  Result := TXmjNode(FXmjList.Items[AIndex]);
+end;
+
+function TGclNode.NewXmjNode(
+  ANode, APeg: TsdIDTreeNode): TXmjNode;
+
+  function GetPegName(APegNode: TsdIDTreeNode): string;
+  begin
+    if Assigned(APegNode) then
+      Result := APegNode.Rec.ValueByName('Name').AsString
+    else
+      Result := '';
+  end;
+
+  // 取树结构的第ALevel层节点的名称(level从0开始)
+  function GetNameByLevel(ANode: TsdIDTreeNode; ALevel: Integer): string;
+  begin
+    Result := '';
+    if not Assigned(ANode) then Exit;
+    if ANode.Level = ALevel then
+      Result := ANode.Rec.ValueByName('Name').AsString
+    else if ANode.Level > ALevel then
+      Result := GetNameByLevel(ANode.Parent, ALevel);
+  end;
+
+  function GetNameDanWei(ANode: TsdIDTreeNode): string;
+  begin
+    // 取树结构的第二层节点的名称
+    Result := GetNameByLevel(ANode, 1);
+  end;
+
+  // ANode为计量单元节点,APegNode为桩号节点
+  function GetNameFenBu(ANode, APegNode: TsdIDTreeNode): string;
+  var
+    vCurNode: TsdIDTreeNode;
+  begin
+    // 如果计量单元节点的名称为桩号(转化为判断计量单元节点与桩号节点为同一个)
+    if not Assigned(APegNode) or (ANode.ID = APegNode.ID) then
+      // 取树结构的第三层节点的名称
+      Result := GetNameByLevel(ANode, 2)
+    // 否则,取桩号节点的子节点的名称
+    else
+    begin
+      vCurNode := ANode;
+      while vCurNode.Level > APegNode.Level + 1 do
+        vCurNode := vCurNode.Parent;
+      Result := vCurNode.Rec.ValueByName('Name').AsString;
+    end;
+  end;
+
+  function GetNameFenXiang(ANode, APegNode: TsdIDTreeNode): string;
+  var
+    iTopLevel: Integer;
+    vCurNode: TsdIDTreeNode;
+  begin
+    if Assigned(APegNode) then
+    begin
+      iTopLevel := 3;
+      if APegNode.ID <> ANode.ID then
+        iTopLevel := APegNode.Level + 2;
+      Result := '';
+      vCurNode := ANode.Parent;
+      while vCurNode.Level >= iTopLevel do
+      begin
+        Result := vCurNode.Rec.ValueByName('Name').AsString + ';' + Result;
+        vCurNode := vCurNode.Parent;
+      end;
+    end
+    else
+      Result := GetNameByLevel(ANode, 3);
+  end;
+
+  function GetNameUnit(ANode: TsdIDTreeNode): string;
+  begin
+    Result := ANode.Rec.ValueByName('Name').AsString;
+  end;
+
+  function GetDrawingCode(ANode: TsdIDTreeNode): string;
+  begin
+    Result := '';
+    if not Assigned(ANode) then Exit;
+    Result := ANode.Rec.ValueByName('DrawingCode').AsString;
+    if Result = '' then
+      Result := GetDrawingCode(ANode.Parent);
+  end;
+
+  function GetPosition(ANode, APegNode: TsdIDTreeNode): string;
+  begin
+    // 如果计量单元节点的名称为桩号(转化为判断计量单元节点与桩号节点为同一个)
+    if not Assigned(APegNode) or (ANode.ID = APegNode.ID) then
+      // 取分部工程
+      Result := GetNameFenXiang(ANode, APegNode)
+    // 反之,取分项工程+计量单元
+    else
+      Result := GetNameFenXiang(ANode, APegNode) + GetNameUnit(ANode);
+  end;
+
+begin
+  Result := TXmjNode.Create;
+  FXmjList.Add(Result);
+  Result.FCode := ANode.Rec.ValueByName('Code').AsString;
+  Result.FName := ANode.Rec.ValueByName('Name').AsString;
+  Result.FUnits := ANode.Rec.ValueByName('Units').AsString;
+  Result.FPeg := GetPegName(APeg);
+  Result.FNameDanWei := GetNameDanWei(ANode);
+  Result.FNameFenBu := GetNameFenBu(ANode, APeg);
+  Result.FNameFenXiang := GetNameFenXiang(ANode, APeg);
+  Result.FNameUnit := GetNameUnit(ANode);
+  Result.FPosition := GetPosition(ANode, APeg);
+  Result.FDrawingCode := GetDrawingCode(ANode);
+end;
+
+{ TrmGclBillsData }
+
+procedure TrmGcl_XmjBillsData.AddRelaLeafXmj(AGclNode: TGclNode;
+  ARec: TsdDataRecord);
+
+  function GetFirstXmjParent(AID: Integer): TsdIDTreeNode;
+  begin
+    with TProjectData(FProjectData).BillsCompileData do
+      Result := BillsCompileTree.FindNode(AID);
+    while Assigned(Result) and (Result.Rec.ValueByName('B_Code').AsString <> '') do
+      Result := Result.Parent;
+  end;
+
+  function GetPegNode(ANode: TsdIDTreeNode): TsdIDTreeNode;
+  begin
+    Result := nil;
+    if not Assigned(ANode) then Exit;
+    if CheckPeg(ANode.Rec.ValueByName('Name').AsString) then
+      Result := ANode
+    else
+      Result := GetPegNode(ANode.Parent);
+  end;
+
+var
+  vNode, vPeg: TsdIDTreeNode;
+  XmjNode: TXmjNode;
+begin
+  vNode := GetFirstXmjParent(ARec.ValueByName('ID').AsInteger);
+  if not Assigned(vNode) then Exit;
+
+  vPeg := GetPegNode(vNode);
+  XmjNode := AGclNode.AddXmjNode(vNode, vPeg);
+
+  XmjNode.FOrgQuantity := XmjNode.FOrgQuantity + ARec.ValueByName('OrgQuantity').AsFloat;
+  XmjNode.FOrgTotalPrice := XmjNode.FOrgTotalPrice + ARec.ValueByName('OrgTotalPrice').AsFloat;
+  XmjNode.FMisQuantity := XmjNode.FMisQuantity + ARec.ValueByName('MisQuantity').AsFloat;
+  XmjNode.FMisTotalPrice := XmjNode.FMisTotalPrice + ARec.ValueByName('MisTotalPrice').AsFloat;
+  XmjNode.FOthQuantity := XmjNode.FOthQuantity + ARec.ValueByName('OthQuantity').AsFloat;
+  XmjNode.FOthTotalPrice := XmjNode.FOthTotalPrice + ARec.ValueByName('OthTotalPrice').AsFloat;
+
+  XmjNode.FQuantity := XmjNode.FQuantity + ARec.ValueByName('Quantity').AsFloat;
+  XmjNode.FTotalPrice := XmjNode.FTotalPrice + ARec.ValueByName('TotalPrice').AsFloat;
+end;
+
+procedure TrmGcl_XmjBillsData.AfterOperation;
+begin
+  ClearObjects(FGclList);
+  FGclList.Free;
+  if FGXType = gxtWithoutXmj then
+  begin
+    cdsGcl.Filter := 'B_Code <> ''''';
+    cdsGcl.Filtered := True;
+  end;
+  cdsGcl.IndexFieldNames := 'IndexCode;IndexID';
+end;
+
+function TrmGcl_XmjBillsData.AssignData(
+  AProjectData: TProjectData; AGXType: TGXType): TDataSet;
+begin
+  FGXType := AGXType;
+  BeforeOperation;
+  try
+    FProjectData := AProjectData;
+    FilterBills(AProjectData.BillsCompileData.BillsCompileTree.FirstNode);
+    FilterDealBills;
+    WriteData;
+  finally
+    AfterOperation;
+    Result := cdsGcl;
+  end;
+end;
+
+procedure TrmGcl_XmjBillsData.BeforeOperation;
+begin
+  FGclList := TList.Create;
+  cdsGcl.Active := True;
+  cdsGcl.Filtered := False;
+  cdsGcl.EmptyDataSet;
+end;
+
+procedure TrmGcl_XmjBillsData.FilterBills(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    FilterBills(ANode.FirstChild)
+  else
+    FilterGclBills(ANode);
+  FilterBills(ANode.NextSibling);
+end;
+
+procedure TrmGcl_XmjBillsData.FilterDealBills;
+var
+  iIndex: Integer;
+  Rec: TsdDataRecord;
+  GclNode: TGclNode;
+begin
+  with FProjectData.DealBillsData do
+    for iIndex := 0 to sddDealBills.RecordCount - 1 do
+    begin
+      Rec := sddDealBills.Records[iIndex];
+      GclNode := GetGclNode(Rec);
+      GclNode.FDealQuantity := GclNode.FDealQuantity + Rec.ValueByName('Quantity').AsFloat;
+      GclNode.FDealTotalPrice := GclNode.FDealTotalPrice + Rec.ValueByName('TotalPrice').AsFloat;
+    end;
+end;
+
+procedure TrmGcl_XmjBillsData.FilterGclBills(ANode: TsdIDTreeNode);
+var
+  Rec: TsdDataRecord;
+  GclNode: TGclNode;
+begin
+  if not Assigned(ANode) then Exit;
+  Rec := ANode.Rec;
+  if Rec.ValueByName('B_Code').AsString = '' then Exit;
+
+  GclNode := GetGclNode(Rec);
+
+  GclNode.FOrgQuantity := GclNode.FOrgQuantity + Rec.ValueByName('OrgQuantity').AsFloat;
+  GclNode.FOrgTotalPrice := GclNode.FOrgTotalPrice + Rec.ValueByName('OrgTotalPrice').AsFloat;
+  GclNode.FMisQuantity := GclNode.FMisQuantity + Rec.ValueByName('MisQuantity').AsFloat;
+  GclNode.FMisTotalPrice := GclNode.FMisTotalPrice + Rec.ValueByName('MisTotalPrice').AsFloat;
+  GclNode.FOthQuantity := GclNode.FOthQuantity + Rec.ValueByName('OthQuantity').AsFloat;
+  GclNode.FOthTotalPrice := GclNode.FOthTotalPrice + Rec.ValueByName('OthTotalPrice').AsFloat;
+
+  GclNode.FQuantity := GclNode.FQuantity + Rec.ValueByName('Quantity').AsFloat;
+  GclNode.FTotalPrice := GclNode.FTotalPrice + Rec.ValueByName('TotalPrice').AsFloat;
+  AddRelaLeafXmj(GclNode, Rec);
+end;
+
+function TrmGcl_XmjBillsData.GetGclNode(ARec: TsdDataRecord): TGclNode;
+
+  function CreateGclNode: TGclNode;
+  begin
+    Result := TGclNode.Create;
+    FGclList.Add(Result);
+    Result.FB_Code := ARec.ValueByName('B_Code').AsString;
+    Result.FIndexCode := B_CodeToIndexCode(ARec.ValueByName('B_Code').AsString);
+    Result.FName := Trim(ARec.ValueByName('Name').AsString);
+    Result.FUnits := ARec.ValueByName('Units').AsString;
+    Result.FPrice := ARec.ValueByName('Price').AsFloat;
+    if Assigned(ARec.ValueByName('NewPrice')) then
+      Result.FNewPrice := ARec.ValueByName('NewPrice').AsFloat
+    else
+      Result.FNewPrice := 0;
+  end;
+
+var
+  I: Integer;
+  GclNode: TGclNode;
+begin
+  Result := nil;
+  for I := 0 to FGclList.Count - 1 do
+  begin
+    GclNode := TGclNode(FGclList.Items[I]);
+    if SameText(GclNode.FB_Code, ARec.ValueByName('B_Code').AsString) and
+        SameText(GclNode.FName, Trim(ARec.ValueByName('Name').AsString)) and
+        SameText(GclNode.FUnits, ARec.ValueByName('Units').AsString) and
+        (GclNode.FPrice = ARec.ValueByName('Price').AsFloat) then
+    begin
+      Result := GclNode;
+      Break;
+    end;
+  end;
+  if not Assigned(Result) then
+    Result := CreateGclNode;
+end;
+
+procedure TrmGcl_XmjBillsData.WriteData;
+begin
+  case FGXType of
+    gxtTopGcl, gxtWithoutXmj: WriteTopGclTypeData;
+    gxtFlowGcl: WriteFlowGclTypeData;
+  end;
+end;
+
+procedure TrmGcl_XmjBillsData.WriteFlowGclNode(AGclNode: TGclNode);
+var
+  i: Integer;
+  XmjNode: TXmjNode;
+begin
+  for i := 0 to AGclNode.XmjCount - 1 do
+  begin
+    XmjNode := AGclNode.XmjNode[i];
+    cdsGcl.Append;
+    cdsGclIndexCode.AsString := AGclNode.FIndexCode;
+    cdsGclIndexID.AsInteger := i+1;
+
+    cdsGclB_Code.AsString := AGclNode.FB_Code;
+    cdsGclName.AsString := AGclNode.FName;
+    cdsGclUnits.AsString := AGclNode.FUnits;
+    cdsGclPrice.AsFloat := AGclNode.FPrice;
+    cdsGclNewPrice.AsFloat := AGclNode.FNewPrice;
+
+    cdsGclCode.AsString := XmjNode.FCode;
+    cdsGclPeg.AsString := XmjNode.FPeg;
+    cdsGclNameDanWei.AsString := XmjNode.FNameDanWei;
+    cdsGclNameFenBu.AsString := XmjNode.FNameFenBu;
+    cdsGclNameFenXiang.AsString := XmjNode.FNameFenXiang;
+    cdsGclNameUnit.AsString := XmjNode.FNameUnit;
+    cdsGclDrawingCode.AsString := XmjNode.FDrawingCode;
+    cdsGclPosition.AsString := XmjNode.FPosition;
+
+    cdsGclOrgQuantity.AsFloat := XmjNode.FOrgQuantity;
+    cdsGclOrgTotalPrice.AsFloat := XmjNode.FOrgTotalPrice;
+    cdsGclMisQuantity.AsFloat := XmjNode.FMisQuantity;
+    cdsGclMisTotalPrice.AsFloat := XmjNode.FMisTotalPrice;
+    cdsGclOthQuantity.AsFloat := XmjNode.FOthQuantity;
+    cdsGclOthTotalPrice.AsFloat := XmjNode.FOthTotalPrice;
+
+    cdsGclQuantity.AsFloat := XmjNode.FQuantity;
+    cdsGclTotalPrice.AsFloat := XmjNode.FTotalPrice;
+    cdsGcl.Post;
+  end;
+end;
+
+procedure TrmGcl_XmjBillsData.WriteFlowGclTypeData;
+var
+  i: Integer;
+begin
+  FIndex := 0;
+  for i := 0 to FGclList.Count - 1 do
+    WriteFlowGclNode(TGclNode(FGclList.Items[i]));
+end;
+
+procedure TrmGcl_XmjBillsData.WriteGclNode(
+  AGclNode: TGclNode);
+var
+  i: Integer;
+begin
+  cdsGcl.Append;
+  cdsGclIndexCode.AsString := AGclNode.FIndexCode;
+  cdsGclIndexID.AsInteger := 0;
+
+  cdsGclB_Code.AsString := AGclNode.FB_Code;
+  cdsGclName.AsString := AGclNode.FName;
+  cdsGclUnits.AsString := AGclNode.FUnits;
+
+  cdsGclPrice.AsFloat := AGclNode.FPrice;
+  cdsGclNewPrice.AsFloat := AGclNode.FNewPrice;
+
+  cdsGclQuantity.AsFloat := AGclNode.FQuantity;
+  cdsGclTotalPrice.AsFloat := AGclNode.FTotalPrice;
+  cdsGclDealQuantity.AsFloat := AGclNode.FDealQuantity;
+  cdsGclDealTotalPrice.AsFloat := AGclNode.FDealTotalPrice;
+  cdsGclDifferQuantity.AsFloat := AGclNode.FDealQuantity - AGclNode.FQuantity;
+  cdsGclDifferTotalPrice.AsFloat := AGclNode.FDealTotalPrice - AGclNode.FTotalPrice;
+
+  cdsGclOrgQuantity.AsFloat := AGclNode.FOrgQuantity;
+  cdsGclOrgTotalPrice.AsFloat := AGclNode.FOrgTotalPrice;
+  cdsGclMisQuantity.AsFloat := AGclNode.FMisQuantity;
+  cdsGclMisTotalPrice.AsFloat := AGclNode.FMisTotalPrice;
+  cdsGclOthQuantity.AsFloat := AGclNode.FOthQuantity;
+  cdsGclOthTotalPrice.AsFloat := AGclNode.FOthTotalPrice;
+  cdsGcl.Post;
+  WriteXmjNode(AGclNode);
+end;
+
+procedure TrmGcl_XmjBillsData.WriteTopGclTypeData;
+var
+  i: Integer;
+begin
+  FIndex := 0;
+  for i := 0 to FGclList.Count - 1 do
+    WriteGclNode(TGclNode(FGclList.Items[i]));
+end;
+
+procedure TrmGcl_XmjBillsData.WriteXmjNode(
+  AGclNode: TGclNode);
+var
+  i: Integer;
+  XmjNode: TXmjNode;
+begin
+  for i := 0 to AGclNode.XmjCount - 1 do
+  begin
+    XmjNode := AGclNode.XmjNode[i];
+    cdsGcl.Append;
+    cdsGclIndexCode.AsString := AGclNode.FIndexCode;
+    cdsGclIndexID.AsInteger := FIndex;
+    cdsGclCode.AsString := XmjNode.FCode;
+    cdsGclPeg.AsString := XmjNode.FPeg;
+    cdsGclNameDanWei.AsString := XmjNode.FNameDanWei;
+    cdsGclNameFenBu.AsString := XmjNode.FNameFenBu;
+    cdsGclNameFenXiang.AsString := XmjNode.FNameFenXiang;
+    cdsGclNameUnit.AsString := XmjNode.FNameUnit;
+    cdsGclPosition.AsString := XmjNode.FPosition;
+    cdsGclDrawingCode.AsString := XmjNode.FDrawingCode;
+
+    cdsGclOrgQuantity.AsFloat := XmjNode.FOrgQuantity;
+    cdsGclOrgTotalPrice.AsFloat := XmjNode.FOrgTotalPrice;
+    cdsGclMisQuantity.AsFloat := XmjNode.FMisQuantity;
+    cdsGclMisTotalPrice.AsFloat := XmjNode.FMisTotalPrice;
+    cdsGclOthQuantity.AsFloat := XmjNode.FOthQuantity;
+    cdsGclOthTotalPrice.AsFloat := XmjNode.FOthTotalPrice;
+
+    cdsGclQuantity.AsFloat := XmjNode.FQuantity;
+    cdsGclTotalPrice.AsFloat := XmjNode.FTotalPrice;
+    cdsGcl.Post;
+    Inc(FIndex);
+  end;
+end;
+
+end.

+ 85 - 0
DataModules/ReportMemoryDm/rmGridHeaderDm.dfm

@@ -0,0 +1,85 @@
+object rmGridHeaderData: TrmGridHeaderData
+  OldCreateOrder = False
+  Left = 527
+  Top = 460
+  Height = 150
+  Width = 215
+  object cdsGridHeader: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'ProjectName'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'DealCode'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'CName'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'SName'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'PhaseIndex'
+        DataType = ftWideString
+        Size = 10
+      end
+      item
+        Name = 'DealName'
+        DataType = ftWideString
+        Size = 100
+      end
+      item
+        Name = 'FlowIndex'
+        DataType = ftInteger
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 56
+    Top = 40
+    Data = {
+      D90000009619E0BD010000001800000007000000000003000000D9000B50726F
+      6A6563744E616D6501004A000000010005574944544802000200640008446561
+      6C436F646501004A000000010005574944544802000200280005434E616D6501
+      004A000000010005574944544802000200640005534E616D6501004A00000001
+      000557494454480200020064000A5068617365496E64657801004A0000000100
+      055749445448020002001400084465616C4E616D6501004A0000000100055749
+      44544802000200C80009466C6F77496E64657804000100000000000000}
+    object cdsGridHeaderProjectName: TWideStringField
+      FieldName = 'ProjectName'
+      Size = 50
+    end
+    object cdsGridHeaderDealCode: TWideStringField
+      FieldName = 'DealCode'
+    end
+    object cdsGridHeaderCName: TWideStringField
+      FieldName = 'CName'
+      Size = 50
+    end
+    object cdsGridHeaderSName: TWideStringField
+      FieldName = 'SName'
+      Size = 50
+    end
+    object cdsGridHeaderPhaseIndex: TWideStringField
+      FieldName = 'PhaseIndex'
+      Size = 10
+    end
+    object cdsGridHeaderDealName: TWideStringField
+      FieldName = 'DealName'
+      Size = 100
+    end
+    object cdsGridHeaderFlowIndex: TIntegerField
+      FieldName = 'FlowIndex'
+    end
+  end
+end

+ 48 - 0
DataModules/ReportMemoryDm/rmGridHeaderDm.pas

@@ -0,0 +1,48 @@
+unit rmGridHeaderDm;
+
+interface
+
+uses
+  SysUtils, Classes, ProjectData, DB, DBClient;
+
+type
+  TrmGridHeaderData = class(TDataModule)
+    cdsGridHeader: TClientDataSet;
+    cdsGridHeaderProjectName: TWideStringField;
+    cdsGridHeaderDealCode: TWideStringField;
+    cdsGridHeaderCName: TWideStringField;
+    cdsGridHeaderSName: TWideStringField;
+    cdsGridHeaderPhaseIndex: TWideStringField;
+    cdsGridHeaderDealName: TWideStringField;
+    cdsGridHeaderFlowIndex: TIntegerField;
+  private
+  public
+    function AssginData(AProjectData: TProjectData): TDataSet;
+  end;
+
+implementation
+
+uses ProjectProperty;
+
+{$R *.dfm}
+
+{ TrmGridHeaderData }
+
+function TrmGridHeaderData.AssginData(
+  AProjectData: TProjectData): TDataSet;
+begin
+  cdsGridHeader.Active := True;
+  cdsGridHeader.EmptyDataSet;
+  cdsGridHeader.Append;
+  cdsGridHeaderProjectName.AsString := AProjectData.ProjProperties.ProjectName;
+  cdsGridHeaderDealCode.AsString := AProjectData.ProjProperties.DealIndex;
+  cdsGridHeaderCName.AsString := AProjectData.ProjProperties.CName;
+  cdsGridHeaderSName.AsString := AProjectData.ProjProperties.SName;
+  cdsGridHeaderPhaseIndex.AsString := Format('%d ÆÚ', [AProjectData.PhaseIndex]);
+  cdsGridHeaderDealName.AsString := AProjectData.ProjProperties.DealName;
+  cdsGridHeaderFlowIndex.AsInteger := 0;
+  cdsGridHeader.Post;
+  Result := cdsGridHeader;
+end;
+
+end.

+ 163 - 0
DataModules/ReportMemoryDm/rmMentalCustomized1Dm.dfm

@@ -0,0 +1,163 @@
+object rmMentalCustomized1Data: TrmMentalCustomized1Data
+  OldCreateOrder = False
+  Left = 562
+  Top = 392
+  Height = 150
+  Width = 215
+  object cdsCustom1: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'ProjectID'
+        DataType = ftInteger
+      end
+      item
+        Name = 'ProjectName'
+        DataType = ftWideString
+        Size = 255
+      end
+      item
+        Name = 'SerialNo'
+        DataType = ftInteger
+      end
+      item
+        Name = 'ChapterID'
+        DataType = ftWideString
+        Size = 255
+      end
+      item
+        Name = 'ChapterName'
+        DataType = ftWideString
+        Size = 255
+      end
+      item
+        Name = 'P_TotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'P_AddQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'P_AddGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'P_Percent'
+        DataType = ftFloat
+      end
+      item
+        Name = 'TotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddQcTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Percent'
+        DataType = ftFloat
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 40
+    Top = 40
+    Data = {
+      510100009619E0BD01000000180000000D00000000000300000051010950726F
+      6A656374494404000100000000000B50726F6A6563744E616D6502004A000000
+      010005574944544802000200FE010853657269616C4E6F040001000000000009
+      43686170746572494402004A000000010005574944544802000200FE010B4368
+      61707465724E616D6502004A000000010005574944544802000200FE010C505F
+      546F74616C5072696365080004000000000011505F4164645163546F74616C50
+      72696365080004000000000015505F416464476174686572546F74616C507269
+      6365080004000000000009505F50657263656E7408000400000000000A546F74
+      616C507269636508000400000000000F4164645163546F74616C507269636508
+      0004000000000013416464476174686572546F74616C50726963650800040000
+      0000000750657263656E7408000400000000000000}
+    object cdsCustom1ProjectID: TIntegerField
+      FieldName = 'ProjectID'
+    end
+    object cdsCustom1ProjectName: TWideStringField
+      FieldName = 'ProjectName'
+      Size = 255
+    end
+    object cdsCustom1SerialNo: TIntegerField
+      FieldName = 'SerialNo'
+    end
+    object cdsCustom1ChapterID: TWideStringField
+      FieldName = 'ChapterID'
+      Size = 255
+    end
+    object cdsCustom1ChapterName: TWideStringField
+      FieldName = 'ChapterName'
+      Size = 255
+    end
+    object cdsCustom1P_TotalPrice: TFloatField
+      FieldName = 'P_TotalPrice'
+    end
+    object cdsCustom1P_AddQcTotalPrice: TFloatField
+      FieldName = 'P_AddQcTotalPrice'
+    end
+    object cdsCustom1P_AddGatherTotalPrice: TFloatField
+      FieldName = 'P_AddGatherTotalPrice'
+    end
+    object cdsCustom1P_Percent: TFloatField
+      FieldName = 'P_Percent'
+    end
+    object cdsCustom1TotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsCustom1AddQcTotalPrice: TFloatField
+      FieldName = 'AddQcTotalPrice'
+    end
+    object cdsCustom1AddGatherTotalPrice: TFloatField
+      FieldName = 'AddGatherTotalPrice'
+    end
+    object cdsCustom1Percent: TFloatField
+      FieldName = 'Percent'
+    end
+  end
+  object cdsCustom2: TClientDataSet
+    Active = True
+    Aggregates = <>
+    Params = <>
+    Left = 136
+    Top = 40
+    Data = {
+      B70000009619E0BD010000001800000007000000000003000000B70007436C61
+      7373494404000100000000000853657269616C4E6F080004000000000009436C
+      6173734E616D6502004A000000010005574944544802000200FE010A54656E64
+      65724E616D6502004A000000010005574944544802000200FE010A546F74616C
+      5072696365080004000000000013456E64476174686572546F74616C50726963
+      6508000400000000000750657263656E7408000400000000000000}
+    object cdsCustom2ClassID: TIntegerField
+      FieldName = 'ClassID'
+    end
+    object cdsCustom2SerialNo: TFloatField
+      FieldName = 'SerialNo'
+    end
+    object cdsCustom2ClassName: TWideStringField
+      FieldName = 'ClassName'
+      Size = 255
+    end
+    object cdsCustom2TenderName: TWideStringField
+      FieldName = 'TenderName'
+      Size = 255
+    end
+    object cdsCustom2TotalPrice: TFloatField
+      FieldName = 'TotalPrice'
+    end
+    object cdsCustom2EndGatherTotalPrice: TFloatField
+      FieldName = 'EndGatherTotalPrice'
+    end
+    object cdsCustom2Percent: TFloatField
+      FieldName = 'Percent'
+    end
+  end
+end

+ 884 - 0
DataModules/ReportMemoryDm/rmMentalCustomized1Dm.pas

@@ -0,0 +1,884 @@
+unit rmMentalCustomized1Dm;
+
+// 工程量清单章级汇总表 -- 交叉表
+// 先统计各项目中,各章级清单的金额,然后汇总
+// 甘肃--高管局定制 -- 严禁任何其他项目使用该单元结果。
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, ZhAPI, rmSelectProjectFrm,
+  ProjectData, sdDB, UtilMethods, sdIDTree;
+
+type
+  {Custom1}
+  TTP_Record = record
+    FTotalPrice: Double;
+    FAddQcTotalPrice: Double;
+    FAddGatherTotalPrice: Double;
+  end;
+
+  TChapterGcl = array [1..9] of Double;
+
+  TProjectChapterGcl = class
+  private
+    FProjectName: string;
+    FTotalPrice: TChapterGcl;
+    FAddQcTotalPrice: TChapterGcl;
+    FAddGatherTotalPrice: TChapterGcl;
+
+    function GetTotalPrice(AIndex: Integer): Double;
+    procedure SetTotalPrice(AIndex: Integer; const Value: Double);
+    function GetAddGatherTotalPrice(AIndex: Integer): Double;
+    function GetAddQcTotalPrice(AIndex: Integer): Double;
+    procedure SetAddGatherTotalPrice(AIndex: Integer; const Value: Double);
+    procedure SetAddQcTotalPrice(AIndex: Integer; const Value: Double);
+    function GetCompletePercent(AIndex: Integer): Double;
+
+    function GetChapterTotal: Double;
+    function GetTempTotal: Double;
+    function GetBidPrice: Double;
+
+    function GetAG_ChapterTotal: Double;
+    function GetAG_TempTotal: Double;
+    function GetAG_BidPrice: Double;
+
+    function GetAQ_ChapterTotal: Double;
+    function GetAQ_TempTotal: Double;
+    function GetAQ_BidPrice: Double;
+
+    function GetCT_CompletePercent: Double;
+    function GetBP_CompletePercent: Double;
+    function GetTT_CompletePercent: Double;
+  public
+    constructor Create(const AProjectName: string);
+
+    property ProjectName: string read FProjectName;
+    property TotalPrice[AIndex: Integer]: Double read GetTotalPrice write SetTotalPrice;
+    property AddQcTotalPrice[AIndex: Integer]: Double read GetAddQcTotalPrice write SetAddQcTotalPrice;
+    property AddGatherTotalPrice[AIndex: Integer]: Double read GetAddGatherTotalPrice write SetAddGatherTotalPrice;
+    property CompletePercent[AIndex: Integer]: Double read GetCompletePercent;
+
+    property ChapterTotal: Double read GetChapterTotal;
+    property TempTotal: Double read GetTempTotal;
+    property BidPrice: Double read GetBidPrice;
+
+    property AQ_ChapterTotal: Double read GetAQ_ChapterTotal;
+    property AQ_TempTotal: Double read GetAQ_TempTotal;
+    property AQ_BidPrice: Double read GetAQ_BidPrice;
+
+    property AG_ChapterTotal: Double read GetAG_ChapterTotal;
+    property AG_TempTotal: Double read GetAG_TempTotal;
+    property AG_BidPrice: Double read GetAG_BidPrice;
+
+    property CT_CompletePercent: Double read GetCT_CompletePercent;
+    property TT_CompletePercent: Double read GetTT_CompletePercent;
+    property BP_CompletePercent: Double read GetBP_CompletePercent;
+  end;
+
+  TChapterGather = class
+  private
+    FProjectsChapter: TList;
+    FTotalChapter: TProjectChapterGcl;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function AddProjectChapterGcl(const AProjectName: string): TProjectChapterGcl;
+
+    procedure CalcTotal;
+  end;
+
+  {Custom2}
+  TTender = class
+  private
+    FTenderName: string;
+    FTotalPrice: Double;
+    FEndGatherTotalPrice: Double;
+    function GetPercent: Double;
+  public
+    constructor Create(ATenderName: string);
+
+    property TenderName: string read FTenderName;
+    property TotalPrice: Double read FTotalPrice write FTotalPrice;
+    property EndGatherTotalPrice: Double read FEndGatherTotalPrice write FEndGatherTotalPrice;
+    property Percent: Double read GetPercent;
+  end;
+
+  TTenderClass = class
+  private
+    FClassName: string;
+    FTenders: TList;
+    function GetPercent: Double;
+    function GetTotalPrice: Double;
+    function GetEndGatherTotalPrice: Double;
+  public
+    constructor Create(const AClassName: string);
+    destructor Destroy; override;
+
+    function AddTender(const ATenderName: string): TTender;
+
+    property TotalPrice: Double read GetTotalPrice;
+    property EndGatherTotalPrice: Double read GetEndGatherTotalPrice;
+    property Percent: Double read GetPercent;
+  end;
+
+  TTenderClassList = class
+  private
+    FClassList: TList;
+
+    function FindTenderClass(const AClassName: string): TTenderClass;
+    function AddTenderClass(const AClassName: string): TTenderClass;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function TenderClass(const AClassName: string): TTenderClass;
+  end;
+
+  TrmMentalCustomized1Data = class(TDataModule)
+    // 格式1
+    cdsCustom1: TClientDataSet;
+    cdsCustom1ProjectID: TIntegerField;
+    cdsCustom1ProjectName: TWideStringField;
+    cdsCustom1SerialNo: TIntegerField;
+    cdsCustom1ChapterID: TWideStringField;
+    cdsCustom1ChapterName: TWideStringField;
+    cdsCustom1P_TotalPrice: TFloatField;
+    cdsCustom1P_AddQcTotalPrice: TFloatField;
+    cdsCustom1P_AddGatherTotalPrice: TFloatField;
+    cdsCustom1P_Percent: TFloatField;
+    cdsCustom1TotalPrice: TFloatField;
+    cdsCustom1AddQcTotalPrice: TFloatField;
+    cdsCustom1AddGatherTotalPrice: TFloatField;
+    cdsCustom1Percent: TFloatField;
+    // 格式2
+    cdsCustom2: TClientDataSet;
+    cdsCustom2ClassID: TIntegerField;
+    cdsCustom2SerialNo: TFloatField;
+    cdsCustom2ClassName: TWideStringField;
+    cdsCustom2TenderName: TWideStringField;
+    cdsCustom2TotalPrice: TFloatField;
+    cdsCustom2EndGatherTotalPrice: TFloatField;
+    cdsCustom2Percent: TFloatField;
+  private
+    FMentalType: Integer;
+    // Custom1
+    FChapterGather: TChapterGather;
+    FProjectData: TProjectData;
+    // Custom2
+    FClasses: TTenderClassList;
+    FWriteSerilaNo: Integer;
+
+    procedure BeforeGather(AProjects: TList);
+    procedure AfterGather;
+
+    function OpenProjectData(AProject: TSelectProject): TProjectChapterGcl;
+    procedure FreeProjectData;
+
+    function XmjNode(const ACode: string): TsdIDTreeNode;
+    // 汇总项目节ACode下的所有起始编号为AChapterID的清单金额
+    function ChapterTotalPrice(const ACode: string; AChapterID: string = ''): TTP_Record;
+
+    function B_CodeToChapter(const AB_Code: string): Integer;
+    procedure GatherGclChapter(AProjectChapter: TProjectChapterGcl);
+    procedure GatherProject(AProject: TSelectProject);
+
+    function TenderClassName(AProjectID: Integer): string;
+    procedure GatherTenderMainData(AProject: TSelectProject);
+
+    procedure CalcuateGather;
+    procedure GatherData(AProjects: TList);
+
+    procedure WriteProjectChapter(AProjectID: Integer; AProject, ATotal: TProjectChapterGcl);
+    procedure WriteCustomized0;
+
+    procedure WriteTenderClass(AClassID: Integer; ATenderClass: TTenderClass);
+    procedure WriteCustomized1;
+
+    procedure WriteData;
+  public
+    function AssignData(AProjects: TList): TDataSet;
+
+    property MentalType: Integer read FMentalType write FMentalType;
+  end;
+
+implementation
+
+uses
+  BillsDm, mDataRecord, Globals, Windows;
+
+{$R *.dfm}
+
+{ TrmGclChapterGatherData }
+
+procedure TrmMentalCustomized1Data.AfterGather;
+begin
+  FChapterGather.Free;
+  cdsCustom1.EnableControls;
+  cdsCustom1.IndexFieldNames := 'ProjectID;SerialNo';
+
+  FClasses.Free;
+  cdsCustom2.EnableControls;
+end;
+
+function TrmMentalCustomized1Data.AssignData(AProjects: TList): TDataSet;
+var
+  iProject: Integer;
+  SelectProject: TSelectProject;
+begin
+  BeforeGather(AProjects);
+  try
+    GatherData(AProjects);
+    WriteData;
+  finally
+    case FMentalType of
+      0: Result := cdsCustom1;
+      1: Result := cdsCustom2;
+    end;
+    AfterGather;
+  end;
+end;
+
+procedure TrmMentalCustomized1Data.BeforeGather(AProjects: TList);
+begin
+  cdsCustom1.DisableControls;
+  cdsCustom1.Active := True;
+  cdsCustom1.EmptyDataSet;
+  FChapterGather := TChapterGather.Create;
+
+  cdsCustom2.DisableControls;
+  cdsCustom2.Active := True;
+  cdsCustom2.EmptyDataSet;
+  FClasses := TTenderClassList.Create;
+end;
+
+function TrmMentalCustomized1Data.B_CodeToChapter(
+  const AB_Code: string): Integer;
+var
+  sgs: TStrings;
+  iFirst, iSecond: Integer;
+begin
+  Result := 0;
+  sgs := TStringList.Create;
+  try
+    sgs.Delimiter := '-';
+    sgs.DelimitedText := AB_Code;
+    iFirst := StrToIntDef(sgs.Strings[0], 0);
+    // X,M表示1-9,其中XMM-M与M-XMM-M同属X章级
+    if (iFirst < 99) and (sgs.Count > 1) then
+    begin
+      iSecond := StrToIntDef(sgs.Strings[1], 0);
+      Result := Trunc(iSecond/100);
+    end
+    else
+      Result := Trunc(iFirst/100);
+  finally
+    sgs.Free;
+  end;
+end;
+
+procedure TrmMentalCustomized1Data.CalcuateGather;
+begin
+  if FMentalType = 0 then
+    FChapterGather.CalcTotal;
+end;
+
+function TrmMentalCustomized1Data.ChapterTotalPrice(const ACode: string;
+  AChapterID: string): TTP_Record;
+var
+  stnNode, stnChild: TsdIDTreeNode;
+  iNext, iTotal: Integer;
+begin 
+  Result.FTotalPrice := 0;
+  Result.FAddQcTotalPrice := 0;
+  Result.FAddGatherTotalPrice := 0;
+  stnNode := XmjNode(ACode);
+  if not Assigned(stnNode) then Exit;
+  
+  stnChild := stnNode.FirstChild;
+  iNext := 1;
+  iTotal := stnNode.PosterityCount;
+  while iNext <= iTotal do
+  begin
+    with TBillsRecord(stnChild.Rec) do
+      if not stnChild.HasChildren and (B_Code.AsString <> '') then
+        if (AChapterID = '') or (Pos(AChapterID, Trim(B_Code.AsString)) = 1) then
+        begin
+          Result.FTotalPrice := Result.FTotalPrice + TotalPrice.AsFloat;
+          Result.FAddQcTotalPrice := Result.FAddQcTotalPrice + AddQcTotalPrice.AsFloat;
+          Result.FAddGatherTotalPrice := Result.FAddGatherTotalPrice + AddGatherTotalPrice.AsFloat;
+        end;
+
+    Inc(iNext);
+    stnChild := stnChild.NextNode;
+  end;
+end;
+
+procedure TrmMentalCustomized1Data.FreeProjectData;
+begin
+  if not Assigned(OpenProjectManager.FindProjectData(FProjectData.ProjectID)) then
+    FProjectData.Free;
+end;
+
+procedure TrmMentalCustomized1Data.GatherData(AProjects: TList);
+var
+  iProject: Integer;
+begin
+  for iProject := 0 to AProjects.Count - 1 do
+    if MentalType = 0 then
+      GatherProject(TSelectProject(AProjects.Items[iProject]))
+    else
+      GatherTenderMainData(TSelectProject(AProjects.Items[iProject]));
+  CalcuateGather;
+end;
+
+procedure TrmMentalCustomized1Data.GatherGclChapter(
+  AProjectChapter: TProjectChapterGcl);
+
+  procedure GatherChapter(AChapterID: Integer; const ACode: string; ASearchChapter: string = '');
+  var
+    CalcRecord: TTP_Record;
+  begin
+    CalcRecord := ChapterTotalPrice(ACode, ASearchChapter);
+
+    AProjectChapter.TotalPrice[AChapterID] :=
+      AProjectChapter.TotalPrice[AChapterID] + CalcRecord.FTotalPrice;
+    AProjectChapter.AddQcTotalPrice[AChapterID] :=
+      AProjectChapter.AddQcTotalPrice[AChapterID] + CalcRecord.FAddQcTotalPrice;
+    AProjectChapter.AddGatherTotalPrice[AChapterID] :=
+      AProjectChapter.AddGatherTotalPrice[AChapterID] + CalcRecord.FAddGatherTotalPrice;
+  end;
+
+begin
+  // 1-1下的全部清单为100章
+  GatherChapter(1, '1-1', '');
+  // 1-2下的全部清单为200章
+  GatherChapter(2, '1-2', '');
+  // 1-3下的全部清单为300章
+  GatherChapter(3, '1-3', '');
+  // 1-4下的全部清单为400章
+  GatherChapter(4, '1-4', '');
+  // 1-5、1-6下的全部清单为500章
+  GatherChapter(5, '1-5', '');
+  GatherChapter(5, '1-6', '');
+  // 1-7下【清单编号以6开头】的全部清单为600章
+  GatherChapter(6, '1-7', '6');
+  // 1-7下【清单编号以2、8开头】的全部清单为600章
+  GatherChapter(8, '1-7', '2');
+  GatherChapter(8, '1-7', '8');
+  // 1-8下的全部清单为800章
+  GatherChapter(7, '1-8', '');
+  // 1-9下的全部清单为900章
+  GatherChapter(9, '1-9', '');
+end;
+
+procedure TrmMentalCustomized1Data.GatherProject(AProject: TSelectProject);
+var
+  ProjectChapter: TProjectChapterGcl;
+begin
+  ProjectChapter := OpenProjectData(AProject);
+  try
+    GatherGclChapter(ProjectChapter);
+  finally
+    FreeProjectData;
+  end;
+end;
+
+procedure TrmMentalCustomized1Data.GatherTenderMainData(
+  AProject: TSelectProject);
+var
+  TenderClass: TTenderClass;
+  Rec: TsdDataRecord;
+  Tender: TTender;
+begin
+  TenderClass := FClasses.TenderClass(TenderClassName(AProject.ProjectID));
+  Rec := ProjectManager.sddProjectsInfo.FindKey('idxID', AProject.ProjectID);
+  Tender := TenderClass.AddTender(Rec.ValueByName('Name').AsString);
+  Tender.TotalPrice := Rec.ValueByName('DealTotalPrice').AsFloat;
+  Tender.EndGatherTotalPrice := Rec.ValueByName('EndTotalPrice').AsFloat;
+end;
+
+function TrmMentalCustomized1Data.OpenProjectData(
+  AProject: TSelectProject): TProjectChapterGcl;
+var
+  Rec: TsdDataRecord;
+begin
+  FProjectData := OpenProjectManager.FindProjectData(AProject.ProjectID);
+  Rec := ProjectManager.sddProjectsInfo.FindKey('idxID', AProject.ProjectID);
+  if not Assigned(FProjectData) then
+  begin
+    FProjectData := TProjectData.Create;
+    FProjectData.OpenForReport(GetMyProjectsFilePath + Rec.ValueByName('FileName').AsString);
+  end;
+  Result := FChapterGather.AddProjectChapterGcl(Rec.ValueByName('Name').AsString);
+end;
+
+function TrmMentalCustomized1Data.TenderClassName(
+  AProjectID: Integer): string;
+var
+  vNode: TsdIDTreeNode;
+begin
+  Result := '';
+  vNode := ProjectManager.ProjectsTree.FindNode(AProjectID);
+  if not Assigned(vNode) then Exit;
+
+  while Assigned(vNode.Parent) do
+    vNode := vNode.Parent;
+  Result := vNode.Rec.ValueByName('Name').AsString;
+end;
+
+procedure TrmMentalCustomized1Data.WriteCustomized0;
+var
+  iProject: Integer;
+  ProjectChapter: TProjectChapterGcl;
+begin
+  for iProject := 0 to FChapterGather.FProjectsChapter.Count - 1 do
+  begin
+    ProjectChapter := TProjectChapterGcl(FChapterGather.FProjectsChapter.Items[iProject]);
+    WriteProjectChapter(iProject, ProjectChapter, FChapterGather.FTotalChapter);
+  end;
+end;
+
+procedure TrmMentalCustomized1Data.WriteCustomized1;
+var
+  iClass: Integer;
+begin
+  FWriteSerilaNo := 1;
+  for iClass := 0 to FClasses.FClassList.Count - 1 do
+    WriteTenderClass(iClass, TTenderClass(FClasses.FClassList.Items[iClass]));
+end;
+
+procedure TrmMentalCustomized1Data.WriteData;
+begin
+  case FMentalType of
+    0: WriteCustomized0;
+    1: WriteCustomized1;
+  end;
+end;
+
+procedure TrmMentalCustomized1Data.WriteProjectChapter(
+  AProjectID: Integer; AProject, ATotal: TProjectChapterGcl);
+const
+  SChapterID: array [1..12] of string = ('100', '200', '300', '400',
+    '500', '600', '700', '800', '900', '', '', '');
+  SChapterName: array [1..12] of string = ('总则', '路基', '路面', '桥梁、涵洞',
+    '隧道', '安全设施及预埋管线', '绿化及环境保护', '机电工程', '房建', '100章至900章清单合计 A', '暂列金额 B=A*10%', '投标价 C=A+B');
+
+  procedure AddProjectChapter(AIndex: Integer);
+  begin
+    cdsCustom1.Append;
+    cdsCustom1ProjectID.AsInteger := AProjectID;
+    cdsCustom1ProjectName.AsString := AProject.FProjectName;
+    cdsCustom1SerialNo.AsInteger := AIndex;
+    cdsCustom1ChapterID.AsString := SChapterID[AIndex];
+    cdsCustom1ChapterName.AsString := SChapterName[AIndex];
+    cdsCustom1P_TotalPrice.AsFloat := AProject.TotalPrice[AIndex];
+    cdsCustom1P_AddQcTotalPrice.AsFloat := AProject.AddQcTotalPrice[AIndex];
+    cdsCustom1P_AddGatherTotalPrice.AsFloat := AProject.AddGatherTotalPrice[AIndex];
+    cdsCustom1P_Percent.AsFloat := AProject.CompletePercent[AIndex];
+    cdsCustom1TotalPrice.AsFloat := ATotal.TotalPrice[AIndex];
+    cdsCustom1AddQcTotalPrice.AsFloat := ATotal.AddQcTotalPrice[AIndex];
+    cdsCustom1AddGatherTotalPrice.AsFloat := ATotal.AddGatherTotalPrice[AIndex];
+    cdsCustom1Percent.AsFloat := ATotal.CompletePercent[AIndex];
+    cdsCustom1.Post;
+  end;
+
+  procedure AddProjectChapterTotal(AIndex: Integer);
+  begin
+    cdsCustom1.Append;
+    cdsCustom1ProjectID.AsInteger := AProjectID;
+    cdsCustom1ProjectName.AsString := AProject.FProjectName; 
+    cdsCustom1SerialNo.AsInteger := AIndex;
+    cdsCustom1ChapterID.AsString := SChapterID[AIndex];
+    cdsCustom1ChapterName.AsString := SChapterName[AIndex];
+    cdsCustom1P_TotalPrice.AsFloat := AProject.ChapterTotal;
+    cdsCustom1P_AddQcTotalPrice.AsFloat := AProject.AQ_ChapterTotal;
+    cdsCustom1P_AddGatherTotalPrice.AsFloat := AProject.AG_ChapterTotal;
+    cdsCustom1P_Percent.AsFloat := AProject.CT_CompletePercent;
+    cdsCustom1TotalPrice.AsFloat := ATotal.ChapterTotal;
+    cdsCustom1AddQcTotalPrice.AsFloat := ATotal.AQ_ChapterTotal;
+    cdsCustom1AddGatherTotalPrice.AsFloat := ATotal.AG_ChapterTotal;
+    cdsCustom1Percent.AsFloat := ATotal.CT_CompletePercent;
+    cdsCustom1.Post;
+  end;
+
+  procedure AddProjectTempTotal(AIndex: Integer);
+  begin
+    cdsCustom1.Append;
+    cdsCustom1ProjectID.AsInteger := AProjectID;
+    cdsCustom1ProjectName.AsString := AProject.FProjectName;
+    cdsCustom1SerialNo.AsInteger := AIndex; 
+    cdsCustom1ChapterID.AsString := SChapterID[AIndex];
+    cdsCustom1ChapterName.AsString := SChapterName[AIndex];
+    cdsCustom1P_TotalPrice.AsFloat := AProject.TempTotal;
+    cdsCustom1P_AddQcTotalPrice.AsFloat := AProject.AQ_TempTotal;
+    cdsCustom1P_AddGatherTotalPrice.AsFloat := AProject.AG_TempTotal;
+    cdsCustom1P_Percent.AsFloat := AProject.TT_CompletePercent;
+    cdsCustom1TotalPrice.AsFloat := ATotal.TempTotal;
+    cdsCustom1AddQcTotalPrice.AsFloat := ATotal.AQ_TempTotal;
+    cdsCustom1AddGatherTotalPrice.AsFloat := ATotal.AG_TempTotal;
+    cdsCustom1Percent.AsFloat := ATotal.TT_CompletePercent;
+    cdsCustom1.Post;
+  end;
+
+  procedure AddProjectBidPrice(AIndex: Integer);
+  begin
+    cdsCustom1.Append;
+    cdsCustom1ProjectID.AsInteger := AProjectID;
+    cdsCustom1ProjectName.AsString := AProject.FProjectName;
+    cdsCustom1SerialNo.AsInteger := AIndex; 
+    cdsCustom1ChapterID.AsString := SChapterID[AIndex];
+    cdsCustom1ChapterName.AsString := SChapterName[AIndex];
+    cdsCustom1P_TotalPrice.AsFloat := AProject.BidPrice;
+    cdsCustom1P_AddQcTotalPrice.AsFloat := AProject.AQ_BidPrice;
+    cdsCustom1P_AddGatherTotalPrice.AsFloat := AProject.AG_BidPrice;
+    cdsCustom1P_Percent.AsFloat := AProject.BP_CompletePercent;
+    cdsCustom1TotalPrice.AsFloat := ATotal.BidPrice;
+    cdsCustom1AddQcTotalPrice.AsFloat := ATotal.AQ_BidPrice;
+    cdsCustom1AddGatherTotalPrice.AsFloat := ATotal.AG_BidPrice;
+    cdsCustom1Percent.AsFloat := ATotal.BP_CompletePercent;
+    cdsCustom1.Post;
+  end;
+
+var
+  iIndex: Integer;
+begin
+  for iIndex := Low(TChapterGcl) to High(TChapterGcl) do
+    AddProjectChapter(iIndex);
+  AddProjectChapterTotal(10);
+  AddProjectTempTotal(11);
+  AddProjectBidPrice(12);
+end;
+
+{ TProjectChapterGcl }
+
+constructor TProjectChapterGcl.Create(const AProjectName: string);
+begin
+  FProjectName := AProjectName;
+  ZeroMemory(@FTotalPrice, SizeOf(TChapterGcl));
+  ZeroMemory(@FAddQcTotalPrice, SizeOf(TChapterGcl));
+  ZeroMemory(@FAddGatherTotalPrice, SizeOf(TChapterGcl));
+end;
+
+function TProjectChapterGcl.GetAddGatherTotalPrice(
+  AIndex: Integer): Double;
+begin
+  Result := FAddGatherTotalPrice[AIndex];
+end;
+
+function TProjectChapterGcl.GetAddQcTotalPrice(AIndex: Integer): Double;
+begin
+  Result := FAddQcTotalPrice[AIndex];
+end;
+
+function TProjectChapterGcl.GetAG_BidPrice: Double;
+begin
+  Result := AG_ChapterTotal + AG_TempTotal;
+end;
+
+function TProjectChapterGcl.GetAG_ChapterTotal: Double;
+var
+  i: Integer;
+begin
+  Result := 0;
+  for i := Low(TChapterGcl) to High(TChapterGcl) do
+    Result := Result + FAddGatherTotalPrice[i];
+end;
+
+function TProjectChapterGcl.GetAG_TempTotal: Double;
+begin
+  Result := AG_ChapterTotal * 0.1;
+end;
+
+function TProjectChapterGcl.GetAQ_BidPrice: Double;
+begin
+  Result := AQ_ChapterTotal + AQ_TempTotal;
+end;
+
+function TProjectChapterGcl.GetAQ_ChapterTotal: Double;
+var
+  i: Integer;
+begin
+  Result := 0;
+  for i := Low(TChapterGcl) to High(TChapterGcl) do
+    Result := Result + FAddQcTotalPrice[i];
+end;
+
+function TProjectChapterGcl.GetAQ_TempTotal: Double;
+begin
+  Result := AQ_ChapterTotal * 0.1;
+end;
+
+function TProjectChapterGcl.GetBidPrice: Double;
+begin
+  Result := ChapterTotal + TempTotal;
+end;
+
+function TProjectChapterGcl.GetBP_CompletePercent: Double;
+begin
+  if (BidPrice + AQ_BidPrice) <> 0 then
+    Result := AG_BidPrice/(BidPrice + AQ_BidPrice)*100
+  else
+    Result := 0;
+end;
+
+function TProjectChapterGcl.GetChapterTotal: Double;
+var
+  i: Integer;
+begin
+  Result := 0;
+  for i := Low(TChapterGcl) to High(TChapterGcl) do
+    Result := Result + FTotalPrice[i];
+end;
+
+function TProjectChapterGcl.GetCompletePercent(AIndex: Integer): Double;
+begin
+  if (FTotalPrice[AIndex] + FAddQcTotalPrice[AIndex]) <> 0 then
+    Result := FAddGatherTotalPrice[AIndex]/(FTotalPrice[AIndex] + FAddQcTotalPrice[AIndex])*100
+  else
+    Result := 0;
+end;
+
+function TProjectChapterGcl.GetCT_CompletePercent: Double;
+begin
+  if (ChapterTotal + AQ_ChapterTotal) <> 0 then
+    Result := AG_ChapterTotal/(ChapterTotal + AQ_ChapterTotal)*100
+  else
+    Result := 0;
+end;
+
+function TProjectChapterGcl.GetTempTotal: Double;
+begin
+  Result := ChapterTotal * 0.1;
+end;
+
+function TProjectChapterGcl.GetTotalPrice(AIndex: Integer): Double;
+begin
+  Result := FTotalPrice[AIndex];
+end;
+
+function TProjectChapterGcl.GetTT_CompletePercent: Double;
+begin
+  if (TempTotal + AQ_TempTotal) <> 0 then
+    Result := AG_TempTotal/(TempTotal + AQ_TempTotal)*100
+  else
+    Result := 0;
+end;
+
+procedure TProjectChapterGcl.SetAddGatherTotalPrice(AIndex: Integer;
+  const Value: Double);
+begin
+  FAddGatherTotalPrice[AIndex] := Value;
+end;
+
+procedure TProjectChapterGcl.SetAddQcTotalPrice(AIndex: Integer;
+  const Value: Double);
+begin
+  FAddQcTotalPrice[AIndex] := Value;
+end;
+
+procedure TProjectChapterGcl.SetTotalPrice(AIndex: Integer;
+  const Value: Double);
+begin
+  FTotalPrice[AIndex] := Value;
+end;
+
+{ TChapterGather }
+
+function TChapterGather.AddProjectChapterGcl(
+  const AProjectName: string): TProjectChapterGcl;
+begin
+  Result := TProjectChapterGcl.Create(AProjectName);
+  FProjectsChapter.Add(Result);
+end;
+
+procedure TChapterGather.CalcTotal;
+var
+  iProject, iChapter: Integer;
+  ProjectChapter: TProjectChapterGcl;
+begin
+  for iProject := 0 to FProjectsChapter.Count - 1 do
+  begin
+    ProjectChapter := TProjectChapterGcl(FProjectsChapter.Items[iProject]);
+    for iChapter := Low(TChapterGcl) to High(TChapterGcl) do
+    begin
+      FTotalChapter.TotalPrice[iChapter] := FTotalChapter.TotalPrice[iChapter] + ProjectChapter.TotalPrice[iChapter];
+      FTotalChapter.AddQcTotalPrice[iChapter] := FTotalChapter.AddQcTotalPrice[iChapter] + ProjectChapter.AddQcTotalPrice[iChapter];
+      FTotalChapter.AddGatherTotalPrice[iChapter] := FTotalChapter.AddGatherTotalPrice[iChapter] + ProjectChapter.AddGatherTotalPrice[iChapter];
+    end;
+  end;
+end;
+
+constructor TChapterGather.Create;
+begin
+  FProjectsChapter := TList.Create;
+  FTotalChapter := TProjectChapterGcl.Create('合计');
+end;
+
+destructor TChapterGather.Destroy;
+begin
+  FTotalChapter.Free;
+  ClearObjects(FProjectsChapter);
+  FProjectsChapter.Free;
+  inherited;
+end;
+
+{ TTender }
+
+constructor TTender.Create(ATenderName: string);
+begin
+  FTenderName := ATenderName;
+end;
+
+function TTender.GetPercent: Double;
+begin
+  if FTotalPrice <> 0 then
+    Result := FEndGatherTotalPrice/FTotalPrice*100
+  else
+    Result := 0;
+end;
+
+{ TTenderClass }
+
+function TTenderClass.AddTender(const ATenderName: string): TTender;
+begin
+  Result := TTender.Create(ATenderName);
+  FTenders.Add(Result);
+end;
+
+constructor TTenderClass.Create(const AClassName: string);
+begin
+  FClassName := AClassName;
+  FTenders := TList.Create;
+end;
+
+destructor TTenderClass.Destroy;
+begin
+  ClearObjects(FTenders);
+  FTenders.Free;
+  inherited;
+end;
+
+function TTenderClass.GetEndGatherTotalPrice: Double;
+var
+  i: Integer;
+begin
+  Result := 0;
+  for i := 0 to FTenders.Count - 1 do
+    Result := Result + TTender(FTenders.Items[i]).EndGatherTotalPrice;
+end;
+
+function TTenderClass.GetPercent: Double;
+begin
+  if TotalPrice <> 0 then
+    Result := EndGatherTotalPrice/TotalPrice*100
+  else
+    Result := 0;
+end;
+
+function TTenderClass.GetTotalPrice: Double;
+var
+  i: Integer;
+begin
+  Result := 0;
+  for i := 0 to FTenders.Count - 1 do
+    Result := Result + TTender(FTenders.Items[i]).TotalPrice;
+end;
+
+{ TTenderClassList }
+
+function TTenderClassList.AddTenderClass(
+  const AClassName: string): TTenderClass;
+begin
+  Result := TTenderClass.Create(AClassName);
+  FClassList.Add(Result);
+end;
+
+constructor TTenderClassList.Create;
+begin
+  FClassList := TList.Create;
+end;
+
+destructor TTenderClassList.Destroy;
+begin
+  ClearObjects(FClassList);
+  FClassList.Free;
+  inherited;
+end;
+
+function TTenderClassList.FindTenderClass(
+  const AClassName: string): TTenderClass;
+var
+  iClass: Integer;
+  TenderClass: TTenderClass;
+begin
+  Result := nil;
+  for iClass := 0 to FClassList.Count - 1 do
+  begin
+    TenderClass := TTenderClass(FClassList.Items[iClass]);
+    if SameText(AClassName, TenderClass.FClassName) then
+    begin
+      Result := TenderClass;
+      Break;
+    end;
+  end;
+end;
+
+function TTenderClassList.TenderClass(
+  const AClassName: string): TTenderClass;
+begin
+  Result := FindTenderClass(AClassName);
+  if not Assigned(Result) then
+    Result := AddTenderClass(AClassName);
+end;
+
+procedure TrmMentalCustomized1Data.WriteTenderClass(AClassID: Integer;
+  ATenderClass: TTenderClass);
+
+  procedure AddTenderRecord(ATender: TTender);
+  begin
+    cdsCustom2.Append;
+    cdsCustom2ClassID.AsInteger := AClassID;
+    cdsCustom2SerialNo.AsInteger := FWriteSerilaNo;
+    cdsCustom2ClassName.AsString := ATenderClass.FClassName;
+    cdsCustom2TenderName.AsString := ATender.TenderName;
+    cdsCustom2TotalPrice.AsFloat := ATender.TotalPrice;
+    cdsCustom2EndGatherTotalPrice.AsFloat := ATender.EndGatherTotalPrice;
+    cdsCustom2Percent.AsFloat := ATender.Percent;
+    cdsCustom2.Post;
+    Inc(FWriteSerilaNo);
+  end;
+
+  procedure AddTotalRecord;
+  begin
+    cdsCustom2.Append;
+    cdsCustom2ClassID.AsInteger := AClassID;
+    cdsCustom2ClassName.AsString := '小计';
+    cdsCustom2TotalPrice.AsFloat := ATenderClass.TotalPrice;
+    cdsCustom2EndGatherTotalPrice.AsFloat := ATenderClass.EndGatherTotalPrice;
+    cdsCustom2Percent.AsFloat := ATenderClass.Percent;
+    cdsCustom2.Post;
+  end;
+
+var
+  iTender: Integer;
+begin
+  for iTender := 0 to ATenderClass.FTenders.Count - 1 do
+    AddTenderRecord(TTender(ATenderClass.FTenders.Items[iTender]));
+  AddTotalRecord;
+end;
+
+function TrmMentalCustomized1Data.XmjNode(
+  const ACode: string): TsdIDTreeNode;
+var
+  iID: Integer;
+  Rec: TsdDataRecord;
+begin
+  Result := nil;
+  Rec := FProjectData.BillsData.sddBills.Locate('Code', ACode);
+  if Assigned(Rec) then
+    Result := FProjectData.BillsCompileData.BillsCompileTree.FindNode(Rec.ValueByName('ID').AsInteger);
+end;
+
+end.

+ 90 - 0
DataModules/ReportMemoryDm/rmOtherReport1Dm.dfm

@@ -0,0 +1,90 @@
+object rmOtherReport1Data: TrmOtherReport1Data
+  OldCreateOrder = False
+  Left = 636
+  Top = 422
+  Height = 150
+  Width = 215
+  object cdsOtherReport1: TClientDataSet
+    Active = True
+    Aggregates = <>
+    Params = <>
+    Left = 56
+    Top = 40
+    Data = {
+      6A0100009619E0BD0100000018000000150000000000030000006A010656616C
+      75653108000400000000000856616C7565315F3108000400000000000856616C
+      7565315F3208000400000000000856616C7565315F3308000400000000000856
+      616C7565315F3408000400000000000856616C7565315F350800040000000000
+      0856616C7565315F3608000400000000000856616C7565315F37080004000000
+      00000856616C7565315F3808000400000000000856616C7565315F3908000400
+      000000000956616C7565315F313008000400000000000656616C756532080004
+      00000000000656616C75653308000400000000000656616C7565340800040000
+      0000000656616C75653508000400000000000656616C75653608000400000000
+      000656616C75653708000400000000000656616C756538080004000000000006
+      56616C75653908000400000000000756616C7565313008000400000000000556
+      616C756508000400000000000000}
+    object cdsOtherReport1Value1: TFloatField
+      FieldName = 'Value1'
+    end
+    object cdsOtherReport1Value1_1: TFloatField
+      FieldName = 'Value1_1'
+    end
+    object cdsOtherReport1Value1_2: TFloatField
+      FieldName = 'Value1_2'
+    end
+    object cdsOtherReport1Value1_3: TFloatField
+      FieldName = 'Value1_3'
+    end
+    object cdsOtherReport1Value1_4: TFloatField
+      FieldName = 'Value1_4'
+    end
+    object cdsOtherReport1Value1_5: TFloatField
+      FieldName = 'Value1_5'
+    end
+    object cdsOtherReport1Value1_6: TFloatField
+      FieldName = 'Value1_6'
+    end
+    object cdsOtherReport1Value1_7: TFloatField
+      FieldName = 'Value1_7'
+    end
+    object cdsOtherReport1Value1_8: TFloatField
+      FieldName = 'Value1_8'
+    end
+    object cdsOtherReport1Value1_9: TFloatField
+      FieldName = 'Value1_9'
+    end
+    object cdsOtherReport1Value1_10: TFloatField
+      FieldName = 'Value1_10'
+    end
+    object cdsOtherReport1Value2: TFloatField
+      FieldName = 'Value2'
+    end
+    object cdsOtherReport1Value3: TFloatField
+      FieldName = 'Value3'
+    end
+    object cdsOtherReport1Value4: TFloatField
+      FieldName = 'Value4'
+    end
+    object cdsOtherReport1Value5: TFloatField
+      FieldName = 'Value5'
+    end
+    object cdsOtherReport1Value6: TFloatField
+      FieldName = 'Value6'
+    end
+    object cdsOtherReport1Value7: TFloatField
+      FieldName = 'Value7'
+    end
+    object cdsOtherReport1Value8: TFloatField
+      FieldName = 'Value8'
+    end
+    object cdsOtherReport1Value9: TFloatField
+      FieldName = 'Value9'
+    end
+    object cdsOtherReport1Value10: TFloatField
+      FieldName = 'Value10'
+    end
+    object cdsOtherReport1Value: TFloatField
+      FieldName = 'Value'
+    end
+  end
+end

+ 251 - 0
DataModules/ReportMemoryDm/rmOtherReport1Dm.pas

@@ -0,0 +1,251 @@
+unit rmOtherReport1Dm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, rmSelectProjectFrm, ProjectData,
+  sdDB;
+
+const
+  FixedID: array [1..10] of Integer = (1, 2, 3, 21, 57, 36, 25, 26, 15, 34);
+  XiangCode: array [1..10] of string = ('1-1', '1-2', '1-3', '1-4', '1-5', '1-6', '1-7', '1-8', '1-9', '1-10');
+
+type
+  TDataArray = array [1..10] of Double;
+
+  TrmOtherReport1Data = class(TDataModule)
+    cdsOtherReport1: TClientDataSet;
+    cdsOtherReport1Value1: TFloatField;
+    cdsOtherReport1Value1_1: TFloatField;
+    cdsOtherReport1Value1_2: TFloatField;
+    cdsOtherReport1Value1_3: TFloatField;
+    cdsOtherReport1Value1_4: TFloatField;
+    cdsOtherReport1Value1_5: TFloatField;
+    cdsOtherReport1Value1_6: TFloatField;
+    cdsOtherReport1Value1_7: TFloatField;
+    cdsOtherReport1Value1_8: TFloatField;
+    cdsOtherReport1Value1_9: TFloatField;
+    cdsOtherReport1Value1_10: TFloatField;
+    cdsOtherReport1Value2: TFloatField;
+    cdsOtherReport1Value3: TFloatField;
+    cdsOtherReport1Value4: TFloatField;
+    cdsOtherReport1Value5: TFloatField;
+    cdsOtherReport1Value6: TFloatField;
+    cdsOtherReport1Value7: TFloatField;
+    cdsOtherReport1Value8: TFloatField;
+    cdsOtherReport1Value9: TFloatField;
+    cdsOtherReport1Value10: TFloatField;
+    cdsOtherReport1Value: TFloatField;
+  private
+    FProjectData: TProjectData;
+    FFixedAB: TDataArray;
+    FFixedFinal: TDataArray;
+    FXiangAB: TDataArray;
+    FXiangFinal: TDataArray;
+    FGatherAB: Double;
+    FGatherFinal: Double;
+
+    procedure ResetDataZero;
+
+    function OpenProject(AProject: TSelectProject): TProjectData;
+    procedure FreeProject(AProjectData: TProjectData);
+
+    procedure GatherFixedData(var AArray: TDataArray; AIndex: Integer);
+    procedure GatherXiangData(var AArray: TDataArray; AIndex: Integer);
+
+    procedure GatherProject(AProject: TSelectProject);
+
+    procedure WriteData;
+  public
+    function AssignData(AProjects: TList): TDataSet;
+  end;
+
+implementation
+
+uses
+  Globals, UtilMethods;
+
+{$R *.dfm}
+
+{ TrmOtherReport1Data }
+
+function TrmOtherReport1Data.AssignData(AProjects: TList): TDataSet;
+var
+  iProject: Integer;
+  SelectProject: TSelectProject;
+begin
+  cdsOtherReport1.Active := True;
+  cdsOtherReport1.DisableControls;
+  cdsOtherReport1.EmptyDataSet;
+  ResetDataZero;
+  try
+    for iProject := 0 to AProjects.Count - 1 do
+      GatherProject(TSelectProject(AProjects.Items[iProject]));
+    WriteData;
+  finally
+    cdsOtherReport1.EnableControls;
+    Result := cdsOtherReport1;
+  end;
+end;
+
+procedure TrmOtherReport1Data.FreeProject(AProjectData: TProjectData);
+begin
+  if not Assigned(OpenProjectManager.FindProjectData(FProjectData.ProjectID)) then
+    FProjectData.Free;
+end;
+
+procedure TrmOtherReport1Data.GatherFixedData(
+  var AArray: TDataArray; AIndex: Integer);
+var
+  i: Integer;
+begin
+  for i := Low(FixedID) to High(FixedID) do
+    AArray[i] := AArray[i] + FProjectData.BillsData.GetGatherTotalPrice(FixedID[i], AIndex);
+end;
+
+procedure TrmOtherReport1Data.GatherProject(AProject: TSelectProject);
+begin
+  FProjectData := OpenProject(AProject);
+  try
+    if AProject.IsAB then
+    begin
+      GatherFixedData(FFixedAB, 0);
+      GatherXiangData(FXiangAB, 0);
+      FGatherAB := FProjectData.BillsData.Settlement[0];
+    end
+    else
+    begin
+      GatherFixedData(FFixedFinal, 4);
+      GatherXiangData(FXiangFinal, 4);
+      FGatherFinal := FGatherFinal + FProjectData.BillsData.Settlement[4];
+    end;
+  finally
+    FreeProject(FProjectData);
+  end;
+end;
+
+procedure TrmOtherReport1Data.GatherXiangData(
+  var AArray: TDataArray; AIndex: Integer);
+var
+  i: Integer;
+  Rec: TsdDataRecord;
+begin
+  for i := Low(XiangCode) to High(XiangCode) do
+  begin
+    Rec := FProjectData.BillsData.sddBills.Locate('Code', XiangCode[i]);
+    if Assigned(Rec) then
+    begin
+      case AIndex of
+        0: AArray[i] := AArray[i] + Rec.ValueByName('TotalPrice').AsFloat;
+        4: AArray[i] := AArray[i] + Rec.ValueByName('AddGatherTotalPrice').AsFloat;
+      end;
+    end;
+  end;
+end;
+
+function TrmOtherReport1Data.OpenProject(AProject: TSelectProject): TProjectData;
+var
+  Rec: TsdDataRecord;
+begin
+  Result := OpenProjectManager.FindProjectData(AProject.ProjectID);
+  if not Assigned(Result) then
+  begin
+    Rec := ProjectManager.sddProjectsInfo.FindKey('idxID', AProject.ProjectID);
+    Result := TProjectData.Create;
+    Result.OpenForReport(GetMyProjectsFilePath + Rec.ValueByName('FileName').AsString);
+  end;
+end;
+
+procedure TrmOtherReport1Data.ResetDataZero;
+begin
+  FillChar(FFixedAB, SizeOf(FFixedAB), 0);
+  FillChar(FFixedFinal, SizeOf(FFixedFinal), 0);
+  FillChar(FXiangAB, SizeOf(FXiangAB), 0);
+  FillChar(FXiangFinal, SizeOf(FXiangFinal), 0);
+  FGatherAB := 0;
+  FGatherFinal := 0;
+end;
+
+procedure TrmOtherReport1Data.WriteData;
+begin
+  //Åú×¼¸ÅËã
+  cdsOtherReport1.Append;
+  cdsOtherReport1Value1.AsFloat := FFixedAB[1];
+  cdsOtherReport1Value2.AsFloat := FFixedAB[2];
+  cdsOtherReport1Value3.AsFloat := FFixedAB[3];
+  cdsOtherReport1Value4.AsFloat := FFixedAB[4];
+  cdsOtherReport1Value5.AsFloat := FFixedAB[5];
+  cdsOtherReport1Value6.AsFloat := FFixedAB[6];
+  cdsOtherReport1Value7.AsFloat := FFixedAB[7];
+  cdsOtherReport1Value8.AsFloat := FFixedAB[8];
+  cdsOtherReport1Value9.AsFloat := FFixedAB[9];
+  cdsOtherReport1Value10.AsFloat := FFixedAB[10];
+
+  cdsOtherReport1Value1_1.AsFloat := FXiangAB[1];
+  cdsOtherReport1Value1_2.AsFloat := FXiangAB[2];
+  cdsOtherReport1Value1_3.AsFloat := FXiangAB[3];
+  cdsOtherReport1Value1_4.AsFloat := FXiangAB[4];
+  cdsOtherReport1Value1_5.AsFloat := FXiangAB[5];
+  cdsOtherReport1Value1_6.AsFloat := FXiangAB[6];
+  cdsOtherReport1Value1_7.AsFloat := FXiangAB[7];
+  cdsOtherReport1Value1_8.AsFloat := FXiangAB[8];
+  cdsOtherReport1Value1_9.AsFloat := FXiangAB[9];
+  cdsOtherReport1Value1_10.AsFloat := FXiangAB[10];
+
+  cdsOtherReport1Value.AsFloat := FGatherAB;
+  cdsOtherReport1.Post;
+  // ¾öËã
+  cdsOtherReport1.Append;
+  cdsOtherReport1Value1.AsFloat := FFixedFinal[1];
+  cdsOtherReport1Value2.AsFloat := FFixedFinal[2];
+  cdsOtherReport1Value3.AsFloat := FFixedFinal[3];
+  cdsOtherReport1Value4.AsFloat := FFixedFinal[4];
+  cdsOtherReport1Value5.AsFloat := FFixedFinal[5];
+  cdsOtherReport1Value6.AsFloat := FFixedFinal[6];
+  cdsOtherReport1Value7.AsFloat := FFixedFinal[7];
+  cdsOtherReport1Value8.AsFloat := FFixedFinal[8];
+  cdsOtherReport1Value9.AsFloat := FFixedFinal[9];
+  cdsOtherReport1Value10.AsFloat := FFixedFinal[10];
+
+  cdsOtherReport1Value1_1.AsFloat := FXiangFinal[1];
+  cdsOtherReport1Value1_2.AsFloat := FXiangFinal[2];
+  cdsOtherReport1Value1_3.AsFloat := FXiangFinal[3];
+  cdsOtherReport1Value1_4.AsFloat := FXiangFinal[4];
+  cdsOtherReport1Value1_5.AsFloat := FXiangFinal[5];
+  cdsOtherReport1Value1_6.AsFloat := FXiangFinal[6];
+  cdsOtherReport1Value1_7.AsFloat := FXiangFinal[7];
+  cdsOtherReport1Value1_8.AsFloat := FXiangFinal[8];
+  cdsOtherReport1Value1_9.AsFloat := FXiangFinal[9];
+  cdsOtherReport1Value1_10.AsFloat := FXiangFinal[10];
+
+  cdsOtherReport1Value.AsFloat := FGatherFinal;
+  cdsOtherReport1.Post;
+  // Ôö¼õ
+  cdsOtherReport1.Append;
+  cdsOtherReport1Value1.AsFloat := FFixedFinal[1] - FFixedAB[1];
+  cdsOtherReport1Value2.AsFloat := FFixedFinal[2] - FFixedAB[2];
+  cdsOtherReport1Value3.AsFloat := FFixedFinal[3] - FFixedAB[3];
+  cdsOtherReport1Value4.AsFloat := FFixedFinal[4] - FFixedAB[4];
+  cdsOtherReport1Value5.AsFloat := FFixedFinal[5] - FFixedAB[5];
+  cdsOtherReport1Value6.AsFloat := FFixedFinal[6] - FFixedAB[6];
+  cdsOtherReport1Value7.AsFloat := FFixedFinal[7] - FFixedAB[7];
+  cdsOtherReport1Value8.AsFloat := FFixedFinal[8] - FFixedAB[8];
+  cdsOtherReport1Value9.AsFloat := FFixedFinal[9] - FFixedAB[9];
+  cdsOtherReport1Value10.AsFloat := FFixedFinal[10] - FFixedAB[10];
+
+  cdsOtherReport1Value1_1.AsFloat := FXiangFinal[1] - FXiangAB[1];
+  cdsOtherReport1Value1_2.AsFloat := FXiangFinal[2] - FXiangAB[2];
+  cdsOtherReport1Value1_3.AsFloat := FXiangFinal[3] - FXiangAB[3];
+  cdsOtherReport1Value1_4.AsFloat := FXiangFinal[4] - FXiangAB[4];
+  cdsOtherReport1Value1_5.AsFloat := FXiangFinal[5] - FXiangAB[5];
+  cdsOtherReport1Value1_6.AsFloat := FXiangFinal[6] - FXiangAB[6];
+  cdsOtherReport1Value1_7.AsFloat := FXiangFinal[7] - FXiangAB[7];
+  cdsOtherReport1Value1_8.AsFloat := FXiangFinal[8] - FXiangAB[8];
+  cdsOtherReport1Value1_9.AsFloat := FXiangFinal[9] - FXiangAB[9];
+  cdsOtherReport1Value1_10.AsFloat := FXiangFinal[10] - FXiangAB[10];
+
+  cdsOtherReport1Value.AsFloat := FGatherFinal - FGatherAB;
+  cdsOtherReport1.Post;
+end;
+
+end.

+ 34 - 0
DataModules/ReportMemoryDm/rmTestFrm.dfm

@@ -0,0 +1,34 @@
+object rmTestForm: TrmTestForm
+  Left = 381
+  Top = 212
+  Width = 979
+  Height = 563
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'MS Sans Serif'
+  Font.Style = []
+  OldCreateOrder = False
+  PixelsPerInch = 96
+  TextHeight = 13
+  object ZJGrid1: TZJGrid
+    Left = 0
+    Top = 0
+    Width = 971
+    Height = 529
+    Options = [goRangeSelect, goRowSizing, goColSizing, goCellNotMaintainData, goFixedRowShowNo, goFixedColShowNo, goAlwaysShowSelection]
+    OptionsEx = []
+    ShowGridLine = False
+    DefaultColWidth = 73
+    Selection.AlphaBlend = False
+    Selection.TransparentColor = False
+    Align = alClient
+  end
+  object ZjGridDBA1: TZjGridDBA
+    Columns = <>
+    Grid = ZJGrid1
+    Left = 136
+    Top = 128
+  end
+end

+ 45 - 0
DataModules/ReportMemoryDm/rmTestFrm.pas

@@ -0,0 +1,45 @@
+unit rmTestFrm;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, ZjGridDBA, ZJGrid, DB;
+
+type
+  TrmTestForm = class(TForm)
+    ZJGrid1: TZJGrid;
+    ZjGridDBA1: TZjGridDBA;
+  private
+    { Private declarations }
+  public
+    constructor Create(ADataSet: TDataSet);
+  end;
+
+procedure ShowTestForm(ADataSet: TDataSet);
+
+implementation
+
+{$R *.dfm}
+
+procedure ShowTestForm(ADataSet: TDataSet);
+var
+  rmTestForm: TrmTestForm;
+begin
+  rmTestForm := TrmTestForm.Create(ADataSet);
+  try
+    rmTestForm.ShowModal;
+  finally
+    rmTestForm.Free;
+  end;
+end;
+
+{ TrmTestForm }
+
+constructor TrmTestForm.Create(ADataSet: TDataSet);
+begin
+  inherited Create(nil);
+  ZjGridDBA1.DataSet := ADataSet;
+end;
+
+end.

+ 185 - 0
DataModules/ReportMemoryDm/rmXmjBGLDetailDm.dfm

@@ -0,0 +1,185 @@
+object rmXmjBGLDetailData: TrmXmjBGLDetailData
+  OldCreateOrder = False
+  Left = 651
+  Top = 311
+  Height = 150
+  Width = 215
+  object cdsXmjBGLDetail: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'DgnQuantity1'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DgnQuantity2'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DgnQuantity'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'Xmj_BGLName'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'BGLCode'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'BGLName'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'BGLType'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'Reason'
+        DataType = ftWideString
+        Size = 255
+      end
+      item
+        Name = 'Direction'
+        DataType = ftWideString
+        Size = 255
+      end
+      item
+        Name = 'EndDealTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'EndGatherTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'BGTotalPrice'
+        DataType = ftFloat
+      end
+      item
+        Name = 'DrawingCode'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'ApprovalCode'
+        DataType = ftWideString
+        Size = 50
+      end
+      item
+        Name = 'BGLRelaFile'
+        DataType = ftWideString
+      end
+      item
+        Name = 'MemoStr'
+        DataType = ftWideString
+        Size = 50
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 72
+    Top = 32
+    Data = {
+      0B0200009619E0BD0100000018000000120000000000030000000B0204436F64
+      650100490000000100055749445448020002003200044E616D6502004A000000
+      01000557494454480200020090010C44676E5175616E74697479310800040000
+      0000000C44676E5175616E746974793208000400000000000B44676E5175616E
+      7469747901004900000001000557494454480200020032000B586D6A5F42474C
+      4E616D6502004A00000001000557494454480200020090010742474C436F6465
+      01004A00000001000557494454480200020064000742474C4E616D6501004A00
+      000001000557494454480200020064000742474C5479706501004A0000000100
+      05574944544802000200280006526561736F6E02004A00000001000557494454
+      4802000200FE0109446972656374696F6E02004A000000010005574944544802
+      000200FE0111456E644465616C546F74616C5072696365080004000000000013
+      456E64476174686572546F74616C507269636508000400000000000C4247546F
+      74616C507269636508000400000000000B44726177696E67436F646501004A00
+      000001000557494454480200020064000C417070726F76616C436F646501004A
+      00000001000557494454480200020064000B42474C52656C6146696C6501004A
+      0000000100055749445448020002000100074D656D6F53747201004A00000001
+      000557494454480200020064000000}
+    object cdsXmjBGLDetailCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsXmjBGLDetailName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsXmjBGLDetailDgnQuantity1: TFloatField
+      FieldName = 'DgnQuantity1'
+    end
+    object cdsXmjBGLDetailDgnQuantity2: TFloatField
+      FieldName = 'DgnQuantity2'
+    end
+    object cdsXmjBGLDetailDgnQuantity: TStringField
+      FieldName = 'DgnQuantity'
+      Size = 50
+    end
+    object cdsXmjBGLDetailXmj_BGLName: TWideStringField
+      FieldName = 'Xmj_BGLName'
+      Size = 200
+    end
+    object cdsXmjBGLDetailBGLCode: TWideStringField
+      FieldName = 'BGLCode'
+      Size = 50
+    end
+    object cdsXmjBGLDetailBGLName: TWideStringField
+      FieldName = 'BGLName'
+      Size = 50
+    end
+    object cdsXmjBGLDetailBGLType: TWideStringField
+      FieldName = 'BGLType'
+    end
+    object cdsXmjBGLDetailReason: TWideStringField
+      FieldName = 'Reason'
+      Size = 255
+    end
+    object cdsXmjBGLDetailDirection: TWideStringField
+      FieldName = 'Direction'
+      Size = 255
+    end
+    object cdsXmjBGLDetailEndDealTotalPrice: TFloatField
+      FieldName = 'EndDealTotalPrice'
+    end
+    object cdsXmjBGLDetailEndGatherTotalPrice: TFloatField
+      FieldName = 'EndGatherTotalPrice'
+    end
+    object cdsXmjBGLDetailBGTotalPrice: TFloatField
+      FieldName = 'BGTotalPrice'
+    end
+    object cdsXmjBGLDetailDrawingCode: TWideStringField
+      FieldName = 'DrawingCode'
+      Size = 50
+    end
+    object cdsXmjBGLDetailApprovalCode: TWideStringField
+      FieldName = 'ApprovalCode'
+      Size = 50
+    end
+    object cdsXmjBGLDetailBGLRelaFile: TWideStringField
+      FieldName = 'BGLRelaFile'
+      Size = 0
+    end
+    object cdsXmjBGLDetailMemoStr: TWideStringField
+      FieldName = 'MemoStr'
+      Size = 50
+    end
+  end
+end

+ 422 - 0
DataModules/ReportMemoryDm/rmXmjBGLDetailDm.pas

@@ -0,0 +1,422 @@
+unit rmXmjBGLDetailDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, ProjectData, sdIDTree, sdDB;
+
+type
+  TBGLNode = class
+  private
+    FBGLCode: string;
+    FBGLName: string;
+    FBGLReason: string;
+    FDirection: string;
+    FBGLType: string;
+    FDrawingCode: string;
+    FApprovalCode: string;
+    FBGLRelaFile: string;
+  end;
+
+  TXmjNode = class
+  private
+    FChildList: TList;
+    FBGLList: TList;
+
+    FCode: string;
+    FName: string;
+
+    FDgnQuantity1: Double;
+    FDgnQuantity2: Double;
+
+    FEndDealTotalPrice: Double;
+    FEndGatherTotalPrice: Double;
+
+    function GetChildCount: Integer;
+    function GetChildNode(AIndex: Integer): TXmjNode;
+    function GetBGLCount: Integer;
+    function GetBGLNode(AIndex: Integer): TBGLNode;
+  public
+    constructor Create;
+    destructor Destroy; override;
+
+    function FindBGLNode(const ABGLCode: string): TBGLNode;
+
+    property ChildCount: Integer read GetChildCount;
+    property ChildNode[AIndex: Integer]: TXmjNode read GetChildNode;
+    property BGLCount: Integer read GetBGLCount;
+    property BGLNode[AIndex: Integer]: TBGLNode read GetBGLNode;
+  end;
+
+  TrmXmjBGLDetailData = class(TDataModule)
+    cdsXmjBGLDetail: TClientDataSet;
+    cdsXmjBGLDetailCode: TStringField;
+    cdsXmjBGLDetailName: TWideStringField;
+    cdsXmjBGLDetailDgnQuantity1: TFloatField;
+    cdsXmjBGLDetailDgnQuantity2: TFloatField;
+    cdsXmjBGLDetailDgnQuantity: TStringField;
+    cdsXmjBGLDetailXmj_BGLName: TWideStringField;
+    cdsXmjBGLDetailBGLCode: TWideStringField;
+    cdsXmjBGLDetailBGLName: TWideStringField;
+    cdsXmjBGLDetailBGLType: TWideStringField;
+    cdsXmjBGLDetailReason: TWideStringField;
+    cdsXmjBGLDetailDirection: TWideStringField;
+    cdsXmjBGLDetailEndDealTotalPrice: TFloatField;
+    cdsXmjBGLDetailEndGatherTotalPrice: TFloatField;
+    cdsXmjBGLDetailBGTotalPrice: TFloatField;
+    cdsXmjBGLDetailDrawingCode: TWideStringField;
+    cdsXmjBGLDetailApprovalCode: TWideStringField;
+    cdsXmjBGLDetailBGLRelaFile: TWideStringField;
+    cdsXmjBGLDetailMemoStr: TWideStringField;
+  private
+    FProjectData: TProjectData;
+    FClassXmjList: TList;
+
+    function GetDgnQuantity(ANum1, ANum2: Double): string;
+
+    procedure AddBGL(ABGLCode: string; AClassNode: TXmjNode);
+    procedure AddBGLsData(ABGLCode: string; AClassNode: TXmjNode);
+    procedure FilterNodeBGLData(ANode: TsdIDTreeNode; AClassNode: TXmjNode);
+    procedure FilterBGLData(ANode: TsdIDTreeNode; AClassNode: TXmjNode);
+
+    procedure AddDetailXmjNode(ANode: TsdIDTreeNode; AClassNode: TXmjNode);
+    function CheckLeafXmj(ANode: TsdIDTreeNode): Boolean;
+    function CheckHasBGL(ANode: TsdIDTreeNode): Boolean;
+    procedure FilterDetailNode(ANode: TsdIDTreeNode; AClassNode: TXmjNode);
+
+    procedure AddClassXmjNode(ANode: TsdIDTreeNode);
+    function CheckChildNodeHasBGL(ANode: TsdIDTreeNode): Boolean;
+    procedure FilterNode(ANode: TsdIDTreeNode);
+
+    procedure WriteBGLNodeData(ABGLNode: TBGLNode);
+    procedure WriteXmjNodeData(AXmjNode: TXmjNode; AIndex: Integer = -1);
+    procedure WriteData;
+  public
+    function AssignData(AProjectData: TProjectData): TDataSet;
+  end;
+
+implementation
+
+uses
+  ZhAPI, DateUtils, BGLDm;
+
+{$R *.dfm}
+
+{ TrmXmjBGLDetailData }
+
+procedure TrmXmjBGLDetailData.AddBGL(ABGLCode: string;
+  AClassNode: TXmjNode);
+var
+  BGLNode: TBGLNode;
+begin
+  BGLNode := AClassNode.FindBGLNode(ABGLCode);
+  if not Assigned(BGLNode) then
+  begin
+    BGLNode := TBGLNode.Create;
+    BGLNode.FBGLCode := ABGLCode;
+    with FProjectData.BGLData do
+    begin
+      if cdsBGL.Locate('Code', ABGLCode, []) then
+      begin
+        BGLNode.FBGLName := cdsBGLName.AsString;
+        BGLNode.FBGLReason := cdsBGLPos_Reason.AsString;
+        BGLNode.FDirection := cdsBGLDirection.AsString;
+        BGLNode.FBGLType := '';
+        BGLNode.FDrawingCode := cdsBGLDrawingCode.AsString;
+        BGLNode.FApprovalCode := cdsBGLApprovalCode.AsString;
+        BGLNode.FBGLRelaFile := '';
+      end;
+    end;
+    AClassNode.FBGLList.Add(BGLNode);
+  end;
+end;
+
+procedure TrmXmjBGLDetailData.AddBGLsData(ABGLCode: string;
+  AClassNode: TXmjNode);
+var
+  sgs: TStrings;
+  i: Integer;
+begin
+  if ABGLCode = '' then Exit;
+  sgs := TStringList.Create;
+  try
+    sgs.Delimiter := ';';
+    sgs.DelimitedText := ABGLCode;
+    for i := 0 to sgs.Count - 1 do
+      AddBGL(sgs.Strings[i], AClassNode);
+  finally
+    sgs.Free;
+  end;
+end;
+
+procedure TrmXmjBGLDetailData.AddClassXmjNode(ANode: TsdIDTreeNode);
+var
+  XmjNode: TXmjNode;
+begin
+  if not Assigned(ANode) then Exit;
+  XmjNode := TXmjNode.Create;
+  FClassXmjList.Add(XmjNode);
+  XmjNode.FCode := ANode.Rec.ValueByName('Code').AsString;
+  XmjNode.FName := ANode.Rec.ValueByName('Name').AsString;
+  XmjNode.FDgnQuantity1 := ANode.Rec.ValueByName('DgnQuantity1').AsFloat;
+  FilterDetailNode(ANode, XmjNode);
+end;
+
+procedure TrmXmjBGLDetailData.AddDetailXmjNode(ANode: TsdIDTreeNode;
+  AClassNode: TXmjNode);
+var
+  DetailNode: TXmjNode;
+  StageRec: TsdDataRecord;
+begin
+  DetailNode := TXmjNode.Create;
+  AClassNode.FChildList.Add(DetailNode);
+  DetailNode.FName := ANode.Rec.ValueByName('Name').AsString;
+  DetailNode.FDgnQuantity1 := ANode.Rec.ValueByName('DgnQuantity1').AsFloat;
+  DetailNode.FDgnQuantity2 := ANode.Rec.ValueByName('DgnQuantity2').AsFloat;
+  if FProjectData.PhaseData.Active then
+  begin
+    StageRec := FProjectData.PhaseData.StageData.StageRecord(ANode.ID);
+    if Assigned(StageRec) then
+    begin
+      DetailNode.FEndDealTotalPrice := StageRec.ValueByName('EndDealTotalPrice').AsFloat;
+      DetailNode.FEndGatherTotalPrice := StageRec.ValueByName('EndGatherTotalPrice').AsFloat;
+    end;
+  end;
+  FilterBGLData(ANode, DetailNode);
+end;
+
+function TrmXmjBGLDetailData.AssignData(
+  AProjectData: TProjectData): TDataSet;
+begin
+  FProjectData := AProjectData;
+  FClassXmjList := TList.Create;
+  cdsXmjBGLDetail.Active := True;
+  cdsXmjBGLDetail.EmptyDataSet;
+  cdsXmjBGLDetail.DisableControls;
+  try
+    FilterNode(AProjectData.BillsCompileData.BillsCompileTree.FirstNode);
+    WriteData;
+  finally
+    cdsXmjBGLDetail.EnableControls;
+    Result := cdsXmjBGLDetail;
+    ClearObjects(FClassXmjList);
+    FClassXmjList.Free;
+  end;
+end;
+
+function TrmXmjBGLDetailData.CheckChildNodeHasBGL(
+  ANode: TsdIDTreeNode): Boolean;
+var
+  iNext, iTotal: Integer;
+  vChild: TsdIDTreeNode;
+begin
+  Result := False;
+  if not Assigned(ANode) then Exit;
+  iNext := 1;
+  iTotal := ANode.PosterityCount;
+  vChild := ANode.NextNode;
+  while (iNext <= iTotal) and not Result do
+  begin
+    if not vChild.HasChildren then
+      Result := CheckHasBGL(vChild);
+    vChild := vChild.NextNode;
+    Inc(iNext);
+  end;
+end;
+
+function TrmXmjBGLDetailData.CheckHasBGL(ANode: TsdIDTreeNode): Boolean;
+var
+  StageRec: TsdDataRecord;
+begin
+  Result := False;
+  StageRec := FProjectData.PhaseData.StageData.StageRecord(ANode.ID);
+  if Assigned(StageRec) then
+    Result := (StageRec.ValueByName('EndQcTotalPrice').AsFloat <> 0)
+           or (StageRec.ValueByName('EndPcTotalPrice').AsFloat <> 0);
+end;
+
+function TrmXmjBGLDetailData.CheckLeafXmj(ANode: TsdIDTreeNode): Boolean;
+var
+  i: Integer;
+begin
+  Result := True;
+  for i := 0 to ANode.ChildCount - 1 do
+  begin
+    if ANode.ChildNodes[i].Rec.ValueByName('B_Code').AsString = '' then
+    begin
+      Result := False;
+      Break;
+    end;
+  end;
+end;
+
+procedure TrmXmjBGLDetailData.FilterBGLData(ANode: TsdIDTreeNode;
+  AClassNode: TXmjNode);
+var
+  i: Integer;
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    for i := 0 to ANode.ChildCount - 1 do
+      FilterBGLData(ANode.ChildNodes[i], AClassNode)
+  else
+    FilterNodeBGLData(ANode, AClassNode);
+end;
+
+procedure TrmXmjBGLDetailData.FilterDetailNode(ANode: TsdIDTreeNode;
+  AClassNode: TXmjNode);
+var
+  i: Integer;
+begin
+  if not Assigned(ANode) and (ANode.Level < 2) then Exit;
+  if ANode.Rec.ValueByName('B_Code').AsString <> '' then Exit;
+
+  if CheckLeafXmj(ANode) and CheckHasBGL(ANode) then
+    AddDetailXmjNode(ANode, AClassNode);
+
+  if ANode.HasChildren then
+  begin
+    for i := 0 to ANode.ChildCount - 1 do
+      FilterDetailNode(ANode.ChildNodes[i], AClassNode);
+  end;
+end;
+
+procedure TrmXmjBGLDetailData.FilterNode(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.Level> 1 then Exit;
+  if ANode.Level = 0 then
+    FilterNode(ANode.FirstChild)
+  else if CheckHasBGL(ANode) then
+    AddClassXmjNode(ANode);
+  FilterNode(ANode.NextSibling);
+end;
+
+procedure TrmXmjBGLDetailData.FilterNodeBGLData(ANode: TsdIDTreeNode;
+  AClassNode: TXmjNode);
+var
+  StageRec: TsdDataRecord;
+begin
+  StageRec := FProjectData.PhaseData.StageData.StageRecord(ANode.ID);
+  if not Assigned(StageRec) then Exit;
+  AddBGLsData(StageRec.ValueByName('EndQcBGLCode').AsString, AClassNode);
+  AddBGLsData(StageRec.ValueByName('EndPcBGLCode').AsString, AClassNode);
+end;
+
+function TrmXmjBGLDetailData.GetDgnQuantity(ANum1, ANum2: Double): string;
+begin
+  Result := '';
+  if ANum1 <> 0 then
+  begin
+    Result := FloatToStr(ANum1);
+    if ANum2 <> 0 then
+      Result := Result + '/' + FloatToStr(ANum2);
+  end;
+end;
+
+procedure TrmXmjBGLDetailData.WriteBGLNodeData(ABGLNode: TBGLNode);
+begin
+  cdsXmjBGLDetail.Append;
+  cdsXmjBGLDetailXmj_BGLName.AsString := ABGLNode.FBGLName;
+
+  cdsXmjBGLDetailBGLCode.AsString := ABGLNode.FBGLCode;
+  cdsXmjBGLDetailBGLName.AsString := ABGLNode.FBGLName;
+
+  cdsXmjBGLDetailReason.AsString := ABGLNode.FBGLReason;
+  cdsXmjBGLDetailDirection.AsString := ABGLNode.FDirection;
+
+  cdsXmjBGLDetailDrawingCode.AsString := ABGLNode.FDrawingCode;
+  cdsXmjBGLDetailApprovalCode.AsString := ABGLNode.FApprovalCode;
+  cdsXmjBGLDetailBGLRelaFile.AsString := ABGLNode.FBGLRelaFile;
+  cdsXmjBGLDetail.Post;
+end;
+
+procedure TrmXmjBGLDetailData.WriteData;
+var
+  i: Integer;
+begin
+  for i := 0 to FClassXmjList.Count - 1 do
+    WriteXmjNodeData(TXmjNode(FClassXmjList.Items[i]));
+end;
+
+procedure TrmXmjBGLDetailData.WriteXmjNodeData(AXmjNode: TXmjNode;
+  AIndex: Integer);
+var
+  i: Integer;
+begin
+  cdsXmjBGLDetail.Append;
+  if AIndex = -1 then
+    cdsXmjBGLDetailCode.AsString := AXmjNode.FCode
+  else
+    cdsXmjBGLDetailCode.AsString := IntToStr(AIndex + 1);
+  cdsXmjBGLDetailName.AsString := AXmjNode.FName;
+
+  cdsXmjBGLDetailDgnQuantity1.AsFloat := AXmjNode.FDgnQuantity1;
+  cdsXmjBGLDetailDgnQuantity2.AsFloat := AXmjNode.FDgnQuantity2;
+  cdsXmjBGLDetailDgnQuantity.AsString := GetDgnQuantity(AXmjNode.FDgnQuantity1, AXmjNode.FDgnQuantity2);
+
+  cdsXmjBGLDetailEndDealTotalPrice.AsFloat := AXmjNode.FEndDealTotalPrice;
+  cdsXmjBGLDetailEndGatherTotalPrice.AsFloat := AXmjNode.FEndGatherTotalPrice;
+  cdsXmjBGLDetailBGTotalPrice.AsFloat := AXmjNode.FEndGatherTotalPrice - AXmjNode.FEndDealTotalPrice;
+
+  cdsXmjBGLDetailXmj_BGLName.AsString := AXmjNode.FName;
+  cdsXmjBGLDetail.Post;
+  for i := 0 to AXmjNode.BGLCount - 1 do
+    WriteBGLNodeData(AXmjNode.BGLNode[i]);
+  for i := 0 to AXmjNode.ChildCount - 1 do
+    WriteXmjNodeData(AXmjNode.ChildNode[i], i);
+end;
+
+{ TXmjNode }
+
+constructor TXmjNode.Create;
+begin
+  FChildList := TList.Create;
+  FBGLList := TList.Create;
+end;
+
+destructor TXmjNode.Destroy;
+begin
+  ClearObjects(FBGLList);
+  FBGLList.Free;
+  ClearObjects(FChildList);
+  FChildList.Free;
+  inherited;
+end;
+
+function TXmjNode.FindBGLNode(const ABGLCode: string): TBGLNode;
+var
+  i: Integer;
+begin
+  Result := nil;
+  for i := 0 to BGLCount - 1 do
+  begin
+    if BGLNode[i].FBGLCode = ABGLCode then
+    begin
+      Result := BGLNode[i];
+      Break;
+    end;
+  end;
+end;
+
+function TXmjNode.GetBGLCount: Integer;
+begin
+  Result := FBGLList.Count;
+end;
+
+function TXmjNode.GetBGLNode(AIndex: Integer): TBGLNode;
+begin
+  Result := TBGLNode(FBGLList.Items[AIndex]);
+end;
+
+function TXmjNode.GetChildCount: Integer;
+begin
+  Result := FChildList.Count;
+end;
+
+function TXmjNode.GetChildNode(AIndex: Integer): TXmjNode;
+begin
+  Result := TXmjNode(FChildList.Items[AIndex]);
+end;
+
+end.

+ 106 - 0
DataModules/SearchDm.dfm

@@ -0,0 +1,106 @@
+object SearchData: TSearchData
+  OldCreateOrder = False
+  Left = 530
+  Top = 323
+  Height = 150
+  Width = 215
+  object cdsSearch: TClientDataSet
+    Active = True
+    Aggregates = <>
+    FieldDefs = <
+      item
+        Name = 'ID'
+        DataType = ftInteger
+      end
+      item
+        Name = 'Code'
+        DataType = ftString
+        Size = 50
+      end
+      item
+        Name = 'B_Code'
+        DataType = ftString
+        Size = 20
+      end
+      item
+        Name = 'Name'
+        DataType = ftWideString
+        Size = 200
+      end
+      item
+        Name = 'Units'
+        DataType = ftWideString
+        Size = 20
+      end
+      item
+        Name = 'Price'
+        DataType = ftFloat
+      end
+      item
+        Name = 'Quantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CurQcQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'AddGatherQuantity'
+        DataType = ftFloat
+      end
+      item
+        Name = 'CompleteRate'
+        DataType = ftFloat
+      end>
+    IndexDefs = <>
+    Params = <>
+    StoreDefs = True
+    Left = 64
+    Top = 32
+    Data = {
+      F00000009619E0BD01000000180000000A000000000003000000F00002494404
+      0001000000000004436F64650100490000000100055749445448020002003200
+      06425F436F64650100490000000100055749445448020002001400044E616D65
+      02004A000000010005574944544802000200900105556E69747301004A000000
+      0100055749445448020002002800055072696365080004000000000008517561
+      6E7469747908000400000000000D43757251635175616E746974790800040000
+      000000114164644761746865725175616E7469747908000400000000000C436F
+      6D706C6574655261746508000400000000000000}
+    object cdsSearchID: TIntegerField
+      FieldName = 'ID'
+    end
+    object cdsSearchCode: TStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsSearchB_Code: TStringField
+      FieldName = 'B_Code'
+    end
+    object cdsSearchName: TWideStringField
+      FieldName = 'Name'
+      Size = 200
+    end
+    object cdsSearchUnits: TWideStringField
+      FieldName = 'Units'
+    end
+    object cdsSearchPrice: TFloatField
+      FieldName = 'Price'
+      OnGetText = cdsSearchQuantityGetText
+    end
+    object cdsSearchQuantity: TFloatField
+      FieldName = 'Quantity'
+      OnGetText = cdsSearchQuantityGetText
+    end
+    object cdsSearchCurQcQuantity: TFloatField
+      FieldName = 'CurQcQuantity'
+      OnGetText = cdsSearchQuantityGetText
+    end
+    object cdsSearchAddGatherQuantity: TFloatField
+      FieldName = 'AddGatherQuantity'
+      OnGetText = cdsSearchQuantityGetText
+    end
+    object cdsSearchCompleteRate: TFloatField
+      FieldName = 'CompleteRate'
+    end
+  end
+end

+ 243 - 0
DataModules/SearchDm.pas

@@ -0,0 +1,243 @@
+unit SearchDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, sdIDTree, sdDB;
+
+type
+  TLocateType = (ltCompile, ltMeasure);
+
+  TSearchData = class(TDataModule)
+    cdsSearch: TClientDataSet;
+    cdsSearchCode: TStringField;
+    cdsSearchB_Code: TStringField;
+    cdsSearchName: TWideStringField;
+    cdsSearchUnits: TWideStringField;
+    cdsSearchQuantity: TFloatField;
+    cdsSearchAddGatherQuantity: TFloatField;
+    cdsSearchID: TIntegerField;
+    cdsSearchCurQcQuantity: TFloatField;
+    cdsSearchPrice: TFloatField;
+    cdsSearchCompleteRate: TFloatField;
+    procedure cdsSearchQuantityGetText(Sender: TField; var Text: String;
+      DisplayText: Boolean);
+  private
+    FProjectData: TObject;
+
+    procedure BeginSearch;
+    procedure EndSearch;
+
+    procedure AddSearchResult(Rec, StageRec: TsdDataRecord);
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure SearchKeyword(const AKeyword: string);
+    procedure SearchOverRange;
+    procedure SearchBelowRange;
+
+    procedure LocateCurrent(ALocateType: TLocateType);
+
+    property ProjectData: TObject read FProjectData;
+  end;
+
+implementation
+
+uses
+  ProjectData, BillsMeasureDm, BillsCompileDm, Math, ZhAPI;
+
+{$R *.dfm}
+
+{ TSearchData }
+
+procedure TSearchData.AddSearchResult(Rec, StageRec: TsdDataRecord);
+begin
+  cdsSearch.Append;
+  cdsSearchID.AsInteger := Rec.ValueByName('ID').AsInteger;
+  cdsSearchCode.AsString := Rec.ValueByName('Code').AsString;
+  cdsSearchB_Code.AsString := Rec.ValueByName('B_Code').AsString;
+  cdsSearchName.AsString := Rec.ValueByName('Name').AsString;
+  cdsSearchUnits.AsString := Rec.ValueByName('Units').AsString;
+  cdsSearchPrice.AsFloat := Rec.ValueByName('Price').AsFloat;
+  cdsSearchQuantity.AsString := Rec.ValueByName('Quantity').AsString;
+  if Assigned(StageRec) then
+    cdsSearchCurQcQuantity.AsFloat := StageRec.ValueByName('QcQuantity').AsFloat;
+  cdsSearchAddGatherQuantity.AsString := Rec.ValueByName('AddGatherQuantity').AsString;
+  if cdsSearchQuantity.AsFloat <> 0 then
+    cdsSearchCompleteRate.AsFloat := advRoundTo(
+        Rec.ValueByName('AddDealQuantity').AsFloat/cdsSearchQuantity.AsFloat*100);
+  cdsSearch.Post;
+end;
+
+procedure TSearchData.BeginSearch;
+begin
+  cdsSearch.DisableControls;
+end;
+
+constructor TSearchData.Create(AProjectData: TObject);
+begin
+  inherited Create(nil);
+  FProjectData := AProjectData;
+end;
+
+destructor TSearchData.Destroy;
+begin
+  inherited;
+end;
+
+procedure TSearchData.EndSearch;
+begin
+  cdsSearch.EnableControls;
+end;
+
+procedure TSearchData.LocateCurrent(ALocateType: TLocateType);
+
+  procedure LocateCompile;
+  var
+    stnNode: TsdIDTreeNode;
+  begin
+    with TProjectData(FProjectData).BillsCompileData do
+    begin
+      stnNode := BillsCompileTree.FindNode(cdsSearchID.AsInteger);
+      sdvBillsCompile.LocateInControl(stnNode.Rec);
+    end;
+  end;
+
+  procedure LocateMeasure;
+  var
+    stnNode: TsdIDTreeNode;
+  begin
+    with TProjectData(FProjectData).BillsMeasureData do
+    begin
+      stnNode := BillsMeasureTree.FindNode(cdsSearchID.AsInteger);
+      sdvBillsMeasure.LocateInControl(stnNode.Rec);
+    end;
+  end;
+
+begin
+  if ALocateType = ltCompile then
+    LocateCompile
+  else if ALocateType = ltMeasure then
+    LocateMeasure;
+end;
+
+procedure TSearchData.SearchKeyword(const AKeyword: string);
+
+  procedure CheckKeyword(ANode: TsdIDTreeNode);
+  var
+    Rec, StageRec: TsdDataRecord;
+  begin
+    Rec := ANode.Rec;
+    StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ANode.ID);
+    // Task 꼇꿴璂淃커쌘,쏭꿴璂묏넋좆헌데
+    if {(Pos(AKeyword, Rec.ValueByName('Code').AsString) > 0) or}
+        (Pos(AKeyword, Rec.ValueByName('B_Code').AsString) > 0) or
+        (Pos(AKeyword, Rec.ValueByName('Name').AsString) > 0) then
+    begin
+      AddSearchResult(Rec, StageRec);
+    end;
+  end;
+
+  procedure RecursiveSearchKeyword(ANode: TsdIDTreeNode);
+  begin
+    if not Assigned(ANode) then Exit;
+    CheckKeyword(ANode);
+    if ANode.HasChildren then
+      RecursiveSearchKeyword(ANode.FirstChild);
+    RecursiveSearchKeyword(ANode.NextSibling);
+  end;
+
+begin
+  if AKeyword = '' then Exit;
+  BeginSearch;
+  try
+    cdsSearch.EmptyDataSet;
+    with TProjectData(FProjectData).BillsMeasureData do
+      RecursiveSearchKeyword(BillsMeasureTree.FirstNode);
+  finally
+    EndSearch;
+  end;
+end;
+
+procedure TSearchData.SearchOverRange;
+
+  procedure CheckOverRange(ANode: TsdIDTreeNode);
+  var
+    Rec, StageRec: TsdDataRecord;
+  begin
+    Rec := ANode.Rec;
+    StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ANode.ID);
+    if Rec.ValueByName('Quantity').AsFloat < Rec.ValueByName('AddDealQuantity').AsFloat then
+    begin
+      AddSearchResult(Rec, StageRec)
+    end;
+  end;
+
+  procedure RecursiveSearchOverRange(ANode: TsdIDTreeNode);
+  begin
+    if not Assigned(ANode) then Exit;
+    if ANode.HasChildren then
+      RecursiveSearchOverRange(ANode.FirstChild)
+    else
+      CheckOverRange(ANode);
+    RecursiveSearchOverRange(ANode.NextSibling);
+  end;
+
+begin
+  BeginSearch;
+  try
+    cdsSearch.EmptyDataSet;
+    with TProjectData(FProjectData).BillsMeasureData do
+      RecursiveSearchOverRange(BillsMeasureTree.FirstNode);
+  finally
+    EndSearch;
+  end;
+end;
+
+procedure TSearchData.cdsSearchQuantityGetText(Sender: TField;
+  var Text: String; DisplayText: Boolean);
+begin
+  if Sender.AsFloat = 0 then
+    Text := ''
+  else
+    Text := Sender.AsString;
+end;
+
+procedure TSearchData.SearchBelowRange;
+
+  procedure CheckBelowRange(ANode: TsdIDTreeNode);
+  var
+    Rec, StageRec: TsdDataRecord;
+  begin
+    Rec := ANode.Rec;
+    if Rec.ValueByName('Quantity').AsFloat = 0 then Exit;
+    StageRec := TProjectData(FProjectData).PhaseData.StageData.StageRecord(ANode.ID);
+    if Rec.ValueByName('Quantity').AsFloat > Rec.ValueByName('AddDealQuantity').AsFloat then
+    begin
+      AddSearchResult(Rec, StageRec)
+    end;
+  end;
+
+  procedure RecursiveSearchBelowRange(ANode: TsdIDTreeNode);
+  begin
+    if not Assigned(ANode) then Exit;
+    if ANode.HasChildren then
+      RecursiveSearchBelowRange(ANode.FirstChild)
+    else
+      CheckBelowRange(ANode);
+    RecursiveSearchBelowRange(ANode.NextSibling);
+  end;
+
+begin
+  BeginSearch;
+  try
+    cdsSearch.EmptyDataSet;
+    with TProjectData(FProjectData).BillsMeasureData do
+      RecursiveSearchBelowRange(BillsMeasureTree.FirstNode);
+  finally
+    EndSearch;
+  end;
+end;
+
+end.

+ 104 - 0
DataModules/StaffDm.dfm

@@ -0,0 +1,104 @@
+object StaffData: TStaffData
+  OldCreateOrder = False
+  Left = 503
+  Top = 424
+  Height = 272
+  Width = 267
+  object atStaff: TADOTable
+    TableName = 'Staff'
+    Left = 40
+    Top = 16
+  end
+  object dspStaff: TDataSetProvider
+    DataSet = atStaff
+    UpdateMode = upWhereKeyOnly
+    Left = 40
+    Top = 80
+  end
+  object cdsStaff: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    ProviderName = 'dspStaff'
+    Left = 40
+    Top = 144
+    object cdsStaffPhaseID: TIntegerField
+      FieldName = 'PhaseID'
+    end
+    object cdsStaffStageID: TIntegerField
+      FieldName = 'StageID'
+    end
+    object cdsStaffCompany: TWideStringField
+      FieldName = 'Company'
+      Size = 50
+    end
+    object cdsStaffRole: TWideStringField
+      FieldName = 'Role'
+    end
+    object cdsStaffName: TWideStringField
+      FieldName = 'Name'
+    end
+    object cdsStaffLocked: TBooleanField
+      FieldName = 'Locked'
+    end
+    object cdsStaffEnable: TBooleanField
+      FieldName = 'Enable'
+    end
+  end
+  object cdsStaffView: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    Left = 112
+    Top = 144
+    object cdsStaffViewPhaseID: TIntegerField
+      FieldName = 'PhaseID'
+    end
+    object cdsStaffViewStageID: TIntegerField
+      FieldName = 'StageID'
+      OnGetText = cdsStaffViewStageIDGetText
+    end
+    object cdsStaffViewCompany: TWideStringField
+      FieldName = 'Company'
+      Size = 50
+    end
+    object cdsStaffViewRole: TWideStringField
+      FieldName = 'Role'
+    end
+    object cdsStaffViewName: TWideStringField
+      FieldName = 'Name'
+    end
+    object cdsStaffViewLocked: TBooleanField
+      FieldName = 'Locked'
+    end
+    object cdsStaffViewEnable: TBooleanField
+      FieldName = 'Enable'
+    end
+  end
+  object cdsStaffUpdate: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    Left = 192
+    Top = 144
+    object cdsStaffUpdatePhaseID: TIntegerField
+      FieldName = 'PhaseID'
+    end
+    object cdsStaffUpdateStageID: TIntegerField
+      FieldName = 'StageID'
+    end
+    object cdsStaffUpdateCompany: TWideStringField
+      FieldName = 'Company'
+      Size = 50
+    end
+    object cdsStaffUpdateRole: TWideStringField
+      FieldName = 'Role'
+    end
+    object cdsStaffUpdateName: TWideStringField
+      FieldName = 'Name'
+    end
+    object cdsStaffUpdateLocked: TBooleanField
+      FieldName = 'Locked'
+    end
+    object cdsStaffUpdateEnable: TBooleanField
+      FieldName = 'Enable'
+    end
+  end
+end

+ 201 - 0
DataModules/StaffDm.pas

@@ -0,0 +1,201 @@
+unit StaffDm;
+
+interface
+
+uses
+  SysUtils, Classes, DB, DBClient, Provider, ADODB;
+
+type
+  TStaffData = class(TDataModule)
+    atStaff: TADOTable;
+    dspStaff: TDataSetProvider;
+    cdsStaff: TClientDataSet;
+    cdsStaffPhaseID: TIntegerField;
+    cdsStaffStageID: TIntegerField;
+    cdsStaffCompany: TWideStringField;
+    cdsStaffRole: TWideStringField;
+    cdsStaffName: TWideStringField;
+    cdsStaffLocked: TBooleanField;
+    cdsStaffView: TClientDataSet;
+    cdsStaffViewPhaseID: TIntegerField;
+    cdsStaffViewStageID: TIntegerField;
+    cdsStaffViewCompany: TWideStringField;
+    cdsStaffViewRole: TWideStringField;
+    cdsStaffViewName: TWideStringField;
+    cdsStaffViewLocked: TBooleanField;
+    cdsStaffUpdate: TClientDataSet;
+    cdsStaffUpdatePhaseID: TIntegerField;
+    cdsStaffUpdateStageID: TIntegerField;
+    cdsStaffUpdateCompany: TWideStringField;
+    cdsStaffUpdateRole: TWideStringField;
+    cdsStaffUpdateName: TWideStringField;
+    cdsStaffUpdateLocked: TBooleanField;
+    cdsStaffEnable: TBooleanField;
+    cdsStaffViewEnable: TBooleanField;
+    cdsStaffUpdateEnable: TBooleanField;
+    procedure cdsStaffViewStageIDGetText(Sender: TField; var Text: String;
+      DisplayText: Boolean);
+  private
+    FProjectData: TObject;
+    procedure InitStaffData(APhaseIndex: Integer);
+    procedure CopyStaffData(APhaseIndex, AStageIndex: Integer);
+  public
+    constructor Create(AProjectData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Close;
+    procedure Save;
+
+    procedure UpdateDataForNewPhase;
+    procedure UpdateDataForNewAudit;
+    procedure LockedDataForAudit;
+    procedure LockedDataForReply;
+    procedure ResetViewFilter(APhaseIndex: Integer);
+
+    function FinalStaffCompany: string;
+  end;
+
+implementation
+
+uses
+  ProjectData;
+
+{$R *.dfm}
+
+{ TStaffData }
+
+constructor TStaffData.Create(AProjectData: TObject);
+begin
+  FProjectData := AProjectData;
+  inherited Create(nil);
+end;
+
+destructor TStaffData.Destroy;
+begin
+  inherited;
+end;
+
+procedure TStaffData.InitStaffData(APhaseIndex: Integer);
+var
+  iStage: Integer;
+begin
+  for iStage := 0 to 9 do
+  begin
+    cdsStaff.Append;
+    cdsStaffPhaseID.AsInteger := APhaseIndex;
+    cdsStaffStageID.AsInteger := iStage;
+    cdsStaffLocked.AsBoolean := False;
+    cdsStaffEnable.AsBoolean := iStage = 0;
+    cdsStaff.Post;
+  end;
+end;
+
+procedure TStaffData.Open(AConnection: TADOConnection);
+begin
+  atStaff.Connection := AConnection;
+  cdsStaff.Open;
+  cdsStaff.IndexFieldNames := 'PhaseID;StageID';
+  cdsStaffView.CloneCursor(cdsStaff, True);
+  cdsStaffUpdate.CloneCursor(cdsStaff, True);
+end;
+
+procedure TStaffData.ResetViewFilter(APhaseIndex: Integer);
+begin
+  cdsStaffView.DisableControls;
+  try
+    cdsStaffView.Filtered := False;
+    cdsStaffView.Filter := 'PhaseID = ' + IntToStr(APhaseIndex);
+    cdsStaffView.Filtered := True;
+  finally
+    cdsStaffView.EnableControls;
+  end;
+end;
+
+procedure TStaffData.Save;
+begin
+  cdsStaff.ApplyUpdates(0);
+end;
+
+procedure TStaffData.UpdateDataForNewPhase;
+var
+  iPhaseCount: Integer;
+begin
+  iPhaseCount := TProjectData(FProjectData).ProjProperties.PhaseCount;
+  InitStaffData(iPhaseCount);
+  CopyStaffData(iPhaseCount, 0);
+end;
+
+procedure TStaffData.cdsStaffViewStageIDGetText(Sender: TField;
+  var Text: String; DisplayText: Boolean);
+begin
+  if Sender.AsInteger = 0 then
+    Text := 'Ô­±¨'
+  else if Sender.AsInteger > 0 then
+    Text := Format('%dÉó', [Sender.AsInteger]);
+end;
+
+procedure TStaffData.UpdateDataForNewAudit;
+begin
+  with TProjectData(FProjectData) do
+    CopyStaffData(PhaseIndex, ProjProperties.AuditStatus);
+end;
+
+procedure TStaffData.LockedDataForAudit;
+begin
+  with TProjectData(FProjectData) do
+    if cdsStaff.FindKey([PhaseIndex, ProjProperties.AuditStatus]) then
+    begin
+      cdsStaff.Edit;
+      cdsStaffLocked.AsBoolean := True;
+      cdsStaff.Post;
+    end;
+end;
+
+procedure TStaffData.LockedDataForReply;
+begin
+  cdsStaff.Filter := 'PhaseID = ' + IntToStr(TProjectData(FProjectData).PhaseIndex);
+  cdsStaff.Filtered := True;
+  try
+    cdsStaff.First;
+    while not cdsStaff.Eof do
+    begin
+      cdsStaff.Edit;
+      cdsStaffLocked.AsBoolean := True;
+      cdsStaff.Post;
+      cdsStaff.Next;
+    end;
+  finally
+    cdsStaff.Filtered := False;
+  end;
+end;
+
+function TStaffData.FinalStaffCompany: string;
+begin
+  with TProjectData(FProjectData) do
+    if cdsStaff.FindKey([PhaseIndex, ProjProperties.AuditStatus]) then
+      Result :=  cdsStaffCompany.AsString;
+end;
+
+procedure TStaffData.CopyStaffData(APhaseIndex, AStageIndex: Integer);
+begin
+  if cdsStaff.FindKey([APhaseIndex, AStageIndex]) then
+  begin
+    cdsStaff.Edit;
+    if cdsStaffUpdate.FindKey([APhaseIndex-1, AStageIndex]) then
+    begin
+      cdsStaffCompany.AsString := cdsStaffUpdateCompany.AsString;
+      cdsStaffRole.AsString := cdsStaffUpdateRole.AsString;
+      cdsStaffName.AsString := cdsStaffUpdateName.AsString;
+    end;
+    cdsStaffEnable.AsBoolean := True;
+    cdsStaff.Post;
+  end;
+end;
+
+procedure TStaffData.Close;
+begin
+  cdsStaff.Close;
+end;
+
+end.

+ 47 - 0
DataModules/StageBookmarkDm.dfm

@@ -0,0 +1,47 @@
+object StageBookmarkData: TStageBookmarkData
+  OldCreateOrder = False
+  Left = 444
+  Top = 345
+  Height = 160
+  Width = 215
+  object sdvStageBookmark: TsdDataView
+    Active = False
+    Filtered = True
+    Columns = <
+      item
+        FieldName = 'BillsID'
+      end
+      item
+        FieldName = 'HasBookmark'
+      end
+      item
+        FieldName = 'MarkMemo'
+      end
+      item
+        FieldName = 'Code'
+        KeyFields = 'BillsID'
+        LookupKeyFields = 'ID'
+        LookupResultField = 'Code'
+      end
+      item
+        FieldName = 'B_Code'
+        KeyFields = 'BillsID'
+        LookupKeyFields = 'ID'
+        LookupResultField = 'Name'
+      end
+      item
+        FieldName = 'Name'
+        KeyFields = 'BillsID'
+        LookupKeyFields = 'ID'
+        LookupResultField = 'Name'
+      end
+      item
+        FieldName = 'Unit'
+        KeyFields = 'BillsID'
+        LookupKeyFields = 'ID'
+        LookupResultField = 'Units'
+      end>
+    Left = 56
+    Top = 48
+  end
+end

+ 21 - 0
DataModules/StageBookmarkDm.pas

@@ -0,0 +1,21 @@
+unit StageBookmarkDm;
+
+interface
+
+uses
+  SysUtils, Classes, sdDB;
+
+type
+  TStageBookmarkData = class(TDataModule)
+    sdvStageBookmark: TsdDataView;
+  private
+
+  public
+    constructor Create(APhase)
+  end;
+
+implementation
+
+{$R *.dfm}
+
+end.

+ 104 - 0
DataModules/StageCompareDm.dfm

@@ -0,0 +1,104 @@
+object StageCompareData: TStageCompareData
+  OldCreateOrder = False
+  Left = 690
+  Top = 294
+  Height = 268
+  Width = 215
+  object sdpStageCompare: TsdADOProvider
+    TableName = 'StageCompare'
+    Left = 72
+    Top = 24
+  end
+  object sddStageCompare: TsdDataSet
+    Active = False
+    Provider = sdpStageCompare
+    Left = 72
+    Top = 96
+    FieldListData = {
+      0101044E616D65060742696C6C734944094669656C644E616D65060742696C6C
+      7349440844617461547970650203084461746153697A6502040549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D6506095175616E7469
+      747930094669656C644E616D6506095175616E74697479300844617461547970
+      650206084461746153697A6502080549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D65060B546F74616C507269636530094669656C64
+      4E616D65060B546F74616C507269636530084461746154797065020608446174
+      6153697A6502080549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D6506095175616E7469747931094669656C644E616D650609517561
+      6E74697479310844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060B546F74
+      616C507269636531094669656C644E616D65060B546F74616C50726963653108
+      44617461547970650206084461746153697A6502080549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D6506095175616E746974793209
+      4669656C644E616D6506095175616E7469747932084461746154797065020608
+      4461746153697A6502080549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D65060B546F74616C507269636532094669656C644E616D65
+      060B546F74616C5072696365320844617461547970650206084461746153697A
+      6502080549734B6579080F4E65656450726F636573734E616D65090001044E61
+      6D6506095175616E7469747933094669656C644E616D6506095175616E746974
+      79330844617461547970650206084461746153697A6502080549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D65060B546F74616C5072
+      69636533094669656C644E616D65060B546F74616C5072696365330844617461
+      547970650206084461746153697A6502080549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D6506095175616E7469747934094669656C
+      644E616D6506095175616E746974793408446174615479706502060844617461
+      53697A6502080549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D65060B546F74616C507269636534094669656C644E616D65060B546F
+      74616C5072696365340844617461547970650206084461746153697A65020805
+      49734B6579080F4E65656450726F636573734E616D65090001044E616D650609
+      5175616E7469747935094669656C644E616D6506095175616E74697479350844
+      617461547970650206084461746153697A6502080549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D65060B546F74616C507269636535
+      094669656C644E616D65060B546F74616C507269636535084461746154797065
+      0206084461746153697A6502080549734B6579080F4E65656450726F63657373
+      4E616D65090001044E616D6506095175616E7469747936094669656C644E616D
+      6506095175616E74697479360844617461547970650206084461746153697A65
+      02080549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      65060B546F74616C507269636536094669656C644E616D65060B546F74616C50
+      72696365360844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D6506095175616E
+      7469747937094669656C644E616D6506095175616E7469747937084461746154
+      7970650206084461746153697A6502080549734B6579080F4E65656450726F63
+      6573734E616D65090001044E616D65060B546F74616C50726963653709466965
+      6C644E616D65060B546F74616C50726963653708446174615479706502060844
+      61746153697A6502080549734B6579080F4E65656450726F636573734E616D65
+      090001044E616D6506095175616E7469747938094669656C644E616D65060951
+      75616E74697479380844617461547970650206084461746153697A6502080549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060B54
+      6F74616C507269636538094669656C644E616D65060B546F74616C5072696365
+      380844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D6506095175616E74697479
+      39094669656C644E616D6506095175616E746974793908446174615479706502
+      06084461746153697A6502080549734B6579080F4E65656450726F636573734E
+      616D65090001044E616D65060B546F74616C507269636539094669656C644E61
+      6D65060B546F74616C5072696365390844617461547970650206084461746153
+      697A6502080549734B6579080F4E65656450726F636573734E616D6509000104
+      4E616D65060A5175616E746974793130094669656C644E616D65060A5175616E
+      7469747931300844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060C546F74
+      616C50726963653130094669656C644E616D65060C546F74616C507269636531
+      300844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D65060A5175616E74697479
+      3131094669656C644E616D65060A5175616E7469747931310844617461547970
+      650206084461746153697A6502080549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D65060C546F74616C50726963653131094669656C
+      644E616D65060C546F74616C5072696365313108446174615479706502060844
+      61746153697A6502080549734B6579080F4E65656450726F636573734E616D65
+      090001044E616D65060A5175616E746974793132094669656C644E616D65060A
+      5175616E7469747931320844617461547970650206084461746153697A650208
+      0549734B6579080F4E65656450726F636573734E616D65090001044E616D6506
+      0C546F74616C50726963653132094669656C644E616D65060C546F74616C5072
+      69636531320844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060A5175616E
+      746974793133094669656C644E616D65060A5175616E74697479313308446174
+      61547970650206084461746153697A6502080549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D65060C546F74616C5072696365313309
+      4669656C644E616D65060C546F74616C50726963653133084461746154797065
+      0206084461746153697A6502080549734B6579080F4E65656450726F63657373
+      4E616D65090001044E616D65060A5175616E746974793134094669656C644E61
+      6D65060A5175616E746974793134084461746154797065020608446174615369
+      7A6502080549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D65060C546F74616C50726963653134094669656C644E616D65060C546F74
+      616C507269636531340844617461547970650206084461746153697A65020805
+      49734B6579080F4E65656450726F636573734E616D65090000}
+  end
+end

+ 160 - 0
DataModules/StageCompareDm.pas

@@ -0,0 +1,160 @@
+unit StageCompareDm;
+{--------------------------------------
+为减少内存占用,项目(当期数据)打开时,该单元不打开
+仅在界面切换至审核比较数据时,更新加载该单元数据,当界面再次切换,应关闭该单元。
+缺陷:每次用户点击切换界面至审核比较时,将消耗较多时间
+--------------------------------------}
+
+interface
+
+uses
+  SysUtils, Classes, sdDB, sdProvider, ADODB;
+
+const
+  TableDeleteSql = 'Drop Table StageCompare';
+
+  TableCreateSql = 'Select BillsID, GatherQuantity As Quantity0, GatherTotalPrice As TotalPrice0,'+
+                   '    GatherQuantity As Quantity1, GatherTotalPrice As TotalPrice1,'+
+                   '    GatherQuantity As Quantity2, GatherTotalPrice As TotalPrice2,'+
+                   '    GatherQuantity As Quantity3, GatherTotalPrice As TotalPrice3,'+
+                   '    GatherQuantity As Quantity4, GatherTotalPrice As TotalPrice4,'+
+                   '    GatherQuantity As Quantity5, GatherTotalPrice As TotalPrice5,'+
+                   '    GatherQuantity As Quantity6, GatherTotalPrice As TotalPrice6,'+
+                   '    GatherQuantity As Quantity7, GatherTotalPrice As TotalPrice7,'+
+                   '    GatherQuantity As Quantity8, GatherTotalPrice As TotalPrice8,'+
+                   '    GatherQuantity As Quantity9, GatherTotalPrice As TotalPrice9,'+
+                   '    GatherQuantity As Quantity10, GatherTotalPrice As TotalPrice10,'+
+                   '    GatherQuantity As Quantity11, GatherTotalPrice As TotalPrice11,'+
+                   '    GatherQuantity As Quantity12, GatherTotalPrice As TotalPrice12,'+
+                   '    GatherQuantity As Quantity13, GatherTotalPrice As TotalPrice13,'+
+                   '    GatherQuantity As Quantity14, GatherTotalPrice As TotalPrice14'+
+                   '  Into StageCompare From Refer Where 1=2';
+
+  KeyCreateSql = 'Alter Table StageCompare Add Constraint PrimaryKey Primary Key (BillsID)';
+
+  InsertSql = 'Insert Into StageCompare (BillsID, Quantity%d, TotalPrice%d)'+
+              '    Select BillsID, GatherQuantity, GatherTotalPrice'+
+              '  From %s';
+
+  UpdateSql = 'Update StageCompare As S, %s As A'+
+              '    Set S.Quantity%d = A.GatherQuantity, S.TotalPrice%d = A.GatherTotalPrice'+
+              '  Where S.BillsID = A.BillsID';
+
+type
+  TStageCompareData = class(TDataModule)
+    sdpStageCompare: TsdADOProvider;
+    sddStageCompare: TsdDataSet;
+  private
+    FPhaseData: TObject;
+
+    function CheckCompareExist: Boolean;
+
+    procedure ExecuteSql(const ASql: string);
+
+    procedure ReloadAllCompareData;
+    procedure InsertLastesyStageData(AIndex: Integer; const ATableName: string);
+    procedure UpdateHistoryStageData(AIndex: Integer; const ATableName: string);
+  public
+    constructor Create(APhaseData: TObject);
+    destructor Destroy; override;
+
+    procedure Open;
+    procedure Close;
+  end;
+
+implementation
+
+uses
+  PhaseData;
+
+{$R *.dfm}
+
+{ TStageCompareData }
+
+function TStageCompareData.CheckCompareExist: Boolean;
+var
+  Tables: TStrings;
+begin
+  Tables := TStringList.Create;
+  try
+    TPhaseData(FPhaseData).ADOConnection.GetTableNames(Tables);
+    Result := Tables.IndexOf('StageCompare') > -1;
+  finally
+    Tables.Free;
+  end;
+end;
+
+procedure TStageCompareData.Close;
+begin
+  sddStageCompare.Close;
+end;
+
+constructor TStageCompareData.Create(APhaseData: TObject);
+begin
+  inherited Create(nil);
+  FPhaseData := APhaseData;
+  sdpStageCompare.Connection :=  TPhaseData(FPhaseData).ADOConnection;
+end;
+
+destructor TStageCompareData.Destroy;
+begin
+  inherited;
+end;
+
+procedure TStageCompareData.ExecuteSql(const ASql: string);
+var
+  FQuery: TADOQuery;
+begin
+  FQuery := TADOQuery.Create(nil);
+  try
+    FQuery.Connection := TPhaseData(FPhaseData).ADOConnection;
+    FQuery.SQL.Clear;
+    FQuery.SQL.Add(ASql);
+    FQuery.ExecSQL;
+  finally
+    FQuery.Free;
+  end;
+end;
+
+procedure TStageCompareData.InsertLastesyStageData(AIndex: Integer;
+  const ATableName: string);
+var
+  sSql: string;
+begin
+  sSql := Format(InsertSql, [AIndex, AIndex, ATableName]);
+  ExecuteSql(sSql);
+end;
+
+procedure TStageCompareData.Open;
+begin
+  ReloadAllCompareData;
+  sddStageCompare.Open;
+end;
+
+procedure TStageCompareData.ReloadAllCompareData;
+var
+  iStage: Integer;
+begin
+  if CheckCompareExist then
+    ExecuteSql(TableDeleteSql);
+  ExecuteSql(TableCreateSql);
+  ExecuteSql(KeyCreateSql);
+  with TPhaseData(FPhaseData) do
+  begin
+    InsertLastesyStageData(AuditCount, StageTableName[AuditCount]);
+    if AuditCount > 0 then
+      for iStage := 0 to AuditCount - 1 do
+        UpdateHistoryStageData(iStage, StageTableName[iStage]);
+  end;
+end;
+
+procedure TStageCompareData.UpdateHistoryStageData(AIndex: Integer;
+  const ATableName: string);
+var
+  sSql: string;
+begin
+  sSql := Format(UpdateSql, [ATableName, AIndex, AIndex]);
+  ExecuteSql(sSql);
+end;
+
+end.

+ 151 - 0
DataModules/StageDm.dfm

@@ -0,0 +1,151 @@
+object StageData: TStageData
+  OldCreateOrder = False
+  Left = 481
+  Top = 334
+  Height = 174
+  Width = 150
+  object sdpStage: TsdADOProvider
+    Left = 48
+    Top = 16
+  end
+  object sddStage: TsdDataSet
+    Active = False
+    Provider = sdpStage
+    BeforeValueChange = sddStageBeforeValueChange
+    AfterValueChanged = sddStageAfterValueChanged
+    OnGetRecordClass = sddStageGetRecordClass
+    Left = 48
+    Top = 72
+    FieldListData = {
+      0101044E616D65060742696C6C734944094669656C644E616D65060742696C6C
+      7349440844617461547970650203084461746153697A6502040549734B657908
+      0F4E65656450726F636573734E616D65090001044E616D65060C4465616C5175
+      616E74697479094669656C644E616D65060C4465616C5175616E746974790844
+      617461547970650206084461746153697A6502080549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D65060E4465616C546F74616C5072
+      696365094669656C644E616D65060E4465616C546F74616C5072696365084461
+      7461547970650206084461746153697A6502080549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D6506084465616C466C616709466965
+      6C644E616D6506084465616C466C616708446174615479706502030844617461
+      53697A6502040549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D65060B4465616C466F726D756C61094669656C644E616D65060B4465
+      616C466F726D756C610844617461547970650201084461746153697A6503FF00
+      0549734B6579080F4E65656450726F636573734E616D65090001044E616D6506
+      0A51635175616E74697479094669656C644E616D65060A51635175616E746974
+      790844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D65060C5163546F74616C50
+      72696365094669656C644E616D65060C5163546F74616C507269636508446174
+      61547970650206084461746153697A6502080549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D6506095163466F726D756C6109466965
+      6C644E616D6506095163466F726D756C61084461746154797065020108446174
+      6153697A6503FF000549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D6506065163466C6167094669656C644E616D6506065163466C61
+      670844617461547970650203084461746153697A6502040549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D650609516342474C436F64
+      65094669656C644E616D650609516342474C436F646508446174615479706502
+      01084461746153697A6503FF000549734B6579080F4E65656450726F63657373
+      4E616D65090001044E616D650608516342474C4E756D094669656C644E616D65
+      0608516342474C4E756D0844617461547970650201084461746153697A6503FF
+      000549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      060A50635175616E74697479094669656C644E616D65060A50635175616E7469
+      74790844617461547970650206084461746153697A6502080549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D65060C5063546F74616C
+      5072696365094669656C644E616D65060C5063546F74616C5072696365084461
+      7461547970650206084461746153697A6502080549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D6506065063466C6167094669656C64
+      4E616D6506065063466C61670844617461547970650203084461746153697A65
+      02040549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      6506095063466F726D756C61094669656C644E616D6506095063466F726D756C
+      610844617461547970650201084461746153697A6503FF000549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D650609506342474C436F
+      6465094669656C644E616D650609506342474C436F6465084461746154797065
+      0201084461746153697A6503FF000549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D650608506342474C4E756D094669656C644E616D
+      650608506342474C4E756D0844617461547970650201084461746153697A6503
+      FF000549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      65060E4761746865725175616E74697479094669656C644E616D65060E476174
+      6865725175616E746974790844617461547970650206084461746153697A6502
+      080549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      0610476174686572546F74616C5072696365094669656C644E616D6506104761
+      74686572546F74616C5072696365084461746154797065020608446174615369
+      7A6502080549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D65060F456E644465616C5175616E74697479094669656C644E616D65060F
+      456E644465616C5175616E746974790844617461547970650206084461746153
+      697A6502080549734B6579080F4E65656450726F636573734E616D6509000104
+      4E616D650611456E644465616C546F74616C5072696365094669656C644E616D
+      650611456E644465616C546F74616C5072696365084461746154797065020608
+      4461746153697A6502080549734B6579080F4E65656450726F636573734E616D
+      65090001044E616D65060D456E6451635175616E74697479094669656C644E61
+      6D65060D456E6451635175616E74697479084461746154797065020608446174
+      6153697A6502080549734B6579080F4E65656450726F636573734E616D650900
+      01044E616D65060F456E645163546F74616C5072696365094669656C644E616D
+      65060F456E645163546F74616C50726963650844617461547970650206084461
+      746153697A6502080549734B6579080F4E65656450726F636573734E616D6509
+      0001044E616D65060C456E64516342474C436F6465094669656C644E616D6506
+      0C456E64516342474C436F64650844617461547970650218084461746153697A
+      6503FF000549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D65060B456E64516342474C4E756D094669656C644E616D65060B456E6451
+      6342474C4E756D0844617461547970650218084461746153697A6503FF000549
+      734B6579080F4E65656450726F636573734E616D65090001044E616D65060D45
+      6E6450635175616E74697479094669656C644E616D65060D456E645063517561
+      6E746974790844617461547970650206084461746153697A6502080549734B65
+      79080F4E65656450726F636573734E616D65090001044E616D65060F456E6450
+      63546F74616C5072696365094669656C644E616D65060F456E645063546F7461
+      6C50726963650844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060C456E64
+      506342474C436F6465094669656C644E616D65060C456E64506342474C436F64
+      650844617461547970650218084461746153697A6503FF000549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D65060B456E6450634247
+      4C4E756D094669656C644E616D65060B456E64506342474C4E756D0844617461
+      547970650218084461746153697A6503FF000549734B6579080F4E6565645072
+      6F636573734E616D65090001044E616D650611456E644761746865725175616E
+      74697479094669656C644E616D650611456E644761746865725175616E746974
+      790844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D650613456E644761746865
+      72546F74616C5072696365094669656C644E616D650613456E64476174686572
+      546F74616C50726963650844617461547970650206084461746153697A650208
+      0549734B6579080F4E65656450726F636573734E616D65090001044E616D6506
+      0F5072654465616C5175616E74697479094669656C644E616D65060F50726544
+      65616C5175616E746974790844617461547970650206084461746153697A6502
+      080549734B6579080F4E65656450726F636573734E616D65090001044E616D65
+      06115072654465616C546F74616C5072696365094669656C644E616D65061150
+      72654465616C546F74616C507269636508446174615479706502060844617461
+      53697A6502080549734B6579080F4E65656450726F636573734E616D65090001
+      044E616D65060D50726551635175616E74697479094669656C644E616D65060D
+      50726551635175616E746974790844617461547970650206084461746153697A
+      6502080549734B6579080F4E65656450726F636573734E616D65090001044E61
+      6D65060F5072655163546F74616C5072696365094669656C644E616D65060F50
+      72655163546F74616C5072696365084461746154797065020608446174615369
+      7A6502080549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D65060C507265516342474C436F6465094669656C644E616D65060C507265
+      516342474C436F64650844617461547970650218084461746153697A6503FF00
+      0549734B6579080F4E65656450726F636573734E616D65090001044E616D6506
+      0B507265516342474C4E756D094669656C644E616D65060B507265516342474C
+      4E756D0844617461547970650218084461746153697A6503FF000549734B6579
+      080F4E65656450726F636573734E616D65090001044E616D65060D5072655063
+      5175616E74697479094669656C644E616D65060D50726550635175616E746974
+      790844617461547970650206084461746153697A6502080549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D65060F5072655063546F74
+      616C5072696365094669656C644E616D65060F5072655063546F74616C507269
+      63650844617461547970650206084461746153697A6502080549734B6579080F
+      4E65656450726F636573734E616D65090001044E616D65060C50726550634247
+      4C436F6465094669656C644E616D65060C507265506342474C436F6465084461
+      7461547970650218084461746153697A6503FF000549734B6579080F4E656564
+      50726F636573734E616D65090001044E616D65060B507265506342474C4E756D
+      094669656C644E616D65060B507265506342474C4E756D084461746154797065
+      0218084461746153697A6503FF000549734B6579080F4E65656450726F636573
+      734E616D65090001044E616D6506115072654761746865725175616E74697479
+      094669656C644E616D6506115072654761746865725175616E74697479084461
+      7461547970650206084461746153697A6502080549734B6579080F4E65656450
+      726F636573734E616D65090001044E616D650613507265476174686572546F74
+      616C5072696365094669656C644E616D650613507265476174686572546F7461
+      6C50726963650844617461547970650206084461746153697A6502080549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D65060B486173
+      426F6F6B6D61726B094669656C644E616D65060B486173426F6F6B6D61726B08
+      44617461547970650205084461746153697A6502010549734B6579080F4E6565
+      6450726F636573734E616D65090001044E616D6506084D61726B4D656D6F0946
+      69656C644E616D6506084D61726B4D656D6F0844617461547970650218084461
+      746153697A6503FF000549734B6579080F4E65656450726F636573734E616D65
+      090000}
+  end
+end

+ 748 - 0
DataModules/StageDm.pas

@@ -0,0 +1,748 @@
+unit StageDm;
+
+// 原报、审核数据通用
+// 原报 - Refer
+// 审核 - Audit1, Audit2 ...
+
+interface
+
+uses
+  mDataRecord, BillsTree,
+  SysUtils, Classes, sdDB, sdProvider, ADODB, ZhAPI, sdIDTree;
+
+type
+  TStageData = class(TDataModule)
+    sdpStage: TsdADOProvider;
+    sddStage: TsdDataSet;
+    procedure sddStageAfterValueChanged(AValue: TsdValue);
+    procedure sddStageBeforeValueChange(AValue: TsdValue;
+      const NewValue: Variant; var Allow: Boolean);
+    procedure sddStageGetRecordClass(var ARecordClass: TsdRecordClass);
+  private
+    FPhaseData: TObject;
+    FIndex: Integer;
+
+    FBeforeChangeQuantity: Double;
+    FBeforeChangeTotalPrice: Double;
+
+    procedure BeforeBatchOperation;
+    procedure AfterBatchOperation;
+
+    procedure UpdateParentRecord(ABillsID: Integer; ATotalPrice: Double; const AFieldName: string);
+    procedure UpdateComplete(ABillsID: Integer; AQuantity, ATotalPrice: Double);
+    procedure CalculateDeal(ABillsID: Integer);
+    procedure CalculateQuantityChange(ABillsID: Integer);
+    procedure CalculatePriceChange(ABillsID: Integer);
+
+    procedure CalculateParent(ANode: TBillsIDTreeNode);
+    procedure CalculateLeaf(ANode: TBillsIDTreeNode);
+
+    function GetTotalPrice(ABillsID, AType, AStageIndex: Integer): Double;
+
+    function GetBillsPrice(ABillsID: Integer): Double;
+    function GetBillsNewPrice(ABillsID: Integer): Double;
+    function GetBillsPriceDiffer(ABillsID: Integer): Double;
+    function GetMainBillsTree: TBillsIDTree;
+    function GetBuildLoadInterest(AType, AIndex: Integer): Double;
+    function GetFirstPart(AType, AIndex: Integer): Double;
+    function GetOtherFee(AType, AIndex: Integer): Double;
+    function GetOtherProjectFee(AType, AIndex: Integer): Double;
+    function GetRecyclingFee(AType, AIndex: Integer): Double;
+    function GetReservedFee(AType, AIndex: Integer): Double;
+    function GetSecondPart(AType, AIndex: Integer): Double;
+    function GetStageSettlement(AType, AIndex: Integer): Double;
+    function GetThirdPart(AType, AIndex: Integer): Double;
+    function GetActive: Boolean;
+    procedure SetTableName(const Value: string);
+    function GetChapterStageGather(AChapter: Integer): Double;
+  public
+    constructor Create(APhaseData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Save;
+
+    procedure CalculateNode(ANode: TsdIDTreeNode);
+    procedure CalculateAll;
+
+    function AddPhaseData(ABillsID: Integer;
+      const AField, ANewValue: string): Boolean;
+
+    function AddStageRecord(ABillsID: Integer): TStageRecord;
+    procedure DeletePhaseRecord(ABillsID: Integer);
+
+    procedure ReCalculate(ABillsID: Integer);
+    procedure UpdateBGLInfo(ARec: TsdDataRecord; const AType: string);
+
+    function StageRecord(ABillsID: Integer): TStageRecord;
+
+    // 将Bills表中存的累计计量数据拷贝至截止本期计量、截止上期计量,除新增一期计量外不可调用
+    procedure CopyPrePhaseData;
+
+    property Active: Boolean read GetActive;
+    property TableName: string Write SetTableName;
+    property MainBillsTree: TBillsIDTree read GetMainBillsTree;
+
+    {可选计算数}
+    // AType表示不同类型,取值如下:
+    // 1: 本期数据  2: 截止本期数据  3: 截止上期数据
+    // AIndex表示AType下不同数据类型,取值如下:
+    // 1: 合同计量 2: 数量变更计量 3: 单价变更计量 4: 完成计量
+    // 第一部分
+    property FirstPart[AType, AIndex: Integer]: Double read GetFirstPart;
+    // 第二部分
+    property SecondPart[AType, AIndex: Integer]: Double read GetSecondPart;
+    // 第三部分
+    property ThirdPart[AType, AIndex: Integer]: Double read GetThirdPart;
+    // 预留费用
+    property ReservedFee[AType, AIndex: Integer]: Double read GetReservedFee;
+    // 其他费用项目
+    property OtherFee[AType, AIndex: Integer]: Double read GetOtherFee;
+    // 建设期贷款利息
+    property BuildLoadInterest[AType, AIndex: Integer]: Double read GetBuildLoadInterest;
+    // 回收金额
+    property RecyclingFee[AType, AIndex: Integer]: Double read GetRecyclingFee;
+    // 公路工程以外的工程费用
+    property OtherProjectFee[AType, AIndex: Integer]: Double read GetOtherProjectFee;
+    // 本期结算价
+    property StageSettlement[AType, AIndex: Integer]: Double read GetStageSettlement;
+
+    // 100/200/.../900章本期完成计量
+    property ChapterStageGather[AChapter: Integer]: Double read GetChapterStageGather;
+  end;
+
+implementation
+
+uses
+  ProjectData, BillsDm, PhaseData, Math, BGLDm, BillsMeasureDm,
+  UtilMethods, ConditionalDefines, FormulaCalc;
+
+{$R *.dfm}
+
+{ TPhaseData }
+
+function TStageData.AddPhaseData(ABillsID: Integer;
+  const AField, ANewValue: string): Boolean;
+
+  procedure SetPhaseRecord(ARec: TsdDataRecord; const AField, AValue: string);
+  begin
+    if CheckNumeric(ANewValue) then
+      ARec.ValueByName(AField).AsString := AValue
+    else
+    begin
+      ARec.ValueByName(AField).AsFloat := EvaluateExprs(AValue);
+      ARec.ValueByName(StringReplace(AField, 'Quantity', 'Flag', [])).AsInteger := 1;
+      ARec.ValueByName(StringReplace(AField, 'Quantity', 'Formula', [])).AsString := AValue;
+    end;
+  end;
+
+var
+  Rec: TsdDataRecord;
+begin
+  if Assigned(sddStage.FindKey('idxBID', ABillsID)) then Exit;
+  Rec := sddStage.Add;
+  Rec.ValueByName('BillsID').AsInteger := ABillsID;
+  SetPhaseRecord(Rec, AField, ANewValue);
+end;
+
+function TStageData.AddStageRecord(ABillsID: Integer): TStageRecord;
+begin
+  Result := TStageRecord(sddStage.FindKey('idxBID', ABillsID));
+  if Assigned(Result) then Exit;
+
+  Result := TStageRecord(sddStage.Add(True));
+  try
+    Result.ValueByName('BillsID').AsInteger := ABillsID;
+  finally
+    Result.EndUpdate;
+  end;
+end;
+
+procedure TStageData.CalculateDeal(ABillsID: Integer);
+var
+  Rec: TsdDataRecord;
+  fQtyDiffer, fTPDiffer: Double;
+begin
+  Rec := sddStage.FindKey('idxBID', ABillsID);
+  if Rec.ValueByName('DealFlag').AsInteger < 2 then
+    Rec.ValueByName('DealTotalPrice').AsFloat :=
+        TotalPriceRoundTo(Rec.ValueByName('DealQuantity').AsFloat * GetBillsPrice(ABillsID));
+
+  fQtyDiffer := Rec.ValueByName('DealQuantity').AsFloat - FBeforeChangeQuantity;
+  fTPDiffer := Rec.ValueByName('DealTotalPrice').AsFloat - FBeforeChangeTotalPrice;
+
+  Rec.ValueByName('EndDealQuantity').AsFloat := QuantityRoundTo(
+      Rec.ValueByName('EndDealQuantity').AsFloat + fQtyDiffer);
+  Rec.ValueByName('EndDealTotalPrice').AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('EndDealTotalPrice').AsFloat + fTPDiffer);
+
+  UpdateParentRecord(ABillsID, fTPDiffer, 'DealTotalPrice');
+  UpdateComplete(ABillsID, fQtyDiffer, fTPDiffer);
+  if TPhaseData(FPhaseData).IsLastStage then
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsMeasureData do
+      UpdateRecordDeal(ABillsID, fQtyDiffer, fTPDiffer);
+  TPhaseData(FPhaseData).PhasePayData.CalculateAll;
+end;
+
+procedure TStageData.CalculatePriceChange(ABillsID: Integer);
+var
+  Rec: TsdDataRecord;
+  fQtyDiffer, fTPDiffer: Double;
+begin
+  Rec := sddStage.FindKey('idxBID', ABillsID);
+  if Rec.ValueByName('PcFlag').AsInteger < 2 then
+    Rec.ValueByName('PcTotalPrice').AsFloat :=
+        TotalPriceRoundTo(Rec.ValueByName('PcQuantity').AsFloat * GetBillsPriceDiffer(ABillsID));
+
+  fQtyDiffer := Rec.ValueByName('PcQuantity').AsFloat - FBeforeChangeQuantity;
+  fTPDiffer := Rec.ValueByName('PcTotalPrice').AsFloat - FBeforeChangeTotalPrice;
+
+  Rec.ValueByName('EndPcQuantity').AsFloat := QuantityRoundTo(
+    Rec.ValueByName('EndPcQuantity').AsFloat + fQtyDiffer);
+  Rec.ValueByName('EndPcTotalPrice').AsFloat := TotalPriceRoundTo(
+    Rec.ValueByName('EndPcTotalPrice').AsFloat + fTPDiffer);
+
+  UpdateParentRecord(ABillsID, fTPDiffer, 'PcTotalPrice');
+  UpdateComplete(ABillsID, 0, fTPDiffer);
+  if TPhaseData(FPhaseData).IsLastStage then
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsMeasureData do
+      UpdateRecordPc(ABillsID, fQtyDiffer, fTPDiffer);
+  TPhaseData(FPhaseData).PhasePayData.CalculateAll;
+end;
+
+procedure TStageData.CalculateQuantityChange(ABillsID: Integer);
+var
+  Rec: TsdDataRecord;
+  fQtyDiffer, fTPDiffer: Double;
+begin
+  Rec := sddStage.FindKey('idxBID', ABillsID);
+  if Rec.ValueByName('QcFlag').AsInteger < 2 then
+    Rec.ValueByName('QcTotalPrice').AsFloat :=
+        TotalPriceRoundTo(Rec.ValueByName('QcQuantity').AsFloat * GetBillsPrice(ABillsID));
+
+  fQtyDiffer := Rec.ValueByName('QcQuantity').AsFloat - FBeforeChangeQuantity;
+  fTPDiffer := Rec.ValueByName('QcTotalPrice').AsFloat - FBeforeChangeTotalPrice;
+
+  Rec.ValueByName('EndQcQuantity').AsFloat := QuantityRoundTo(
+      Rec.ValueByName('EndQcQuantity').AsFloat + fQtyDiffer);
+  Rec.ValueByName('EndQcTotalPrice').AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('EndQcTotalPrice').AsFloat + fTPDiffer);
+
+  UpdateParentRecord(ABillsID, fTPDiffer, 'QcTotalPrice');
+  UpdateComplete(ABillsID, fQtyDiffer, fTPDiffer);
+  if TPhaseData(FPhaseData).IsLastStage then
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsMeasureData do
+      UpdateRecordQc(ABillsID, fQtyDiffer, fTPDiffer);
+  TPhaseData(FPhaseData).PhasePayData.CalculateAll;
+end;
+
+constructor TStageData.Create(APhaseData: TObject);
+begin
+  inherited Create(nil);
+  FPhaseData := APhaseData;
+end;
+
+procedure TStageData.DeletePhaseRecord(ABillsID: Integer);
+var
+  Rec: TsdDataRecord;
+begin
+  Rec := sddStage.FindKey('idxBID', ABillsID);
+  if Assigned(Rec) then
+    sddStage.Remove(Rec);
+end;
+
+destructor TStageData.Destroy;
+begin
+  inherited;
+end;
+
+function TStageData.GetBillsNewPrice(ABillsID: Integer): Double;
+begin
+  Result := MainBillsTree.FindNode(ABillsID).Rec.ValueByName('NewPrice').AsFloat;
+end;
+
+function TStageData.GetBillsPrice(ABillsID: Integer): Double;
+begin
+  Result := MainBillsTree.FindNode(ABillsID).Rec.ValueByName('Price').AsFloat;
+end;
+
+procedure TStageData.Open(AConnection: TADOConnection);
+begin
+  sdpStage.Connection := AConnection;
+  sddStage.Open;
+  if not Assigned(sddStage.IndexList.FindByName('idxBID')) then
+    sddStage.AddIndex('idxBID', 'BillsID');
+
+  sddStage.FieldByName('DealQuantity').ValidChars := sddStage.FieldByName('DealQuantity').ValidChars + ArithmeticCharSet;
+end;
+
+function TStageData.StageRecord(ABillsID: Integer): TStageRecord;
+begin
+  Result := nil;
+  if Assigned(sddStage.IndexList.FindByName('idxBID')) then
+    Result := TStageRecord(sddStage.FindKey('idxBID', ABillsID));
+end;
+
+procedure TStageData.ReCalculate(ABillsID: Integer);
+var
+  Rec: TsdDataRecord;
+  fDiffer: Double;
+begin
+  Rec := sddStage.FindKey('idxBID', ABillsID);
+  if not Assigned(Rec) then Exit;
+
+  if Rec.ValueByName('DealFlag').AsInteger = 1 then
+    Rec.ValueByName('DealQuantity').AsFloat := QuantityRoundTo(
+        EvaluateExprs(Rec.ValueByName('DealFormula').AsString));
+  if Rec.ValueByName('DealFlag').AsInteger < 2 then
+  begin
+    fDiffer := Rec.ValueByName('DealQuantity').AsFloat * GetBillsPrice(ABillsID)
+        - Rec.ValueByName('DealTotalPrice').AsFloat;
+    Rec.ValueByName('DealTotalPrice').AsFloat := TotalPriceRoundTo(
+        Rec.ValueByName('DealQuantity').AsFloat * GetBillsPrice(ABillsID));
+  end;
+  Rec.ValueByName('EndDealQuantity').AsFloat := QuantityRoundTo(
+      Rec.ValueByName('PreDealQuantity').AsFloat + Rec.ValueByName('DealQuantity').AsFloat);
+  Rec.ValueByName('EndDealTotalPrice').AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('PreDealTotalPrice').AsFloat + Rec.ValueByName('DealTotalPrice').AsFloat);
+
+  if Rec.ValueByName('QcFlag').AsInteger = 1 then
+    Rec.ValueByName('QcQuantity').AsFloat := QuantityRoundTo(
+        EvaluateExprs(Rec.ValueByName('QcFormula').AsString));
+  if Rec.ValueByName('QcFlag').AsInteger < 2 then
+  begin
+    fDiffer := Rec.ValueByName('QcQuantity').AsFloat * GetBillsPrice(ABillsID)
+        - Rec.ValueByName('QcTotalPrice').AsFloat;
+    Rec.ValueByName('QcTotalPrice').AsFloat := TotalPriceRoundTo(
+        Rec.ValueByName('QcQuantity').AsFloat * GetBillsPrice(ABillsID));
+  end;
+  Rec.ValueByName('EndQcQuantity').AsFloat := QuantityRoundTo(
+      Rec.ValueByName('PreQcQuantity').AsFloat + Rec.ValueByName('QcQuantity').AsFloat);
+  Rec.ValueByName('EndQcTotalPrice').AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('PreQcTotalPrice').AsFloat + Rec.ValueByName('QcTotalPrice').AsFloat);
+
+  if Rec.ValueByName('PcFlag').AsInteger = 1 then
+    Rec.ValueByName('PcQuantity').AsFloat := QuantityRoundTo(
+        EvaluateExprs(Rec.ValueByName('PcFormula').AsString));
+  if Rec.ValueByName('DealFlag').AsInteger < 2 then
+  begin
+    fDiffer := Rec.ValueByName('PcQuantity').AsFloat * GetBillsNewPrice(ABillsID)
+        - Rec.ValueByName('PcTotalPrice').AsFloat;
+    Rec.ValueByName('PcTotalPrice').AsFloat := TotalPriceRoundTo(
+        Rec.ValueByName('PcQuantity').AsFloat * GetBillsNewPrice(ABillsID));
+  end;
+  Rec.ValueByName('EndPcQuantity').AsFloat := QuantityRoundTo(
+      Rec.ValueByName('PrePcQuantity').AsFloat + Rec.ValueByName('PcQuantity').AsFloat);
+  Rec.ValueByName('EndPcTotalPrice').AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('PrePcTotalPrice').AsFloat + Rec.ValueByName('PcTotalPrice').AsFloat);
+end;
+
+procedure TStageData.Save;
+begin
+  sddStage.Save;
+end;
+
+procedure TStageData.sddStageAfterValueChanged(AValue: TsdValue);
+var
+  iBillsID: Integer;
+  stnNode: TsdIDTreeNode;
+begin
+  iBillsID := AValue.Owner.ValueByName('BillsID').AsInteger;
+  stnNode := MainBillsTree.FindNode(iBillsID);
+  if not Assigned(stnNode) or stnNode.HasChildren then Exit;
+  
+  if (AValue.FieldName = 'DealQuantity') or
+     (AValue.FieldName = 'DealFormula') or
+     (AValue.FieldName = 'DealTotalPrice') then
+    CalculateDeal(AValue.Owner.ValueByName('BillsID').AsInteger);
+  if (AValue.FieldName = 'QcQuantity') or
+     (AValue.FieldName = 'QcFormula') or
+     (AValue.FieldName = 'QcTotalPrice') then
+    CalculateQuantityChange(AValue.Owner.ValueByName('BillsID').AsInteger);
+  if (AValue.FieldName = 'PcQuantity') or
+     (AValue.FieldName = 'PcFormula') or
+     (AValue.FieldName = 'PcTotalPrice') then
+    CalculatePriceChange(AValue.Owner.ValueByName('BillsID').AsInteger);
+end;
+
+function TStageData.GetMainBillsTree: TBillsIDTree;
+begin
+  with TProjectData(TPhaseData(FPhaseData).ProjectData) do
+    Result := BillsMeasureData.BillsMeasureTree;
+end;
+
+procedure TStageData.sddStageBeforeValueChange(AValue: TsdValue;
+  const NewValue: Variant; var Allow: Boolean);
+
+  procedure SetBeforeChangeValue(const AType: string);
+  begin
+    if SameText(AValue.FieldName, AType + 'Quantity') or
+       SameText(AValue.FieldName, AType + 'Formula') or
+       SameText(AValue.FieldName, AType + 'TotalPrice') then
+    begin
+      FBeforeChangeQuantity := AValue.Owner.ValueByName(AType + 'Quantity').AsFloat;
+      FBeforeChangeTotalPrice := AValue.Owner.ValueByName(AType + 'TotalPrice').AsFloat;
+    end;
+  end;
+
+  procedure CheckOverRange;
+  var
+    vNode: TsdIDTreeNode;
+    fAvailableQty: Double;
+  begin
+    if SameText(AValue.FieldName, 'DealQuantity') then
+    begin
+      vNode := MainBillsTree.FindNode(AValue.Owner.ValueByName('BillsID').AsInteger);
+      fAvailableQty := vNode.Rec.ValueByName('Quantity').AsFloat
+          - vNode.Rec.ValueByName('AddDealQuantity').AsFloat + AValue.AsFloat;
+      if VarToFloatDef(NewValue, 0) > fAvailableQty then
+        DataSetErrorMessage(Allow, '不可超过0号台账合同数量!');
+    end;
+  end;
+
+begin
+  // 不检查超计
+  //CheckOverRange;
+  SetBeforeChangeValue('Deal');
+  SetBeforeChangeValue('Qc');
+  SetBeforeChangeValue('Pc');
+end;
+
+procedure TStageData.AfterBatchOperation;
+begin
+  sddStage.BeforeValueChange := sddStageBeforeValueChange;
+  sddStage.AfterValueChanged := sddStageAfterValueChanged;
+end;
+
+procedure TStageData.BeforeBatchOperation;
+begin
+  sddStage.BeforeValueChange := nil;
+  sddStage.AfterValueChanged := nil;
+end;
+
+function TStageData.GetBillsPriceDiffer(ABillsID: Integer): Double;
+begin
+  with MainBillsTree.FindNode(ABillsID).Rec do
+    Result := ValueByName('NewPrice').AsFloat - ValueByName('Price').AsFloat;
+end;
+
+procedure TStageData.UpdateComplete(ABillsID: Integer; AQuantity,
+  ATotalPrice: Double);
+var
+  Rec: TsdDataRecord;
+begin
+  if ABillsID = -1 then Exit;
+  Rec := StageRecord(ABillsID);
+  Rec.ValueByName('GatherQuantity').AsFloat := QuantityRoundTo(
+      Rec.ValueByName('GatherQuantity').AsFloat + AQuantity);
+  Rec.ValueByName('GatherTotalPrice').AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('GatherTotalPrice').AsFloat + ATotalPrice);
+  Rec.ValueByName('EndGatherQuantity').AsFloat := QuantityRoundTo(
+      Rec.ValueByName('EndGatherQuantity').AsFloat + AQuantity);
+  Rec.ValueByName('EndGatherTotalPrice').AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('EndGatherTotalPrice').AsFloat + ATotalPrice);
+  // 数量不向上汇总
+  UpdateParentRecord(ABillsID, ATotalPrice, 'GatherTotalPrice');
+end;
+
+procedure TStageData.UpdateParentRecord(ABillsID: Integer;
+  ATotalPrice: Double; const AFieldName: string);
+var
+  iParentID: Integer;
+  Rec: TsdDataRecord;
+begin
+  iParentID := MainBillsTree.FindNode(ABillsID).ParentID;
+  if iParentID = -1 then Exit;
+  Rec := StageRecord(iParentID);
+  if not Assigned(Rec) then
+    Rec := AddStageRecord(iParentID);
+  Rec.ValueByName(AFieldName).AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName(AFieldName).AsFloat + ATotalPrice);
+  Rec.ValueByName('End' + AFieldName).AsFloat := TotalPriceRoundTo(
+      Rec.ValueByName('End' + AFieldName).AsFloat + ATotalPrice);
+  UpdateParentRecord(iParentID, ATotalPrice, AFieldName);
+end;
+
+function TStageData.GetBuildLoadInterest(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(34, AType, AIndex);
+end;
+
+function TStageData.GetFirstPart(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(1, AType, AIndex);
+end;
+
+function TStageData.GetOtherFee(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(15, AType, AIndex);
+end;
+
+function TStageData.GetOtherProjectFee(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(9, AType, AIndex);
+end;
+
+function TStageData.GetRecyclingFee(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(16, AType, AIndex);
+end;
+
+function TStageData.GetReservedFee(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(7, AType, AIndex);
+end;
+
+function TStageData.GetSecondPart(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(2, AType, AIndex);
+end;
+
+function TStageData.GetStageSettlement(AType, AIndex: Integer): Double;
+begin
+  // 全国
+  // 第一部分+第二部分+第三部分+预备费+新增加费用项目(其他费用_广东)-回收金额
+  Result := FirstPart[AType, AIndex] + SecondPart[AType, AIndex] + ThirdPart[AType, AIndex]
+         + ReservedFee[AType, AIndex] + OtherFee[AType, AIndex] - RecyclingFee[AType, AIndex];
+  // 广东
+  // 全国的基础上+建设期贷款利息+公路功能以外的项目
+  if _IsGuangDong then
+    Result := Result + BuildLoadInterest[AType, AIndex] + OtherProjectFee[AType, AIndex]
+end;
+
+function TStageData.GetThirdPart(AType, AIndex: Integer): Double;
+begin
+  Result := GetTotalPrice(3, AType, AIndex);
+end;
+
+function TStageData.GetTotalPrice(ABillsID, AType, AStageIndex: Integer): Double;
+var
+  Rec: TsdDataRecord;
+  sFieldName: string;
+begin
+  Result := 0;
+  Rec := StageRecord(ABillsID);
+  if not Assigned(Rec) then Exit;
+  case AType of
+    1: sFieldName := '';
+    2: sFieldName := 'End';
+    3: sFieldName := 'Pre';
+  end;
+  case AStageIndex of
+    1: sFieldName := sFieldName + 'DealTotalPrice';
+    2: sFieldName := sFieldName + 'QcTotalPrice';
+    3: sFieldName := sFieldName + 'PcTotalPrice';
+    4: sFieldName := sFieldName + 'GatherTotalPrice';
+  end;
+  Result := Rec.ValueByName(sFieldName).AsFloat;
+end;
+
+procedure TStageData.CopyPrePhaseData;
+var
+  iRecord: Integer;
+  Rec, NewRec: TsdDataRecord;
+begin
+  BeforeBatchOperation;
+  try
+    with TProjectData(TPhaseData(FPhaseData).ProjectData).BillsData do
+      for iRecord := 0 to sddBills.RecordCount - 1 do
+      begin
+        Rec := sddBills.Records[iRecord];
+        if (Rec.ValueByName('AddGatherTotalPrice').AsFloat = 0) and
+           (Rec.ValueByName('AddDealTotalPrice').AsFloat = 0) and
+           (Rec.ValueByName('AddQcTotalPrice').AsFloat = 0) and
+           (Rec.ValueByName('AddPcTotalPrice').AsFloat = 0) then Continue;
+           
+        NewRec := sddStage.Add;
+        NewRec.ValueByName('BillsID').AsInteger := Rec.ValueByName('ID').AsInteger;
+        NewRec.ValueByName('EndDealQuantity').AsFloat := Rec.ValueByName('AddDealQuantity').AsFloat;
+        NewRec.ValueByName('EndDealTotalPrice').AsFloat := Rec.ValueByName('AddDealTotalPrice').AsFloat;
+        NewRec.ValueByName('EndQcQuantity').AsFloat := Rec.ValueByName('AddQcQuantity').AsFloat;
+        NewRec.ValueByName('EndQcTotalPrice').AsFloat := Rec.ValueByName('AddQcTotalPrice').AsFloat;
+        NewRec.ValueByName('EndQcBGLCode').AsString := Rec.ValueByName('AddQcBGLCode').AsString;
+        NewRec.ValueByName('EndQcBGLNum').AsString := Rec.ValueByName('AddQcBGLNum').AsString;
+        NewRec.ValueByName('EndPcQuantity').AsFloat := Rec.ValueByName('AddPcQuantity').AsFloat;
+        NewRec.ValueByName('EndPcTotalPrice').AsFloat := Rec.ValueByName('AddPcTotalPrice').AsFloat;
+        NewRec.ValueByName('EndPcBGLCode').AsString := Rec.ValueByName('AddPcBGLCode').AsString;
+        NewRec.ValueByName('EndPcBGLNum').AsString := Rec.ValueByName('AddPcBGLNum').AsString;
+        NewRec.ValueByName('EndGatherQuantity').AsFloat := Rec.ValueByName('AddGatherQuantity').AsFloat;
+        NewRec.ValueByName('EndGatherTotalPrice').AsFloat := Rec.ValueByName('AddGatherTotalPrice').AsFloat;
+        NewRec.ValueByName('PreDealQuantity').AsFloat := Rec.ValueByName('AddDealQuantity').AsFloat;
+        NewRec.ValueByName('PreDealTotalPrice').AsFloat := Rec.ValueByName('AddDealTotalPrice').AsFloat;
+        NewRec.ValueByName('PreQcQuantity').AsFloat := Rec.ValueByName('AddQcQuantity').AsFloat;
+        NewRec.ValueByName('PreQcTotalPrice').AsFloat := Rec.ValueByName('AddQcTotalPrice').AsFloat;
+        NewRec.ValueByName('PreQcBGLCode').AsString := Rec.ValueByName('AddQcBGLCode').AsString;
+        NewRec.ValueByName('PreQcBGLNum').AsString := Rec.ValueByName('AddQcBGLNum').AsString;
+        NewRec.ValueByName('PrePcQuantity').AsFloat := Rec.ValueByName('AddPcQuantity').AsFloat;
+        NewRec.ValueByName('PrePcTotalPrice').AsFloat := Rec.ValueByName('AddPcTotalPrice').AsFloat;
+        NewRec.ValueByName('PrePcBGLCode').AsString := Rec.ValueByName('AddPcBGLCode').AsString;
+        NewRec.ValueByName('PrePcBGLNum').AsString := Rec.ValueByName('AddPcBGLNum').AsString;
+        NewRec.ValueByName('PreGatherQuantity').AsFloat := Rec.ValueByName('AddGatherQuantity').AsFloat;
+        NewRec.ValueByName('PreGatherTotalPrice').AsFloat := Rec.ValueByName('AddGatherTotalPrice').AsFloat;
+      end;
+  finally
+    AfterBatchOperation;
+  end;
+end;
+
+procedure TStageData.UpdateBGLInfo(ARec: TsdDataRecord; const AType: string);
+var
+  sPreBGLCode, sPreBGLNum, sCurBGLCode, sCurBGLNum: string;
+begin
+  sPreBGLCode := ARec.ValueByName('Pre' + AType + 'BGLCode').AsString;
+  sPreBGLNum := ARec.ValueByName('Pre' + AType + 'BGLNum').AsString;
+  sCurBGLCode := ARec.ValueByName(AType + 'BGLCode').AsString;
+  sCurBGLNum := ARec.ValueByName(AType + 'BGLNum').AsString;
+  MergeRelaBGLAndNum(sPreBGLCode, sPreBGLNum, sCurBGLCode, sCurBGLNum);
+  ARec.ValueByName('End' + AType + 'BGLCode').AsString := sPreBGLCode;
+  ARec.ValueByName('End' + AType + 'BGLNum').AsString := sPreBGLNum;
+end;
+
+procedure TStageData.CalculateAll;
+begin
+  BeforeBatchOperation;
+  CalculateNode(MainBillsTree.FirstNode);
+  AfterBatchOperation;
+end;
+
+procedure TStageData.CalculateNode(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+  begin
+    CalculateNode(ANode.FirstChild);
+    CalculateParent(TBillsIDTreeNode(ANode));
+  end
+  else
+    CalculateLeaf(TBillsIDTreeNode(ANode));
+  CalculateNode(ANode.NextSibling);
+end;
+
+procedure TStageData.CalculateParent(ANode: TBillsIDTreeNode);
+var
+  iChild: Integer;
+  ChildNode: TBillsIDTreeNode;
+  fDeal, fQc, fPc: Double;
+begin
+  if not Assigned(ANode.StageRec) then Exit;
+
+  fDeal := 0;
+  fQc := 0;
+  FPc := 0;
+  for iChild := 0 to ANode.ChildCount - 1 do
+  begin
+    ChildNode := TBillsIDTreeNode(ANode.ChildNodes[iChild]);
+    if not Assigned(ChildNode.StageRec) then Continue;
+    fDeal := TotalPriceRoundTo(fDeal + ChildNode.StageRec.DealTotalPrice.AsFloat);
+    fQc := TotalPriceRoundTo(fQc + ChildNode.StageRec.QcTotalPrice.AsFloat);
+    fPc := TotalPriceRoundTo(fPc + ChildNode.StageRec.PcTotalPrice.AsFloat);
+  end;
+
+  with ANode.StageRec do
+  begin
+    DealTotalPrice.AsFloat := fDeal;
+    QcTotalPrice.AsFloat := fQc;
+    PcTotalPrice.AsFloat := fPc;
+    GatherTotalPrice.AsFloat := TotalPriceRoundTo(fDeal + fQc + fPc);
+    EndDealTotalPrice.AsFloat := TotalPriceRoundTo(PreDealTotalPrice.AsFloat + fDeal);
+    EndQcTotalPrice.AsFloat := TotalPriceRoundTo(PreQcTotalPrice.AsFloat + fQc);
+    EndPcTotalPrice.AsFloat := TotalPriceRoundTo(PrePcTotalPrice.AsFloat + fPc);
+    EndGatherTotalPrice.AsFloat := TotalPriceRoundTo(
+      PreGatherTotalPrice.AsFloat + GatherTotalPrice.AsFloat);
+  end;
+end;
+
+procedure TStageData.CalculateLeaf(ANode: TBillsIDTreeNode);
+
+  procedure CalculateMeasure(ARec: TsdDataRecord; const AType: string);
+  var
+    fPrice: Double;
+  begin
+    if ARec.ValueByName(AType + 'Flag').AsInteger = 1 then
+      ARec.ValueByName(AType + 'Quantity').AsFloat := QuantityRoundTo(
+          EvaluateExprs(ARec.ValueByName(AType + 'Formula').AsString));
+    if ARec.ValueByName(AType + 'Flag').AsInteger < 2 then
+    begin
+      fPrice := GetBillsPrice(ARec.ValueByName('BillsID').AsInteger);
+      ARec.ValueByName(AType + 'TotalPrice').AsFloat := TotalPriceRoundTo(
+        ARec.ValueByName(AType + 'Quantity').AsFloat * fPrice);
+    end;
+    ARec.ValueByName('End' + AType + 'Quantity').AsFloat := QuantityRoundTo(
+      ARec.ValueByName('Pre' + AType + 'Quantity').AsFloat + ARec.ValueByName(AType + 'Quantity').AsFloat);
+    ARec.ValueByName('End' + AType + 'TotalPrice').AsFloat := TotalPriceRoundTo(
+      ARec.ValueByName('Pre' + AType + 'TotalPrice').AsFloat + ARec.ValueByName(AType + 'TotalPrice').AsFloat);
+  end;
+
+var
+  Rec: TStageRecord;
+begin
+  Rec := ANode.StageRec;
+  if not Assigned(Rec) then Exit;
+  CalculateMeasure(Rec, 'Deal');
+  CalculateMeasure(Rec, 'Pc');
+  CalculateMeasure(Rec, 'Qc');
+  Rec.GatherQuantity.AsFloat := QuantityRoundTo(
+      Rec.DealQuantity.AsFloat + Rec.QcQuantity.AsFloat);
+  Rec.GatherTotalPrice.AsFloat := TotalPriceRoundTo(
+      Rec.DealTotalPrice.AsFloat + Rec.QcTotalPrice.AsFloat + Rec.PcTotalPrice.AsFloat);
+  Rec.EndGatherQuantity.AsFloat := QuantityRoundTo(
+      Rec.PreGatherQuantity.AsFloat + Rec.GatherQuantity.AsFloat);
+  Rec.EndGatherTotalPrice.AsFloat := TotalPriceRoundTo(
+      Rec.PreGatherTotalPrice.AsFloat + Rec.GatherTotalPrice.AsFloat);
+end;
+
+function TStageData.GetActive: Boolean;
+begin
+  Result := sddStage.Active;
+end;
+
+procedure TStageData.SetTableName(const Value: string);
+begin
+  sdpStage.TableName := Value;
+end;
+
+procedure TStageData.sddStageGetRecordClass(
+  var ARecordClass: TsdRecordClass);
+begin
+  ARecordClass := TStageRecord;
+end;
+
+function TStageData.GetChapterStageGather(AChapter: Integer): Double;
+
+  function CheckCodeChapter(const ACode: string): Boolean;
+  var
+    iFirst: Integer;
+    sgs: TStrings;
+  begin
+    sgs := TStringList.Create;
+    try
+      sgs.Delimiter := '-';
+      sgs.DelimitedText := ACode;
+      if sgs.Count > 1 then
+      begin
+        iFirst := StrToIntDef(sgs[0], 0) div 100;
+        Result := iFirst = AChapter;
+      end
+      else
+        Result := False;
+    finally
+      sgs.Free;
+    end;
+  end;
+
+var
+  iIndex: Integer;
+  Rec: TsdDataRecord;
+  stnNode: TsdIDTreeNode;
+begin
+  Result := 0;
+  for iIndex := 0 to sddStage.RecordCount - 1 do
+  begin
+    Rec := sddStage.Records[iIndex];
+    stnNode := MainBillsTree.FindNode(Rec.ValueByName('BillsID').AsInteger);
+    if not stnNode.HasChildren and CheckCodeChapter(stnNode.Rec.ValueByName('B_Code').AsString) then
+      Result := Result + Rec.ValueByName('GatherTotalPrice').AsFloat;
+  end;
+end;
+
+end.

+ 64 - 0
DataModules/StandardBillsDm.dfm

@@ -0,0 +1,64 @@
+object StandardBillsData: TStandardBillsData
+  OldCreateOrder = False
+  Left = 191
+  Top = 110
+  Height = 355
+  Width = 295
+  object sdpStdBills: TsdADOProvider
+    Left = 216
+    Top = 16
+  end
+  object sddStdBills: TsdDataSet
+    Active = False
+    Provider = sdpStdBills
+    Left = 216
+    Top = 72
+    FieldListData = {
+      0101044E616D6506024944094669656C644E616D650602494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D650608506172656E744944094669656C644E61
+      6D650608506172656E7449440844617461547970650203084461746153697A65
+      02040549734B6579080F4E65656450726F636573734E616D65090001044E616D
+      6506064E6578744944094669656C644E616D6506064E65787449440844617461
+      547970650203084461746153697A6502040549734B6579080F4E65656450726F
+      636573734E616D65090001044E616D650604436F6465094669656C644E616D65
+      0604436F64650844617461547970650201084461746153697A6502320549734B
+      6579080F4E65656450726F636573734E616D65090001044E616D650606425F43
+      6F6465094669656C644E616D650606425F436F64650844617461547970650201
+      084461746153697A6502320549734B6579080F4E65656450726F636573734E61
+      6D65090001044E616D6506044E616D65094669656C644E616D6506044E616D65
+      0844617461547970650218084461746153697A6503C8000549734B6579080F4E
+      65656450726F636573734E616D65090001044E616D650604556E697409466965
+      6C644E616D650604556E69740844617461547970650218084461746153697A65
+      02140549734B6579080F4E65656450726F636573734E616D65090000}
+  end
+  object sdvStdBills: TsdDataView
+    Active = False
+    DataSet = sddStdBills
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'ParentID'
+      end
+      item
+        FieldName = 'NextID'
+      end
+      item
+        FieldName = 'Code'
+      end
+      item
+        FieldName = 'B_Code'
+      end
+      item
+        FieldName = 'Name'
+      end
+      item
+        FieldName = 'Unit'
+      end>
+    Left = 216
+    Top = 136
+  end
+end

+ 80 - 0
DataModules/StandardBillsDm.pas

@@ -0,0 +1,80 @@
+unit StandardBillsDm;
+
+interface
+
+uses
+  SysUtils, Classes, ADODB, DB, DBClient, Provider, sdIDTree,
+  UtilMethods, sdDB, sdProvider;
+
+type
+  TStandardBillsData = class(TDataModule)
+    sdpStdBills: TsdADOProvider;
+    sddStdBills: TsdDataSet;
+    sdvStdBills: TsdDataView;
+  private
+    FBillsTree: TsdIDTree;
+
+    procedure CreateBillsTree;
+    procedure OpenConnetion(AConnection: TADOConnection);
+    procedure ExpandFirstNode;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+
+    property BillsTree: TsdIDTree read FBillsTree;
+  end;
+
+implementation
+
+{$R *.dfm}
+
+{ TStandardBillsData }
+
+constructor TStandardBillsData.Create(AOwner: TComponent);
+begin
+  inherited;
+  CreateBillsTree;
+end;
+
+procedure TStandardBillsData.CreateBillsTree;
+begin
+  FBillsTree := TsdIDTree.Create;
+  FBillsTree.KeyFieldName := 'ID';
+  FBillsTree.ParentFieldName := 'ParentID';
+  FBillsTree.NextSiblingFieldName := 'NextID';
+  FBillsTree.AutoExpand := False;
+end;
+
+destructor TStandardBillsData.Destroy;
+begin
+  FBillsTree.Free;
+  inherited;
+end;
+
+procedure TStandardBillsData.ExpandFirstNode;
+begin
+  if FBillsTree.FirstNode <> nil then
+    FBillsTree.FirstNode.Expand;
+end;
+
+procedure TStandardBillsData.Open(AConnection: TADOConnection);
+begin
+  OpenConnetion(AConnection);
+  FBillsTree.DataView := sdvStdBills;
+  ExpandFirstNode;
+end;
+
+procedure TStandardBillsData.OpenConnetion(AConnection: TADOConnection);
+begin
+  sdpStdBills.Connection := AConnection;
+  sdpStdBills.TableName := 'BillsTree';
+  sddStdBills.Open;
+  sdvStdBills.Open;
+  sddStdBills.AddIndex('idxID', 'ID');
+  sddStdBills.AddIndex('sdxCode', 'Code');
+  sddStdBills.AddIndex('sddBCode', 'B_Code');
+end;
+
+end.

+ 80 - 0
DataModules/TenderBackupDm.dfm

@@ -0,0 +1,80 @@
+object TenderBackupData: TTenderBackupData
+  OldCreateOrder = False
+  Left = 425
+  Top = 328
+  Height = 228
+  Width = 238
+  object sdpTenderBackup: TsdADOProvider
+    TableName = 'TenderBackup'
+    Left = 48
+    Top = 16
+  end
+  object sddTenderBackup: TsdDataSet
+    Active = False
+    Provider = sdpTenderBackup
+    Left = 48
+    Top = 72
+    FieldListData = {
+      0101044E616D6506024944094669656C644E616D650602494408446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D65060950726F6A6563744944094669656C644E
+      616D65060950726F6A6563744944084461746154797065020308446174615369
+      7A6502040549734B6579080F4E65656450726F636573734E616D65090001044E
+      616D65060454797065094669656C644E616D6506045479706508446174615479
+      70650203084461746153697A6502040549734B6579080F4E65656450726F6365
+      73734E616D65090001044E616D65060846696C654E616D65094669656C644E61
+      6D65060846696C654E616D650844617461547970650218084461746153697A65
+      03FF000549734B6579080F4E65656450726F636573734E616D65090001044E61
+      6D65060E4372656174654461746554696D65094669656C644E616D65060E4372
+      656174654461746554696D65084461746154797065020B084461746153697A65
+      02080549734B6579080F4E65656450726F636573734E616D65090000}
+  end
+  object sdvTenderBackup: TsdDataView
+    Active = False
+    DataSet = sddTenderBackup
+    Filtered = True
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'ProjectID'
+      end
+      item
+        FieldName = 'Type'
+      end
+      item
+        FieldName = 'FileName'
+      end
+      item
+        FieldName = 'CreateDateTime'
+      end>
+    OnFilterRecord = sdvTenderBackupFilterRecord
+    OnGetText = sdvTenderBackupGetText
+    Left = 48
+    Top = 128
+  end
+  object sdvSearchTB: TsdDataView
+    Active = False
+    DataSet = sddTenderBackup
+    Filtered = False
+    Columns = <
+      item
+        FieldName = 'ID'
+      end
+      item
+        FieldName = 'ProjectID'
+      end
+      item
+        FieldName = 'Type'
+      end
+      item
+        FieldName = 'FileName'
+      end
+      item
+        FieldName = 'CreateDateTime'
+      end>
+    Left = 144
+    Top = 128
+  end
+end

+ 220 - 0
DataModules/TenderBackupDm.pas

@@ -0,0 +1,220 @@
+unit TenderBackupDm;
+
+interface
+
+uses
+  SysUtils, Classes, ADODB, sdDB, sdProvider, Variants;
+
+type
+  TTenderBackupData = class(TDataModule)
+    sdpTenderBackup: TsdADOProvider;
+    sddTenderBackup: TsdDataSet;
+    sdvTenderBackup: TsdDataView;
+    sdvSearchTB: TsdDataView;
+    procedure sdvTenderBackupFilterRecord(ARecord: TsdDataRecord;
+      var Allow: Boolean);
+    procedure sdvTenderBackupGetText(var Text: String;
+      ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+      DisplayText: Boolean);
+  private
+    FProjectID: Integer;
+    FNewID: Integer;
+
+    function TenderBackupCount(AProjectID, AType: Integer): Integer;
+    function NewTenderBackup(AProjectID, AType: Integer): TsdDataRecord;
+    function OldestTenderBackup(AProjectID, AType: Integer): TsdDataRecord;
+    function AddTenderBackup(AProjectID, AType: Integer): TsdDataRecord;
+
+    procedure SetProjectID(const Value: Integer);
+  public
+    procedure Open(AConnection: TADOConnection);
+    procedure Save;
+
+    function AddOpenTenderBackup(AProjectID: Integer): TsdDataRecord;
+    function AddSaveTenderBackup(AProjectID: Integer): TsdDataRecord;
+
+    function HasTodayOpenTenderBackup(AProjectID: Integer): Boolean;
+
+    property ProjectID: Integer read FProjectID write SetProjectID;
+  end;
+
+implementation
+
+uses DateUtils;
+
+{$R *.dfm}
+
+{ TTenderBackupData }
+
+procedure TTenderBackupData.Open(AConnection: TADOConnection);
+var
+  idxID: TsdIndex;
+begin
+  sdpTenderBackup.Connection := AConnection;
+  sddTenderBackup.Open;
+  sddTenderBackup.AddIndex('idxID', 'ID');
+  sddTenderBackup.AddIndex('idxFilter', 'ProjectID;Type');
+  sddTenderBackup.AddIndex('idxView', 'ProjectID;Type;ID');
+  sdvTenderBackup.Open;
+  sdvTenderBackup.IndexName := 'idxView';
+  sdvSearchTB.Open;
+  sdvSearchTB.IndexName := 'idxFilter';
+
+  if sddTenderBackup.RecordCount > 0 then
+  begin
+    idxID := sddTenderBackup.FindIndex('idxID');
+    FNewID := idxID.Records[sddTenderBackup.RecordCount - 1].ValueByName('ID').AsInteger + 1;
+  end
+  else
+    FNewID := 1;
+end;
+
+procedure TTenderBackupData.Save;
+begin
+  sddTenderBackup.Save;
+end;
+
+procedure TTenderBackupData.SetProjectID(const Value: Integer);
+begin
+  FProjectID := Value;
+  sdvTenderBackup.RefreshFilter;
+end;
+
+procedure TTenderBackupData.sdvTenderBackupFilterRecord(
+  ARecord: TsdDataRecord; var Allow: Boolean);
+begin
+  Allow := ARecord.ValueByName('ProjectID').AsInteger = ProjectID;
+end;
+
+function TTenderBackupData.TenderBackupCount(AProjectID,
+  AType: Integer): Integer;
+var
+  idx: TsdIndex;
+  iFirst, iLast: Integer;
+  Rec: TsdDataRecord;
+begin
+  Result := 0;
+  sdvSearchTB.IndexName := 'idxFilter';
+  sdvSearchTB.SetRange([AProjectID, AType], [AProjectID, AType]);
+  Result := sdvSearchTB.RecordCount;
+  sdvSearchTB.CancelRange;
+{  idx := sddTenderBackup.FindIndex('idxFilter');
+  iFirst := idx.FindKeyIndex(VarArrayOf([AProjectID, AType]));
+  iLast := idx.FindKeyLastIndex(VarArrayOf([AProjectID, AType]));
+  if iFirst > 0 then
+    Result := iLast - iFirst + 1;}
+end;
+
+function TTenderBackupData.AddOpenTenderBackup(
+  AProjectID: Integer): TsdDataRecord;
+begin
+  Result := AddTenderBackup(AProjectID, 1);
+end;
+
+function TTenderBackupData.AddSaveTenderBackup(
+  AProjectID: Integer): TsdDataRecord;
+begin
+  Result := AddTenderBackup(AProjectID, 0);
+end;
+
+function TTenderBackupData.AddTenderBackup(AProjectID,
+  AType: Integer): TsdDataRecord;
+var
+  iCount: Integer;
+begin
+  iCount := TenderBackupCount(AProjectID, AType);
+  if iCount < 5 then
+    Result := NewTenderBackup(AProjectID, AType)
+  else
+    Result := OldestTenderBackup(AProjectID, AType);
+end;
+
+function TTenderBackupData.NewTenderBackup(AProjectID,
+  AType: Integer): TsdDataRecord;
+var
+  iCount: Integer;
+begin
+  iCount := TenderBackupCount(AProjectID, AType);
+  Result := sddTenderBackup.Add;
+  Result.ValueByName('ID').AsInteger := FNewID;
+  Inc(FNewID);
+  Result.ValueByName('ProjectID').AsInteger := FProjectID;
+  Result.ValueByName('Type').AsInteger := AType;
+  if AType = 0 then
+    Result.ValueByName('FileName').AsString := Format('s%d.mtf', [iCount + 1])
+  else
+    Result.ValueByName('FileName').AsString := Format('o%d.mtf', [iCount + 1]);
+end;
+
+function TTenderBackupData.OldestTenderBackup(AProjectID,
+  AType: Integer): TsdDataRecord;
+var
+  idx: TsdIndex;
+  iIndex, iFirst, iLast: Integer;
+  Rec: TsdDataRecord;
+begin
+  idx := sddTenderBackup.FindIndex('idxFilter');
+  iFirst := idx.FindKeyIndex(VarArrayOf([AProjectID, AType]));
+  iLast := idx.FindKeyLastIndex(VarArrayOf([AProjectID, AType]));
+  Result := idx.Records[iFirst];
+  for iIndex := iFirst + 1 to iLast do
+  begin
+    Rec := idx.Records[iIndex];
+    if Result.ValueByName('CreateDateTime').AsDateTime > Rec.ValueByName('CreateDateTime').AsDateTime then
+      Result := Rec;
+  end;
+end;
+
+function TTenderBackupData.HasTodayOpenTenderBackup(
+  AProjectID: Integer): Boolean;
+var
+  idx: TsdIndex;
+  iIndex, iFirst, iLast: Integer;
+  Rec: TsdDataRecord;
+begin
+  Result := False;
+  sdvSearchTB.IndexName := 'idxFilter';
+  sdvSearchTB.SetRange([AProjectID, 1], [AProjectID, 1]);
+  for iIndex := 0 to sdvSearchTB.RecordCount - 1 do
+  begin
+    Rec := sdvSearchTB.Records[iIndex];
+    if Date = Trunc(Rec.ValueByName('CreateDateTime').AsDateTime) then
+    begin
+      Result := True;
+      Break;
+    end;
+  end;
+  sdvSearchTB.CancelRange;
+  {idx := sddTenderBackup.FindIndex('idxFilter');
+  iFirst := idx.FindKeyIndex(VarArrayOf([AProjectID, 1]));
+  iLast := idx.FindKeyLastIndex(VarArrayOf([AProjectID, 1]));
+  if iFirst = -1 then Exit;
+  for iIndex := iFirst to iLast do
+  begin
+    Rec := idx.Records[iIndex];
+    if Date = Trunc(Rec.ValueByName('CreateDateTime').AsDateTime) then
+    begin
+      Result := True;
+      Break;
+    end;
+  end;}
+end;
+
+procedure TTenderBackupData.sdvTenderBackupGetText(var Text: String;
+  ARecord: TsdDataRecord; AValue: TsdValue; AColumn: TsdViewColumn;
+  DisplayText: Boolean);
+begin
+  if SameText(AValue.FieldName, 'Type') then
+  begin
+    if AValue.AsInteger = 0 then
+      Text := '±£´æ±¸·Ýµã'
+    else if AValue.AsInteger = 1 then
+      Text := '´ò¿ª±¸·Ýµã';
+  end
+  else if SameText(AValue.FieldName, 'CreateDateTime') then
+  begin
+    Text := DateTimeToStr(AValue.AsDateTime);
+  end;
+end;
+
+end.

+ 90 - 0
DataModules/ZJJLDm.dfm

@@ -0,0 +1,90 @@
+object ZJJLData: TZJJLData
+  OldCreateOrder = False
+  Left = 691
+  Top = 246
+  Height = 241
+  Width = 166
+  object atZJJL: TADOTable
+    TableName = 'ZJJL'
+    Left = 33
+    Top = 17
+  end
+  object dspZJJL: TDataSetProvider
+    DataSet = atZJJL
+    UpdateMode = upWhereKeyOnly
+    Left = 33
+    Top = 80
+  end
+  object cdsZJJL: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    ProviderName = 'dspZJJL'
+    Left = 33
+    Top = 144
+    object cdsZJJLID: TIntegerField
+      FieldName = 'ID'
+    end
+    object cdsZJJLBillsID: TIntegerField
+      FieldName = 'BillsID'
+    end
+    object cdsZJJLCode: TWideStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsZJJLCertificateCode: TWideStringField
+      FieldName = 'CertificateCode'
+      Size = 50
+    end
+    object cdsZJJLBillsCode: TWideStringField
+      FieldName = 'BillsCode'
+      Size = 50
+    end
+    object cdsZJJLFormulaMemo: TWideStringField
+      FieldName = 'FormulaMemo'
+      Size = 255
+    end
+    object cdsZJJLRelaFile: TWideStringField
+      FieldName = 'RelaFile'
+      Size = 200
+    end
+    object cdsZJJLType: TIntegerField
+      FieldName = 'Type'
+    end
+  end
+  object cdsZJJLView: TClientDataSet
+    Aggregates = <>
+    Params = <>
+    AfterScroll = cdsZJJLViewAfterScroll
+    Left = 97
+    Top = 144
+    object cdsZJJLViewID: TIntegerField
+      FieldName = 'ID'
+    end
+    object cdsZJJLViewBillsID: TIntegerField
+      FieldName = 'BillsID'
+    end
+    object cdsZJJLViewCode: TWideStringField
+      FieldName = 'Code'
+      Size = 50
+    end
+    object cdsZJJLViewCertificateCode: TWideStringField
+      FieldName = 'CertificateCode'
+      Size = 50
+    end
+    object cdsZJJLViewBillsCode: TWideStringField
+      FieldName = 'BillsCode'
+      Size = 50
+    end
+    object cdsZJJLViewFormulaMemo: TWideStringField
+      FieldName = 'FormulaMemo'
+      Size = 255
+    end
+    object cdsZJJLViewRelaFile: TWideStringField
+      FieldName = 'RelaFile'
+      Size = 200
+    end
+    object cdsZJJLViewType: TIntegerField
+      FieldName = 'Type'
+    end
+  end
+end

+ 547 - 0
DataModules/ZJJLDm.pas

@@ -0,0 +1,547 @@
+unit ZJJLDm;
+
+interface
+
+uses
+  ZjGrid,
+  SysUtils, Classes, DB, DBClient, ADODB, sdIDTree, sdDB, Provider,
+  Windows;
+
+type
+  TZJJLNode = class
+  private
+    FBillsID: Integer;
+    FCode: string;
+    FCertificateCode: string;
+    FBillsCode: string;
+    FFormulaMemo: string;
+    FRelaFile: string;
+    FType: Integer;
+  end;
+
+  TZJJLInfoRec = Record
+    FBFXName: string;
+    PegName: string;
+    BGLCode: string;
+    DrawingCode: string;
+    UnitName: string;
+  end;
+
+  TZJJLData = class(TDataModule)
+    atZJJL: TADOTable;
+    dspZJJL: TDataSetProvider;
+    cdsZJJL: TClientDataSet;
+    cdsZJJLID: TIntegerField;
+    cdsZJJLBillsID: TIntegerField;
+    cdsZJJLRelaFile: TWideStringField;
+    cdsZJJLFormulaMemo: TWideStringField;
+    cdsZJJLView: TClientDataSet;
+    cdsZJJLViewID: TIntegerField;
+    cdsZJJLViewBillsID: TIntegerField;
+    cdsZJJLViewFormulaMemo: TWideStringField;
+    cdsZJJLViewRelaFile: TWideStringField;
+    cdsZJJLCode: TWideStringField;
+    cdsZJJLCertificateCode: TWideStringField;
+    cdsZJJLBillsCode: TWideStringField;
+    cdsZJJLViewCode: TWideStringField;
+    cdsZJJLViewCertificateCode: TWideStringField;
+    cdsZJJLViewBillsCode: TWideStringField;
+    cdsZJJLType: TIntegerField;
+    cdsZJJLViewType: TIntegerField;
+    procedure cdsZJJLViewAfterScroll(DataSet: TDataSet);
+  private
+    FPhaseData: TObject;
+    FCanModified: Boolean;
+    FNewID: Integer;
+    FOrgDataList: TList;
+    FDetailGrid: TZJGrid;
+
+    procedure GenerateZJJLNode(ANode: TsdIDTreeNode; AType: Integer);
+
+    function CheckLastXmj(AID: Integer): Boolean;
+    function CheckBGExist(ANode: TsdIDTreeNode): Boolean;
+    function CheckMeasureExist(ANode: TsdIDTreeNode): Boolean;
+    procedure GenerateLastXmj(ANode: TsdIDTreeNode);
+    procedure GenerateNode(ANode: TsdIDTreeNode);
+
+    procedure GenerateLeafNode(ANode: TsdIDTreeNode);
+    procedure GenerateNodeByB_Code(ANode: TsdIDTreeNode);
+
+    procedure DeleteAll;
+    procedure RestoreOrgData;
+
+    procedure DetailGridCellCanEdit(Sender: TObject; const ACoord: TPoint;
+      var Allow: Boolean);
+    procedure DetailGridCellTextChanged(Sender: TObject; Col, Row: Integer);
+
+    function GetMainBillsTree: TsdIDTree;
+  public
+    constructor Create(APhaseData: TObject);
+    destructor Destroy; override;
+
+    procedure Open(AConnection: TADOConnection);
+    procedure Save;
+
+    procedure GenerateAll;
+    procedure GenerateAllByB_Code;
+    procedure AssignedCurData;
+
+    function GetInfoRecByCode(ABillsID: Integer): TZJJLInfoRec;
+    function GetInfoRecByB_Code(ABillsID: Integer): TZJJLInfoRec;
+    function GetInfoRec(ABillsID, AType: Integer): TZJJLInfoRec;
+
+    procedure LocateBills;
+
+    property PhaseData: TObject read FPhaseData;
+    property MainBillsTree: TsdIDTree read GetMainBillsTree;
+    property CanModified: Boolean read FCanModified write FCanModified;
+    property DetailGrid: TZJGrid read FDetailGrid;
+  end;
+
+implementation
+
+uses
+  PhaseData, ProjectData, BillsDm, UtilMethods, ProjectProperty, ZhAPI,
+  BillsCompileDm, BillsMeasureDm;
+
+{$R *.dfm}
+
+{ TZJJLData }
+
+constructor TZJJLData.Create(APhaseData: TObject);
+begin
+  inherited Create(nil);
+  FPhaseData := APhaseData;
+  FOrgDataList := TList.Create;
+  FDetailGrid := TZJGrid.Create(nil);
+  FDetailGrid.Options := FDetailGrid.Options + [goWarpText];
+  FDetailGrid.OnCellCanEdit := DetailGridCellCanEdit;
+  FDetailGrid.OnCellTextChanged := DetailGridCellTextChanged;
+end;
+
+destructor TZJJLData.Destroy;
+begin
+  FDetailGrid.Free;
+  ClearObjects(FOrgDataList);
+  FOrgDataList.Free;
+  inherited;
+end;
+
+function TZJJLData.GetMainBillsTree: TsdIDTree;
+begin
+  with TProjectData(TPhaseData(FPhaseData).ProjectData) do
+    Result := BillsMeasureData.BillsMeasureTree;
+end;
+
+procedure TZJJLData.Open(AConnection: TADOConnection);
+begin
+  atZJJL.Connection := AConnection;
+  cdsZJJL.Open;
+  cdsZJJL.IndexFieldNames := 'ID';
+  cdsZJJLView.CloneCursor(cdsZJJL, True);
+  cdsZJJLView.IndexFieldNames := 'ID';
+end;
+
+procedure TZJJLData.Save;
+begin
+  cdsZJJL.ApplyUpdates(0);
+end;
+
+function TZJJLData.CheckLastXmj(AID: Integer): Boolean;
+var
+  stnNode, stnChild: TsdIDTreeNode;
+begin
+  stnNode := MainBillsTree.FindNode(AID);
+  Result := stnNode.Rec.ValueByName('Code').AsString <> '';
+  if not stnNode.HasChildren or not Result then Exit;
+  stnChild := stnNode.FirstChild;
+  Result := stnChild.Rec.ValueByName('B_Code').AsString <> '';
+end;
+
+procedure TZJJLData.AssignedCurData;
+var
+  iRowIndex: Integer;
+  InfoRec: TZJJLInfoRec;
+begin
+  FDetailGrid.OnCellTextChanged := nil;
+  FDetailGrid.FixedRowCount := 0;
+  FDetailGrid.FixedColCount := 0;
+  FDetailGrid.ColCount := 1;
+  FDetailGrid.RowCount := 9;
+  FDetailGrid.DefaultColWidth := 300;
+  for iRowIndex := 0 to FDetailGrid.RowCount - 1 do
+    FDetailGrid[0, iRowIndex].Align := gaTopLeft;
+  InfoRec := GetInfoRec(cdsZJJLViewBillsID.AsInteger, cdsZJJLViewType.AsInteger);
+  FDetailGrid.Cells[0, 0].Text := '变更令号:' + InfoRec.BGLCode;
+  FDetailGrid.Cells[0, 1].Text := '桩号或部位:' + InfoRec.PegName;
+  FDetailGrid.Cells[0, 2].Text := '分部分项工程:' + InfoRec.FBFXName;
+  FDetailGrid.Cells[0, 3].Text := '计量单元:' + InfoRec.UnitName;
+  FDetailGrid.Cells[0, 4].Text := '图号:' + InfoRec.DrawingCode;
+  FDetailGrid.Cells[0, 5].Text := '计算式说明:';
+  FDetailGrid.Cells[0, 6].Text := cdsZJJLViewFormulaMemo.AsString;
+  FDetailGrid.Cells[0, 6].Align := gaTopLeft;
+  FDetailGrid.RowHeights[6] := 57;
+  FDetailGrid.Cells[0, 7].Text := '计算草图几何尺寸:';
+  FDetailGrid.Cells[0, 8].Text := cdsZJJLViewRelaFile.AsString;
+  FDetailGrid.Cells[0, 8].Align := gaTopLeft;
+  FDetailGrid.RowHeights[8] := 57;
+  FDetailGrid.OnCellTextChanged := DetailGridCellTextChanged;
+end;
+
+procedure TZJJLData.GenerateAll;
+begin
+  RestoreOrgData;
+  FNewID := 1;
+  DeleteAll;
+  GenerateNode(MainBillsTree.FirstNode);
+end;
+
+procedure TZJJLData.GenerateNode(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if CheckLastXmj(ANode.ID) then
+    GenerateLastXmj(ANode)
+  else
+    GenerateNode(ANode.FirstChild);
+  GenerateNode(ANode.NextSibling);
+end;
+
+procedure TZJJLData.GenerateLastXmj(ANode: TsdIDTreeNode);
+begin
+  if CheckMeasureExist(ANode) then
+    GenerateZJJLNode(ANode, 0);
+end;
+
+function TZJJLData.CheckBGExist(ANode: TsdIDTreeNode): Boolean;
+
+  function CheckBGLExist(AID: Integer): Boolean;
+  var
+    StageRec: TsdDataRecord;
+  begin
+    StageRec := TPhaseData(FPhaseData).StageData.StageRecord(AID);
+    Result := Assigned(StageRec) and
+           ((StageRec.ValueByName('QcBGLCode').AsString <> '')
+           or (StageRec.ValueByName('PcBGLCode').AsString <> ''));
+  end;
+
+var
+  iChild: Integer;
+begin
+  Result := False;
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+  begin
+    for iChild := 0 to ANode.ChildCount - 1 do
+    begin
+      Result := Result or CheckBGExist(ANode.ChildNodes[iChild]);
+      if Result then Break;
+    end;
+  end
+  else
+    Result := CheckBGLExist(ANode.ID);
+end;
+
+procedure TZJJLData.DeleteAll;
+begin
+  cdsZJJL.First;
+  while not cdsZJJL.Eof do
+    cdsZJJL.Delete;
+end;
+
+procedure TZJJLData.RestoreOrgData;
+
+  function CreateNodeData: TZJJLNode;
+  begin
+    Result := TZJJLNode.Create;
+    Result.FBillsID := cdsZJJLBillsID.AsInteger;
+    Result.FCode := cdsZJJLCode.AsString;
+    Result.FCertificateCode := cdsZJJLCertificateCode.AsString;
+    Result.FBillsCode := cdsZJJLBillsCode.AsString;
+    Result.FFormulaMemo := cdsZJJLFormulaMemo.AsString;
+    Result.FRelaFile := cdsZJJLRelaFile.AsString;
+    Result.FType := cdsZJJLType.AsInteger;
+  end;
+
+begin
+  FOrgDataList.Clear;
+  cdsZJJL.First;
+  while not cdsZJJL.Eof do
+  begin
+    FOrgDataList.Add(CreateNodeData);
+    cdsZJJL.Next;
+  end;
+end;
+
+function TZJJLData.CheckMeasureExist(ANode: TsdIDTreeNode): Boolean;
+
+  function CheckStageCompleteData(AID: Integer): Boolean;
+  var
+    StageRec: TsdDataRecord;
+  begin
+    StageRec := TPhaseData(FPhaseData).StageData.StageRecord(AID);
+    Result := Assigned(StageRec) and
+           ((StageRec.ValueByName('GatherQuantity').AsFloat <> 0)
+           or (StageRec.ValueByName('GatherTotalPrice').AsFloat <> 0));
+  end;
+
+var
+  iChild: Integer;
+begin
+  Result := False;
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+  begin
+    for iChild := 0 to ANode.ChildCount - 1 do
+    begin
+      Result := Result or CheckMeasureExist(ANode.ChildNodes[iChild]);
+      if Result then Break;
+    end;
+  end
+  else
+    Result := CheckStageCompleteData(ANode.ID);
+end;
+
+procedure TZJJLData.cdsZJJLViewAfterScroll(DataSet: TDataSet);
+begin
+  AssignedCurData;
+end;
+
+procedure TZJJLData.DetailGridCellCanEdit(Sender: TObject;
+  const ACoord: TPoint; var Allow: Boolean);
+begin
+  Allow := ((ACoord.Y = 6) or (ACoord.Y = 8)) and
+      not TPhaseData(FPhaseData).StageDataReadOnly;
+end;
+
+function TZJJLData.GetInfoRecByCode(ABillsID: Integer): TZJJLInfoRec;
+
+  function GetBGLCode(ANode: TsdIDTreeNode): string;
+  begin
+    with TProjectData(TPhaseData(FPhaseData).ProjectData) do
+      Result := BillsMeasureData.GatherRelaBGL(ANode);
+  end;
+
+  function GetPegName(APegNode: TsdIDTreeNode): string;
+  begin
+    if Assigned(APegNode) then
+      Result := APegNode.Rec.ValueByName('Name').AsString
+    else
+      Result := '';
+  end;
+
+  function GetPegNode(ANode: TsdIDTreeNode): TsdIDTreeNode;
+  begin
+    Result := nil;
+    if not Assigned(ANode) then Exit;
+    if CheckPeg(ANode.Rec.ValueByName('Name').AsString) then
+      Result := ANode
+    else
+      Result := GetPegNode(ANode.Parent);
+  end;
+
+  // 取树结构的第ALevel层节点的名称(level从0开始)
+  function GetNameByLevel(ANode: TsdIDTreeNode; ALevel: Integer): string;
+  begin
+    Result := '';
+    if not Assigned(ANode) then Exit;
+    if ANode.Level = ALevel then
+      Result := ANode.Rec.ValueByName('Name').AsString
+    else if ANode.Level > ALevel then
+      Result := GetNameByLevel(ANode.Parent, ALevel);
+  end;
+
+  function GetFBFXName(ANode, APegNode: TsdIDTreeNode): string;
+  var
+    vCurNode: TsdIDTreeNode;
+  begin
+    Result := '';
+    if not Assigned(ANode) then Exit;
+    // 如果计量单元节点的名称为桩号(转化为判断计量单元节点与桩号节点为同一个)
+    if not Assigned(APegNode) or (ANode.ID = APegNode.ID) then
+    begin
+      // 取树结构的第三、四层节点的名称
+      Result := GetNameByLevel(ANode, 2);
+      if (Result <> '') and (GetNameByLevel(ANode, 3) <> '') then
+        Result := Result + ',';
+      Result := Result + GetNameByLevel(ANode, 3);
+    end
+    // 否则,合并[桩号节点的子节点]至[计量单元节点的父节点]的名称
+    else
+    begin
+      vCurNode := ANode.Parent;
+      // 转化为判断层次,层次大于[桩号节点的子节点]的层次
+      while vCurNode.Level > APegNode.Level do
+      begin
+        Result := vCurNode.Rec.ValueByName('Name').AsString + ',' + Result;
+        vCurNode := vCurNode.Parent;
+      end;
+    end;
+  end;
+
+  function GetFieldStrDef(ANode: TsdIDTreeNode; const AFieldName, ADef: string): string;
+  begin
+    if Assigned(ANode) then
+      Result := ANode.Rec.ValueByName(AFieldName).AsString
+    else
+      Result := '';
+  end;
+
+var
+  vPeg, vNode: TsdIDTreeNode;
+begin
+  vNode := MainBillsTree.FindNode(ABillsID);
+  vPeg := GetPegNode(vNode);
+  Result.BGLCode := GetBGLCode(vNode);
+  Result.PegName := GetPegName(vPeg);
+  Result.FBFXName := GetFBFXName(vNode, vPeg);
+  Result.UnitName := GetFieldStrDef(vNode, 'Name', '');
+  Result.DrawingCode := GetFieldStrDef(vNode, 'DrawingCode', '');
+end;
+
+procedure TZJJLData.DetailGridCellTextChanged(Sender: TObject; Col,
+  Row: Integer);
+begin
+  if (Row = 6) then
+  begin
+    cdsZJJLView.Edit;
+    cdsZJJLViewFormulaMemo.AsString := TZJGrid(Sender).Cells[Col, Row].Text;
+    cdsZJJLView.Post;
+  end
+  else if (Row = 8) then
+  begin
+    cdsZJJLView.Edit;
+    cdsZJJLViewRelaFile.AsString := TZJGrid(Sender).Cells[Col, Row].Text;
+    cdsZJJLView.Post;
+  end;
+end;
+
+procedure TZJJLData.GenerateAllByB_Code;
+begin
+  RestoreOrgData;
+  FNewID := 1;
+  DeleteAll;
+  GenerateNodeByB_Code(MainBillsTree.FirstNode);
+end;
+
+procedure TZJJLData.GenerateNodeByB_Code(ANode: TsdIDTreeNode);
+begin
+  if not Assigned(ANode) then Exit;
+  if ANode.HasChildren then
+    GenerateNodeByB_Code(ANode.FirstChild)
+  else
+    GenerateLeafNode(ANode);
+  GenerateNodeByB_Code(ANode.NextSibling);
+end;
+
+procedure TZJJLData.GenerateLeafNode(ANode: TsdIDTreeNode);
+
+  function CheckMeasureExist(AID: Integer): Boolean;
+  var
+    StageRec: TsdDataRecord;
+  begin
+    StageRec := TPhaseData(FPhaseData).StageData.StageRecord(AID);
+    Result := Assigned(StageRec) and
+           ((StageRec.ValueByName('GatherQuantity').AsFloat <> 0)
+           or (StageRec.ValueByName('GatherTotalPrice').AsFloat <> 0));
+  end;
+
+begin
+  if (ANode.Rec.ValueByName('B_Code').AsString <> '') and
+      CheckMeasureExist(ANode.ID) then
+    GenerateZJJLNode(ANode, 1);
+end;
+
+procedure TZJJLData.GenerateZJJLNode(ANode: TsdIDTreeNode;
+  AType: Integer);
+
+  function GetNewCode: string;
+  begin
+    with TProjectData(TPhaseData(FPhaseData).ProjectData) do
+    begin
+      Result := ProjProperties.ZJJLPreText;
+      if (Result <> '') and (Result[Length(Result)] <> '-') then
+        Result := Result + '-';
+      Result := Result + Format('%d-%d', [PhaseIndex, FNewID]);
+    end;
+  end;
+
+  function GetOrgZJJLNode(ABillsID: Integer): TZJJLNode;
+  var
+    iIndex: Integer;
+  begin
+    Result := nil;
+    for iIndex := 0 to FOrgDataList.Count - 1 do
+      // 7/30新增了一个“总量控制”模式,Type字段控制。真的是要疯掉了。
+      if (TZJJLNode(FOrgDataList.Items[iIndex]).FBillsID = ABillsID)
+          and (TZJJLNode(FOrgDataList.Items[iIndex]).FType = AType) then
+      begin
+        Result := TZJJLNode(FOrgDataList.Items[iIndex]);
+        Break;
+      end;
+  end;
+
+var
+  ZJJLNode: TZJJLNode;
+begin
+  cdsZJJL.Append;
+  cdsZJJLID.AsInteger := FNewID;
+  cdsZJJLBillsID.AsInteger := ANode.ID;
+  cdsZJJLType.AsInteger := AType;
+  ZJJLNode := GetOrgZJJLNode(ANode.ID);
+  if not Assigned(ZJJLNode) then
+  begin
+    cdsZJJLCode.AsString := GetNewCode;
+    cdsZJJLBillsCode.AsString := ANode.Rec.ValueByName('Code').AsString;
+  end
+  else
+  begin
+    cdsZJJLCode.AsString := ZJJLNode.FCode;
+    cdsZJJLCertificateCode.AsString := ZJJLNode.FCertificateCode;
+    cdsZJJLBillsCode.AsString := ZJJLNode.FBillsCode;
+    cdsZJJLFormulaMemo.AsString := ZJJLNode.FFormulaMemo;
+    cdsZJJLRelaFile.AsString := ZJJLNode.FRelaFile;
+  end;
+  cdsZJJL.Post;
+  Inc(FNewID);
+end;
+
+function TZJJLData.GetInfoRecByB_Code(ABillsID: Integer): TZJJLInfoRec;
+
+  function GetBGLCode(ANode: TsdIDTreeNode): string;
+  begin
+    with TProjectData(TPhaseData(FPhaseData).ProjectData) do
+      Result := BillsMeasureData.GatherRelaBGL(ANode);
+  end;
+
+var
+  vNode: TsdIDTreeNode;
+begin
+  vNode := MainBillsTree.FindNode(ABillsID);
+  Result.BGLCode := GetBGLCode(vNode);
+  if Assigned(vNode.Parent) then
+    Result.PegName := vNode.Parent.Rec.ValueByName('Name').AsString;
+  Result.FBFXName := '';
+  Result.UnitName := '';
+  Result.DrawingCode := vNode.Rec.ValueByName('DrawingCode').AsString;
+end;
+
+function TZJJLData.GetInfoRec(ABillsID, AType: Integer): TZJJLInfoRec;
+begin
+  if AType = 0 then
+    Result := GetInfoRecByCode(ABillsID)
+  else if AType = 1 then
+    Result := GetInfoRecByB_Code(ABillsID);
+end;
+
+procedure TZJJLData.LocateBills;
+var
+  Rec: TsdDataRecord;
+begin
+  with TProjectData(TPhaseData(FPhaseData).ProjectData) do
+  begin
+    Rec := BillsData.sddBills.FindKey('idxID', cdsZJJLViewBillsID.AsInteger);
+    BillsCompileData.sdvBillsCompile.LocateInControl(Rec);
+  end;
+end;
+
+end.

+ 41 - 0
Dprs/Pro/Measure.cfg

@@ -0,0 +1,41 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"E:\SmartCostExe\Measure"
+-N"..\..\Dcus"
+-LE"d:\program files\borland\delphi7\Projects\Bpl"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-D_mEncrypt;
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

+ 165 - 0
Dprs/Pro/Measure.dof

@@ -0,0 +1,165 @@
+[FileVersion]
+Version=7.0
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=0
+K=0
+L=1
+M=0
+N=1
+O=1
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=0
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+NamespacePrefix=
+SymbolDeprecated=1
+SymbolLibrary=1
+SymbolPlatform=1
+UnitLibrary=1
+UnitPlatform=1
+UnitDeprecated=1
+HResultCompat=1
+HidingMember=1
+HiddenVirtual=1
+Garbage=1
+BoundsError=1
+ZeroNilCompat=1
+StringConstTruncated=1
+ForLoopVarVarPar=1
+TypedConstVarPar=1
+AsgToTypedConst=1
+CaseLabelRange=1
+ForVariable=1
+ConstructingAbstract=1
+ComparisonFalse=1
+ComparisonTrue=1
+ComparingSignedUnsigned=1
+CombiningSignedUnsigned=1
+UnsupportedConstruct=1
+FileOpen=1
+FileOpenUnitSrc=1
+BadGlobalSymbol=1
+DuplicateConstructorDestructor=1
+InvalidDirective=1
+PackageNoLink=1
+PackageThreadVar=1
+ImplicitImport=1
+HPPEMITIgnored=1
+NoRetVal=1
+UseBeforeDef=1
+ForLoopVarUndef=1
+UnitNameMismatch=1
+NoCFGFileFound=1
+MessageDirective=1
+ImplicitVariants=1
+UnicodeToLocale=1
+LocaleToUnicode=1
+ImagebaseMultiple=1
+SuspiciousTypecast=1
+PrivatePropAccessor=1
+UnsafeType=0
+UnsafeCode=0
+UnsafeCast=0
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=E:\SmartCostExe\Measure
+UnitOutputDir=..\..\Dcus
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=
+Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;Rave50CLX;Rave50VCL;dclOfficeXP;ZjGridD7;DPanel;ExTree;JimComboBoxs;JimTab;PrintComRep;XPMenu_tom;ZjGridFereD7;ZjCommon;SmartDataSet;ZjGridActns;MBaseControls
+Conditionals=_mEncrypt;
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Language]
+ActiveLang=
+ProjectLang=
+RootDir=D:\Program Files\Borland\Delphi7\Bin\
+[Version Info]
+IncludeVerInfo=1
+AutoIncBuild=1
+MajorVer=3
+MinorVer=1
+Release=3
+Build=1031
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=2052
+CodePage=936
+[Version Info Keys]
+CompanyName=珠海纵横创新软件有限公司
+FileDescription=纵横结算决算计量一体化专业版
+FileVersion=3.1.3.1031
+InternalName=Measure
+LegalCopyright=版权所有(C) 珠海纵横创新软件有限公司 2003-2014。保留所有权利。
+LegalTrademarks=Measure
+OriginalFilename=
+ProductName=纵横公路工程计量决算一体化软件
+ProductVersion=3
+Comments=
+[HistoryLists\hlConditionals]
+Count=10
+Item0=_mEncrypt;
+Item1=_mEncrypt;cplPrint;cplOutputToExcelRange
+Item2=cplPrint;_mEncrypt;cplPrint;cplOutputToExcelRange
+Item3=cplPrint;_mEncrypt;cplPrint
+Item4=cplPrint;_mEncrypt
+Item5=cplPrint;
+Item6=cplPrint;_mEncrypt;
+Item7=cplPrint;mEncrypt;
+Item8=cplPrint
+Item9=cplPrint;cplOutputToExcelRange;
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlUnitOutputDirectory]
+Count=2
+Item0=..\..\Dcus
+Item1=..\Dcus
+[HistoryLists\hlOutputDirectorry]
+Count=8
+Item0=E:\SmartCostExe\Measure
+Item1=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(专业版4)
+Item2=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(专业版)
+Item3=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(专业版2)
+Item4=D:\Program Files (x86)\纵横软件\纵横公路工程计量支付(专业版)
+Item5=D:\Program Files\纵横软件\Environment
+Item6=..\..\Environment
+Item7=..\Dcus

+ 169 - 0
Dprs/Pro/Measure.dpr

@@ -0,0 +1,169 @@
+program Measure;
+
+uses
+  Windows,
+  ShareMem,
+  Forms,
+  MainFrm in '..\..\Forms\MainFrm.pas' {MainForm},
+  ProjectManagerFme in '..\..\Frames\ProjectManagerFme.pas' {ProjectManagerFrame: TFrame},
+  UtilMethods in '..\..\Units\UtilMethods.pas',
+  ProjectManagerDm in '..\..\DataModules\ProjectManagerDm.pas' {ProjectManagerData: TDataModule},
+  Connections in '..\..\Units\Connections.pas',
+  TransFile in '..\..\Units\TransFile.pas',
+  ZhAPI in '..\..\Units\ZhAPI.pas',
+  CompactDB in '..\..\Units\CompactDB.pas',
+  OpenProjectManager in '..\..\Units\OpenProjectManager.pas',
+  ProjectData in '..\..\Units\ProjectData.pas',
+  UpdateDataBase in '..\..\Units\UpdateDataBase.pas',
+  DataBaseTables in '..\..\Units\DataBaseTables.pas',
+  ConfigDoc in '..\..\Units\ConfigDoc.pas',
+  SupportUnit in '..\..\Units\SupportUnit.pas',
+  StandardLibs in '..\..\Units\StandardLibs.pas',
+  StandardLib in '..\..\Units\StandardLib.pas',
+  NewProjectFrm in '..\..\Forms\NewProjectFrm.pas' {NewProjectForm},
+  ProjectFme in '..\..\Frames\ProjectFme.pas' {ProjectFrame: TFrame},
+  StandardBillsDm in '..\..\DataModules\StandardBillsDm.pas' {StandardBillsData: TDataModule},
+  StandardBillsFme in '..\..\Frames\StandardBillsFme.pas' {StandardBillsFrame: TFrame},
+  StandardLibsFme in '..\..\Frames\StandardLibsFme.pas' {StandardLibsFrame: TFrame},
+  BillsDm in '..\..\DataModules\BillsDm.pas' {BillsData: TDataModule},
+  BillsMeasureFme in '..\..\Frames\BillsMeasureFme.pas' {BillsMeasureFrame: TFrame},
+  Globals in '..\..\Units\Globals.pas',
+  StageDm in '..\..\DataModules\StageDm.pas' {StageData: TDataModule},
+  ExcelImport in '..\..\Units\ExcelImport.pas',
+  CacheTree in '..\..\Units\CacheTree.pas',
+  MCacheTree in '..\..\Units\MCacheTree.pas',
+  ProjectPropertiesFrm in '..\..\Forms\ProjectPropertiesFrm.pas' {ProjectPropertiesForm},
+  ProjectProperty in '..\..\Units\ProjectProperty.pas',
+  FormulaCalc in '..\..\Units\FormulaCalc.pas',
+  BillsCommand in '..\..\Units\BillsCommand.pas',
+  PhaseData in '..\..\Units\PhaseData.pas',
+  PhaseProperty in '..\..\Units\PhaseProperty.pas',
+  BillsClipboard in '..\..\Units\BillsClipboard.pas',
+  BillsTree in '..\..\Units\BillsTree.pas',
+  ProjectCommands in '..\..\Units\ProjectCommands.pas',
+  PhaseCompareDm in '..\..\DataModules\PhaseCompareDm.pas' {PhaseCompareData: TDataModule},
+  PhaseCompareFme in '..\..\Frames\PhaseCompareFme.pas' {PhaseCompareFrame: TFrame},
+  OptionFrm in '..\..\Forms\OptionFrm.pas' {OptionForm},
+  DealPaymentDm in '..\..\DataModules\DealPaymentDm.pas' {DealPaymentData: TDataModule},
+  DealPaymentFme in '..\..\Frames\DealPaymentFme.pas' {DealPaymentFrame: TFrame},
+  PhasePayDm in '..\..\DataModules\PhasePayDm.pas' {PhasePayData: TDataModule},
+  BillsGatherFme in '..\..\Frames\BillsGatherFme.pas' {BillsGatherFrame: TFrame},
+  BillsGatherDm in '..\..\DataModules\BillsGatherDm.pas' {BillsGatherData: TDataModule},
+  ZJJLFme in '..\..\Frames\ZJJLFme.pas' {ZJJLFrame: TFrame},
+  ZJJLDm in '..\..\DataModules\ZJJLDm.pas' {ZJJLData: TDataModule},
+  BGLFme in '..\..\Frames\BGLFme.pas' {BGLFrame: TFrame},
+  BGLDm in '..\..\DataModules\BGLDm.pas' {BGLData: TDataModule},
+  StaffDm in '..\..\DataModules\StaffDm.pas' {StaffData: TDataModule},
+  ConstUnit in '..\..\Units\ConstUnit.pas',
+  PHPWebDm in '..\..\DataModules\PHPWebDm.pas' {PHPWeb: TDataModule},
+  uLkJSON in '..\..\Units\uLkJSON.pas',
+  MergeTextFrm in '..\..\Forms\MergeTextFrm.pas' {MergeTextForm},
+  BGLSelectFrm in '..\..\Forms\BGLSelectFrm.pas' {BGLSelectForm},
+  EstimateFme in '..\..\Frames\EstimateFme.pas' {EstimateFrame: TFrame},
+  EstimateDm in '..\..\DataModules\EstimateDm.pas' {EstimateData: TDataModule},
+  WebNewTenderFrm in '..\..\Forms\WebNewTenderFrm.pas' {WebNewTenderForm},
+  ExportExcel in '..\..\Units\ExportExcel.pas',
+  ReportsFrm in '..\..\Forms\ReportsFrm.pas' {ReportsForm},
+  ReportManager in '..\..\Units\ReportManager.pas',
+  BillsCompileDm in '..\..\DataModules\BillsCompileDm.pas' {BillsCompileData: TDataModule},
+  BillsCompileFme in '..\..\Frames\BillsCompileFme.pas' {BillsCompileFrame: TFrame},
+  BillsMeasureDm in '..\..\DataModules\BillsMeasureDm.pas' {BillsMeasureData: TDataModule},
+  PasswordInputFrm in '..\..\Forms\PasswordInputFrm.pas' {PasswordInputForm},
+  AboutFrm in '..\..\Forms\AboutFrm.pas' {AboutForm},
+  AuthFrm in '..\..\Forms\AuthFrm.pas' {AuthorizeForm},
+  mEncryptUnit in '..\..\Encrypt\mEncryptUnit.pas',
+  mEncryptPWD in '..\..\Encrypt\mEncryptPWD.pas',
+  mSNSEncrypt in '..\..\Encrypt\mSNSEncrypt.pas',
+  mR1Encrypt in '..\..\Encrypt\mR1Encrypt.pas',
+  mEncryptEditions in '..\..\Encrypt\mEncryptEditions.pas',
+  mEncryptTypes in '..\..\Encrypt\mEncryptTypes.pas',
+  mConnectEncrypt in '..\..\Encrypt\NetClient\mConnectEncrypt.pas',
+  CryptUtils in '..\..\Encrypt\CryptUtils.pas',
+  EncryptDog in '..\..\Encrypt\EncryptDog.pas',
+  ScFileArchiver in '..\..\Encrypt\ScFileArchiver.pas',
+  SearchFme in '..\..\Frames\SearchFme.pas' {SearchFrame: TFrame},
+  BatchInsertBillsFrm in '..\..\Forms\BatchInsertBillsFrm.pas' {BatchInsertBillsForm},
+  SearchDm in '..\..\DataModules\SearchDm.pas' {SearchData: TDataModule},
+  CslJson in '..\..\Units\CslJson.pas',
+  FindUserFrm in '..\..\Forms\FindUserFrm.pas' {FindUserForm},
+  ImportExcelHintFrm in '..\..\Forms\ImportExcelHintFrm.pas' {ImportExcelHintForm},
+  CheckerFme in '..\..\Frames\CheckerFme.pas' {CheckerFrame: TFrame},
+  OrderCheckerFme in '..\..\Frames\OrderCheckerFme.pas' {OrderCheckerFrame: TFrame},
+  ReportAdjustFrm in '..\..\Forms\ReportAdjustFrm.pas' {ReportAdjustForm},
+  DealBillsDm in '..\..\DataModules\DealBillsDm.pas' {DealBillsData: TDataModule},
+  BatchReplaceBillsFrm in '..\..\Forms\BatchReplaceBillsFrm.pas' {BatchReplaceBillsForm},
+  MD5Unit in '..\..\Units\MD5Unit.pas',
+  MainDataListDm in '..\..\DataModules\MainDataListDm.pas' {MainListData: TDataModule},
+  mProgressFrm in '..\..\Forms\mProgressFrm.pas' {mProgress},
+  rmGclBillsBGDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsBGDm.pas' {DataModule1: TDataModule},
+  rmBGLExecutionDm in '..\..\DataModules\ReportMemoryDm\rmBGLExecutionDm.pas' {rmBGLExecutionData: TDataModule},
+  rmBillsGatherDm in '..\..\DataModules\ReportMemoryDm\rmBillsGatherDm.pas' {rmBillsGatherData: TDataModule},
+  rmCacheData in '..\..\DataModules\ReportMemoryDm\rmCacheData.pas',
+  rmFxBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsAddDm.pas' {rmFxBillsAddData: TDataModule},
+  rmFxBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsCompareDm.pas' {rmFxBillsCompareData: TDataModule},
+  rmGclBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAddDm.pas' {rmGclBillsAddData: TDataModule},
+  rmGclBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCompareDm.pas' {rmGclBillsCompareData: TDataModule},
+  rmGridHeaderDm in '..\..\DataModules\ReportMemoryDm\rmGridHeaderDm.pas' {rmGridHeaderData: TDataModule},
+  rmSelectProjectFrm in '..\..\Forms\rmSelectProjectFrm.pas' {ProjectSelectForm},
+  ConditionalDefines in '..\..\Units\ConditionalDefines.pas',
+  ProgressHintFrm in '..\..\Forms\ProgressHintFrm.pas' {ProgressHintForm},
+  rmGclBillsAuditCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAuditCompareDm.pas' {rmGclBillsAuditCompareData: TDataModule},
+  rmTestFrm in '..\..\DataModules\ReportMemoryDm\rmTestFrm.pas' {rmTestForm},
+  CheckAndClearFrm in '..\..\Forms\CheckAndClearFrm.pas' {CheckAndClearForm},
+  DealBillsFrm in '..\..\Forms\DealBillsFrm.pas' {DealBillsForm},
+  TenderBackupFrm in '..\..\Forms\TenderBackupFrm.pas' {TenderBackupForm},
+  TenderBackupDm in '..\..\DataModules\TenderBackupDm.pas' {TenderBackupData: TDataModule},
+  BillsBookmarkDm in '..\..\DataModules\BillsBookmarkDm.pas' {BillsBookmarkData: TDataModule},
+  BookmarkFme in '..\..\Frames\BookmarkFme.pas' {BookmarkFrame: TFrame},
+  rmDealInfosDm in '..\..\DataModules\ReportMemoryDm\rmDealInfosDm.pas' {rmDealInfosData: TDataModule},
+  rmXmjBGLDetailDm in '..\..\DataModules\ReportMemoryDm\rmXmjBGLDetailDm.pas' {rmXmjBGLDetailData: TDataModule},
+  WelcomeFrm in '..\..\Forms\WelcomeFrm.pas' {WelcomeForm},
+  rmOtherReport1Dm in '..\..\DataModules\ReportMemoryDm\rmOtherReport1Dm.pas' {rmOtherReport1Data: TDataModule},
+  CheckerMemoFrm in '..\..\Forms\CheckerMemoFrm.pas' {CheckerMemoForm},
+  CslHint in '..\..\Units\CslHint.pas',
+  rmGclBillsCheckDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCheckDm.pas' {rmGclBillsCheckData: TDataModule},
+  TenderBackupManager in '..\..\Units\TenderBackupManager.pas',
+  UpFileFrame in '..\..\Forms\UpFileFrame.pas',
+  UpFileManageFrame in '..\..\Forms\UpFileManageFrame.pas',
+  UpFileManageUnit in '..\..\Units\UpFileManageUnit.pas',
+  SheetSelectFrm in '..\..\Forms\SheetSelectFrm.pas' {SheetSelectForm},
+  AuditSelectFrm in '..\..\Forms\ReportInteractFrms\AuditSelectFrm.pas' {AuditSelctForm},
+  Checker in '..\..\Units\Checker.pas',
+  ReportInteractInfo in '..\..\Units\ReportInteractInfo.pas',
+  DealBillsFme in '..\..\Frames\DealBillsFme.pas' {DealBillsFrame: TFrame},
+  rmGclBillsPlaneDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsPlaneDm.pas' {rmGclBillsPlaneData: TDataModule},
+  StageCompareDm in '..\..\DataModules\StageCompareDm.pas' {StageCompareData: TDataModule},
+  mDataRecord in '..\..\Units\mDataRecord.pas',
+  rmMentalCustomized1Dm in '..\..\DataModules\ReportMemoryDm\rmMentalCustomized1Dm.pas' {rmMentalCustomized1Data: TDataModule},
+  BGLClipboard in '..\..\Units\BGLClipboard.pas',
+  rmGcl_XmjBillsDm in '..\..\DataModules\ReportMemoryDm\rmGcl_XmjBillsDm.pas' {rmGcl_XmjBillsData: TDataModule},
+  rmCustomized2Dm in '..\..\DataModules\ReportMemoryDm\rmCustomized2Dm.pas' {rmCustomized2Data: TDataModule},
+  CalcDecimal in '..\..\Units\CalcDecimal.pas';
+
+{$R *.res}
+
+var Mutex: THandle;
+begin
+  Mutex := CreateMutex(nil, True, G_AppHandleName);
+
+  if GetLastError = ERROR_ALREADY_EXISTS then
+    Application.MessageBox('程序正在运行, 请勿重复打开该软件!', '系统提示', MB_OK + MB_ICONINFORMATION)
+  else
+  begin
+    Application.CreateHandle;
+    Application.Initialize;
+    Application.Title := '纵横公路工程结算决算计量一体化软件专业版';
+
+    ShowWelcome;
+    if CheckDogExists then
+    begin
+      HideWelcome;
+      Application.CreateForm(TMainForm, MainForm);
+  end
+    else  HideWelcome;
+    Application.Run;
+  end;
+
+  ReleaseMutex(Mutex);
+end.
+

二进制
Dprs/Pro/Measure.res


+ 41 - 0
Dprs/Pro/Measure_Cloud.cfg

@@ -0,0 +1,41 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"E:\SmartCostExe\Measure"
+-N"..\..\Dcus"
+-LE"d:\program files\borland\delphi7\Projects\Bpl"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-D_mCloud;_mEncrypt;
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

+ 162 - 0
Dprs/Pro/Measure_Cloud.dof

@@ -0,0 +1,162 @@
+[FileVersion]
+Version=7.0
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=0
+K=0
+L=1
+M=0
+N=1
+O=1
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=0
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+NamespacePrefix=
+SymbolDeprecated=1
+SymbolLibrary=1
+SymbolPlatform=1
+UnitLibrary=1
+UnitPlatform=1
+UnitDeprecated=1
+HResultCompat=1
+HidingMember=1
+HiddenVirtual=1
+Garbage=1
+BoundsError=1
+ZeroNilCompat=1
+StringConstTruncated=1
+ForLoopVarVarPar=1
+TypedConstVarPar=1
+AsgToTypedConst=1
+CaseLabelRange=1
+ForVariable=1
+ConstructingAbstract=1
+ComparisonFalse=1
+ComparisonTrue=1
+ComparingSignedUnsigned=1
+CombiningSignedUnsigned=1
+UnsupportedConstruct=1
+FileOpen=1
+FileOpenUnitSrc=1
+BadGlobalSymbol=1
+DuplicateConstructorDestructor=1
+InvalidDirective=1
+PackageNoLink=1
+PackageThreadVar=1
+ImplicitImport=1
+HPPEMITIgnored=1
+NoRetVal=1
+UseBeforeDef=1
+ForLoopVarUndef=1
+UnitNameMismatch=1
+NoCFGFileFound=1
+MessageDirective=1
+ImplicitVariants=1
+UnicodeToLocale=1
+LocaleToUnicode=1
+ImagebaseMultiple=1
+SuspiciousTypecast=1
+PrivatePropAccessor=1
+UnsafeType=0
+UnsafeCode=0
+UnsafeCast=0
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=E:\SmartCostExe\Measure
+UnitOutputDir=..\..\Dcus
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=
+Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;Rave50CLX;Rave50VCL;dclOfficeXP;ZjGridD7;DPanel;ExTree;JimComboBoxs;JimTab;PrintComRep;XPMenu_tom;ZjGridFereD7;ZjCommon;SmartDataSet;ZjGridActns
+Conditionals=_mCloud;_mEncrypt;
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Language]
+ActiveLang=
+ProjectLang=
+RootDir=D:\Program Files\Borland\Delphi7\Bin\
+[Version Info]
+IncludeVerInfo=1
+AutoIncBuild=1
+MajorVer=3
+MinorVer=1
+Release=3
+Build=1031
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=2052
+CodePage=936
+[Version Info Keys]
+CompanyName=珠海纵横创新软件有限公司
+FileDescription=纵横结算决算计量一体化云版
+FileVersion=3.1.3.1031
+InternalName=Measure
+LegalCopyright=版权所有(C) 珠海纵横创新软件有限公司 2003-2014。保留所有权利。
+LegalTrademarks=Measure
+OriginalFilename=
+ProductName=纵横公路工程计量决算一体化软件
+ProductVersion=3
+Comments=
+[HistoryLists\hlConditionals]
+Count=5
+Item0=_mCloud;_mEncrypt;
+Item1=_OnLine;_mEncrypt;
+Item2=_OnLine;_mEncrypt;cplPrint;cplOutputToExcelRange
+Item3=_OnLine;cplPrint;cplOutputToExcelRange
+Item4=_OnLine;cplPrint;_mEncrypt;cplPrint;cplOutputToExcelRange
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlUnitOutputDirectory]
+Count=3
+Item0=..\..\Dcus
+Item1=E:\DelphiTemp
+Item2=D:\Dcu
+[HistoryLists\hlOutputDirectorry]
+Count=3
+Item0=E:\SmartCostExe\Measure
+Item1=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(云版)
+Item2=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(专业版)
+[HistoryLists\hlBPLOutput]
+Count=1
+Item0=..\Bin
+[HistoryLists\hlDCPOutput]
+Count=1
+Item0=D:\Dcu

+ 194 - 0
Dprs/Pro/Measure_Cloud.dpr

@@ -0,0 +1,194 @@
+program Measure_Cloud;
+
+uses
+  Windows,
+  ShareMem,
+  Forms,
+  Controls,
+  MainFrm in '..\..\Forms\MainFrm.pas' {MainForm},
+  ProjectManagerFme in '..\..\Frames\ProjectManagerFme.pas' {ProjectManagerFrame: TFrame},
+  UtilMethods in '..\..\Units\UtilMethods.pas',
+  ProjectManagerDm in '..\..\DataModules\ProjectManagerDm.pas' {ProjectManagerData: TDataModule},
+  Connections in '..\..\Units\Connections.pas',
+  TransFile in '..\..\Units\TransFile.pas',
+  ZhAPI in '..\..\Units\ZhAPI.pas',
+  CompactDB in '..\..\Units\CompactDB.pas',
+  OpenProjectManager in '..\..\Units\OpenProjectManager.pas',
+  ProjectData in '..\..\Units\ProjectData.pas',
+  UpdateDataBase in '..\..\Units\UpdateDataBase.pas',
+  DataBaseTables in '..\..\Units\DataBaseTables.pas',
+  ConfigDoc in '..\..\Units\ConfigDoc.pas',
+  SupportUnit in '..\..\Units\SupportUnit.pas',
+  StandardLibs in '..\..\Units\StandardLibs.pas',
+  StandardLib in '..\..\Units\StandardLib.pas',
+  NewProjectFrm in '..\..\Forms\NewProjectFrm.pas' {NewProjectForm},
+  ProjectFme in '..\..\Frames\ProjectFme.pas' {ProjectFrame: TFrame},
+  StandardBillsDm in '..\..\DataModules\StandardBillsDm.pas' {StandardBillsData: TDataModule},
+  StandardBillsFme in '..\..\Frames\StandardBillsFme.pas' {StandardBillsFrame: TFrame},
+  StandardLibsFme in '..\..\Frames\StandardLibsFme.pas' {StandardLibsFrame: TFrame},
+  BillsDm in '..\..\DataModules\BillsDm.pas' {BillsData: TDataModule},
+  Globals in '..\..\Units\Globals.pas',
+  StageDm in '..\..\DataModules\StageDm.pas' {StageData: TDataModule},
+  ExcelImport in '..\..\Units\ExcelImport.pas',
+  CacheTree in '..\..\Units\CacheTree.pas',
+  MCacheTree in '..\..\Units\MCacheTree.pas',
+  ProjectPropertiesFrm in '..\..\Forms\ProjectPropertiesFrm.pas' {ProjectPropertiesForm},
+  ProjectProperty in '..\..\Units\ProjectProperty.pas',
+  FormulaCalc in '..\..\Units\FormulaCalc.pas',
+  BillsCommand in '..\..\Units\BillsCommand.pas',
+  PhaseData in '..\..\Units\PhaseData.pas',
+  PhaseProperty in '..\..\Units\PhaseProperty.pas',
+  BillsClipboard in '..\..\Units\BillsClipboard.pas',
+  BillsTree in '..\..\Units\BillsTree.pas',
+  ProjectCommands in '..\..\Units\ProjectCommands.pas',
+  PhaseCompareDm in '..\..\DataModules\PhaseCompareDm.pas' {PhaseCompareData: TDataModule},
+  PhaseCompareFme in '..\..\Frames\PhaseCompareFme.pas' {PhaseCompareFrame: TFrame},
+  OptionFrm in '..\..\Forms\OptionFrm.pas' {OptionForm},
+  DealPaymentDm in '..\..\DataModules\DealPaymentDm.pas' {DealPaymentData: TDataModule},
+  DealPaymentFme in '..\..\Frames\DealPaymentFme.pas' {DealPaymentFrame: TFrame},
+  PhasePayDm in '..\..\DataModules\PhasePayDm.pas' {PhasePayData: TDataModule},
+  ZJJLDm in '..\..\DataModules\ZJJLDm.pas' {ZJJLData: TDataModule},
+  BillsGatherDm in '..\..\DataModules\BillsGatherDm.pas' {BillsGatherData: TDataModule},
+  BillsGatherFme in '..\..\Frames\BillsGatherFme.pas' {BillsGatherFrame: TFrame},
+  LoginFrm in '..\..\Forms\LoginFrm.pas' {LoginFrm},
+  PHPWebDm in '..\..\DataModules\PHPWebDm.pas' {PHPWeb: TDataModule},
+  MD5Unit in '..\..\Units\MD5Unit.pas',
+  ConstUnit in '..\..\Units\ConstUnit.pas',
+  ExportExcel in '..\..\Units\ExportExcel.pas',
+  mEncryptEditions in '..\..\Encrypt\mEncryptEditions.pas',
+  mEncryptUnit in '..\..\Encrypt\mEncryptUnit.pas',
+  CryptUtils in '..\..\Encrypt\CryptUtils.pas',
+  EncryptDog in '..\..\Encrypt\EncryptDog.pas',
+  mEncryptPWD in '..\..\Encrypt\mEncryptPWD.pas',
+  mEncryptTypes in '..\..\Encrypt\mEncryptTypes.pas',
+  mR1Encrypt in '..\..\Encrypt\mR1Encrypt.pas',
+  mS4Utils in '..\..\Encrypt\mS4Utils.pas',
+  mSNSEncrypt in '..\..\Encrypt\mSNSEncrypt.pas',
+  Rockey1 in '..\..\Encrypt\Rockey1.pas',
+  mConnectEncrypt in '..\..\Encrypt\NetClient\mConnectEncrypt.pas',
+  FindUserFrm in '..\..\Forms\FindUserFrm.pas' {FindUserForm},
+  CslJson in '..\..\Units\CslJson.pas',
+  OrderCheckerFme in '..\..\Frames\OrderCheckerFme.pas' {OrderCheckerFrame: TFrame},
+  CheckerFme in '..\..\Frames\CheckerFme.pas' {CheckerFrame: TFrame},
+  WebNewTenderFrm in '..\..\Forms\WebNewTenderFrm.pas' {WebNewTenderForm},
+  ScFileArchiver in '..\..\Encrypt\ScFileArchiver.pas',
+  SearchDm in '..\..\DataModules\SearchDm.pas' {SearchData: TDataModule},
+  DealBillsDm in '..\..\DataModules\DealBillsDm.pas' {DealBillsData: TDataModule},
+  BGLDm in '..\..\DataModules\BGLDm.pas' {BGLData: TDataModule},
+  StaffDm in '..\..\DataModules\StaffDm.pas' {StaffData: TDataModule},
+  EstimateDm in '..\..\DataModules\EstimateDm.pas' {EstimateData: TDataModule},
+  BillsCompileDm in '..\..\DataModules\BillsCompileDm.pas' {BillsCompileData: TDataModule},
+  BillsMeasureDm in '..\..\DataModules\BillsMeasureDm.pas' {BillsMeasureData: TDataModule},
+  ReportManager in '..\..\Units\ReportManager.pas',
+  BGLSelectFrm in '..\..\Forms\BGLSelectFrm.pas' {BGLSelectForm},
+  BillsCompileFme in '..\..\Frames\BillsCompileFme.pas' {BillsCompileFrame: TFrame},
+  BillsMeasureFme in '..\..\Frames\BillsMeasureFme.pas' {BillsMeasureFrame: TFrame},
+  BatchReplaceBillsFrm in '..\..\Forms\BatchReplaceBillsFrm.pas' {BatchReplaceBillsForm},
+  ZJJLFme in '..\..\Frames\ZJJLFme.pas' {ZJJLFrame: TFrame},
+  BGLFme in '..\..\Frames\BGLFme.pas' {BGLFrame: TFrame},
+  MergeTextFrm in '..\..\Forms\MergeTextFrm.pas' {MergeTextForm},
+  EstimateFme in '..\..\Frames\EstimateFme.pas' {EstimateFrame: TFrame},
+  ReportsFrm in '..\..\Forms\ReportsFrm.pas' {ReportsForm},
+  ReportAdjustFrm in '..\..\Forms\ReportAdjustFrm.pas' {ReportAdjustForm},
+  SearchFme in '..\..\Frames\SearchFme.pas' {SearchFrame: TFrame},
+  AuthFrm in '..\..\Forms\AuthFrm.pas' {AuthorizeForm},
+  AboutFrm in '..\..\Forms\AboutFrm.pas' {AboutForm},
+  ImportExcelHintFrm in '..\..\Forms\ImportExcelHintFrm.pas' {ImportExcelHintForm},
+  PasswordInputFrm in '..\..\Forms\PasswordInputFrm.pas' {PasswordInputForm},
+  BatchInsertBillsFrm in '..\..\Forms\BatchInsertBillsFrm.pas' {BatchInsertBillsForm},
+  MainDataListDm in '..\..\DataModules\MainDataListDm.pas' {MainListData: TDataModule},
+  mProgressFrm in '..\..\Forms\mProgressFrm.pas' {mProgress},
+  rmGclBillsBGDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsBGDm.pas' {rmGclBillsBGData: TDataModule},
+  rmGclBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCompareDm.pas' {rmGclBillsCompareData: TDataModule},
+  rmBGLExecutionDm in '..\..\DataModules\ReportMemoryDm\rmBGLExecutionDm.pas' {rmBGLExecutionData: TDataModule},
+  rmBillsGatherDm in '..\..\DataModules\ReportMemoryDm\rmBillsGatherDm.pas' {rmBillsGatherData: TDataModule},
+  rmFxBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsAddDm.pas' {rmFxBillsAddData: TDataModule},
+  rmFxBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsCompareDm.pas' {rmFxBillsCompareData: TDataModule},
+  rmGclBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAddDm.pas' {rmGclBillsAddData: TDataModule},
+  rmGridHeaderDm in '..\..\DataModules\ReportMemoryDm\rmGridHeaderDm.pas' {rmGridHeaderData: TDataModule},
+  rmCacheData in '..\..\DataModules\ReportMemoryDm\rmCacheData.pas',
+  rmSelectProjectFrm in '..\..\Forms\rmSelectProjectFrm.pas' {ProjectSelectForm},
+  ConditionalDefines in '..\..\Units\ConditionalDefines.pas',
+  ProgressHintFrm in '..\..\Forms\ProgressHintFrm.pas' {ProgressHintForm},
+  CheckAndClearFrm in '..\..\Forms\CheckAndClearFrm.pas' {CheckAndClearForm},
+  rmGclBillsAuditCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAuditCompareDm.pas' {rmGclBillsAuditCompareData: TDataModule},
+  rmTestFrm in '..\..\DataModules\ReportMemoryDm\rmTestFrm.pas' {rmTestForm},
+  DealBillsFrm in '..\..\Forms\DealBillsFrm.pas' {DealBillsForm},
+  TenderBackupFrm in '..\..\Forms\TenderBackupFrm.pas' {TenderBackupForm},
+  TenderBackupDm in '..\..\DataModules\TenderBackupDm.pas' {TenderBackupData: TDataModule},
+  BillsBookmarkDm in '..\..\DataModules\BillsBookmarkDm.pas' {BillsBookmarkData: TDataModule},
+  BookmarkFme in '..\..\Frames\BookmarkFme.pas' {BookmarkFrame: TFrame},
+  rmDealInfosDm in '..\..\DataModules\ReportMemoryDm\rmDealInfosDm.pas' {rmDealInfosData: TDataModule},
+  rmXmjBGLDetailDm in '..\..\DataModules\ReportMemoryDm\rmXmjBGLDetailDm.pas' {rmXmjBGLDetailData: TDataModule},
+  WelcomeFrm in '..\..\Forms\WelcomeFrm.pas' {WelcomeForm},
+  rmOtherReport1Dm in '..\..\DataModules\ReportMemoryDm\rmOtherReport1Dm.pas' {rmOtherReport1Data: TDataModule},
+  CheckerMemoFrm in '..\..\Forms\CheckerMemoFrm.pas' {CheckerMemoForm},
+  CslHint in '..\..\Units\CslHint.pas',
+  rmGclBillsCheckDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCheckDm.pas' {rmGclBillsCheckData: TDataModule},
+  IPFrm in '..\..\Forms\IPFrm.pas' {IPForm},
+  TenderBackupManager in '..\..\Units\TenderBackupManager.pas',
+  UpFileManageUnit in '..\..\Units\UpFileManageUnit.pas',
+  UpFileFrame in '..\..\Forms\UpFileFrame.pas',
+  UpFileManageFrame in '..\..\Forms\UpFileManageFrame.pas',
+  SheetSelectFrm in '..\..\Forms\SheetSelectFrm.pas' {SheetSelectForm},
+  ReportInteractInfo in '..\..\Units\ReportInteractInfo.pas',
+  Checker in '..\..\Units\Checker.pas',
+  AuditSelectFrm in '..\..\Forms\ReportInteractFrms\AuditSelectFrm.pas' {AuditSelctForm},
+  DealBillsFme in '..\..\Frames\DealBillsFme.pas' {DealBillsFrame: TFrame},
+  rmGclBillsPlaneDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsPlaneDm.pas' {rmGclBillsPlaneData: TDataModule},
+  StageCompareDm in '..\..\DataModules\StageCompareDm.pas' {StageCompareData: TDataModule},
+  mDataRecord in '..\..\Units\mDataRecord.pas',
+  BGLClipboard in '..\..\Units\BGLClipboard.pas',
+  rmMentalCustomized1Dm in '..\..\DataModules\ReportMemoryDm\rmMentalCustomized1Dm.pas' {rmMentalCustomized1Data: TDataModule},
+  rmGcl_XmjBillsDm in '..\..\DataModules\ReportMemoryDm\rmGcl_XmjBillsDm.pas' {rmGcl_XmjBillsData: TDataModule},
+  rmCustomized2Dm in '..\..\DataModules\ReportMemoryDm\rmCustomized2Dm.pas' {rmCustomized2Data: TDataModule},
+  CalcDecimal in '..\..\Units\CalcDecimal.pas';
+
+{$R *.res}
+
+var
+  Mutex: THandle;
+  IPForm: TIPForm;
+
+begin
+  Mutex := CreateMutex(nil, True, G_AppHandleName);
+
+  if GetLastError = ERROR_ALREADY_EXISTS then
+    Application.MessageBox('程序正在运行, 请勿重复打开该软件!', '系统提示', MB_OK + MB_ICONINFORMATION)
+  else
+  begin
+    Application.CreateHandle;
+    Application.Initialize;
+    Application.Title := '纵横公路工程结算决算计量一体化软件云版';
+    {$IFDEF _mCloud}
+      IPForm := TIPForm.Create(nil);
+      try
+        if not IPForm.HasIP then
+        begin
+          IPForm.ShowModal;
+          if IPForm.ModalResult <> mrOK then
+          begin
+            Application.Terminate;
+            Exit;
+          end;
+        end;
+      finally
+        IPForm.Free;
+      end;
+
+      if not LoginForm then
+      begin
+        Application.Terminate;
+        Exit;
+      end;
+    {$ENDIF}
+
+    if CheckDogExists then
+    begin
+      Application.CreateForm(TMainForm, MainForm);
+  end;
+    Application.Run;
+  end;
+
+  ReleaseMutex(Mutex);
+end.

二进制
Dprs/Pro/Measure_Cloud.res


+ 41 - 0
Dprs/Pro/Measure_GuangDong.cfg

@@ -0,0 +1,41 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"E:\SmartCostExe\Measure"
+-N"..\..\Dcus"
+-LE"d:\program files\borland\delphi7\Projects\Bpl"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-D_mEncrypt;_mGuangDong
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

+ 157 - 0
Dprs/Pro/Measure_GuangDong.dof

@@ -0,0 +1,157 @@
+[FileVersion]
+Version=7.0
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=0
+K=0
+L=1
+M=0
+N=1
+O=1
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=0
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+NamespacePrefix=
+SymbolDeprecated=1
+SymbolLibrary=1
+SymbolPlatform=1
+UnitLibrary=1
+UnitPlatform=1
+UnitDeprecated=1
+HResultCompat=1
+HidingMember=1
+HiddenVirtual=1
+Garbage=1
+BoundsError=1
+ZeroNilCompat=1
+StringConstTruncated=1
+ForLoopVarVarPar=1
+TypedConstVarPar=1
+AsgToTypedConst=1
+CaseLabelRange=1
+ForVariable=1
+ConstructingAbstract=1
+ComparisonFalse=1
+ComparisonTrue=1
+ComparingSignedUnsigned=1
+CombiningSignedUnsigned=1
+UnsupportedConstruct=1
+FileOpen=1
+FileOpenUnitSrc=1
+BadGlobalSymbol=1
+DuplicateConstructorDestructor=1
+InvalidDirective=1
+PackageNoLink=1
+PackageThreadVar=1
+ImplicitImport=1
+HPPEMITIgnored=1
+NoRetVal=1
+UseBeforeDef=1
+ForLoopVarUndef=1
+UnitNameMismatch=1
+NoCFGFileFound=1
+MessageDirective=1
+ImplicitVariants=1
+UnicodeToLocale=1
+LocaleToUnicode=1
+ImagebaseMultiple=1
+SuspiciousTypecast=1
+PrivatePropAccessor=1
+UnsafeType=0
+UnsafeCode=0
+UnsafeCast=0
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=E:\SmartCostExe\Measure
+UnitOutputDir=..\..\Dcus
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=
+Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;Rave50CLX;Rave50VCL;dclOfficeXP;ZjGridD7;DPanel;ExTree;JimComboBoxs;JimTab;PrintComRep;XPMenu_tom;ZjGridFereD7;ZjCommon;SmartDataSet;ZjGridActns;MBaseControls
+Conditionals=_mEncrypt;_mGuangDong
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Language]
+ActiveLang=
+ProjectLang=
+RootDir=D:\Program Files\Borland\Delphi7\Bin\
+[Version Info]
+IncludeVerInfo=1
+AutoIncBuild=1
+MajorVer=3
+MinorVer=1
+Release=3
+Build=1031
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=2052
+CodePage=936
+[Version Info Keys]
+CompanyName=珠海纵横创新软件有限公司
+FileDescription=纵横结算决算计量一体化广东专业版
+FileVersion=3.1.3.1031
+InternalName=Measure
+LegalCopyright=版权所有(C) 珠海纵横创新软件有限公司 2003-2014。保留所有权利。
+LegalTrademarks=Measure
+OriginalFilename=
+ProductName=纵横公路工程计量决算一体化软件
+ProductVersion=3
+Comments=
+[HistoryLists\hlConditionals]
+Count=1
+Item0=_mEncrypt;_mGuangDong
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlUnitOutputDirectory]
+Count=3
+Item0=..\..\Dcus
+Item1=..\Dcus
+Item2=D:\Dcu
+[HistoryLists\hlOutputDirectorry]
+Count=2
+Item0=E:\SmartCostExe\Measure
+Item1=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(广东专业版)
+[HistoryLists\hlBPLOutput]
+Count=1
+Item0=..\Bin
+[HistoryLists\hlDCPOutput]
+Count=1
+Item0=D:\Dcu

+ 167 - 0
Dprs/Pro/Measure_GuangDong.dpr

@@ -0,0 +1,167 @@
+program Measure_GuangDong;
+
+uses
+  Windows,
+  ShareMem,
+  Forms,
+  MainFrm in '..\..\Forms\MainFrm.pas' {MainForm},
+  ProjectManagerFme in '..\..\Frames\ProjectManagerFme.pas' {ProjectManagerFrame: TFrame},
+  UtilMethods in '..\..\Units\UtilMethods.pas',
+  ProjectManagerDm in '..\..\DataModules\ProjectManagerDm.pas' {ProjectManagerData: TDataModule},
+  Connections in '..\..\Units\Connections.pas',
+  TransFile in '..\..\Units\TransFile.pas',
+  ZhAPI in '..\..\Units\ZhAPI.pas',
+  CompactDB in '..\..\Units\CompactDB.pas',
+  OpenProjectManager in '..\..\Units\OpenProjectManager.pas',
+  ProjectData in '..\..\Units\ProjectData.pas',
+  UpdateDataBase in '..\..\Units\UpdateDataBase.pas',
+  DataBaseTables in '..\..\Units\DataBaseTables.pas',
+  ConfigDoc in '..\..\Units\ConfigDoc.pas',
+  SupportUnit in '..\..\Units\SupportUnit.pas',
+  StandardLibs in '..\..\Units\StandardLibs.pas',
+  StandardLib in '..\..\Units\StandardLib.pas',
+  NewProjectFrm in '..\..\Forms\NewProjectFrm.pas' {NewProjectForm},
+  ProjectFme in '..\..\Frames\ProjectFme.pas' {ProjectFrame: TFrame},
+  StandardBillsDm in '..\..\DataModules\StandardBillsDm.pas' {StandardBillsData: TDataModule},
+  StandardBillsFme in '..\..\Frames\StandardBillsFme.pas' {StandardBillsFrame: TFrame},
+  StandardLibsFme in '..\..\Frames\StandardLibsFme.pas' {StandardLibsFrame: TFrame},
+  BillsDm in '..\..\DataModules\BillsDm.pas' {BillsData: TDataModule},
+  BillsMeasureFme in '..\..\Frames\BillsMeasureFme.pas' {BillsMeasureFrame: TFrame},
+  Globals in '..\..\Units\Globals.pas',
+  StageDm in '..\..\DataModules\StageDm.pas' {StageData: TDataModule},
+  ExcelImport in '..\..\Units\ExcelImport.pas',
+  CacheTree in '..\..\Units\CacheTree.pas',
+  MCacheTree in '..\..\Units\MCacheTree.pas',
+  ProjectPropertiesFrm in '..\..\Forms\ProjectPropertiesFrm.pas' {ProjectPropertiesForm},
+  ProjectProperty in '..\..\Units\ProjectProperty.pas',
+  FormulaCalc in '..\..\Units\FormulaCalc.pas',
+  BillsCommand in '..\..\Units\BillsCommand.pas',
+  PhaseData in '..\..\Units\PhaseData.pas',
+  PhaseProperty in '..\..\Units\PhaseProperty.pas',
+  BillsClipboard in '..\..\Units\BillsClipboard.pas',
+  BillsTree in '..\..\Units\BillsTree.pas',
+  ProjectCommands in '..\..\Units\ProjectCommands.pas',
+  PhaseCompareDm in '..\..\DataModules\PhaseCompareDm.pas' {PhaseCompareData: TDataModule},
+  PhaseCompareFme in '..\..\Frames\PhaseCompareFme.pas' {PhaseCompareFrame: TFrame},
+  OptionFrm in '..\..\Forms\OptionFrm.pas' {OptionForm},
+  DealPaymentDm in '..\..\DataModules\DealPaymentDm.pas' {DealPaymentData: TDataModule},
+  DealPaymentFme in '..\..\Frames\DealPaymentFme.pas' {DealPaymentFrame: TFrame},
+  PhasePayDm in '..\..\DataModules\PhasePayDm.pas' {PhasePayData: TDataModule},
+  BillsGatherFme in '..\..\Frames\BillsGatherFme.pas' {BillsGatherFrame: TFrame},
+  BillsGatherDm in '..\..\DataModules\BillsGatherDm.pas' {BillsGatherData: TDataModule},
+  ZJJLFme in '..\..\Frames\ZJJLFme.pas' {ZJJLFrame: TFrame},
+  ZJJLDm in '..\..\DataModules\ZJJLDm.pas' {ZJJLData: TDataModule},
+  BGLFme in '..\..\Frames\BGLFme.pas' {BGLFrame: TFrame},
+  BGLDm in '..\..\DataModules\BGLDm.pas' {BGLData: TDataModule},
+  StaffDm in '..\..\DataModules\StaffDm.pas' {StaffData: TDataModule},
+  ConstUnit in '..\..\Units\ConstUnit.pas',
+  PHPWebDm in '..\..\DataModules\PHPWebDm.pas' {PHPWeb: TDataModule},
+  uLkJSON in '..\..\Units\uLkJSON.pas',
+  MergeTextFrm in '..\..\Forms\MergeTextFrm.pas' {MergeTextForm},
+  BGLSelectFrm in '..\..\Forms\BGLSelectFrm.pas' {BGLSelectForm},
+  EstimateFme in '..\..\Frames\EstimateFme.pas' {EstimateFrame: TFrame},
+  EstimateDm in '..\..\DataModules\EstimateDm.pas' {EstimateData: TDataModule},
+  WebNewTenderFrm in '..\..\Forms\WebNewTenderFrm.pas' {WebNewTenderForm},
+  ExportExcel in '..\..\Units\ExportExcel.pas',
+  ReportsFrm in '..\..\Forms\ReportsFrm.pas' {ReportsForm},
+  ReportManager in '..\..\Units\ReportManager.pas',
+  BillsCompileDm in '..\..\DataModules\BillsCompileDm.pas' {BillsCompileData: TDataModule},
+  BillsCompileFme in '..\..\Frames\BillsCompileFme.pas' {BillsCompileFrame: TFrame},
+  BillsMeasureDm in '..\..\DataModules\BillsMeasureDm.pas' {BillsMeasureData: TDataModule},
+  PasswordInputFrm in '..\..\Forms\PasswordInputFrm.pas' {PasswordInputForm},
+  AboutFrm in '..\..\Forms\AboutFrm.pas' {AboutForm},
+  AuthFrm in '..\..\Forms\AuthFrm.pas' {AuthorizeForm},
+  mEncryptUnit in '..\..\Encrypt\mEncryptUnit.pas',
+  mEncryptPWD in '..\..\Encrypt\mEncryptPWD.pas',
+  mSNSEncrypt in '..\..\Encrypt\mSNSEncrypt.pas',
+  mR1Encrypt in '..\..\Encrypt\mR1Encrypt.pas',
+  mEncryptEditions in '..\..\Encrypt\mEncryptEditions.pas',
+  mEncryptTypes in '..\..\Encrypt\mEncryptTypes.pas',
+  mConnectEncrypt in '..\..\Encrypt\NetClient\mConnectEncrypt.pas',
+  CryptUtils in '..\..\Encrypt\CryptUtils.pas',
+  EncryptDog in '..\..\Encrypt\EncryptDog.pas',
+  ScFileArchiver in '..\..\Encrypt\ScFileArchiver.pas',
+  SearchFme in '..\..\Frames\SearchFme.pas' {SearchFrame: TFrame},
+  BatchInsertBillsFrm in '..\..\Forms\BatchInsertBillsFrm.pas' {BatchInsertBillsForm},
+  SearchDm in '..\..\DataModules\SearchDm.pas' {SearchData: TDataModule},
+  CslJson in '..\..\Units\CslJson.pas',
+  FindUserFrm in '..\..\Forms\FindUserFrm.pas' {FindUserForm},
+  ImportExcelHintFrm in '..\..\Forms\ImportExcelHintFrm.pas' {ImportExcelHintForm},
+  CheckerFme in '..\..\Frames\CheckerFme.pas' {CheckerFrame: TFrame},
+  OrderCheckerFme in '..\..\Frames\OrderCheckerFme.pas' {OrderCheckerFrame: TFrame},
+  ReportAdjustFrm in '..\..\Forms\ReportAdjustFrm.pas' {ReportAdjustForm},
+  DealBillsDm in '..\..\DataModules\DealBillsDm.pas' {DealBillsData: TDataModule},
+  BatchReplaceBillsFrm in '..\..\Forms\BatchReplaceBillsFrm.pas' {BatchReplaceBillsForm},
+  MD5Unit in '..\..\Units\MD5Unit.pas',
+  MainDataListDm in '..\..\DataModules\MainDataListDm.pas' {MainListData: TDataModule},
+  mProgressFrm in '..\..\Forms\mProgressFrm.pas' {mProgress},
+  rmGclBillsBGDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsBGDm.pas' {DataModule1: TDataModule},
+  rmBGLExecutionDm in '..\..\DataModules\ReportMemoryDm\rmBGLExecutionDm.pas' {rmBGLExecutionData: TDataModule},
+  rmBillsGatherDm in '..\..\DataModules\ReportMemoryDm\rmBillsGatherDm.pas' {rmBillsGatherData: TDataModule},
+  rmCacheData in '..\..\DataModules\ReportMemoryDm\rmCacheData.pas',
+  rmFxBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsAddDm.pas' {rmFxBillsAddData: TDataModule},
+  rmFxBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsCompareDm.pas' {rmFxBillsCompareData: TDataModule},
+  rmGclBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAddDm.pas' {rmGclBillsAddData: TDataModule},
+  rmGclBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCompareDm.pas' {rmGclBillsCompareData: TDataModule},
+  rmGridHeaderDm in '..\..\DataModules\ReportMemoryDm\rmGridHeaderDm.pas' {rmGridHeaderData: TDataModule},
+  rmSelectProjectFrm in '..\..\Forms\rmSelectProjectFrm.pas' {ProjectSelectForm},
+  ConditionalDefines in '..\..\Units\ConditionalDefines.pas',
+  ProgressHintFrm in '..\..\Forms\ProgressHintFrm.pas' {ProgressHintForm},
+  rmTestFrm in '..\..\DataModules\ReportMemoryDm\rmTestFrm.pas' {rmTestForm},
+  CheckAndClearFrm in '..\..\Forms\CheckAndClearFrm.pas' {CheckAndClearForm},
+  rmGclBillsAuditCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAuditCompareDm.pas' {rmGclBillsAuditCompareData: TDataModule},
+  DealBillsFrm in '..\..\Forms\DealBillsFrm.pas' {DealBillsForm},
+  TenderBackupFrm in '..\..\Forms\TenderBackupFrm.pas' {TenderBackupForm},
+  TenderBackupDm in '..\..\DataModules\TenderBackupDm.pas' {TenderBackupData: TDataModule},
+  BillsBookmarkDm in '..\..\DataModules\BillsBookmarkDm.pas' {BillsBookmarkData: TDataModule},
+  BookmarkFme in '..\..\Frames\BookmarkFme.pas' {BookmarkFrame: TFrame},
+  rmDealInfosDm in '..\..\DataModules\ReportMemoryDm\rmDealInfosDm.pas' {rmDealInfosData: TDataModule},
+  rmXmjBGLDetailDm in '..\..\DataModules\ReportMemoryDm\rmXmjBGLDetailDm.pas' {rmXmjBGLDetailData: TDataModule},
+  WelcomeFrm in '..\..\Forms\WelcomeFrm.pas' {WelcomeForm},
+  rmOtherReport1Dm in '..\..\DataModules\ReportMemoryDm\rmOtherReport1Dm.pas' {rmOtherReport1Data: TDataModule},
+  CheckerMemoFrm in '..\..\Forms\CheckerMemoFrm.pas' {CheckerMemoForm},
+  CslHint in '..\..\Units\CslHint.pas',
+  rmGclBillsCheckDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCheckDm.pas' {rmGclBillsCheckData: TDataModule},
+  TenderBackupManager in '..\..\Units\TenderBackupManager.pas',
+  UpFileManageUnit in '..\..\Units\UpFileManageUnit.pas',
+  UpFileFrame in '..\..\Forms\UpFileFrame.pas',
+  UpFileManageFrame in '..\..\Forms\UpFileManageFrame.pas',
+  SheetSelectFrm in '..\..\Forms\SheetSelectFrm.pas' {SheetSelectForm},
+  Checker in '..\..\Units\Checker.pas',
+  ReportInteractInfo in '..\..\Units\ReportInteractInfo.pas',
+  AuditSelectFrm in '..\..\Forms\ReportInteractFrms\AuditSelectFrm.pas' {AuditSelctForm},
+  DealBillsFme in '..\..\Frames\DealBillsFme.pas' {DealBillsFrame: TFrame},
+  rmGclBillsPlaneDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsPlaneDm.pas' {rmGclBillsPlaneData: TDataModule},
+  StageCompareDm in '..\..\DataModules\StageCompareDm.pas' {StageCompareData: TDataModule},
+  BGLClipboard in '..\..\Units\BGLClipboard.pas',
+  rmMentalCustomized1Dm in '..\..\DataModules\ReportMemoryDm\rmMentalCustomized1Dm.pas' {rmMentalCustomized1Data: TDataModule},
+  mDataRecord in '..\..\Units\mDataRecord.pas',
+  rmGcl_XmjBillsDm in '..\..\DataModules\ReportMemoryDm\rmGcl_XmjBillsDm.pas' {rmGcl_XmjBillsData: TDataModule},
+  rmCustomized2Dm in '..\..\DataModules\ReportMemoryDm\rmCustomized2Dm.pas' {rmCustomized2Data: TDataModule},
+  CalcDecimal in '..\..\Units\CalcDecimal.pas';
+
+{$R *.res}
+
+var Mutex: THandle;
+begin
+  Mutex := CreateMutex(nil, True, G_AppHandleName);
+
+  if GetLastError = ERROR_ALREADY_EXISTS then
+    Application.MessageBox('程序正在运行, 请勿重复打开该软件!', '系统提示', MB_OK + MB_ICONINFORMATION)
+  else
+  begin
+    Application.CreateHandle;
+    Application.Initialize;
+    Application.Title := '纵横公路工程结算决算计量一体化软件广东专业版';
+    ShowWelcome;
+    if CheckDogExists then
+    begin
+      HideWelcome;
+      Application.CreateForm(TMainForm, MainForm);
+  end
+    else  HideWelcome;
+    Application.Run;
+  end;
+
+  ReleaseMutex(Mutex);
+end.

二进制
Dprs/Pro/Measure_GuangDong.res


+ 41 - 0
Dprs/Pro/Measure_GuangDong_Cloud.cfg

@@ -0,0 +1,41 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"E:\SmartCostExe\Measure"
+-N"..\..\Dcus"
+-LE"d:\program files\borland\delphi7\Projects\Bpl"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-D_mCloud;_mEncrypt;_mGuangDong
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

+ 165 - 0
Dprs/Pro/Measure_GuangDong_Cloud.dof

@@ -0,0 +1,165 @@
+[FileVersion]
+Version=7.0
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=0
+K=0
+L=1
+M=0
+N=1
+O=1
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=0
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+NamespacePrefix=
+SymbolDeprecated=1
+SymbolLibrary=1
+SymbolPlatform=1
+UnitLibrary=1
+UnitPlatform=1
+UnitDeprecated=1
+HResultCompat=1
+HidingMember=1
+HiddenVirtual=1
+Garbage=1
+BoundsError=1
+ZeroNilCompat=1
+StringConstTruncated=1
+ForLoopVarVarPar=1
+TypedConstVarPar=1
+AsgToTypedConst=1
+CaseLabelRange=1
+ForVariable=1
+ConstructingAbstract=1
+ComparisonFalse=1
+ComparisonTrue=1
+ComparingSignedUnsigned=1
+CombiningSignedUnsigned=1
+UnsupportedConstruct=1
+FileOpen=1
+FileOpenUnitSrc=1
+BadGlobalSymbol=1
+DuplicateConstructorDestructor=1
+InvalidDirective=1
+PackageNoLink=1
+PackageThreadVar=1
+ImplicitImport=1
+HPPEMITIgnored=1
+NoRetVal=1
+UseBeforeDef=1
+ForLoopVarUndef=1
+UnitNameMismatch=1
+NoCFGFileFound=1
+MessageDirective=1
+ImplicitVariants=1
+UnicodeToLocale=1
+LocaleToUnicode=1
+ImagebaseMultiple=1
+SuspiciousTypecast=1
+PrivatePropAccessor=1
+UnsafeType=0
+UnsafeCode=0
+UnsafeCast=0
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=E:\SmartCostExe\Measure
+UnitOutputDir=..\..\Dcus
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=
+Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;Rave50CLX;Rave50VCL;dclOfficeXP;ZjGridD7;DPanel;ExTree;JimComboBoxs;JimTab;PrintComRep;XPMenu_tom;ZjGridFereD7;ZjCommon;SmartDataSet;ZjGridActns
+Conditionals=_mCloud;_mEncrypt;_mGuangDong
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Language]
+ActiveLang=
+ProjectLang=
+RootDir=D:\Program Files\Borland\Delphi7\Bin\
+[Version Info]
+IncludeVerInfo=1
+AutoIncBuild=1
+MajorVer=3
+MinorVer=1
+Release=3
+Build=1031
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=2052
+CodePage=936
+[Version Info Keys]
+CompanyName=珠海纵横创新软件有限公司
+FileDescription=纵横结算决算计量一体化广东云版
+FileVersion=3.1.3.1031
+InternalName=Measure
+LegalCopyright=版权所有(C) 珠海纵横创新软件有限公司 2003-2014。保留所有权利。
+LegalTrademarks=Measure
+OriginalFilename=
+ProductName=纵横公路工程计量决算一体化软件
+ProductVersion=3
+Comments=
+[HistoryLists\hlConditionals]
+Count=8
+Item0=_mCloud;_mEncrypt;_mGuangDong
+Item1=_mCloud;_mEncrypt;_mGuangDong;_Test
+Item2=_mCloud;_mEncrypt;_mGuangDong;_mTest
+Item3=_mCloud;_mEncrypt;_mGuangDong;
+Item4=_OnLine;_mEncrypt;_mGuangDong;cplPrint;cplOutputToExcelRange
+Item5=_OnLine;_mEncrypt;cplPrint;cplOutputToExcelRange
+Item6=_OnLine;cplPrint;cplOutputToExcelRange
+Item7=_OnLine;cplPrint;_mEncrypt;cplPrint;cplOutputToExcelRange
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlUnitOutputDirectory]
+Count=3
+Item0=..\..\Dcus
+Item1=E:\DelphiTemp
+Item2=D:\Dcu
+[HistoryLists\hlOutputDirectorry]
+Count=3
+Item0=E:\SmartCostExe\Measure
+Item1=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(广东云版)15审核人
+Item2=D:\Program Files (x86)\纵横软件\纵横计量决算一体化软件(专业版)
+[HistoryLists\hlBPLOutput]
+Count=1
+Item0=..\Bin
+[HistoryLists\hlDCPOutput]
+Count=1
+Item0=D:\Dcu

+ 196 - 0
Dprs/Pro/Measure_GuangDong_Cloud.dpr

@@ -0,0 +1,196 @@
+program Measure_GuangDong_Cloud;
+
+uses
+  Windows,
+  ShareMem,
+  Forms,
+  Controls,
+  MainFrm in '..\..\Forms\MainFrm.pas' {MainForm},
+  ProjectManagerFme in '..\..\Frames\ProjectManagerFme.pas' {ProjectManagerFrame: TFrame},
+  UtilMethods in '..\..\Units\UtilMethods.pas',
+  ProjectManagerDm in '..\..\DataModules\ProjectManagerDm.pas' {ProjectManagerData: TDataModule},
+  Connections in '..\..\Units\Connections.pas',
+  TransFile in '..\..\Units\TransFile.pas',
+  ZhAPI in '..\..\Units\ZhAPI.pas',
+  CompactDB in '..\..\Units\CompactDB.pas',
+  OpenProjectManager in '..\..\Units\OpenProjectManager.pas',
+  ProjectData in '..\..\Units\ProjectData.pas',
+  UpdateDataBase in '..\..\Units\UpdateDataBase.pas',
+  DataBaseTables in '..\..\Units\DataBaseTables.pas',
+  ConfigDoc in '..\..\Units\ConfigDoc.pas',
+  SupportUnit in '..\..\Units\SupportUnit.pas',
+  StandardLibs in '..\..\Units\StandardLibs.pas',
+  StandardLib in '..\..\Units\StandardLib.pas',
+  NewProjectFrm in '..\..\Forms\NewProjectFrm.pas' {NewProjectForm},
+  ProjectFme in '..\..\Frames\ProjectFme.pas' {ProjectFrame: TFrame},
+  StandardBillsDm in '..\..\DataModules\StandardBillsDm.pas' {StandardBillsData: TDataModule},
+  StandardBillsFme in '..\..\Frames\StandardBillsFme.pas' {StandardBillsFrame: TFrame},
+  StandardLibsFme in '..\..\Frames\StandardLibsFme.pas' {StandardLibsFrame: TFrame},
+  BillsDm in '..\..\DataModules\BillsDm.pas' {BillsData: TDataModule},
+  Globals in '..\..\Units\Globals.pas',
+  StageDm in '..\..\DataModules\StageDm.pas' {StageData: TDataModule},
+  ExcelImport in '..\..\Units\ExcelImport.pas',
+  CacheTree in '..\..\Units\CacheTree.pas',
+  MCacheTree in '..\..\Units\MCacheTree.pas',
+  ProjectPropertiesFrm in '..\..\Forms\ProjectPropertiesFrm.pas' {ProjectPropertiesForm},
+  ProjectProperty in '..\..\Units\ProjectProperty.pas',
+  FormulaCalc in '..\..\Units\FormulaCalc.pas',
+  BillsCommand in '..\..\Units\BillsCommand.pas',
+  PhaseData in '..\..\Units\PhaseData.pas',
+  PhaseProperty in '..\..\Units\PhaseProperty.pas',
+  BillsClipboard in '..\..\Units\BillsClipboard.pas',
+  BillsTree in '..\..\Units\BillsTree.pas',
+  ProjectCommands in '..\..\Units\ProjectCommands.pas',
+  PhaseCompareDm in '..\..\DataModules\PhaseCompareDm.pas' {PhaseCompareData: TDataModule},
+  PhaseCompareFme in '..\..\Frames\PhaseCompareFme.pas' {PhaseCompareFrame: TFrame},
+  OptionFrm in '..\..\Forms\OptionFrm.pas' {OptionForm},
+  DealPaymentDm in '..\..\DataModules\DealPaymentDm.pas' {DealPaymentData: TDataModule},
+  DealPaymentFme in '..\..\Frames\DealPaymentFme.pas' {DealPaymentFrame: TFrame},
+  PhasePayDm in '..\..\DataModules\PhasePayDm.pas' {PhasePayData: TDataModule},
+  ZJJLDm in '..\..\DataModules\ZJJLDm.pas' {ZJJLData: TDataModule},
+  BillsGatherDm in '..\..\DataModules\BillsGatherDm.pas' {BillsGatherData: TDataModule},
+  BillsGatherFme in '..\..\Frames\BillsGatherFme.pas' {BillsGatherFrame: TFrame},
+  LoginFrm in '..\..\Forms\LoginFrm.pas' {LoginFrm},
+  PHPWebDm in '..\..\DataModules\PHPWebDm.pas' {PHPWeb: TDataModule},
+  MD5Unit in '..\..\Units\MD5Unit.pas',
+  ConstUnit in '..\..\Units\ConstUnit.pas',
+  ExportExcel in '..\..\Units\ExportExcel.pas',
+  mEncryptEditions in '..\..\Encrypt\mEncryptEditions.pas',
+  mEncryptUnit in '..\..\Encrypt\mEncryptUnit.pas',
+  CryptUtils in '..\..\Encrypt\CryptUtils.pas',
+  EncryptDog in '..\..\Encrypt\EncryptDog.pas',
+  mEncryptPWD in '..\..\Encrypt\mEncryptPWD.pas',
+  mEncryptTypes in '..\..\Encrypt\mEncryptTypes.pas',
+  mR1Encrypt in '..\..\Encrypt\mR1Encrypt.pas',
+  mS4Utils in '..\..\Encrypt\mS4Utils.pas',
+  mSNSEncrypt in '..\..\Encrypt\mSNSEncrypt.pas',
+  Rockey1 in '..\..\Encrypt\Rockey1.pas',
+  mConnectEncrypt in '..\..\Encrypt\NetClient\mConnectEncrypt.pas',
+  FindUserFrm in '..\..\Forms\FindUserFrm.pas' {FindUserForm},
+  CslJson in '..\..\Units\CslJson.pas',
+  OrderCheckerFme in '..\..\Frames\OrderCheckerFme.pas' {OrderCheckerFrame: TFrame},
+  CheckerFme in '..\..\Frames\CheckerFme.pas' {CheckerFrame: TFrame},
+  WebNewTenderFrm in '..\..\Forms\WebNewTenderFrm.pas' {WebNewTenderForm},
+  ScFileArchiver in '..\..\Encrypt\ScFileArchiver.pas',
+  SearchDm in '..\..\DataModules\SearchDm.pas' {SearchData: TDataModule},
+  DealBillsDm in '..\..\DataModules\DealBillsDm.pas' {DealBillsData: TDataModule},
+  BGLDm in '..\..\DataModules\BGLDm.pas' {BGLData: TDataModule},
+  StaffDm in '..\..\DataModules\StaffDm.pas' {StaffData: TDataModule},
+  EstimateDm in '..\..\DataModules\EstimateDm.pas' {EstimateData: TDataModule},
+  BillsCompileDm in '..\..\DataModules\BillsCompileDm.pas' {BillsCompileData: TDataModule},
+  BillsMeasureDm in '..\..\DataModules\BillsMeasureDm.pas' {BillsMeasureData: TDataModule},
+  ReportManager in '..\..\Units\ReportManager.pas',
+  BGLSelectFrm in '..\..\Forms\BGLSelectFrm.pas' {BGLSelectForm},
+  BillsCompileFme in '..\..\Frames\BillsCompileFme.pas' {BillsCompileFrame: TFrame},
+  BillsMeasureFme in '..\..\Frames\BillsMeasureFme.pas' {BillsMeasureFrame: TFrame},
+  BatchReplaceBillsFrm in '..\..\Forms\BatchReplaceBillsFrm.pas' {BatchReplaceBillsForm},
+  ZJJLFme in '..\..\Frames\ZJJLFme.pas' {ZJJLFrame: TFrame},
+  BGLFme in '..\..\Frames\BGLFme.pas' {BGLFrame: TFrame},
+  MergeTextFrm in '..\..\Forms\MergeTextFrm.pas' {MergeTextForm},
+  EstimateFme in '..\..\Frames\EstimateFme.pas' {EstimateFrame: TFrame},
+  ReportsFrm in '..\..\Forms\ReportsFrm.pas' {ReportsForm},
+  ReportAdjustFrm in '..\..\Forms\ReportAdjustFrm.pas' {ReportAdjustForm},
+  SearchFme in '..\..\Frames\SearchFme.pas' {SearchFrame: TFrame},
+  AuthFrm in '..\..\Forms\AuthFrm.pas' {AuthorizeForm},
+  AboutFrm in '..\..\Forms\AboutFrm.pas' {AboutForm},
+  ImportExcelHintFrm in '..\..\Forms\ImportExcelHintFrm.pas' {ImportExcelHintForm},
+  PasswordInputFrm in '..\..\Forms\PasswordInputFrm.pas' {PasswordInputForm},
+  BatchInsertBillsFrm in '..\..\Forms\BatchInsertBillsFrm.pas' {BatchInsertBillsForm},
+  MainDataListDm in '..\..\DataModules\MainDataListDm.pas' {MainListData: TDataModule},
+  mProgressFrm in '..\..\Forms\mProgressFrm.pas' {mProgress},
+  rmGclBillsBGDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsBGDm.pas' {rmGclBillsBGData: TDataModule},
+  rmGclBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCompareDm.pas' {rmGclBillsCompareData: TDataModule},
+  rmBGLExecutionDm in '..\..\DataModules\ReportMemoryDm\rmBGLExecutionDm.pas' {rmBGLExecutionData: TDataModule},
+  rmBillsGatherDm in '..\..\DataModules\ReportMemoryDm\rmBillsGatherDm.pas' {rmBillsGatherData: TDataModule},
+  rmFxBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsAddDm.pas' {rmFxBillsAddData: TDataModule},
+  rmFxBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsCompareDm.pas' {rmFxBillsCompareData: TDataModule},
+  rmGclBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAddDm.pas' {rmGclBillsAddData: TDataModule},
+  rmGridHeaderDm in '..\..\DataModules\ReportMemoryDm\rmGridHeaderDm.pas' {rmGridHeaderData: TDataModule},
+  rmCacheData in '..\..\DataModules\ReportMemoryDm\rmCacheData.pas',
+  rmSelectProjectFrm in '..\..\Forms\rmSelectProjectFrm.pas' {ProjectSelectForm},
+  ConditionalDefines in '..\..\Units\ConditionalDefines.pas',
+  ProgressHintFrm in '..\..\Forms\ProgressHintFrm.pas' {ProgressHintForm},
+  rmGclBillsAuditCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAuditCompareDm.pas' {rmGclBillsAuditCompareData: TDataModule},
+  rmTestFrm in '..\..\DataModules\ReportMemoryDm\rmTestFrm.pas' {rmTestForm},
+  CheckAndClearFrm in '..\..\Forms\CheckAndClearFrm.pas' {CheckAndClearForm},
+  DealBillsFrm in '..\..\Forms\DealBillsFrm.pas' {DealBillsForm},
+  TenderBackupFrm in '..\..\Forms\TenderBackupFrm.pas' {TenderBackupForm},
+  TenderBackupDm in '..\..\DataModules\TenderBackupDm.pas' {TenderBackupData: TDataModule},
+  BillsBookmarkDm in '..\..\DataModules\BillsBookmarkDm.pas' {BillsBookmarkData: TDataModule},
+  BookmarkFme in '..\..\Frames\BookmarkFme.pas' {BookmarkFrame: TFrame},
+  rmDealInfosDm in '..\..\DataModules\ReportMemoryDm\rmDealInfosDm.pas' {rmDealInfosData: TDataModule},
+  rmXmjBGLDetailDm in '..\..\DataModules\ReportMemoryDm\rmXmjBGLDetailDm.pas' {rmXmjBGLDetailData: TDataModule},
+  WelcomeFrm in '..\..\Forms\WelcomeFrm.pas' {Form1},
+  rmOtherReport1Dm in '..\..\DataModules\ReportMemoryDm\rmOtherReport1Dm.pas' {rmOtherReport1Data: TDataModule},
+  CheckerMemoFrm in '..\..\Forms\CheckerMemoFrm.pas' {CheckerMemoForm},
+  CslHint in '..\..\Units\CslHint.pas',
+  rmGclBillsCheckDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCheckDm.pas' {rmGclBillsCheckData: TDataModule},
+  IPFrm in '..\..\Forms\IPFrm.pas' {IPForm},
+  TenderBackupManager in '..\..\Units\TenderBackupManager.pas',
+  UpFileFrame in '..\..\Forms\UpFileFrame.pas',
+  UpFileManageFrame in '..\..\Forms\UpFileManageFrame.pas',
+  UpFileManageUnit in '..\..\Units\UpFileManageUnit.pas',
+  SheetSelectFrm in '..\..\Forms\SheetSelectFrm.pas' {SheetSelectForm},
+  Checker in '..\..\Units\Checker.pas',
+  ReportInteractInfo in '..\..\Units\ReportInteractInfo.pas',
+  AuditSelectFrm in '..\..\Forms\ReportInteractFrms\AuditSelectFrm.pas' {AuditSelctForm},
+  DealBillsFme in '..\..\Frames\DealBillsFme.pas' {DealBillsFrame: TFrame},
+  rmGclBillsPlaneDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsPlaneDm.pas' {rmGclBillsPlaneData: TDataModule},
+  StageCompareDm in '..\..\DataModules\StageCompareDm.pas' {StageCompareData: TDataModule},
+  mDataRecord in '..\..\Units\mDataRecord.pas',
+  BGLClipboard in '..\..\Units\BGLClipboard.pas',
+  rmMentalCustomized1Dm in '..\..\DataModules\ReportMemoryDm\rmMentalCustomized1Dm.pas' {rmMentalCustomized1Data: TDataModule},
+  rmGcl_XmjBillsDm in '..\..\DataModules\ReportMemoryDm\rmGcl_XmjBillsDm.pas' {rmGcl_XmjBillsData: TDataModule},
+  rmCustomized2Dm in '..\..\DataModules\ReportMemoryDm\rmCustomized2Dm.pas' {rmCustomized2Data: TDataModule},
+  CalcDecimal in '..\..\Units\CalcDecimal.pas';
+
+{$R *.res}
+
+var
+  Mutex: THandle;
+  IPForm: TIPForm;
+
+begin
+  Mutex := CreateMutex(nil, True, G_AppHandleName);
+
+  if GetLastError = ERROR_ALREADY_EXISTS then
+    Application.MessageBox('程序正在运行, 请勿重复打开该软件!', '系统提示', MB_OK + MB_ICONINFORMATION)
+  else
+  begin
+    Application.CreateHandle;
+    Application.Initialize;
+    Application.Title := '纵横公路工程结算决算计量一体化软件广东云版';
+
+    {$IFDEF _mCloud}
+      IPForm := TIPForm.Create(nil);
+      try
+        if not IPForm.HasIP then
+        begin
+          IPForm.ShowModal;
+          if IPForm.ModalResult <> mrOK then
+          begin
+            Application.Terminate;
+            Exit;
+          end;
+        end;
+      finally
+        IPForm.Free;
+      end;
+
+      if not LoginForm then
+      begin
+        Application.Terminate;
+        Exit;
+      end;
+    {$ENDIF}
+
+
+    if CheckDogExists then
+    begin
+      Application.CreateForm(TMainForm, MainForm);
+  end;
+    Application.Run;
+  end;
+
+  ReleaseMutex(Mutex);
+end.

二进制
Dprs/Pro/Measure_GuangDong_Cloud.res


+ 40 - 0
Dprs/Pro/Measure_GuangDong_TZ.cfg

@@ -0,0 +1,40 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"E:\SmartCostExe\Measure"
+-N"..\..\Dcus"
+-LE"d:\program files\borland\delphi7\Projects\Bpl"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

文件差异内容过多而无法显示
+ 146 - 0
Dprs/Pro/Measure_GuangDong_TZ.dof


+ 168 - 0
Dprs/Pro/Measure_GuangDong_TZ.dpr

@@ -0,0 +1,168 @@
+program Measure_GuangDong_TZ;
+
+uses
+  Windows,
+  ShareMem,
+  Forms,
+  MainFrm in '..\..\Forms\MainFrm.pas' {MainForm},
+  ProjectManagerFme in '..\..\Frames\ProjectManagerFme.pas' {ProjectManagerFrame: TFrame},
+  UtilMethods in '..\..\Units\UtilMethods.pas',
+  ProjectManagerDm in '..\..\DataModules\ProjectManagerDm.pas' {ProjectManagerData: TDataModule},
+  Connections in '..\..\Units\Connections.pas',
+  TransFile in '..\..\Units\TransFile.pas',
+  ZhAPI in '..\..\Units\ZhAPI.pas',
+  CompactDB in '..\..\Units\CompactDB.pas',
+  OpenProjectManager in '..\..\Units\OpenProjectManager.pas',
+  ProjectData in '..\..\Units\ProjectData.pas',
+  UpdateDataBase in '..\..\Units\UpdateDataBase.pas',
+  DataBaseTables in '..\..\Units\DataBaseTables.pas',
+  ConfigDoc in '..\..\Units\ConfigDoc.pas',
+  SupportUnit in '..\..\Units\SupportUnit.pas',
+  StandardLibs in '..\..\Units\StandardLibs.pas',
+  StandardLib in '..\..\Units\StandardLib.pas',
+  NewProjectFrm in '..\..\Forms\NewProjectFrm.pas' {NewProjectForm},
+  ProjectFme in '..\..\Frames\ProjectFme.pas' {ProjectFrame: TFrame},
+  StandardBillsDm in '..\..\DataModules\StandardBillsDm.pas' {StandardBillsData: TDataModule},
+  StandardBillsFme in '..\..\Frames\StandardBillsFme.pas' {StandardBillsFrame: TFrame},
+  StandardLibsFme in '..\..\Frames\StandardLibsFme.pas' {StandardLibsFrame: TFrame},
+  BillsDm in '..\..\DataModules\BillsDm.pas' {BillsData: TDataModule},
+  BillsMeasureFme in '..\..\Frames\BillsMeasureFme.pas' {BillsMeasureFrame: TFrame},
+  Globals in '..\..\Units\Globals.pas',
+  StageDm in '..\..\DataModules\StageDm.pas' {StageData: TDataModule},
+  ExcelImport in '..\..\Units\ExcelImport.pas',
+  CacheTree in '..\..\Units\CacheTree.pas',
+  MCacheTree in '..\..\Units\MCacheTree.pas',
+  ProjectPropertiesFrm in '..\..\Forms\ProjectPropertiesFrm.pas' {ProjectPropertiesForm},
+  ProjectProperty in '..\..\Units\ProjectProperty.pas',
+  FormulaCalc in '..\..\Units\FormulaCalc.pas',
+  BillsCommand in '..\..\Units\BillsCommand.pas',
+  PhaseData in '..\..\Units\PhaseData.pas',
+  PhaseProperty in '..\..\Units\PhaseProperty.pas',
+  BillsClipboard in '..\..\Units\BillsClipboard.pas',
+  BillsTree in '..\..\Units\BillsTree.pas',
+  ProjectCommands in '..\..\Units\ProjectCommands.pas',
+  PhaseCompareDm in '..\..\DataModules\PhaseCompareDm.pas' {PhaseCompareData: TDataModule},
+  PhaseCompareFme in '..\..\Frames\PhaseCompareFme.pas' {PhaseCompareFrame: TFrame},
+  OptionFrm in '..\..\Forms\OptionFrm.pas' {OptionForm},
+  DealPaymentDm in '..\..\DataModules\DealPaymentDm.pas' {DealPaymentData: TDataModule},
+  DealPaymentFme in '..\..\Frames\DealPaymentFme.pas' {DealPaymentFrame: TFrame},
+  PhasePayDm in '..\..\DataModules\PhasePayDm.pas' {PhasePayData: TDataModule},
+  BillsGatherFme in '..\..\Frames\BillsGatherFme.pas' {BillsGatherFrame: TFrame},
+  BillsGatherDm in '..\..\DataModules\BillsGatherDm.pas' {BillsGatherData: TDataModule},
+  ZJJLFme in '..\..\Frames\ZJJLFme.pas' {ZJJLFrame: TFrame},
+  ZJJLDm in '..\..\DataModules\ZJJLDm.pas' {ZJJLData: TDataModule},
+  BGLFme in '..\..\Frames\BGLFme.pas' {BGLFrame: TFrame},
+  BGLDm in '..\..\DataModules\BGLDm.pas' {BGLData: TDataModule},
+  StaffDm in '..\..\DataModules\StaffDm.pas' {StaffData: TDataModule},
+  ConstUnit in '..\..\Units\ConstUnit.pas',
+  PHPWebDm in '..\..\DataModules\PHPWebDm.pas' {PHPWeb: TDataModule},
+  uLkJSON in '..\..\Units\uLkJSON.pas',
+  MergeTextFrm in '..\..\Forms\MergeTextFrm.pas' {MergeTextForm},
+  BGLSelectFrm in '..\..\Forms\BGLSelectFrm.pas' {BGLSelectForm},
+  EstimateFme in '..\..\Frames\EstimateFme.pas' {EstimateFrame: TFrame},
+  EstimateDm in '..\..\DataModules\EstimateDm.pas' {EstimateData: TDataModule},
+  WebNewTenderFrm in '..\..\Forms\WebNewTenderFrm.pas' {WebNewTenderForm},
+  ExportExcel in '..\..\Units\ExportExcel.pas',
+  ReportsFrm in '..\..\Forms\ReportsFrm.pas' {ReportsForm},
+  ReportManager in '..\..\Units\ReportManager.pas',
+  BillsCompileDm in '..\..\DataModules\BillsCompileDm.pas' {BillsCompileData: TDataModule},
+  BillsCompileFme in '..\..\Frames\BillsCompileFme.pas' {BillsCompileFrame: TFrame},
+  BillsMeasureDm in '..\..\DataModules\BillsMeasureDm.pas' {BillsMeasureData: TDataModule},
+  PasswordInputFrm in '..\..\Forms\PasswordInputFrm.pas' {PasswordInputForm},
+  AboutFrm in '..\..\Forms\AboutFrm.pas' {AboutForm},
+  AuthFrm in '..\..\Forms\AuthFrm.pas' {AuthorizeForm},
+  mEncryptUnit in '..\..\Encrypt\mEncryptUnit.pas',
+  mEncryptPWD in '..\..\Encrypt\mEncryptPWD.pas',
+  mSNSEncrypt in '..\..\Encrypt\mSNSEncrypt.pas',
+  mR1Encrypt in '..\..\Encrypt\mR1Encrypt.pas',
+  mEncryptEditions in '..\..\Encrypt\mEncryptEditions.pas',
+  mEncryptTypes in '..\..\Encrypt\mEncryptTypes.pas',
+  mConnectEncrypt in '..\..\Encrypt\NetClient\mConnectEncrypt.pas',
+  CryptUtils in '..\..\Encrypt\CryptUtils.pas',
+  EncryptDog in '..\..\Encrypt\EncryptDog.pas',
+  ScFileArchiver in '..\..\Encrypt\ScFileArchiver.pas',
+  SearchFme in '..\..\Frames\SearchFme.pas' {SearchFrame: TFrame},
+  BatchInsertBillsFrm in '..\..\Forms\BatchInsertBillsFrm.pas' {BatchInsertBillsForm},
+  SearchDm in '..\..\DataModules\SearchDm.pas' {SearchData: TDataModule},
+  CslJson in '..\..\Units\CslJson.pas',
+  FindUserFrm in '..\..\Forms\FindUserFrm.pas' {FindUserForm},
+  ImportExcelHintFrm in '..\..\Forms\ImportExcelHintFrm.pas' {ImportExcelHintForm},
+  CheckerFme in '..\..\Frames\CheckerFme.pas' {CheckerFrame: TFrame},
+  OrderCheckerFme in '..\..\Frames\OrderCheckerFme.pas' {OrderCheckerFrame: TFrame},
+  ReportAdjustFrm in '..\..\Forms\ReportAdjustFrm.pas' {ReportAdjustForm},
+  DealBillsDm in '..\..\DataModules\DealBillsDm.pas' {DealBillsData: TDataModule},
+  BatchReplaceBillsFrm in '..\..\Forms\BatchReplaceBillsFrm.pas' {BatchReplaceBillsForm},
+  MD5Unit in '..\..\Units\MD5Unit.pas',
+  MainDataListDm in '..\..\DataModules\MainDataListDm.pas' {MainListData: TDataModule},
+  mProgressFrm in '..\..\Forms\mProgressFrm.pas' {mProgress},
+  rmGclBillsBGDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsBGDm.pas' {DataModule1: TDataModule},
+  rmBGLExecutionDm in '..\..\DataModules\ReportMemoryDm\rmBGLExecutionDm.pas' {rmBGLExecutionData: TDataModule},
+  rmBillsGatherDm in '..\..\DataModules\ReportMemoryDm\rmBillsGatherDm.pas' {rmBillsGatherData: TDataModule},
+  rmCacheData in '..\..\DataModules\ReportMemoryDm\rmCacheData.pas',
+  rmFxBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsAddDm.pas' {rmFxBillsAddData: TDataModule},
+  rmFxBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmFxBillsCompareDm.pas' {rmFxBillsCompareData: TDataModule},
+  rmGclBillsAddDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAddDm.pas' {rmGclBillsAddData: TDataModule},
+  rmGclBillsCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCompareDm.pas' {rmGclBillsCompareData: TDataModule},
+  rmGridHeaderDm in '..\..\DataModules\ReportMemoryDm\rmGridHeaderDm.pas' {rmGridHeaderData: TDataModule},
+  rmSelectProjectFrm in '..\..\Forms\rmSelectProjectFrm.pas' {ProjectSelectForm},
+  ConditionalDefines in '..\..\Units\ConditionalDefines.pas',
+  ProgressHintFrm in '..\..\Forms\ProgressHintFrm.pas' {ProgressHintForm},
+  CheckAndClearFrm in '..\..\Forms\CheckAndClearFrm.pas' {CheckAndClearForm},
+  rmGclBillsAuditCompareDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsAuditCompareDm.pas' {rmGclBillsAuditCompareData: TDataModule},
+  rmTestFrm in '..\..\DataModules\ReportMemoryDm\rmTestFrm.pas' {rmTestForm},
+  DealBillsFrm in '..\..\Forms\DealBillsFrm.pas' {DealBillsForm},
+  TenderBackupFrm in '..\..\Forms\TenderBackupFrm.pas' {TenderBackupForm},
+  TenderBackupDm in '..\..\DataModules\TenderBackupDm.pas' {TenderBackupData: TDataModule},
+  BillsBookmarkDm in '..\..\DataModules\BillsBookmarkDm.pas' {BillsBookmarkData: TDataModule},
+  BookmarkFme in '..\..\Frames\BookmarkFme.pas' {BookmarkFrame: TFrame},
+  rmDealInfosDm in '..\..\DataModules\ReportMemoryDm\rmDealInfosDm.pas' {rmDealInfosData: TDataModule},
+  rmXmjBGLDetailDm in '..\..\DataModules\ReportMemoryDm\rmXmjBGLDetailDm.pas' {rmXmjBGLDetailData: TDataModule},
+  WelcomeFrm in '..\..\Forms\WelcomeFrm.pas' {WelcomeForm},
+  rmOtherReport1Dm in '..\..\DataModules\ReportMemoryDm\rmOtherReport1Dm.pas' {rmOtherReport1Data: TDataModule},
+  CheckerMemoFrm in '..\..\Forms\CheckerMemoFrm.pas' {CheckerMemoForm},
+  CslHint in '..\..\Units\CslHint.pas',
+  rmGclBillsCheckDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsCheckDm.pas' {rmGclBillsCheckData: TDataModule},
+  TenderBackupManager in '..\..\Units\TenderBackupManager.pas',
+  UpFileManageUnit in '..\..\Units\UpFileManageUnit.pas',
+  UpFileFrame in '..\..\Forms\UpFileFrame.pas',
+  UpFileManageFrame in '..\..\Forms\UpFileManageFrame.pas',
+  SheetSelectFrm in '..\..\Forms\SheetSelectFrm.pas' {SheetSelectForm},
+  ReportInteractInfo in '..\..\Units\ReportInteractInfo.pas',
+  Checker in '..\..\Units\Checker.pas',
+  DealBillsFme in '..\..\Frames\DealBillsFme.pas' {DealBillsFrame: TFrame},
+  AuditSelectFrm in '..\..\Forms\ReportInteractFrms\AuditSelectFrm.pas' {AuditSelctForm},
+  rmGclBillsPlaneDm in '..\..\DataModules\ReportMemoryDm\rmGclBillsPlaneDm.pas' {rmGclBillsPlaneData: TDataModule},
+  StageCompareDm in '..\..\DataModules\StageCompareDm.pas' {StageCompareData: TDataModule},
+  BGLClipboard in '..\..\Units\BGLClipboard.pas',
+  rmMentalCustomized1Dm in '..\..\DataModules\ReportMemoryDm\rmMentalCustomized1Dm.pas' {rmMentalCustomized1Data: TDataModule},
+  mDataRecord in '..\..\Units\mDataRecord.pas',
+  rmGcl_XmjBillsDm in '..\..\DataModules\ReportMemoryDm\rmGcl_XmjBillsDm.pas' {rmGcl_XmjBillsData: TDataModule},
+  rmCustomized2Dm in '..\..\DataModules\ReportMemoryDm\rmCustomized2Dm.pas' {rmCustomized2Data: TDataModule},
+  CalcDecimal in '..\..\Units\CalcDecimal.pas';
+
+{$R *.res}
+
+var Mutex: THandle;
+begin
+  Mutex := CreateMutex(nil, True, G_AppHandleName);
+
+  if GetLastError = ERROR_ALREADY_EXISTS then
+    Application.MessageBox('程序正在运行, 请勿重复打开该软件!', '系统提示', MB_OK + MB_ICONINFORMATION)
+  else
+  begin
+    Application.CreateHandle;
+    Application.Initialize;
+    Application.Title := '纵横公路工程0号台账软件广东版';
+    
+
+    if CheckDogExists then
+    begin
+      Application.CreateForm(TMainForm, MainForm);
+  end;
+    Application.Run;
+  end;
+
+  ReleaseMutex(Mutex);
+end.
+
+

二进制
Dprs/Pro/Measure_GuangDong_TZ.res


+ 41 - 0
Dprs/Pro/Measure_TZ.cfg

@@ -0,0 +1,41 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"E:\SmartCostExe\Measure"
+-N"..\..\Dcus"
+-LE"d:\program files\borland\delphi7\Projects\Bpl"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-D_mEncrypt;_mcompile;
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

+ 0 - 0
Dprs/Pro/Measure_TZ.dof


部分文件因为文件数量过多而无法显示