| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950 | unit MCacheTree;// CacheTree For Measure, Inherit From CacheTreeinterfaceuses  Classes, CacheTree, Math, ZhAPI, sdIDTree;type  // For Import Temp Excel  TBillsCacheNode = class(TCacheNode)  private    FLevelCode: string;    FCode: string;    FB_Code: string;    FName: string;    FUnits: string;    FCanDelete: Boolean;    FOrgQuantity: Double;    FMisQuantity: Double;    FOthQuantity: Double;    FDgnQuantity1: Double;    FDgnQuantity2: Double;    FMemoStr: string;    FPrice: Double;    FDrawingCode: string;  public    property LevelCode: string read FLevelCode write FLevelCode;    property Code: string read FCode write FCode;    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 CanDelete: Boolean read FCanDelete write FCanDelete;    property Price: Double read FPrice write FPrice;    property OrgQuantity: Double read FOrgQuantity write FOrgQuantity;    property MisQuantity: Double read FMisQuantity write FMisQuantity;    property OthQuantity: Double read FOthQuantity write FOthQuantity;    property DgnQuantity1: Double read FDgnQuantity1 write FDgnQuantity1;    property DgnQuantity2: Double read FDgnQuantity2 write FDgnQuantity2;    property DrawingCode: string read FDrawingCode write FDrawingCode;    property MemoStr: string read FMemoStr write FMemoStr;  end;  TBillsCacheTree = class(TCacheTree)  private    FLastNode: TCacheNode;    FSeparateChar: Char;    FAutoSort: Boolean;    FFixedIDNodes: TList;    function GetNewNode(AID: Integer = -1): TBillsCacheNode; overload;    function FindNode(const ACode: string): TBillsCacheNode; overload;    function FindNode(AParent: TBillsCacheNode; const ACode: string): TBillsCacheNode; overload;    function FindParent(const ACode: string): TBillsCacheNode;    function FindNextSibling(const ACode: string): TBillsCacheNode;    procedure SetSeparateChar(const Value: Char);  public    constructor Create; override;    destructor Destroy; override;    function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil; AFixedID: Integer = -1): TBillsCacheNode;    function AddNodeByCode(const ACode: string; AFixedID: Integer = -1): TBillsCacheNode;    function AddLeafBillsNode(const AB_Code: string): TBillsCacheNode;    function FindXmjChild(AParent: TBillsCacheNode; const ACode, AName: string): TBillsCacheNode;    function FindGclChild(AParent: TBillsCacheNode; const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;    function FindFixedIDNode(AID: Integer): TBillsCacheNode;    // Only for Debugging lot of Data    procedure SaveTreeToFile(const AFileName: string);    property SeparateChar: Char read FSeparateChar write SetSeparateChar;    property AutoSort: Boolean read FAutoSort write FAutoSort;    property FixedIDNodes: TList read FFixedIDNodes;  end;  // 此树仅用于导入工程量清单,禁止作为它用  // 如须使用应遵守以下两点:1.完全清楚相关的导入方法类及需求 2.派生子类。  TGclCacheNode = class(TCacheNode)  private    FB_Code: string;    FName: string;    FUnits: string;    FPrice: Double;    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 Price: Double read FPrice write FPrice;    property Quantity: Double read FQuantity write FQuantity;  end;  TGclCacheTree = class(TCacheTree)  private    FLastBlank1: TGclCacheNode;    FLastNode: TGclCacheNode;    function AddNodeByName(const AName: string): TGclCacheNode;    function AddNodeByB_Code(const AB_Code: string): TGclCacheNode;  protected    function GetNewNode: TCacheNode; override;  public    function AddNodeByData(const AB_Code, AName: string): TGclCacheNode;    procedure SaveTreeToFile(const AFileName: string);  end;  {For Report Memory(Gather or Compare Projects)}  TDoubleArray = array of Double;  TReportCacheNode = class(TCacheNode)  private    FCode: string;    FB_Code: string;    FName: string;    FUnits: string;    FMemoStr: string;    FXiangCode: string;    FMuCode: string;    FJieCode: string;    FXiMuCode: string;    FPrice: Double;    FQuantity: Double;    FTotalPrice: Double;    FRatioPercent: Double; // 0号台账 - 各项费用所占比例    FDesignQuantity1: Double;    FDesignQuantity2: Double;    FAddQcQuantity: Double;    FAddPcTotalPrice: Double;    FAddQcTotalPrice: Double;    FAddDealQuantity: Double;    FAddDealTotalPrice: Double;    FAddPcQuantity: Double;    FAddRatioPercent: Double; // 决算 - 各项费用所占比例    FDealDesignQuantity1: Double;    FDealDesignQuantity2: Double;    FCDesignQuantity1: Double;    FCDesignQuantity2: Double;    FPDQuantity: Double;    FPDTotalPrice: Double;    FPDDesignQuantity1: Double;    FPDDesignQuantity2: Double;    FPDDesignPrice: Double;    FCDDQuantity: Double;    FCDDTotalPrice: Double;    FCDDDesignQuantity1: Double;    FCDDDesignQuantity2: Double;    FCDDDesignPrice: Double;    FABTotalPrice: Double;    FABQuantity: Double;    FABDesignQuantity1: Double;    FABDesignQuantity2: Double;    FABDesignPrice: Double;    FProjectCount: Integer;    FP_TotalPrice: TDoubleArray;    FP_Quantity: TDoubleArray;    FP_Price: TDoubleArray;    FP_DgnQuantity1: TDoubleArray;    FP_DgnQuantity2: TDoubleArray;    procedure ResolveCode;    function GetDoubleArrayTotal(ADoubleArray: TDoubleArray): Double;    procedure SetCode(const Value: string);    function GetGatherP_TotalPrice: Double;    function GetAddGatherQuantity: Double;    function GetAddGatherTotalPrice: Double;  public    constructor Create(ACacheTree: TCacheTree; AID, AProjectCount: Integer);    property Code: string read FCode write SetCode;    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 MemoStr: string read FMemoStr write FMemoStr;    property XiangCode: string read FXiangCode;    property MuCode: string read FMuCode;    property JieCode: string read FJieCode;    property XiMuCode: string read FXiMuCode;    // 用于汇总多个项目的合同、变更(数量、金额)    property Price: Double read FPrice write FPrice;    // 0号台账合同    property Quantity: Double read FQuantity write FQuantity;    property TotalPrice: Double read FTotalPrice write FTotalPrice;    property RatioPercent: Double read FRatioPercent write FRatioPercent;    property DesignQuantity1: Double read FDesignQuantity1 write FDesignQuantity1;    property DesignQuantity2: Double read FDesignQuantity2 write FDesignQuantity2;    // 累计各值    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 AddGatherQuantity: Double read GetAddGatherQuantity;    property AddGatherTotalPrice: Double read GetAddGatherTotalPrice;    property AddRatioPercent: Double read FAddRatioPercent write FAddRatioPercent;    // 合同&变更 设计数量    property DealDesignQuantity1: Double read FDealDesignQuantity1 write FDealDesignQuantity1;    property DealDesignQuantity2: Double read FDealDesignQuantity2 write FDealDesignQuantity2;    property CDesignQuantity1: Double read FCDesignQuantity1 write FCDesignQuantity1;    property CDesignQuantity2: Double read FCDesignQuantity2 write FCDesignQuantity2;    // ----仅用于汇总生成决算02表----    // 初步设计 Preliminary Design    property PDQuantity: Double read FPDQuantity write FPDQuantity;    property PDTotalPrice: Double read FPDTotalPrice write FPDTotalPrice;    property PDDesignQuantity1: Double read FPDDesignQuantity1 write FPDDesignQuantity1;    property PDDesignQuantity2: Double read FPDDesignQuantity2 write FPDDesignQuantity2;    property PDDesignPrice: Double read FPDDesignPrice write FPDDesignPrice;    // 施工图设计 Construction Drawing Design    property CDDQuantity: Double read FCDDQuantity write FCDDQuantity;    property CDDTotalPrice: Double read FCDDTotalPrice write FCDDTotalPrice;    property CDDDesignQuantity1: Double read FCDDDesignQuantity1 write FCDDDesignQuantity1;    property CDDDesignQuantity2: Double read FCDDDesignQuantity2 write FCDDDesignQuantity2;    property CDDDesignPrice: Double read FCDDDesignPrice write FCDDDesignPrice;    // ------------------------------    // ----仅用于汇总生成决算02表(部颁)----    // 批准概(预算)算 Approved Budget    property ABQuantity: Double read FABQuantity write FABQuantity;    property ABTotalPrice: Double read FABTotalPrice write FABTotalPrice;    property ABDesignQuantity1: Double read FABDesignQuantity1 write FABDesignQuantity1;    property ABDesignQuantity2: Double read FABDesignQuantity2 write FABDesignQuantity2;    property ABDesignPrice: Double read FABDesignPrice write FABDesignPrice;    // ------------------------------------    // 用于记录多个项目的数量、单价、金额、设计数量    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_DgnQuantity1: TDoubleArray read FP_DgnQuantity1 write FP_DgnQuantity1;    property P_DgnQuantity2: TDoubleArray read FP_DgnQuantity2 write FP_DgnQuantity2;    property GatherP_TotalPrice: Double read GetGatherP_TotalPrice;    property ProjectCount: Integer read FProjectCount;  end;  TStringArray = array of string;  TReportCacheTree = class(TCacheTree)  private    FProjectCount: Integer;    FGatherCacheNode: TReportCacheNode;    FProjectName: TStringArray;    function GetNewNode(AProjectCount: Integer): TReportCacheNode; overload;  public    constructor Create(AProjectCount: Integer);    destructor Destroy; override;    function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil): TReportCacheNode;    function FindNextSibling(AParent: TCacheNode; ACode, AB_Code: string): TReportCacheNode;    function FindNode(AParent: TCacheNode; ACode, AB_Code: string): TReportCacheNode; overload;    function FindNode(AParent: TCacheNode; AName: string): TReportCacheNode; overload;    function FindNode(AParent: TCacheNode; ACode, AB_Code, AName: string): TReportCacheNode; overload;    procedure ReCalcGatherData;    // 调用此方法先须先调用ReCalcGatherData    // RatioPercent = 金额/总金额,这里的总金额取GatherCacheNode的金额,故须先汇总计算GatherCacheNode。    procedure ReCalcRatioPercent;    // Only for Debugging lot of Data    procedure SaveTreeToFile(const AFileName: string);    property ProjectCount: Integer read FProjectCount;    property GatherCacheNode: TReportCacheNode read FGatherCacheNode;    property ProjectName: TStringArray read FProjectName write FProjectName;  end;  TapDoubleArray = array [1..50] of Double;  TAllPhaseCacheNode = class(TCacheNode)  private    FCode: string;    FB_Code: string;    FName: string;    FUnits: string;    FPrice: Double;    FQuantity: Double;    FTotalPrice: Double;    FMemoStr: string;  public    FP_Quantity: TapDoubleArray;    FP_TotalPrice: TapDoubleArray;    property Code: string read FCode write FCode;    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;    property MemoStr: string read FMemoStr write FMemoStr;  end;  // 仅用于汇总同一项目的不同期数据  TAllPhaseCacheTree = class(TCacheTree)  private    function GetNewNode(AID: Integer): TAllPhaseCacheNode;  public    function AddNode(AID: Integer; AParent: TCacheNode; ANextSibling: TCacheNode = nil): TAllPhaseCacheNode;    function FindNode(AID: Integer): TAllPhaseCacheNode;    // Only for Debugging lot of Data    procedure SaveTreeToFile(const AFileName: string);  end;implementationuses  SysUtils, UtilMethods;{ TBillsCacheTree }function TBillsCacheTree.AddNodeByCode(const ACode: string;  AFixedID: Integer): TBillsCacheNode;var  Parent, NextSibling: TBillsCacheNode;begin  Result := FindNode(ACode);  FLastNode := Result;  if Assigned(Result) then Exit;  Parent := FindParent(ACode);  if AutoSort then    NextSibling := FindNextSibling(ACode)  else    NextSibling := nil;  Result := AddNode(Parent, NextSibling, AFixedID);  Result.FLevelCode := ACode;  FLastNode := Result;end;function TBillsCacheTree.FindNode(const ACode: string): TBillsCacheNode;begin  Result := FindNode(TBillsCacheNode(Root), ACode);end;function TBillsCacheTree.FindNextSibling(  const ACode: string): TBillsCacheNode;var  Parent, Node: TBillsCacheNode;  sCodeID, sCodeID2: string;begin  Parent := FindParent(ACode);  if Assigned(Parent) then    Node := TBillsCacheNode(Parent.FirstChild)  else    Node := TBillsCacheNode(Root.FirstChild);  Result := nil;  sCodeID := ConvertDigitCode(ACode, 3, '-');  while Assigned(Node) do  begin    sCodeID2 := ConvertDigitCode(Node.LevelCode, 3, SeparateChar);    if sCodeID < sCodeID2 then    begin      Result := Node;      Break;    end;    Node := TBillsCacheNode(Node.NextSibling);  end;end;function TBillsCacheTree.FindNode(AParent: TBillsCacheNode;  const ACode: string): TBillsCacheNode;begin  Result := TBillsCacheNode(AParent.FirstChild);  while Assigned(Result) do  begin    if Result.LevelCode = ACode then      Break    else if Pos(Result.LevelCode + SeparateChar, ACode) = 1 then    begin      Result := FindNode(Result, ACode);      Break;    end    else      Result := TBillsCacheNode(Result.NextSibling);  end;end;function TBillsCacheTree.FindParent(const ACode: string): TBillsCacheNode;var  sCode: string;begin  Result := nil;  sCode := GetPrefixOfCode(ACode, SeparateChar);  while (Result = nil) and (sCode <> '') do  begin    Result := FindNode(sCode);    sCode := GetPrefixOfCode(sCode, SeparateChar);  end;end;function TBillsCacheTree.GetNewNode(AID: Integer): TBillsCacheNode;begin  if AID = -1 then    Result := TBillsCacheNode.Create(Self, GetNewNodeID)  else    Result := TBillsCacheNode.Create(Self, AID);  CacheNodes.Add(Result);  if Result.ID < 100 then    FFixedIDNodes.Add(Result);end;function TBillsCacheTree.AddNode(AParent, ANextSibling: TCacheNode;  AFixedID: Integer): TBillsCacheNode;begin  Result := GetNewNode(AFixedID);  if Assigned(ANextSibling) then    ANextSibling.InsertPreSibling(Result)  else if Assigned(AParent) then    AParent.InsertChild(Result)  else    Root.InsertChild(Result);end;function TBillsCacheTree.AddLeafBillsNode(const AB_Code: string): TBillsCacheNode;  function GetLastXmjParent: TBillsCacheNode;  begin    Result := TBillsCacheNode(FLastNode);    while Assigned(Result) and (Result.B_Code <> '') do      Result := TBillsCacheNode(Result.Parent);  end;var  Parent: TBillsCacheNode;begin  Parent := GetLastXmjParent;  Result := AddNodeByCode(Parent.Code + '-' + AB_Code, -1);end;procedure TBillsCacheTree.SetSeparateChar(const Value: Char);var  I: Integer;  Node: TBillsCacheNode;begin  for I := 0 to CacheNodes.Count - 1 do  begin    Node := TBillsCacheNode(CacheNodes.Items[I]);    Node.FLevelCode := StringReplace(Node.FLevelCode, FSeparateChar, Value, [rfReplaceAll]);  end;  FSeparateChar := Value;end;procedure TBillsCacheTree.SaveTreeToFile(const AFileName: string);var  sgs: TStringList;  I: Integer;  Node: TBillsCacheNode;begin  sgs := TStringList.Create;  try    for I := 0 to CacheNodes.Count - 1 do    begin      Node := TBillsCacheNode(CacheNodes.Items[I]);      sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',        [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));    end;    sgs.SaveToFile(AFileName);  finally    sgs.Free;  end;end;function TBillsCacheTree.FindGclChild(AParent: TBillsCacheNode;  const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;var  vChild: TBillsCacheNode;begin  Result := nil;  if Assigned(AParent) then    vChild := TBillsCacheNode(AParent.FirstChild)  else    vChild := TBillsCacheNode(Root.FirstChild);  while Assigned(vChild) and not Assigned(Result) do  begin    if SameText(AB_Code, vChild.B_Code) and        SameText(AName, vChild.Name) and        SameText(AUnits, vChild.Units) and        (APrice = vChild.Price) then      Result := vChild;    vChild := TBillsCacheNode(vChild.NextSibling);  end;end;function TBillsCacheTree.FindXmjChild(AParent: TBillsCacheNode;  const ACode, AName: string): TBillsCacheNode;var  vChild: TBillsCacheNode;begin  Result := nil;  if Assigned(AParent) then    vChild := TBillsCacheNode(AParent.FirstChild)  else    vChild := TBillsCacheNode(Root.FirstChild);  while Assigned(vChild) and not Assigned(Result) do  begin    if SameText(ACode, vChild.Code) and SameText(AName, vChild.Name) then      Result := vChild;    vChild := TBillsCacheNode(vChild.NextSibling);  end;end;constructor TBillsCacheTree.Create;begin  inherited;  FFixedIDNodes := TList.Create;end;destructor TBillsCacheTree.Destroy;begin  FFixedIDNodes.Free;  inherited;end;function TBillsCacheTree.FindFixedIDNode(AID: Integer): TBillsCacheNode;var  iNode: Integer;  vNode: TCacheNode;begin  Result := nil;  for iNode := 0 to FFixedIDNodes.Count - 1 do  begin    vNode := TCacheNode(FFixedIDNodes.Items[iNode]);    if vNode.ID = AID then    begin      Result := TBillsCacheNode(vNode);      Break;    end;  end;end;{ TReportCacheNode }constructor TReportCacheNode.Create(ACacheTree: TCacheTree; AID,  AProjectCount: Integer);begin  inherited Create(ACacheTree, AID);  FProjectCount := AProjectCount;  SetLength(FP_Quantity, AProjectCount);  SetLength(FP_Price, AProjectCount);  SetLength(FP_TotalPrice, AProjectCount);  SetLength(FP_DgnQuantity1, AProjectCount);  SetLength(FP_DgnQuantity2, AProjectCount);end;function TReportCacheNode.GetAddGatherQuantity: Double;begin  Result := AddDealQuantity + AddQcQuantity;end;function TReportCacheNode.GetAddGatherTotalPrice: Double;begin  Result := AddDealTotalPrice + AddQcTotalPrice + AddPcTotalPrice;end;function TReportCacheNode.GetDoubleArrayTotal(  ADoubleArray: TDoubleArray): Double;var  i: Integer;begin  Result := 0;  for i := Low(ADoubleArray) to High(ADoubleArray) do    Result := Result + ADoubleArray[i];end;function TReportCacheNode.GetGatherP_TotalPrice: Double;begin  Result := GetDoubleArrayTotal(FP_TotalPrice);end;procedure TReportCacheNode.ResolveCode;var  sgs: TStrings;  i: Integer;begin  sgs := TStringList.Create;  try    sgs.Delimiter := '-';    sgs.DelimitedText := FCode;    FXiangCode := '';    FMuCode := '';    FJieCode := '';    FXiMuCode := '';    case sgs.Count of      1: FXiangCode := '';      2: FXiangCode := ChinessNum(StrToIntDef(sgs[1], 0));      3: FMuCode := sgs[2];      4: FJieCode := sgs[3];      else      begin        for i := 4 to sgs.Count - 1 do          if FXiMuCode = '' then            FXiMuCode := sgs[i]          else            FXiMuCode := FXiMuCode + '-' + sgs[i];      end;    end;  finally    sgs.Free;  end;end;procedure TReportCacheNode.SetCode(const Value: string);begin  FCode := Value;  ResolveCode;end;{ TReportCacheTree }function TReportCacheTree.AddNode(AParent,  ANextSibling: TCacheNode): TReportCacheNode;begin  Result := GetNewNode(FProjectCount);  if Assigned(ANextSibling) then    ANextSibling.InsertPreSibling(Result)  else if Assigned(AParent) then    AParent.InsertChild(Result)  else    Root.InsertChild(Result);end;constructor TReportCacheTree.Create(AProjectCount: Integer);begin  inherited Create;  FProjectCount := AProjectCount;  FGatherCacheNode := TReportCacheNode.Create(nil, -2, AProjectCount);  SetLength(FProjectName, AProjectCount);end;destructor TReportCacheTree.Destroy;begin  FGatherCacheNode.Free;  inherited;end;function TReportCacheTree.FindNextSibling(AParent: TCacheNode; ACode,  AB_Code: string): TReportCacheNode;var  Node: TReportCacheNode;  sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;begin  if Assigned(AParent) then    Node := TReportCacheNode(AParent.FirstChild)  else    Node := TReportCacheNode(Root.FirstChild);  Result := nil;  if (ACode = '') and (AB_Code = '') then Exit;  sCodeID := ConvertDigitCode(ACode, 3, '-');  sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');  while Assigned(Node) do  begin    sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');    sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');    if sCodeID < sCodeID2 then    begin      Result := Node;      Break;    end    else if sB_CodeID < sB_CodeID2 then    begin      Result := Node;      Break;    end;    Node := TReportCacheNode(Node.NextSibling);  end;end;function TReportCacheTree.FindNode(AParent: TCacheNode; ACode,  AB_Code: string): TReportCacheNode;var  Node: TReportCacheNode;begin  if Assigned(AParent) then    Node := TReportCacheNode(AParent.FirstChild)  else    Node := TReportCacheNode(Root.FirstChild);  Result := nil;  while Assigned(Node) do  begin    if (Node.Code = ACode) and (Node.B_Code = AB_Code) then    begin      Result := Node;      Break;    end;    Node := TReportCacheNode(Node.NextSibling);  end;end;function TReportCacheTree.FindNode(AParent: TCacheNode;  AName: string): TReportCacheNode;var  Node: TReportCacheNode;begin  if Assigned(AParent) then    Node := TReportCacheNode(AParent.FirstChild)  else    Node := TReportCacheNode(Root.FirstChild);  Result := nil;  while Assigned(Node) do  begin    if SameText(Node.Name, AName) then    begin      Result := Node;      Break;    end;    Node := TReportCacheNode(Node.NextSibling);  end;end;function TReportCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,  AName: string): TReportCacheNode;var  Node: TReportCacheNode;begin  if Assigned(AParent) then    Node := TReportCacheNode(AParent.FirstChild)  else    Node := TReportCacheNode(Root.FirstChild);  Result := nil;  while Assigned(Node) do  begin    if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)        and SameText(Node.Name, AName) then    begin      Result := Node;      Break;    end;    Node := TReportCacheNode(Node.NextSibling);  end;end;function TReportCacheTree.GetNewNode(  AProjectCount: Integer): TReportCacheNode;begin  Result := TReportCacheNode.Create(Self, GetNewNodeID, AProjectCount);  CacheNodes.Add(Result);end;procedure TReportCacheTree.ReCalcGatherData;var  i: Integer;  CacheNode: TReportCacheNode;begin  FGatherCacheNode.Free;  FGatherCacheNode := TReportCacheNode.Create(nil, -2, FProjectCount);  CacheNode := TReportCacheNode(FirstNode);  while Assigned(CacheNode) do  begin    FGatherCacheNode.TotalPrice := FGatherCacheNode.TotalPrice + CacheNode.TotalPrice;    FGatherCacheNode.AddDealTotalPrice := FGatherCacheNode.AddDealTotalPrice + CacheNode.AddDealTotalPrice;    FGatherCacheNode.AddQcTotalPrice := FGatherCacheNode.AddQcTotalPrice + CacheNode.AddQcTotalPrice;    FGatherCacheNode.AddPcTotalPrice := FGatherCacheNode.AddPcTotalPrice + CacheNode.AddPcTotalPrice;    FGatherCacheNode.PDTotalPrice := FGatherCacheNode.PDTotalPrice + CacheNode.PDTotalPrice;    FGatherCacheNode.CDDTotalPrice := FGatherCacheNode.CDDTotalPrice + CacheNode.CDDTotalPrice;    FGatherCacheNode.ABTotalPrice := FGatherCacheNode.ABTotalPrice + CacheNode.ABTotalPrice;    for i := 0 to FProjectCount - 1 do      FGatherCacheNode.P_TotalPrice[i] := FGatherCacheNode.P_TotalPrice[i] + CacheNode.P_TotalPrice[i];    CacheNode := TReportCacheNode(CacheNode.NextSibling);  end;end;procedure TReportCacheTree.ReCalcRatioPercent;var  i: Integer;  CacheNode: TReportCacheNode;begin  for i := 0 to CacheNodes.Count - 1 do  begin    CacheNode := TReportCacheNode(CacheNodes.Items[i]);    if GatherCacheNode.TotalPrice <> 0 then      CacheNode.RatioPercent := AdvRoundTo(CacheNode.TotalPrice/GatherCacheNode.TotalPrice*100);    if GatherCacheNode.AddGatherTotalPrice <> 0 then      CacheNode.AddRatioPercent := AdvRoundTo(CacheNode.AddGatherTotalPrice/GatherCacheNode.AddGatherTotalPrice*100);  end;end;procedure TReportCacheTree.SaveTreeToFile(const AFileName: string);var  sgs: TStringList;  I: Integer;  Node: TReportCacheNode;begin  sgs := TStringList.Create;  try    for I := 0 to CacheNodes.Count - 1 do    begin      Node := TReportCacheNode(CacheNodes.Items[I]);      sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',        [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));    end;    sgs.SaveToFile(AFileName);  finally    sgs.Free;  end;end;{ TAllPhaseCacheTree }function TAllPhaseCacheTree.AddNode(AID: Integer; AParent,  ANextSibling: TCacheNode): TAllPhaseCacheNode;begin  Result := GetNewNode(AID);  if Assigned(ANextSibling) then    ANextSibling.InsertPreSibling(Result)  else if Assigned(AParent) then    AParent.InsertChild(Result)  else    Root.InsertChild(Result);end;function TAllPhaseCacheTree.FindNode(AID: Integer): TAllPhaseCacheNode;var  i: Integer;  Node: TAllPhaseCacheNode;begin  Result := nil;  for i := 0 to CacheNodes.Count - 1 do  begin    Node := TAllPhaseCacheNode(CacheNodes.Items[i]);    if Node.ID = AID then    begin      Result := Node;      Break;    end;  end;end;function TAllPhaseCacheTree.GetNewNode(  AID: Integer): TAllPhaseCacheNode;begin  Result := TAllPhaseCacheNode.Create(Self, AID);  CacheNodes.Add(Result);end;procedure TAllPhaseCacheTree.SaveTreeToFile(const AFileName: string);var  sgs: TStringList;  I: Integer;  Node: TAllPhaseCacheNode;begin  sgs := TStringList.Create;  try    for I := 0 to CacheNodes.Count - 1 do    begin      Node := TAllPhaseCacheNode(CacheNodes.Items[I]);      sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',        [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));    end;    sgs.SaveToFile(AFileName);  finally    sgs.Free;  end;end;{ TGclCacheTree }function TGclCacheTree.AddNodeByB_Code(  const AB_Code: string): TGclCacheNode;  function FindParent: TGclCacheNode;  begin    Result := FLastNode;    while Assigned(Result) and (Result <> Root) and (Result.B_Code <> '') and (Pos(Result.B_Code + '-', AB_Code) <> 1) do      Result := TGclCacheNode(Result.Parent);  end;var  vParent: TGclCacheNode;begin  vParent := FindParent;  Result := TGclCacheNode(AddNode(vParent));  FLastNode := Result;end;function TGclCacheTree.AddNodeByData(const AB_Code,  AName: string): TGclCacheNode;begin  if AB_Code = '' then    Result := AddNodeByName(AName)  else    Result := AddNodeByB_Code(AB_Code);end;function TGclCacheTree.AddNodeByName(const AName: string): TGclCacheNode;begin  if Pos('第100章至', AName) <> 0 then  begin    Result := TGclCacheNode(AddNode(nil));    FLastBlank1 := Result;  end  else    Result := TGclCacheNode(AddNode(FLastBlank1));  FLastNode := Result;end;function TGclCacheTree.GetNewNode: TCacheNode;begin  Result := TGclCacheNode.Create(Self, GetNewNodeID);  CacheNodes.Add(Result);end;procedure TGclCacheTree.SaveTreeToFile(const AFileName: string);var  sgs: TStringList;  I: Integer;  Node: TGclCacheNode;begin  sgs := TStringList.Create;  try    for I := 0 to CacheNodes.Count - 1 do    begin      Node := TGclCacheNode(CacheNodes.Items[I]);      sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; B_Code: %s; Name: %s;',        [Node.ID, Node.ParentID, Node.NextSiblingID, Node.B_Code, Node.Name]));    end;    sgs.SaveToFile(AFileName);  finally    sgs.Free;  end;end;end.
 |