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.