unit StdBillsLibDM; interface uses SysUtils, Classes, DBClient, Provider, DB, ADODB, ScBillsTree, ZjIDTree, ZjLists, ScProjectManager, DataBase; type TDMStdBillsLib = class(TDataModule) acnBillsLib: TADOConnection; atBillsLib: TADOTable; dspBillsLib: TDataSetProvider; cdsBillsLib: TClientDataSet; cdsBillsLibID: TIntegerField; cdsBillsLibParentID: TIntegerField; cdsBillsLibNextID: TIntegerField; cdsBillsLibCode: TWideStringField; cdsBillsLibB_Code: TWideStringField; cdsBillsLibName: TWideStringField; cdsBillsLibUnit: TWideStringField; cdsBillsLibStaticID: TIntegerField; cdsBillsLibExpr: TWideStringField; cdsBillsLibView: TClientDataSet; cdsBillsLibViewID: TIntegerField; cdsBillsLibViewParentID: TIntegerField; cdsBillsLibViewNextID: TIntegerField; cdsBillsLibViewCode: TWideStringField; cdsBillsLibViewB_Code: TWideStringField; cdsBillsLibViewName: TWideStringField; cdsBillsLibViewUnit: TWideStringField; cdsBillsLibViewStaticID: TIntegerField; cdsBillsLibViewExpr: TWideStringField; atDrawingQuantity: TADOTable; dspDrawingQuantity: TDataSetProvider; cdsDrawingQuantity: TClientDataSet; cdsDrawingQuantityID: TIntegerField; cdsDrawingQuantityName: TWideStringField; cdsDrawingQuantityUnits: TWideStringField; cdsDrawingQuantityDesignQuantity: TFloatField; cdsDrawingQuantityDesignQuantity2: TFloatField; cdsDrawingQuantityMemoStr: TWideStringField; cdsDrawingQuantityBillsID: TIntegerField; dspCustomStep: TDataSetProvider; cdsCustomStep: TClientDataSet; atCustomStep: TADOTable; cdsDrawQView: TClientDataSet; cdsDrawQViewID: TIntegerField; cdsDrawQViewName: TWideStringField; cdsDrawQViewUnits: TWideStringField; cdsDrawQViewDesignQuantity: TFloatField; cdsDrawQViewDesignQuantity2: TFloatField; cdsDrawQViewMemoStr: TWideStringField; cdsDrawQViewBillsID: TIntegerField; dsBillsDQ: TDataSource; cdsStaticID: TClientDataSet; cdsStaticIDName: TWideStringField; cdsStaticIDStaticID: TIntegerField; cdsStaticIDID: TIntegerField; cdsDQSetRange: TClientDataSet; cdsDQSetRangeID: TIntegerField; cdsDQSetRangeName: TWideStringField; cdsDQSetRangeUnits: TWideStringField; cdsDQSetRangeDesignQuantity: TFloatField; cdsDQSetRangeDesignQuantity2: TFloatField; cdsDQSetRangeMemoStr: TWideStringField; cdsDQSetRangeBillsID: TIntegerField; cdsCustomStepID: TIntegerField; cdsCustomStepFmtName: TWideStringField; cdsCustomStepStartValue: TFloatField; cdsCustomStepStepValue: TFloatField; cdsCustomStepView: TClientDataSet; cdsCustomStepBillsCode: TWideStringField; cdsCustomStepIsCode: TBooleanField; cdsCustomStepDisName: TWideStringField; cdsCustomStepUnits: TWideStringField; cdsCustomStepViewFmtName: TWideStringField; cdsCustomStepViewStartValue: TFloatField; cdsCustomStepViewStepValue: TFloatField; cdsCustomStepViewBillsCode: TWideStringField; cdsCustomStepViewIsCode: TBooleanField; cdsCustomStepViewDisName: TWideStringField; cdsCustomStepViewUnits: TWideStringField; cdsCustomStepViewCustomValue: TFloatField; cdsCustomStepOldValue: TFloatField; cdsCustomStepViewOldValue: TFloatField; cdsCustomStepStartCodeID: TIntegerField; cdsCustomStepViewStartCodeID: TIntegerField; cdsCustomStepViewCustomBillsCode: TWideStringField; atBillsQty: TADOTable; dspBillsQty: TDataSetProvider; cdsBillsQty: TClientDataSet; cdsBillsQtyView: TClientDataSet; acnBillsQty: TADOConnection; cdsBillsQtyID: TIntegerField; cdsBillsQtyParentID: TIntegerField; cdsBillsQtyNextID: TIntegerField; cdsBillsQtyCode: TWideStringField; cdsBillsQtyB_Code: TWideStringField; cdsBillsQtyName: TWideStringField; cdsBillsQtyUnit: TWideStringField; cdsBillsQtyStaticID: TIntegerField; cdsBillsQtyViewID: TIntegerField; cdsBillsQtyViewParentID: TIntegerField; cdsBillsQtyViewNextID: TIntegerField; cdsBillsQtyViewCode: TWideStringField; cdsBillsQtyViewB_Code: TWideStringField; cdsBillsQtyViewName: TWideStringField; cdsBillsQtyViewUnit: TWideStringField; cdsBillsQtyViewStaticID: TIntegerField; cdsBillsQtyExpr: TWideStringField; cdsBillsQtyViewExpr: TWideStringField; acCustomStep: TADOConnection; atBQDrawingQty: TADOTable; dspBQDrawingQty: TDataSetProvider; cdsBQDrawingQty: TClientDataSet; cdsBQDrawingQtyView: TClientDataSet; dsBillsQty: TDataSource; cdsBQDrawingQtyID: TIntegerField; cdsBQDrawingQtyName: TWideStringField; cdsBQDrawingQtyUnits: TWideStringField; cdsBQDrawingQtyDesignQuantity: TFloatField; cdsBQDrawingQtyDesignQuantity2: TFloatField; cdsBQDrawingQtyMemoStr: TWideStringField; cdsBQDrawingQtyBillsID: TIntegerField; cdsBQDrawingQtyViewID: TIntegerField; cdsBQDrawingQtyViewName: TWideStringField; cdsBQDrawingQtyViewUnits: TWideStringField; cdsBQDrawingQtyViewDesignQuantity: TFloatField; cdsBQDrawingQtyViewDesignQuantity2: TFloatField; cdsBQDrawingQtyViewMemoStr: TWideStringField; cdsBQDrawingQtyViewBillsID: TIntegerField; cdsFastSearch: TClientDataSet; cdsBQFastSearch: TClientDataSet; cdsBQFastSearchID: TIntegerField; cdsBQFastSearchParentID: TIntegerField; cdsBQFastSearchNextID: TIntegerField; cdsBQFastSearchCode: TWideStringField; cdsBQFastSearchB_Code: TWideStringField; cdsBQFastSearchName: TWideStringField; cdsBQFastSearchUnit: TWideStringField; cdsBQFastSearchStaticID: TIntegerField; cdsBQFastSearchExpr: TWideStringField; cdsFastSearchID: TIntegerField; cdsFastSearchParentID: TIntegerField; cdsFastSearchNextID: TIntegerField; cdsFastSearchCode: TWideStringField; cdsFastSearchB_Code: TWideStringField; cdsFastSearchName: TWideStringField; cdsFastSearchUnit: TWideStringField; cdsFastSearchStaticID: TIntegerField; cdsFastSearchExpr: TWideStringField; cdsCustomStepFmtName2: TWideStringField; cdsCustomStepViewFmtName2: TWideStringField; cdsCustomStepSubArea: TBooleanField; cdsCustomStepViewSubArea: TBooleanField; procedure cdsBillsLibAfterOpen(DataSet: TDataSet); procedure cdsDrawingQuantityAfterOpen(DataSet: TDataSet); procedure DataModuleCreate(Sender: TObject); procedure DataModuleDestroy(Sender: TObject); procedure cdsCustomStepViewCustomValueChange(Sender: TField); procedure cdsCustomStepViewAfterPost(DataSet: TDataSet); procedure cdsCustomStepViewBeforeInsert(DataSet: TDataSet); procedure cdsCustomStepViewBeforeDelete(DataSet: TDataSet); procedure cdsBillsLibViewBeforeInsert(DataSet: TDataSet); procedure cdsBillsLibAfterClose(DataSet: TDataSet); procedure cdsBillsQtyAfterOpen(DataSet: TDataSet); procedure cdsBQDrawingQtyAfterOpen(DataSet: TDataSet); procedure cdsBillsLibViewAfterPost(DataSet: TDataSet); procedure cdsBillsLibViewCodeChange(Sender: TField); procedure cdsBillsLibViewAfterInsert(DataSet: TDataSet); procedure cdsBillsQtyViewAfterPost(DataSet: TDataSet); procedure cdsBillsQtyViewAfterInsert(DataSet: TDataSet); procedure cdsDrawQViewNewRecord(DataSet: TDataSet); procedure cdsBQDrawingQtyViewNewRecord(DataSet: TDataSet); private FActive: Boolean; FMaxBillsID: Integer; FStdBillsCtrl: TObject; FCustomStepFlag: Boolean; FAdding: Boolean; FCdsStaticID: TClientDataSet; FCdsModifyBills: TClientDataSet; FStdBillNode: TStdBillNode; FStdBillsTree: TStdBillsTree; FBillsQtyTree: TStdBillsTree; FBillsData: TDMDataBase; FProjectMgr: TProjectManager; procedure Initialize(aType: Integer; AIsAll: Boolean); procedure Finalize(aType: Integer; AIsAll: Boolean); procedure CreateCDS; procedure DestroyCDs; procedure DoInitDBRecord; {compare code} function CompareDiagitCode(AsCode, ACode: string): Integer; function IsStaticIDExist(ALibNode: TZjIDTreeNode): Boolean; {add drawingquantity} procedure AddRelaDrawQ(ADestID, ASrcID: Integer); {add bills items} function AddNewItem(AStdNode: TStdBillNode): TScBillsItem; {calculate code and name by customstep} function CalculateCode(var aCustomValue: Double; var ACode, ADisName, AUnits: string; AIncrease: Boolean = False): Boolean; procedure RecodeCurBills(aCustomValue: Double; const ACode, ADisName, AUnits: string; AIsCode, AIncrease: Boolean); procedure EditCustomStepOldValue(const ACode: string; const Value: Double); procedure EditCustomStepViewOldValue(const Value: Double); {locate customstep by code} function LocateCustomStepByCode(aID: Integer; const ACode, AOldCode: string): Boolean; {add qty item} function CanAddQtyItem(var aNode: TScBillsItem): Boolean; procedure AddQtyRelaDrawQ(ADestID, ASrcID: Integer); function AddNewQtyItems(aNode: TScBillsItem; aQtyNode: TStdBillNode): TScBillsItem; function GetNewID(DataSet: TClientDataSet): Integer; public constructor Create(AProjMgr: TProjectManager); { close } procedure CloseLib(aFileFlag: Integer); {open new std lib} procedure LoadNewStdLib(const ALibName: string); procedure LoadBillsQtyLib(const ALibName: string); procedure LoadCustomStep(const aLibName: string); {add items to cur project} function AddItems(ASelList: TIntegerSList): Boolean; procedure AddItem; {add billsQty items} function AddBillsQtyItems(aSelList: TIntegerSList): Boolean; procedure AddBillsQtyItem; function IsCodeStepItem(AB_Code: string; var AUnits: string): Boolean; {refresh customstep} procedure RefreshCustomStep; {only be used in before post} procedure AutoIncreaseBillsCode; {find code in std lib} function FindLibCode(const ACode: string; var AName, AUnits: string; AIsCode: Boolean): Boolean; function FindRecord(aNode: TZjIDTreeNode; const aCode, aName: string): Boolean; // Added by GiLi 2012-3-20 11:00:46 // 定位至标准清单 procedure LocateCurBillsToStdBills; procedure Save; property StdBillsCtrl: TObject read FStdBillsCtrl write FStdBillsCtrl; property StdBillsTree: TStdBillsTree read FStdBillsTree write FStdBillsTree; property BillsQtyTree: TStdBillsTree read FBillsQtyTree write FBillsQtyTree; // 这两个属性是为了和SmartCost定义保持一致,方便代码Copy. chenshilong, 2011-07-20 property StdTree: TStdTree read FStdBillsTree write FStdBillsTree; property BQStdTree: TStdTree read FBillsQtyTree write FBillsQtyTree; procedure CloneActive(IsActive: Boolean); end; implementation {$R *.dfm} uses Windows, Controls, ConstVarUnit, ConstMethodUnit, ScStdBillsCtrl, Math; procedure TDMStdBillsLib.cdsBillsLibAfterOpen(DataSet: TDataSet); begin cdsBillsLibView.CloneCursor(cdsBillsLib, True); cdsStaticID.CloneCursor(cdsBillsLib, True); cdsStaticID.IndexFieldNames := SID; cdsStaticID.Filter := 'StaticID>0'; cdsStaticID.Filtered := True; FStdBillsTree.DataSet := cdsBillsLibView; FStdBillsTree.Selected.Expand; cdsFastSearch.CloneCursor(cdsBillsLib, True); cdsFastSearch.IndexFieldNames := 'Code'; cdsFastSearch.Filter := 'Code is not null'; cdsFastSearch.Filtered := True; end; procedure TDMStdBillsLib.cdsDrawingQuantityAfterOpen(DataSet: TDataSet); begin cdsDrawQView.CloneCursor(cdsDrawingQuantity, True); cdsDrawQView.MasterSource := dsBillsDQ; cdsDrawQView.MasterFields := SID; cdsDrawQView.IndexFieldNames := Format('%s;%s', [sBillsID, SID]); cdsDQSetRange.CloneCursor(cdsDrawingQuantity, True); cdsDQSetRange.IndexFieldNames := sBillsID; end; procedure TDMStdBillsLib.LoadNewStdLib(const ALibName: string); begin cdsDrawQView.DisableControls; cdsBillsLibView.DisableControls; try acnBillsLib.Connected := False; acnBillsLib.ConnectionString := Format(SAdoConnectStr, [ALibName, 'Admin', '']); acnBillsLib.Connected := True; IncProgressUI(10); {refresh bills} cdsBillsLib.Close; cdsBillsLib.Open; IncProgressUI(40); {refresh drawingQuantity} cdsDrawingQuantity.Close; cdsDrawingQuantity.Open; cdsDrawingQuantity.IndexFieldNames := 'ID'; IncProgressUI(100); {refresh custom step} { cdsCustomStep.Close; cdsCustomStep.Open; IncProgressUI(100); } FActive := True; finally cdsDrawQView.EnableControls; cdsBillsLibView.EnableControls; end; end; procedure TDMStdBillsLib.DataModuleCreate(Sender: TObject); begin FStdBillsTree := TStdBillsTree.Create; FStdBillsTree.KeyFieldName := 'ID'; FStdBillsTree.ParentFieldName := 'ParentID'; FStdBillsTree.NextSiblingFieldName := 'NextID'; FStdBillsTree.AutoCreateKeyID := True; {如果太早设置BillsTree.dataset,则定位会错乱,应该写在AfterOpen之后} // FStdBillsTree.DataSet := cdsBillsLibView; FBillsQtyTree := TStdBillsTree.Create; FBillsQtyTree.KeyFieldName := 'ID'; FBillsQtyTree.ParentFieldName := 'ParentID'; FBillsQtyTree.NextSiblingFieldName := 'NextID'; FBillsQtyTree.AutoCreateKeyID := True; cdsCustomStepView.Open; end; procedure TDMStdBillsLib.DataModuleDestroy(Sender: TObject); begin FStdBillsTree.Free; FBillsQtyTree.Free; end; function TDMStdBillsLib.AddNewItem(AStdNode: TStdBillNode): TScBillsItem; {比较节点前后关系, 小于返回小于0, 等于返回0, 大于返回大于0} function CompareNodesDifference(ASNode: TStdBillNode; ANode: TScBillsItem): Integer; function TranslateChineseToALB(AWord: WideString): Integer; const chaArr: array [0..9] of WideString = ('十', '一', '二', '三', '四', '五', '六', '七', '八', '九'); function ChnToNum(ANum: WideString): Integer; var J: Integer; begin Result := -1; for J := 0 to 9 do begin if SameText(ANum, chaArr[J]) then begin Result := J; if Result = 0 then Result := 10; Break; end; end; end; var I, len, icha: Integer; begin Result := 0; len := Length(AWord); for I := 1 to Len do begin icha := ChnToNum(AWord[I]); if icha = 10 then begin if Result = 0 then Result := 10 else Result := Result * 10; end else begin if Result = 0 then Result := icha else Result := Result + icha; end; end; end; function CompareNodeCode(const ASCode, ACode: string; var AResult: Integer): Boolean; var l1, l2: Integer; begin if SameText(ASCode, ACode) then begin Result := False; Exit; end; Result := True; l1 := -1; l2 := -1; if not SameText(ASCode, '') and not SameText(ACode, '') then begin if Length(ASCode) - Length(WideString(ASCode)) > 0 then l1 := TranslateChineseToALB(ASCode); if Length(ACode) - Length(WideString(ACode)) > 0 then l2 := TranslateChineseToALB(ACode); if (l1 = -1) and (l2 = -1) then AResult := CompareDiagitCode(ASCode, ACode) else AResult := l1 - l2; end else Result := False; end; function CompareNodeBCode(const ASBCode, ABCode: string; var AResult: Integer): Boolean; begin if SameText(ASBCode, ABCode) then begin Result := False; Exit; end; Result := True; if not SameText(ASBCode, '') and not SameText(ABCode, '') then AResult := CompareDiagitCode(ASBCode, ABCode) else Result := False; end; function CompareNodeName(const ASName, AName: string; var AResult: Integer): Boolean; begin if (pos('…', ASName) <> 0) or (pos('…', AName) <> 0) then AResult := CompareText(ASName, AName) * -1 else AResult := CompareText(ASName, AName); end; begin if CompareNodeCode(ASNode.Code, ANode.SBillCode, Result) then Exit; if CompareNodeBCode(ASNode.BCode, ANode.SBillBCode, Result) then Exit; CompareNodeName(ASNode.Name, ANode.SBillName, Result); end; procedure EditPropertyInDB(ANode: TScBillsItem; ASNode: TStdBillNode); var sLibNodeStaticExpr: string; begin ANode.SBillCode := ASNode.Code; ANode.SBillBCode := ASNode.BCode; ANode.SBillName := ASNode.Name; ANode.Units := ASNode.Units; { if not SameText(ASNode.Exprs, '') then begin // sLibNodeStaticExpr := ASNode.Exprs; // sLibNodeStaticExpr := ExprsGraph.PretreatExprs(sLibNodeStaticExpr); // 表达式计算图,用来进行表达式的运算管理等 // ExprsGraph.SetExpression(ANode.ID, Copy(sLibNodeStaticExpr, 2, MaxInt)); // sLibNodeStaticExpr := ExprsGraph.ConvertExprsForSave(sLibNodeStaticExpr); // FProject.Exprs.AddExprs(1, 3, ANode.ID, sLibNodeStaticExpr, Evaluate(sLibNodeStaticExpr), 0); // ANode.IsCalcExprs := True; end; } end; {取最顶层节点} function GetAnsctorNode(ASNode: TStdBillNode; AList: TList): TScBillsItem; var vNode: TStdBillNode; vItem: TScBillsItem; iPreID: Integer; begin vNode := ASNode.TopestAncestor(AList); vItem := TScBillsItem(FBillsData.BillsTree.FirstNode); while Assigned(vItem) do begin if SameText(vNode.Code, vItem.SBillCode) and SameText(vNode.Name, vItem.SBillName) then Break; vItem := TScBillsItem(vItem.NextSibling); end; if Assigned(vItem) then Result := vItem else begin FStdBillNode := vNode; with FBillsData do begin // 有固定ID的黑体字项,也要求能找到自己的正确位置。 if vNode.StaticID <> -1 then begin iPreID := PreBlackFontItemID(vNode.StaticID); Result := BillsTree.AddBillsItem(vNode.StaticID, -1, BillsTree[iPreID].NextSiblingID); end // 因某种情况没有设置固定ID的黑体字项(如老版本标准项目表),要求也能正确添加不会报错,用于兼容 else begin Result := BillsTree.AddBillsItem(FMaxBillsID, -1, -1); Inc(FMaxBillsID); end; EditPropertyInDB(Result, vNode); AddRelaDrawQ(Result.ID, vNode.ID); end; end; end; {往清单中添加指定节点} function AddCurStdNodeToBills(AParentNode: TScBillsItem; ASNode: TStdBillNode): TScBillsItem; var I, iResult: Integer; blFlag: Boolean; vItem: TScBillsItem; begin blFlag := False; FStdBillNode := ASNode; for I := 0 to AParentNode.ChildCount - 1 do begin vItem := TScBillsItem(AParentNode.ChildNodes[I]); iResult := CompareNodesDifference(ASNode, vItem); if iResult < 0 then begin with FBillsData do begin if ASNode.StaticID = -1 then begin Result := TScBillsItem(BillsTree.AddBillsItem(FMaxBillsID, AParentNode.ID, vItem.ID)); Inc(FMaxBillsID); end else Result := TScBillsItem(BillsTree.AddBillsItem(ASNode.StaticID, AParentNode.ID, vItem.ID)); // ModifyParentIsLeaf(AParentNode.ID); EditPropertyInDB(Result, ASNode); AddRelaDrawQ(Result.ID, ASNode.ID); blFlag := True; Break; end; end else if iResult = 0 then begin Result := vItem; //AddRelaDrawQ(Result.ID, ASNode.ID); blFlag := True; Break; end; end; if not blFlag then begin if ASNode.StaticID = -1 then begin Result := TScBillsItem(FBillsData.BillsTree.AddBillsItem(FMaxBillsID, AParentNode.ID, -1)); Inc(FMaxBillsID); end else Result := TScBillsItem(FBillsData.BillsTree.AddBillsItem(ASNode.StaticID, AParentNode.ID, -1)); // ModifyParentIsLeaf(AParentNode.ID); EditPropertyInDB(Result, ASNode); AddRelaDrawQ(Result.ID, ASNode.ID); end; end; {在清单树中检查并返回父节点,如果没有,则创建父节点} function CheckAndThenGetParent(ASNode: TStdBillNode): TScBillsItem; var ansctor: TScBillsItem; lstNode: TList; vNode: TStdBillNode; I: Integer; begin lstNode := TList.Create; try ansctor := GetAnsctorNode(ASNode, lstNode); if not Assigned(ansctor) then begin FStdBillNode := ASNode; if ASNode.StaticID <> -1 then ansctor := TScBillsItem(FBillsData.BillsTree.AddBillsItem(ASNode.StaticID, -1, -1)) else begin ansctor := TScBillsItem(FBillsData.BillsTree.AddBillsItem(FMaxBillsID, -1, -1)); Inc(FMaxBillsID); end; EditPropertyInDB(ansctor, ASNode); AddRelaDrawQ(Result.ID, ASNode.ID); end; Result := ansctor; for I := lstNode.Count - 2 downto 0 do begin vNode := TStdBillNode(lstNode[I]); Result := AddCurStdNodeToBills(Result, vNode); end; finally lstNode.Free; end; end; var vItem: TScBillsItem; begin vItem := CheckAndThenGetParent(AStdNode); Result := vItem; if not Assigned(AStdNode.Parent) and Assigned(vItem) and (CompareNodesDifference(AStdNode, vItem) = 0) then Exit; if Assigned(vItem) then Result := AddCurStdNodeToBills(vItem, AStdNode); end; function TDMStdBillsLib.AddItems(ASelList: TIntegerSList): Boolean; var I: Integer; Node: TStdBillNode; vNode: TZjIDTreeNode; begin Result := False; if not Assigned(FProjectMgr.ActiveProject) then Exit; if not cdsBillsLib.Active then Exit; FBillsData := FProjectMgr.ActiveProject.BillsData; FMaxBillsID := FBillsData.GetMaxBillsID; Initialize(1, True); FAdding := True; try vNode := nil; for I := 0 to FStdBillsTree.Count - 1 do begin Node := TStdBillNode(FStdBillsTree.Items[I]); if (ASelList[I] <> 0) and not IsStaticIDExist(Node) then begin vNode := AddNewItem(Node); // TStdBillsCtrl(FStdBillsCtrl).IncStep := 1; end; end; Result := True; finally Finalize(1, True); FAdding := False; if Assigned(vNode) then vNode.LocateDBRecord; end; end; procedure TDMStdBillsLib.AddItem; var vNode: TZjIDTreeNode; begin if not Assigned(FProjectMgr.ActiveProject) then Exit; FBillsData := FProjectMgr.ActiveProject.BillsData; FMaxBillsID := FBillsData.GetMaxBillsID; Initialize(1, False); FAdding := True; try if IsStaticIDExist(FStdBillsTree.Selected) then Exit; vNode := AddNewItem(TStdBillNode(FStdBillsTree.Selected)); // 双击定位 if Assigned(vNode) then vNode.LocateDBRecord; finally Finalize(1, False); FAdding := False; end; end; constructor TDMStdBillsLib.Create(AProjMgr: TProjectManager); begin inherited Create(nil); FProjectMgr := AProjMgr; end; procedure TDMStdBillsLib.Finalize(aType: Integer; AIsAll: Boolean); begin with FBillsData do begin if AIsAll then begin {endUpdate} TStdBillsCtrl(FStdBillsCtrl).EndUpdateUI(aType); EnabledUITreeEvt(True, False); EnabledUIDrawQtyEvt(True); end; BillsTree.InternalEvent := nil; EndHandler; DestroyCDs; end; end; procedure TDMStdBillsLib.Initialize(aType: Integer; AIsAll: Boolean); begin with FBillsData do begin if AIsAll then begin {beginUpdate} TStdBillsCtrl(FStdBillsCtrl).BeginUpdateUI(aType); EnabledUITreeEvt(False, False); EnabledUIDrawQtyEvt(False); end; BillsTree.InternalEvent := DoInitDBRecord; {Events} BeginHandler; CreateCDS; end; end; procedure TDMStdBillsLib.DoInitDBRecord; begin with FBillsData.BillsTree do begin DataSet.FieldByName('Code').AsString := FStdBillNode.Code; DataSet.FieldByName('B_Code').AsString := FStdBillNode.BCode; DataSet.FieldByName('Name').AsString := FStdBillNode.Name; DataSet.FieldByName('Units').AsString := FStdBillNode.Units; // DataSet.FieldByName('IsLeaf').AsBoolean := True; end; end; function TDMStdBillsLib.IsStaticIDExist(ALibNode: TZjIDTreeNode): Boolean; var CheckID: Integer; CheckName, sHintName: string; begin Result := False; if ALibNode.ID >= 100 then Exit; if cdsStaticID.FindKey([ALibNode.ID]) then begin CheckName := cdsStaticIDName.AsString; CheckID := cdsStaticIDStaticID.AsInteger; with FBillsData do begin // ID号相同名称不同视作ID被占用。 // ID号相同名称也相同表示清单已存在。 if FCdsStaticID.FindKey([CheckID]) then begin Result := True; BillsTree[CheckID].LocateDBRecord; if FCdsStaticID.FieldByName('Name').AsString <> CheckName then begin if FCdsStaticID.FieldByName('Code').AsString <> '' then sHintName := FCdsStaticID.FieldByName('Code').AsString + FCdsStaticID.FieldByName('Name').AsString else sHintName := FCdsStaticID.FieldByName('Name').AsString; MessageHint(0, Format('固定ID(%d)已被清单“%s”占用,添加失败,可先将其删除然后再添加。', [CheckID, sHintName])); end; end; end; end; end; procedure TDMStdBillsLib.CreateCDS; begin with FBillsData do begin FCdsStaticID := TClientDataSet.Create(nil); FCdsStaticID.CloneCursor(cdsBills, True); FCdsStaticID.IndexFieldNames := SID; FCdsStaticID.Filter := 'ID>0 and ID<100'; FCdsStaticID.Filtered := True; FCdsModifyBills := TClientDataSet.Create(nil); FCdsModifyBills.CloneCursor(cdsBills, True); FCdsModifyBills.IndexFieldNames := SID; end; end; procedure TDMStdBillsLib.DestroyCDs; begin FCdsStaticID.Free; FCdsModifyBills.Free; end; procedure TDMStdBillsLib.AddRelaDrawQ(ADestID, ASrcID: Integer); var iMaxDQID, iSerinalNo: Integer; begin iSerinalNo := 1; iMaxDQID := FBillsData.GetMaxDrawingQuangtiyID; cdsDQSetRange.SetRange([ASrcID], [ASrcID]); while not cdsDQSetRange.Eof do begin FBillsData.cdsDrawingQuantity.Insert; FBillsData.cdsDrawingQuantityID.Value := iMaxDQID; FBillsData.cdsDrawingQuantitySerinalNo.Value := iSerinalNo; FBillsData.cdsDrawingQuantityBillsID.Value := ADestID; FBillsData.cdsDrawingQuantityName.Value := cdsDQSetRangeName.Value; FBillsData.cdsDrawingQuantityUnits.Value := cdsDQSetRangeUnits.Value; FBillsData.cdsDrawingQuantityDQuantity1.Value := cdsDQSetRangeDesignQuantity.Value; FBillsData.cdsDrawingQuantityMemoContext.Value := cdsDQSetRangeMemoStr.Value; FBillsData.cdsDrawingQuantity.Post; Inc(iMaxDQID); Inc(iSerinalNo); cdsDQSetRange.Next; end; cdsDQSetRange.CancelRange; end; function TDMStdBillsLib.CalculateCode(var aCustomValue: Double; var ACode, ADisName, AUnits: string; AIncrease: Boolean): Boolean; var iSuffix: Integer; dCustomValue: Double; begin dCustomValue := cdsCustomStepViewCustomValue.Value; if AIncrease then begin dCustomValue := cdsCustomStepViewOldValue.Value + cdsCustomStepViewStepValue.Value; end; aCustomValue := dCustomValue; iSuffix := Ceil((dCustomValue - cdsCustomStepViewStartValue.Value) / cdsCustomStepViewStepValue.Value); if iSuffix >= 0 then begin if AIncrease and (cdsCustomStepViewStartCodeID.Value > 0) then dCustomValue := cdsCustomStepViewStartValue.Value + (iSuffix - 1) * cdsCustomStepViewStepValue.Value else dCustomValue := cdsCustomStepViewStartValue.Value + iSuffix * cdsCustomStepViewStepValue.Value; if dCustomValue <= cdsCustomStepViewStartValue.AsFloat then ADisName := Format(cdsCustomStepViewFmtName.AsString, [FloatToStr(dCustomValue)]) else if cdsCustomStepViewSubArea.AsBoolean then ADisName := Format(cdsCustomStepViewFmtName2.AsString, [FloatToStr(dCustomValue - cdsCustomStepViewStepValue.AsFloat), FloatToStr(dCustomValue)]) else ADisName := Format(cdsCustomStepViewFmtName2.AsString, [FloatToStr(dCustomValue)]); if cdsCustomStepViewStartCodeID.Value > 0 then begin if AIncrease then iSuffix := iSuffix + cdsCustomStepViewStartCodeID.Value - 2 else iSuffix := iSuffix + cdsCustomStepViewStartCodeID.Value - 1; end; ACode := Format('%s-%d', [cdsCustomStepViewBillsCode.AsString, iSuffix + 1]); AUnits := cdsCustomStepViewUnits.AsString; if AIncrease and (cdsCustomStepViewStartCodeID.Value > 0) then dCustomValue := dCustomValue + cdsCustomStepViewStepValue.Value; EditCustomStepViewOldValue(dCustomValue); if cdsCustomStepViewCustomBillsCode.Value = '' then EditCustomStepOldValue(cdsCustomStepViewBillsCode.Value, dCustomValue) else EditCustomStepOldValue(cdsCustomStepViewCustomBillsCode.Value, dCustomValue); end else begin ADisName := ''; ACode := ''; AUnits := ''; end; Result := cdsCustomStepViewIsCode.Value; end; procedure TDMStdBillsLib.RecodeCurBills(aCustomValue: Double; const ACode, ADisName, AUnits: string; AIsCode, AIncrease: Boolean); begin if (ACode = '') and (ADisName = '') then Exit; with FBillsData do begin if not AIncrease then cdsOrgBills.Edit; if AIsCode then cdsOrgBillsCode.Value := ACode else cdsOrgBillsB_Code.Value := ACode; cdsOrgBillsName.Value := ADisName; cdsOrgBillsUnits.Value := AUnits; cdsOrgBillsCustomValue.Value := aCustomValue; if not AIncrease then cdsOrgBills.Post else begin cdsOrgBillsCode.Tag := 0; cdsOrgBillsB_Code.Tag := 0; end; end; end; procedure TDMStdBillsLib.cdsCustomStepViewCustomValueChange( Sender: TField); begin Sender.Tag := 1; end; procedure TDMStdBillsLib.RefreshCustomStep; var iID, iParentID: Integer; strCode, strOldCode: string; begin if not cdsCustomStep.Active then Exit; FBillsData := FProjectMgr.ActiveProject.BillsData; cdsCustomStepView.EmptyDataSet; with FBillsData do begin iID := cdsOrgBillsID.AsInteger; iParentID := cdsOrgBillsParentID.AsInteger; if iParentID <> -1 then begin if cdsBills.FindKey([iParentID]) then begin strCode := cdsBillsCode.AsString; if strCode = '' then strCode := cdsBillsB_Code.AsString; end else strCode := ''; //while strCode <> '' do if strCode <> '' then begin if LocateCustomStepByCode(iID, strCode, '') then Exit; strOldCode := strCode; strCode := GetPreCode(strCode); strCode := Format('%s-X', [strCode]); {search -X} LocateCustomStepByCode(iID, strCode, strOldCode); end; end; end; end; function TDMStdBillsLib.FindLibCode(const ACode: string; var AName, AUnits: string; AIsCode: Boolean): Boolean; begin Result := False; if not FActive then Exit; AName := ''; AUnits := ''; if AIsCode then begin if cdsBillsLib.Locate(sCode, ACode, []) then Result := True; end else begin if cdsBillsLib.Locate(sB_Code, ACode, []) then Result := True; end; if Result then begin AName := cdsBillsLibName.Value; AUnits := cdsBillsLibUnit.Value; end; end; procedure TDMStdBillsLib.AutoIncreaseBillsCode; var bIsCode: Boolean; strCode, strDisName, strUnits: string; dCustomValue: Double; begin if not Assigned(FProjectMgr.ActiveProject) then Exit; if cdsCustomStepView.RecordCount = 0 then Exit; FBillsData := FProjectMgr.ActiveProject.BillsData; bIsCode := CalculateCode(dCustomValue, strCode, strDisName, strUnits, True); RecodeCurBills(dCustomValue, strCode, strDisName, strUnits, bIsCode, True); end; procedure TDMStdBillsLib.cdsCustomStepViewAfterPost(DataSet: TDataSet); var bIsCode: Boolean; strCode, strDisName, strUnits: string; dCustomValue: Double; begin if FCustomStepFlag then Exit; if cdsCustomStepViewCustomValue.Tag = 1 then begin FBillsData := FProjectMgr.ActiveProject.BillsData; bIsCode := CalculateCode(dCustomValue, strCode, strDisName, strUnits); RecodeCurBills(dCustomValue, strCode, strDisName, strUnits, bIsCode, False); cdsCustomStepViewCustomValue.Tag := 0; end; end; procedure TDMStdBillsLib.EditCustomStepOldValue(const ACode: string; const Value: Double); begin if cdsCustomStep.Locate(sBillsCode, ACode, []) then begin cdsCustomStep.Edit; cdsCustomStepOldValue.Value := Value; cdsCustomStep.Post; end; end; procedure TDMStdBillsLib.EditCustomStepViewOldValue(const Value: Double); begin FCustomStepFlag := True; cdsCustomStepView.Edit; cdsCustomStepViewOldValue.Value := Value; cdsCustomStepView.Post; FCustomStepFlag := False; end; procedure TDMStdBillsLib.cdsCustomStepViewBeforeInsert(DataSet: TDataSet); begin if not FCustomStepFlag then raise Exception.Create('不能添加记录!'); end; procedure TDMStdBillsLib.cdsCustomStepViewBeforeDelete(DataSet: TDataSet); begin if not FCustomStepFlag then raise Exception.Create('不能删除记录!'); end; procedure TDMStdBillsLib.cdsBillsLibViewBeforeInsert(DataSet: TDataSet); begin raise Exception.Create('不能添加记录!'); end; procedure TDMStdBillsLib.cdsBillsLibAfterClose(DataSet: TDataSet); begin FStdBillsTree.DataSet := nil; end; function TDMStdBillsLib.LocateCustomStepByCode(aID: Integer; const ACode, AOldCode: string): Boolean; begin if cdsCustomStep.Locate(sBillsCode, ACode, []) then begin FCustomStepFlag := True; cdsCustomStepView.Append; if AOldCode = '' then begin cdsCustomStepViewBillsCode.Value := cdsCustomStepBillsCode.Value; cdsCustomStepViewCustomBillsCode.Value := AOldCode; end else begin cdsCustomStepViewBillsCode.Value := AOldCode; cdsCustomStepViewCustomBillsCode.Value := ACode; end; cdsCustomStepViewFmtName.Value := cdsCustomStepFmtName.AsString; cdsCustomStepViewFmtName2.Value := cdsCustomStepFmtName2.AsString; cdsCustomStepViewStartValue.Value := cdsCustomStepStartValue.Value; cdsCustomStepViewStepValue.Value := cdsCustomStepStepValue.Value; cdsCustomStepViewDisName.Value := cdsCustomStepDisName.AsString; cdsCustomStepViewUnits.Value := cdsCustomStepUnits.AsString; cdsCustomStepViewStartCodeID.Value := cdsCustomStepStartCodeID.Value; cdsCustomStepViewSubArea.Value := cdsCustomStepSubArea.Value; if (cdsCustomStepOldValue.Value <> 0) and (not FAdding) then cdsCustomStepViewOldValue.Value := cdsCustomStepOldValue.Value else cdsCustomStepViewOldValue.Value := cdsCustomStepStartValue.Value; if FBillsData.cdsBills.FindKey([aID]) then begin if FBillsData.cdsBillsCustomValue.AsFloat <> 0 then cdsCustomStepViewCustomValue.Value := FBillsData.cdsBillsCustomValue.AsFloat else begin cdsCustomStepViewCustomValue.Value := cdsCustomStepViewOldValue.AsFloat; FBillsData.cdsBills.Edit; FBillsData.cdsBillsCustomValue.Value := cdsCustomStepViewOldValue.AsFloat; FBillsData.cdsBills.Post; end; end; cdsCustomStepView.Post; FCustomStepFlag := False; Result := True; end else Result := False; end; procedure TDMStdBillsLib.cdsBillsQtyAfterOpen(DataSet: TDataSet); begin cdsBillsQtyView.CloneCursor(cdsBillsQty, True); FBillsQtyTree.DataSet := cdsBillsQtyView; FBillsQtyTree.Selected.Expand; cdsBQFastSearch.CloneCursor(cdsBillsQty, True); cdsBQFastSearch.IndexFieldNames := 'B_Code'; cdsBQFastSearch.Filter := 'B_Code is not null'; cdsBQFastSearch.Filtered := True; end; procedure TDMStdBillsLib.LoadBillsQtyLib(const ALibName: string); begin cdsBillsQtyView.DisableControls; try acnBillsQty.Connected := False; acnBillsQty.ConnectionString := Format(SAdoConnectStr, [ALibName, 'Admin', '']); acnBillsQty.Connected := True; IncProgressUI(20); {refresh billsQty} cdsBillsQty.Close; cdsBillsQty.Open; IncProgressUI(40); cdsBQDrawingQty.Close; cdsBQDrawingQty.Open; cdsBQDrawingQty.IndexFieldNames := 'ID'; IncProgressUI(40); finally cdsBillsQtyView.EnableControls; end; end; procedure TDMStdBillsLib.AddBillsQtyItem; var selNode: TScBillsItem; begin if not Assigned(FProjectMgr.ActiveProject) then Exit; FBillsData := FProjectMgr.ActiveProject.BillsData; selNode := TScBillsItem(FBillsData.BillsTree.Selected); if not CanAddQtyItem(selNode) or not Assigned(selNode) then Exit; FMaxBillsID := FBillsData.GetMaxBillsID; Initialize(2, False); try selNode := AddNewQtyItems(selNode, TStdBillNode(FBillsQtyTree.Selected)); if Assigned(selNode) then selNode.LocateDBRecord; finally Finalize(2, False); end; end; function TDMStdBillsLib.AddBillsQtyItems(aSelList: TIntegerSList): Boolean; var I: Integer; sbnNode: TStdBillNode; sbiNewNode: TScBillsItem; selNode: TScBillsItem; begin Result := False; if not Assigned(FProjectMgr.ActiveProject) then Exit; if not cdsBillsQty.Active then Exit; FBillsData := FProjectMgr.ActiveProject.BillsData; selNode := TScBillsItem(FBillsData.BillsTree.Selected); if not CanAddQtyItem(selNode) or not Assigned(selNode) then Exit; FMaxBillsID := FBillsData.GetMaxBillsID; Initialize(2, True); try sbiNewNode := nil; for I := 0 to FBillsQtyTree.Count - 1 do begin if aSelList[I] <> 0 then begin sbnNode := TStdBillNode(FBillsQtyTree.Items[I]); if sbnNode.Code = '' then sbiNewNode := AddNewQtyItems(selNode, sbnNode); end; end; Result := True; if Assigned(sbiNewNode) then sbiNewNode.LocateDBRecord; finally Finalize(2, True); end; end; function TDMStdBillsLib.CanAddQtyItem(var aNode: TScBillsItem): Boolean; begin if ((aNode.SBillCode <> '') and aNode.HasChildren and (TScBillsItem(aNode.FirstChild).SBillCode <> '')) or not aNode.IsInheritFrom(1) then Result := False else begin Result := True; while aNode.SBillCode = '' do aNode := TScBillsItem(aNode.Parent); end; end; function TDMStdBillsLib.AddNewQtyItems(aNode: TScBillsItem; aQtyNode: TStdBillNode): TScBillsItem; var I: Integer; iNextID: Integer; iCompareValue: Integer; bFlag: Boolean; sbnParent: TStdBillNode; sbiNewItem, sbiChildItem: TScBillsItem; begin sbiNewItem := aNode; sbnParent := TStdBillNode(aQtyNode.Parent); if sbnParent.BCode <> '' then sbiNewItem := AddNewQtyItems(sbiNewItem, sbnParent); bFlag := True; iNextID := -1; FStdBillNode := aQtyNode; for I := 0 to sbiNewItem.ChildCount - 1 do begin sbiChildItem := TScBillsItem(sbiNewItem.ChildNodes[I]); if Pos(aQtyNode.BCode + '-', sbiChildItem.SBillBCode) = 1 then begin Result := sbiNewItem; bFlag := False; Break; end; iCompareValue := CompareDiagitCode(sbiChildItem.SBillBCode, aQtyNode.BCode); if iCompareValue = 0 then begin Result := sbiChildItem; bFlag := False; Break;; end else if iCompareValue > 0 then begin iNextID := sbiChildItem.ID; Break; end; end; if bFlag then begin Result := FBillsData.BillsTree.AddBillsItem(FMaxBillsID, sbiNewItem.ID, iNextID); Result.SBillBCode := aQtyNode.BCode; Result.SBillName := aQtyNode.Name; AddQtyRelaDrawQ(FMaxBillsID, aQtyNode.ID); Inc(FMaxBillsID); end; end; function TDMStdBillsLib.CompareDiagitCode(AsCode, ACode: string): Integer; var s1, s2: string; p1, p2: Integer; v1, v2, e1, e2: Integer; begin p1 := pos('-', AsCode); p2 := pos('-', ACode); while (p1 <> 0) and (p2 <> 0) do begin s1 := copy(AsCode, 1, p1 - 1); s2 := copy(ACode, 1, p2 - 1); if SameText(s1, s2) then begin AsCode := copy(AsCode, p1 + 1, Length(AsCode)); ACode := copy(ACode, p2 + 1, Length(ACode)); p1 := pos('-', AsCode); p2 := pos('-', ACode); end else begin Val(s1, v1, e1); Val(s2, v2, e2); if (e1 = 0) and (e2 = 0) then Result := v1 - v2 else Result := CompareText(s1, s2); Exit; end; end; if (p1 = 0) and (p2 = 0) then begin Val(AsCode, v1, e1); Val(ACode, v2, e2); if (e1 = 0) and (e2 = 0) then Result := v1 - v2 else Result := CompareText(AsCode, ACode); end else if p1 <> 0 then begin s1 := copy(AsCode, 1, p1 - 1); Val(s1, v1, e1); Val(ACode, v2, e2); if (e1 = 0) and (e2 = 0) then begin Result := v1 - v2; if Result = 0 then Result := Length(AsCode) - Length(ACode); end else Result := CompareText(s1, ACode); end else begin s2 := copy(ACode, 1, p2 - 1); Val(AsCode, v1, e1); Val(s2, v2, e2); if (e1 = 0) and (e2 = 0) then begin Result := v1 - v2; if Result = 0 then Result := Length(AsCode) - Length(ACode); end else Result := CompareText(AsCode, s2); end; end; procedure TDMStdBillsLib.CloseLib(aFileFlag: Integer); begin if aFileFlag = 1 then begin acnBillsLib.Close; cdsBillsLib.Active := False; end else begin acnBillsQty.Close; cdsBillsQty.Active := False; end; end; function TDMStdBillsLib.FindRecord(aNode: TZjIDTreeNode; const aCode, aName: string): Boolean; begin Result := False; if aNode = nil then Exit; if (aCode <> '') and (aName <> '') then begin if ((Pos(aCode, TStdBillNode(aNode).Code) = 1) or (Pos(aCode, TStdBillNode(aNode).BCode) = 1)) and (Pos(aName, TStdBillNode(aNode).Name) <> 0) then Result := True; end else if (aCode <> '') and (aName = '') then begin if (Pos(aCode, TStdBillNode(aNode).Code) = 1) or (Pos(aCode, TStdBillNode(aNode).BCode) = 1) then Result := True; end else if (aCode = '') and (aName <> '') then begin if Pos(aName, TStdBillNode(aNode).Name) <> 0 then Result := True; end else Exit; if Result then begin aNode.LocateDBRecord; Exit; end; Result := FindRecord(aNode.NextNode, aCode, aName); end; procedure TDMStdBillsLib.LoadCustomStep(const aLibName: string); begin cdsCustomStepView.DisableControls; try acCustomStep.Connected := False; acCustomStep.ConnectionString := Format(SAdoConnectStr, [ALibName, 'Admin', '']); acCustomStep.Connected := True; {refresh billsQty} cdsCustomStep.Close; cdsCustomStep.Open; finally cdsCustomStepView.EnableControls; end; end; procedure TDMStdBillsLib.cdsBQDrawingQtyAfterOpen(DataSet: TDataSet); begin //cdsBQDrawingQty.IndexFieldNames := sBillsID; cdsBQDrawingQtyView.CloneCursor(cdsBQDrawingQty, True); cdsBQDrawingQtyView.MasterSource := dsBillsQty; cdsBQDrawingQtyView.MasterFields := SID; cdsBQDrawingQtyView.IndexFieldNames := sBillsID; end; procedure TDMStdBillsLib.AddQtyRelaDrawQ(ADestID, ASrcID: Integer); var iMaxDQID, iSerinalNo: Integer; begin iSerinalNo := 1; iMaxDQID := FBillsData.GetMaxDrawingQuangtiyID; cdsBQDrawingQty.Filter := Format('BillsID = %d', [ASrcID]); cdsBQDrawingQty.Filtered := True; while not cdsBQDrawingQty.Eof do begin FBillsData.cdsDrawingQuantity.Insert; FBillsData.cdsDrawingQuantityID.Value := iMaxDQID; FBillsData.cdsDrawingQuantitySerinalNo.Value := iSerinalNo; FBillsData.cdsDrawingQuantityBillsID.Value := ADestID; FBillsData.cdsDrawingQuantityName.Value := cdsBQDrawingQtyName.Value; FBillsData.cdsDrawingQuantityUnits.Value := cdsBQDrawingQtyUnits.Value; FBillsData.cdsDrawingQuantityDQuantity1.Value := cdsBQDrawingQtyDesignQuantity.Value; FBillsData.cdsDrawingQuantityMemoContext.Value := cdsBQDrawingQtyMemoStr.Value; FBillsData.cdsDrawingQuantity.Post; Inc(iMaxDQID); Inc(iSerinalNo); cdsBQDrawingQty.Next; end; cdsBQDrawingQty.Filtered := False; end; function TDMStdBillsLib.IsCodeStepItem(AB_Code: string; var AUnits: string): Boolean; begin Result := False; cdsCustomStep.First; while not cdsCustomStep.Eof do begin if Pos(cdsCustomStepBillsCode.AsString, AB_Code) = 1 then begin AUnits := cdsCustomStepUnits.AsString; Result := True; Break; end; cdsCustomStep.Next; end; end; // Added by GiLi 2012-3-20 14:48:28 // 反向定位标准清单 procedure TDMStdBillsLib.LocateCurBillsToStdBills; var AID, AStdID, AStdParentID, vNodeLevel, PrevLevel: Integer; ACode, ABillsCode: string; vNode, vTempNode: TScBillsItem; vStdNode, vTmpStdNode: TZjIDTreeNode; // 递归查找该项目节编号下的清单编号的节点(定位条件 项目节编号、清单编号) function FindNodeByBCode(ANode: TZjIDTreeNode): TZjIDTreeNode; var ACurStdBCode: string; begin Result := nil; if ANode = nil then Exit; ACurStdBCode := TStdBillNode(ANode).BCode; if SameText(Trim(ABillsCode), ACurStdBCode) then begin Result := ANode; Exit; end; if Result = nil then Result := FindNodeByBCode(ANode.FirstChild); if Result = nil then Result := FindNodeByBCode(ANode.NextSibling); end; begin if not Assigned(FProjectMgr.ActiveProject) then Exit; if not cdsBillsLibView.Active then Exit; if not FBillsData.cdsOrgBills.Active then begin raise Exception.Create('标准清单未打开,无法定位!'); Exit; end; FBillsData := FProjectMgr.ActiveProject.BillsData; ACode := FBillsData.cdsOrgBillsCode.AsString; ABillsCode := FBillsData.cdsOrgBillsB_Code.AsString; AID := FBillsData.cdsOrgBillsID.AsInteger; AStdParentID := FBillsData.cdsOrgBillsParentID.AsInteger; vNodeLevel := 0; PrevLevel := 0; // 如果清单编号不为空,那么直接查找编号,找不到给出提示 if Trim(ACode) <> '' then begin if not cdsBillsLibView.Locate('Code', ACode, []) then begin if mrYes <> MessageQuest(0, '标准清单中不存在编号为' + ACode + '的项!' + #13#10 + '您是否要进行模糊定位? Y/N', '询问', MB_YESNO) then Exit; vNode := FBillsData.BillsTree.FindNode(AID); while (not cdsBillsLibView.Locate('Code', ACode, [])) and (vNode <> nil) do begin vNode := TScBillsItem(vNode.Parent); ACode := vNode.Code; end; if vNode = nil then begin cdsBillsLibView.First; end; end; Exit; end; // 如果当前项的编号是空,那么找当前节点下的妈妈,取妈妈的Code if Trim(ACode) = '' then begin vNode := FBillsData.BillsTree.FindNode(AID); vTempNode := vNode; // 求同层下,排第几个 while vTempNode <> nil do begin Inc(PrevLevel); vTempNode := TScBillsItem(vTempNode.PrevSibling); end; // 找妈妈,并记录层数 while (vNode <> nil) and (Trim(ACode) = '') do begin ACode := vNode.Code; // 记录层数 Inc(vNodeLevel); vNode := TScBillsItem(vNode.Parent); end; end; if Trim(ACode) = '' then begin MessageHint(0, '标准清单中不存在该项!', '提示', 0); Exit; end; // 先定位到有项目节编号的标准清单项的妈妈下 if not cdsBillsLibView.Locate('Code', ACode, []) then begin MessageHint(0, '标准清单中不存在该项!', '提示', 0); Exit; end; AStdID := cdsBillsLibViewID.AsInteger; vStdNode := FStdBillsTree.FindNode(AStdID); vTmpStdNode := vStdNode; // 递归之前记录位置 if Assigned(vStdNode) then vStdNode := FindNodeByBCode(vStdNode.FirstChild); if Assigned(vStdNode) then begin vStdNode.LocateDBRecord; Exit; end else begin if mrYes <> MessageQuest(0, '标准清单中不存在该项!' + #13#10 + '您是否要进行模糊定位? Y/N', '询问', MB_YESNO) then Exit; end; vStdNode := vTmpStdNode; // 找到层 while vNodeLevel > 1 do begin if not Assigned(vStdNode) then begin MessageHint(0, '标准清单中不存在该项的相似清单!', '提示', 0); Exit; end; vStdNode := vStdNode.FirstChild; Dec(vNodeLevel); end; // 确定层下的位置 while PrevLevel > 1 do begin if not Assigned(vStdNode.NextSibling) then begin vStdNode.LocateDBRecord; //MessageHint(0, '标准清单中不存在该项!', '提示', 0); Exit; end; vStdNode := vStdNode.NextSibling; Dec(PrevLevel); end; if Assigned(vStdNode) then vStdNode.LocateDBRecord; //else // MessageHint(0, '标准清单中不存在该项!', '提示', 0); { AID := FBillsData.cdsOrgBillsID.AsInteger; vNode := FStdBillsTree.FindNode(AID); if Assigned(vNode) then begin vNode.LocateDBRecord; end; } end; procedure TDMStdBillsLib.CloneActive(IsActive: Boolean); begin if Assigned(FCdsStaticID) and Assigned(FCdsModifyBills) then begin FCdsStaticID.Active := IsActive; FCdsModifyBills.Active := IsActive; end; end; procedure TDMStdBillsLib.Save; begin if acnBillsLib.Connected then begin cdsBillsLib.ApplyUpdates(0); cdsDrawingQuantity.ApplyUpdates(0); end; if acnBillsQty.Connected then begin cdsBillsQty.ApplyUpdates(0); cdsBQDrawingQty.ApplyUpdates(0); end; end; procedure TDMStdBillsLib.cdsBillsLibViewAfterPost(DataSet: TDataSet); var Node: TStdBillNode; begin if (cdsBillsLibViewCode.Tag = 1) or (cdsBillsLibViewB_Code.Tag = 1) or (cdsBillsLibViewName.Tag = 1) or (cdsBillsLibViewUnit.Tag = 1) then begin Node := TStdBillNode(FStdBillsTree.FindNode(cdsBillsLibViewID.AsInteger)); Node.Code := cdsBillsLibViewCode.AsString; Node.BCode := cdsBillsLibViewB_Code.AsString; Node.Name := cdsBillsLibViewName.AsString; Node.Units := cdsBillsLibViewUnit.AsString; if cdsBillsLibViewStaticID.IsNull then Node.StaticID := -1 else Node.StaticID := cdsBillsLibViewStaticID.AsInteger; end; cdsBillsLibViewCode.Tag := 0; cdsBillsLibViewB_Code.Tag := 0; cdsBillsLibViewName.Tag := 0; cdsBillsLibViewUnit.Tag := 0; end; procedure TDMStdBillsLib.cdsBillsLibViewCodeChange(Sender: TField); begin Sender.Tag := 1; end; procedure TDMStdBillsLib.cdsBillsLibViewAfterInsert(DataSet: TDataSet); var Node: TStdBillNode; begin Node := TStdBillNode(FStdBillsTree.FindNode(cdsBillsQtyViewID.AsInteger)); if cdsBillsLibViewStaticID.IsNull then Node.StaticID := -1 else Node.StaticID := cdsBillsLibViewStaticID.AsInteger; end; procedure TDMStdBillsLib.cdsBillsQtyViewAfterPost(DataSet: TDataSet); var Node: TStdBillNode; begin if (cdsBillsQtyViewCode.Tag = 1) or (cdsBillsQtyViewB_Code.Tag = 1) or (cdsBillsQtyViewName.Tag = 1) or (cdsBillsQtyViewUnit.Tag = 1) then begin Node := TStdBillNode(FBillsQtyTree.FindNode(cdsBillsQtyViewID.AsInteger)); Node.Code := cdsBillsQtyViewCode.AsString; Node.BCode := cdsBillsQtyViewB_Code.AsString; Node.Name := cdsBillsQtyViewName.AsString; Node.Units := cdsBillsQtyViewUnit.AsString; if cdsBillsQtyViewStaticID.IsNull then Node.StaticID := -1 else Node.StaticID := cdsBillsQtyViewStaticID.AsInteger; end; cdsBillsQtyViewCode.Tag := 0; cdsBillsQtyViewB_Code.Tag := 0; cdsBillsQtyViewName.Tag := 0; cdsBillsQtyViewUnit.Tag := 0; end; procedure TDMStdBillsLib.cdsBillsQtyViewAfterInsert(DataSet: TDataSet); var Node: TStdBillNode; begin Node := TStdBillNode(FBillsQtyTree.FindNode(cdsBillsQtyViewID.AsInteger)); if cdsBillsQtyViewStaticID.IsNull then Node.StaticID := -1 else Node.StaticID := cdsBillsQtyViewStaticID.AsInteger; end; function TDMStdBillsLib.GetNewID(DataSet: TClientDataSet): Integer; begin DataSet.Last; Result := DataSet.FieldByName('ID').AsInteger + 1; end; procedure TDMStdBillsLib.cdsDrawQViewNewRecord(DataSet: TDataSet); begin cdsDrawQViewID.AsInteger := GetNewID(cdsDrawingQuantity); end; procedure TDMStdBillsLib.cdsBQDrawingQtyViewNewRecord(DataSet: TDataSet); begin cdsBQDrawingQtyViewID.AsInteger := GetNewID(cdsBQDrawingQty); end; end.