MCacheTree.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950
  1. unit MCacheTree;
  2. // CacheTree For Measure, Inherit From CacheTree
  3. interface
  4. uses
  5. Classes, CacheTree, Math, ZhAPI, sdIDTree;
  6. type
  7. // For Import Temp Excel
  8. TBillsCacheNode = class(TCacheNode)
  9. private
  10. FLevelCode: string;
  11. FCode: string;
  12. FB_Code: string;
  13. FName: string;
  14. FUnits: string;
  15. FCanDelete: Boolean;
  16. FOrgQuantity: Double;
  17. FMisQuantity: Double;
  18. FOthQuantity: Double;
  19. FDgnQuantity1: Double;
  20. FDgnQuantity2: Double;
  21. FMemoStr: string;
  22. FPrice: Double;
  23. FDrawingCode: string;
  24. public
  25. property LevelCode: string read FLevelCode write FLevelCode;
  26. property Code: string read FCode write FCode;
  27. property B_Code: string read FB_Code write FB_Code;
  28. property Name: string read FName write FName;
  29. property Units: string read FUnits write FUnits;
  30. property CanDelete: Boolean read FCanDelete write FCanDelete;
  31. property Price: Double read FPrice write FPrice;
  32. property OrgQuantity: Double read FOrgQuantity write FOrgQuantity;
  33. property MisQuantity: Double read FMisQuantity write FMisQuantity;
  34. property OthQuantity: Double read FOthQuantity write FOthQuantity;
  35. property DgnQuantity1: Double read FDgnQuantity1 write FDgnQuantity1;
  36. property DgnQuantity2: Double read FDgnQuantity2 write FDgnQuantity2;
  37. property DrawingCode: string read FDrawingCode write FDrawingCode;
  38. property MemoStr: string read FMemoStr write FMemoStr;
  39. end;
  40. TBillsCacheTree = class(TCacheTree)
  41. private
  42. FLastNode: TCacheNode;
  43. FSeparateChar: Char;
  44. FAutoSort: Boolean;
  45. FFixedIDNodes: TList;
  46. function GetNewNode(AID: Integer = -1): TBillsCacheNode; overload;
  47. function FindNode(const ACode: string): TBillsCacheNode; overload;
  48. function FindNode(AParent: TBillsCacheNode; const ACode: string): TBillsCacheNode; overload;
  49. function FindParent(const ACode: string): TBillsCacheNode;
  50. function FindNextSibling(const ACode: string): TBillsCacheNode;
  51. procedure SetSeparateChar(const Value: Char);
  52. public
  53. constructor Create; override;
  54. destructor Destroy; override;
  55. function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil; AFixedID: Integer = -1): TBillsCacheNode;
  56. function AddNodeByCode(const ACode: string; AFixedID: Integer = -1): TBillsCacheNode;
  57. function AddLeafBillsNode(const AB_Code: string): TBillsCacheNode;
  58. function FindXmjChild(AParent: TBillsCacheNode; const ACode, AName: string): TBillsCacheNode;
  59. function FindGclChild(AParent: TBillsCacheNode; const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;
  60. function FindFixedIDNode(AID: Integer): TBillsCacheNode;
  61. // Only for Debugging lot of Data
  62. procedure SaveTreeToFile(const AFileName: string);
  63. property SeparateChar: Char read FSeparateChar write SetSeparateChar;
  64. property AutoSort: Boolean read FAutoSort write FAutoSort;
  65. property FixedIDNodes: TList read FFixedIDNodes;
  66. end;
  67. // 此树仅用于导入工程量清单,禁止作为它用
  68. // 如须使用应遵守以下两点:1.完全清楚相关的导入方法类及需求 2.派生子类。
  69. TGclCacheNode = class(TCacheNode)
  70. private
  71. FB_Code: string;
  72. FName: string;
  73. FUnits: string;
  74. FPrice: Double;
  75. FQuantity: Double;
  76. public
  77. property B_Code: string read FB_Code write FB_Code;
  78. property Name: string read FName write FName;
  79. property Units: string read FUnits write FUnits;
  80. property Price: Double read FPrice write FPrice;
  81. property Quantity: Double read FQuantity write FQuantity;
  82. end;
  83. TGclCacheTree = class(TCacheTree)
  84. private
  85. FLastBlank1: TGclCacheNode;
  86. FLastNode: TGclCacheNode;
  87. function AddNodeByName(const AName: string): TGclCacheNode;
  88. function AddNodeByB_Code(const AB_Code: string): TGclCacheNode;
  89. protected
  90. function GetNewNode: TCacheNode; override;
  91. public
  92. function AddNodeByData(const AB_Code, AName: string): TGclCacheNode;
  93. procedure SaveTreeToFile(const AFileName: string);
  94. end;
  95. {For Report Memory(Gather or Compare Projects)}
  96. TDoubleArray = array of Double;
  97. TReportCacheNode = class(TCacheNode)
  98. private
  99. FCode: string;
  100. FB_Code: string;
  101. FName: string;
  102. FUnits: string;
  103. FMemoStr: string;
  104. FXiangCode: string;
  105. FMuCode: string;
  106. FJieCode: string;
  107. FXiMuCode: string;
  108. FPrice: Double;
  109. FQuantity: Double;
  110. FTotalPrice: Double;
  111. FRatioPercent: Double; // 0号台账 - 各项费用所占比例
  112. FDesignQuantity1: Double;
  113. FDesignQuantity2: Double;
  114. FAddQcQuantity: Double;
  115. FAddPcTotalPrice: Double;
  116. FAddQcTotalPrice: Double;
  117. FAddDealQuantity: Double;
  118. FAddDealTotalPrice: Double;
  119. FAddPcQuantity: Double;
  120. FAddRatioPercent: Double; // 决算 - 各项费用所占比例
  121. FDealDesignQuantity1: Double;
  122. FDealDesignQuantity2: Double;
  123. FCDesignQuantity1: Double;
  124. FCDesignQuantity2: Double;
  125. FPDQuantity: Double;
  126. FPDTotalPrice: Double;
  127. FPDDesignQuantity1: Double;
  128. FPDDesignQuantity2: Double;
  129. FPDDesignPrice: Double;
  130. FCDDQuantity: Double;
  131. FCDDTotalPrice: Double;
  132. FCDDDesignQuantity1: Double;
  133. FCDDDesignQuantity2: Double;
  134. FCDDDesignPrice: Double;
  135. FABTotalPrice: Double;
  136. FABQuantity: Double;
  137. FABDesignQuantity1: Double;
  138. FABDesignQuantity2: Double;
  139. FABDesignPrice: Double;
  140. FProjectCount: Integer;
  141. FP_TotalPrice: TDoubleArray;
  142. FP_Quantity: TDoubleArray;
  143. FP_Price: TDoubleArray;
  144. FP_DgnQuantity1: TDoubleArray;
  145. FP_DgnQuantity2: TDoubleArray;
  146. procedure ResolveCode;
  147. function GetDoubleArrayTotal(ADoubleArray: TDoubleArray): Double;
  148. procedure SetCode(const Value: string);
  149. function GetGatherP_TotalPrice: Double;
  150. function GetAddGatherQuantity: Double;
  151. function GetAddGatherTotalPrice: Double;
  152. public
  153. constructor Create(ACacheTree: TCacheTree; AID, AProjectCount: Integer);
  154. property Code: string read FCode write SetCode;
  155. property B_Code: string read FB_Code write FB_Code;
  156. property Name: string read FName write FName;
  157. property Units: string read FUnits write FUnits;
  158. property MemoStr: string read FMemoStr write FMemoStr;
  159. property XiangCode: string read FXiangCode;
  160. property MuCode: string read FMuCode;
  161. property JieCode: string read FJieCode;
  162. property XiMuCode: string read FXiMuCode;
  163. // 用于汇总多个项目的合同、变更(数量、金额)
  164. property Price: Double read FPrice write FPrice;
  165. // 0号台账合同
  166. property Quantity: Double read FQuantity write FQuantity;
  167. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  168. property RatioPercent: Double read FRatioPercent write FRatioPercent;
  169. property DesignQuantity1: Double read FDesignQuantity1 write FDesignQuantity1;
  170. property DesignQuantity2: Double read FDesignQuantity2 write FDesignQuantity2;
  171. // 累计各值
  172. property AddDealQuantity: Double read FAddDealQuantity write FAddDealQuantity;
  173. property AddDealTotalPrice: Double read FAddDealTotalPrice write FAddDealTotalPrice;
  174. property AddQcQuantity: Double read FAddQcQuantity write FAddQcQuantity;
  175. property AddQcTotalPrice: Double read FAddQcTotalPrice write FAddQcTotalPrice;
  176. property AddPcQuantity: Double read FAddPcQuantity write FAddPcQuantity;
  177. property AddPcTotalPrice: Double read FAddPcTotalPrice write FAddPcTotalPrice;
  178. property AddGatherQuantity: Double read GetAddGatherQuantity;
  179. property AddGatherTotalPrice: Double read GetAddGatherTotalPrice;
  180. property AddRatioPercent: Double read FAddRatioPercent write FAddRatioPercent;
  181. // 合同&变更 设计数量
  182. property DealDesignQuantity1: Double read FDealDesignQuantity1 write FDealDesignQuantity1;
  183. property DealDesignQuantity2: Double read FDealDesignQuantity2 write FDealDesignQuantity2;
  184. property CDesignQuantity1: Double read FCDesignQuantity1 write FCDesignQuantity1;
  185. property CDesignQuantity2: Double read FCDesignQuantity2 write FCDesignQuantity2;
  186. // ----仅用于汇总生成决算02表----
  187. // 初步设计 Preliminary Design
  188. property PDQuantity: Double read FPDQuantity write FPDQuantity;
  189. property PDTotalPrice: Double read FPDTotalPrice write FPDTotalPrice;
  190. property PDDesignQuantity1: Double read FPDDesignQuantity1 write FPDDesignQuantity1;
  191. property PDDesignQuantity2: Double read FPDDesignQuantity2 write FPDDesignQuantity2;
  192. property PDDesignPrice: Double read FPDDesignPrice write FPDDesignPrice;
  193. // 施工图设计 Construction Drawing Design
  194. property CDDQuantity: Double read FCDDQuantity write FCDDQuantity;
  195. property CDDTotalPrice: Double read FCDDTotalPrice write FCDDTotalPrice;
  196. property CDDDesignQuantity1: Double read FCDDDesignQuantity1 write FCDDDesignQuantity1;
  197. property CDDDesignQuantity2: Double read FCDDDesignQuantity2 write FCDDDesignQuantity2;
  198. property CDDDesignPrice: Double read FCDDDesignPrice write FCDDDesignPrice;
  199. // ------------------------------
  200. // ----仅用于汇总生成决算02表(部颁)----
  201. // 批准概(预算)算 Approved Budget
  202. property ABQuantity: Double read FABQuantity write FABQuantity;
  203. property ABTotalPrice: Double read FABTotalPrice write FABTotalPrice;
  204. property ABDesignQuantity1: Double read FABDesignQuantity1 write FABDesignQuantity1;
  205. property ABDesignQuantity2: Double read FABDesignQuantity2 write FABDesignQuantity2;
  206. property ABDesignPrice: Double read FABDesignPrice write FABDesignPrice;
  207. // ------------------------------------
  208. // 用于记录多个项目的数量、单价、金额、设计数量
  209. property P_Price: TDoubleArray read FP_Price write FP_Price;
  210. property P_Quantity: TDoubleArray read FP_Quantity write FP_Quantity;
  211. property P_TotalPrice: TDoubleArray read FP_TotalPrice write FP_TotalPrice;
  212. property P_DgnQuantity1: TDoubleArray read FP_DgnQuantity1 write FP_DgnQuantity1;
  213. property P_DgnQuantity2: TDoubleArray read FP_DgnQuantity2 write FP_DgnQuantity2;
  214. property GatherP_TotalPrice: Double read GetGatherP_TotalPrice;
  215. property ProjectCount: Integer read FProjectCount;
  216. end;
  217. TStringArray = array of string;
  218. TReportCacheTree = class(TCacheTree)
  219. private
  220. FProjectCount: Integer;
  221. FGatherCacheNode: TReportCacheNode;
  222. FProjectName: TStringArray;
  223. function GetNewNode(AProjectCount: Integer): TReportCacheNode; overload;
  224. public
  225. constructor Create(AProjectCount: Integer);
  226. destructor Destroy; override;
  227. function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil): TReportCacheNode;
  228. function FindNextSibling(AParent: TCacheNode; ACode, AB_Code: string): TReportCacheNode;
  229. function FindNode(AParent: TCacheNode; ACode, AB_Code: string): TReportCacheNode; overload;
  230. function FindNode(AParent: TCacheNode; AName: string): TReportCacheNode; overload;
  231. function FindNode(AParent: TCacheNode; ACode, AB_Code, AName: string): TReportCacheNode; overload;
  232. procedure ReCalcGatherData;
  233. // 调用此方法先须先调用ReCalcGatherData
  234. // RatioPercent = 金额/总金额,这里的总金额取GatherCacheNode的金额,故须先汇总计算GatherCacheNode。
  235. procedure ReCalcRatioPercent;
  236. // Only for Debugging lot of Data
  237. procedure SaveTreeToFile(const AFileName: string);
  238. property ProjectCount: Integer read FProjectCount;
  239. property GatherCacheNode: TReportCacheNode read FGatherCacheNode;
  240. property ProjectName: TStringArray read FProjectName write FProjectName;
  241. end;
  242. TapDoubleArray = array [1..50] of Double;
  243. TAllPhaseCacheNode = class(TCacheNode)
  244. private
  245. FCode: string;
  246. FB_Code: string;
  247. FName: string;
  248. FUnits: string;
  249. FPrice: Double;
  250. FQuantity: Double;
  251. FTotalPrice: Double;
  252. FMemoStr: string;
  253. public
  254. FP_Quantity: TapDoubleArray;
  255. FP_TotalPrice: TapDoubleArray;
  256. property Code: string read FCode write FCode;
  257. property B_Code: string read FB_Code write FB_Code;
  258. property Name: string read FName write FName;
  259. property Units: string read FUnits write FUnits;
  260. property Price: Double read FPrice write FPrice;
  261. property Quantity: Double read FQuantity write FQuantity;
  262. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  263. property MemoStr: string read FMemoStr write FMemoStr;
  264. end;
  265. // 仅用于汇总同一项目的不同期数据
  266. TAllPhaseCacheTree = class(TCacheTree)
  267. private
  268. function GetNewNode(AID: Integer): TAllPhaseCacheNode;
  269. public
  270. function AddNode(AID: Integer; AParent: TCacheNode; ANextSibling: TCacheNode = nil): TAllPhaseCacheNode;
  271. function FindNode(AID: Integer): TAllPhaseCacheNode;
  272. // Only for Debugging lot of Data
  273. procedure SaveTreeToFile(const AFileName: string);
  274. end;
  275. implementation
  276. uses
  277. SysUtils, UtilMethods;
  278. { TBillsCacheTree }
  279. function TBillsCacheTree.AddNodeByCode(const ACode: string;
  280. AFixedID: Integer): TBillsCacheNode;
  281. var
  282. Parent, NextSibling: TBillsCacheNode;
  283. begin
  284. Result := FindNode(ACode);
  285. FLastNode := Result;
  286. if Assigned(Result) then Exit;
  287. Parent := FindParent(ACode);
  288. if AutoSort then
  289. NextSibling := FindNextSibling(ACode)
  290. else
  291. NextSibling := nil;
  292. Result := AddNode(Parent, NextSibling, AFixedID);
  293. Result.FLevelCode := ACode;
  294. FLastNode := Result;
  295. end;
  296. function TBillsCacheTree.FindNode(const ACode: string): TBillsCacheNode;
  297. begin
  298. Result := FindNode(TBillsCacheNode(Root), ACode);
  299. end;
  300. function TBillsCacheTree.FindNextSibling(
  301. const ACode: string): TBillsCacheNode;
  302. var
  303. Parent, Node: TBillsCacheNode;
  304. sCodeID, sCodeID2: string;
  305. begin
  306. Parent := FindParent(ACode);
  307. if Assigned(Parent) then
  308. Node := TBillsCacheNode(Parent.FirstChild)
  309. else
  310. Node := TBillsCacheNode(Root.FirstChild);
  311. Result := nil;
  312. sCodeID := ConvertDigitCode(ACode, 3, '-');
  313. while Assigned(Node) do
  314. begin
  315. sCodeID2 := ConvertDigitCode(Node.LevelCode, 3, SeparateChar);
  316. if sCodeID < sCodeID2 then
  317. begin
  318. Result := Node;
  319. Break;
  320. end;
  321. Node := TBillsCacheNode(Node.NextSibling);
  322. end;
  323. end;
  324. function TBillsCacheTree.FindNode(AParent: TBillsCacheNode;
  325. const ACode: string): TBillsCacheNode;
  326. begin
  327. Result := TBillsCacheNode(AParent.FirstChild);
  328. while Assigned(Result) do
  329. begin
  330. if Result.LevelCode = ACode then
  331. Break
  332. else if Pos(Result.LevelCode + SeparateChar, ACode) = 1 then
  333. begin
  334. Result := FindNode(Result, ACode);
  335. Break;
  336. end
  337. else
  338. Result := TBillsCacheNode(Result.NextSibling);
  339. end;
  340. end;
  341. function TBillsCacheTree.FindParent(const ACode: string): TBillsCacheNode;
  342. var
  343. sCode: string;
  344. begin
  345. Result := nil;
  346. sCode := GetPrefixOfCode(ACode, SeparateChar);
  347. while (Result = nil) and (sCode <> '') do
  348. begin
  349. Result := FindNode(sCode);
  350. sCode := GetPrefixOfCode(sCode, SeparateChar);
  351. end;
  352. end;
  353. function TBillsCacheTree.GetNewNode(AID: Integer): TBillsCacheNode;
  354. begin
  355. if AID = -1 then
  356. Result := TBillsCacheNode.Create(Self, GetNewNodeID)
  357. else
  358. Result := TBillsCacheNode.Create(Self, AID);
  359. CacheNodes.Add(Result);
  360. if Result.ID < 100 then
  361. FFixedIDNodes.Add(Result);
  362. end;
  363. function TBillsCacheTree.AddNode(AParent, ANextSibling: TCacheNode;
  364. AFixedID: Integer): TBillsCacheNode;
  365. begin
  366. Result := GetNewNode(AFixedID);
  367. if Assigned(ANextSibling) then
  368. ANextSibling.InsertPreSibling(Result)
  369. else if Assigned(AParent) then
  370. AParent.InsertChild(Result)
  371. else
  372. Root.InsertChild(Result);
  373. end;
  374. function TBillsCacheTree.AddLeafBillsNode(const AB_Code: string): TBillsCacheNode;
  375. function GetLastXmjParent: TBillsCacheNode;
  376. begin
  377. Result := TBillsCacheNode(FLastNode);
  378. while Assigned(Result) and (Result.B_Code <> '') do
  379. Result := TBillsCacheNode(Result.Parent);
  380. end;
  381. var
  382. Parent: TBillsCacheNode;
  383. begin
  384. Parent := GetLastXmjParent;
  385. Result := AddNodeByCode(Parent.Code + '-' + AB_Code, -1);
  386. end;
  387. procedure TBillsCacheTree.SetSeparateChar(const Value: Char);
  388. var
  389. I: Integer;
  390. Node: TBillsCacheNode;
  391. begin
  392. for I := 0 to CacheNodes.Count - 1 do
  393. begin
  394. Node := TBillsCacheNode(CacheNodes.Items[I]);
  395. Node.FLevelCode := StringReplace(Node.FLevelCode, FSeparateChar, Value, [rfReplaceAll]);
  396. end;
  397. FSeparateChar := Value;
  398. end;
  399. procedure TBillsCacheTree.SaveTreeToFile(const AFileName: string);
  400. var
  401. sgs: TStringList;
  402. I: Integer;
  403. Node: TBillsCacheNode;
  404. begin
  405. sgs := TStringList.Create;
  406. try
  407. for I := 0 to CacheNodes.Count - 1 do
  408. begin
  409. Node := TBillsCacheNode(CacheNodes.Items[I]);
  410. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  411. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  412. end;
  413. sgs.SaveToFile(AFileName);
  414. finally
  415. sgs.Free;
  416. end;
  417. end;
  418. function TBillsCacheTree.FindGclChild(AParent: TBillsCacheNode;
  419. const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;
  420. var
  421. vChild: TBillsCacheNode;
  422. begin
  423. Result := nil;
  424. if Assigned(AParent) then
  425. vChild := TBillsCacheNode(AParent.FirstChild)
  426. else
  427. vChild := TBillsCacheNode(Root.FirstChild);
  428. while Assigned(vChild) and not Assigned(Result) do
  429. begin
  430. if SameText(AB_Code, vChild.B_Code) and
  431. SameText(AName, vChild.Name) and
  432. SameText(AUnits, vChild.Units) and
  433. (APrice = vChild.Price) then
  434. Result := vChild;
  435. vChild := TBillsCacheNode(vChild.NextSibling);
  436. end;
  437. end;
  438. function TBillsCacheTree.FindXmjChild(AParent: TBillsCacheNode;
  439. const ACode, AName: string): TBillsCacheNode;
  440. var
  441. vChild: TBillsCacheNode;
  442. begin
  443. Result := nil;
  444. if Assigned(AParent) then
  445. vChild := TBillsCacheNode(AParent.FirstChild)
  446. else
  447. vChild := TBillsCacheNode(Root.FirstChild);
  448. while Assigned(vChild) and not Assigned(Result) do
  449. begin
  450. if SameText(ACode, vChild.Code) and SameText(AName, vChild.Name) then
  451. Result := vChild;
  452. vChild := TBillsCacheNode(vChild.NextSibling);
  453. end;
  454. end;
  455. constructor TBillsCacheTree.Create;
  456. begin
  457. inherited;
  458. FFixedIDNodes := TList.Create;
  459. end;
  460. destructor TBillsCacheTree.Destroy;
  461. begin
  462. FFixedIDNodes.Free;
  463. inherited;
  464. end;
  465. function TBillsCacheTree.FindFixedIDNode(AID: Integer): TBillsCacheNode;
  466. var
  467. iNode: Integer;
  468. vNode: TCacheNode;
  469. begin
  470. Result := nil;
  471. for iNode := 0 to FFixedIDNodes.Count - 1 do
  472. begin
  473. vNode := TCacheNode(FFixedIDNodes.Items[iNode]);
  474. if vNode.ID = AID then
  475. begin
  476. Result := TBillsCacheNode(vNode);
  477. Break;
  478. end;
  479. end;
  480. end;
  481. { TReportCacheNode }
  482. constructor TReportCacheNode.Create(ACacheTree: TCacheTree; AID,
  483. AProjectCount: Integer);
  484. begin
  485. inherited Create(ACacheTree, AID);
  486. FProjectCount := AProjectCount;
  487. SetLength(FP_Quantity, AProjectCount);
  488. SetLength(FP_Price, AProjectCount);
  489. SetLength(FP_TotalPrice, AProjectCount);
  490. SetLength(FP_DgnQuantity1, AProjectCount);
  491. SetLength(FP_DgnQuantity2, AProjectCount);
  492. end;
  493. function TReportCacheNode.GetAddGatherQuantity: Double;
  494. begin
  495. Result := AddDealQuantity + AddQcQuantity;
  496. end;
  497. function TReportCacheNode.GetAddGatherTotalPrice: Double;
  498. begin
  499. Result := AddDealTotalPrice + AddQcTotalPrice + AddPcTotalPrice;
  500. end;
  501. function TReportCacheNode.GetDoubleArrayTotal(
  502. ADoubleArray: TDoubleArray): Double;
  503. var
  504. i: Integer;
  505. begin
  506. Result := 0;
  507. for i := Low(ADoubleArray) to High(ADoubleArray) do
  508. Result := Result + ADoubleArray[i];
  509. end;
  510. function TReportCacheNode.GetGatherP_TotalPrice: Double;
  511. begin
  512. Result := GetDoubleArrayTotal(FP_TotalPrice);
  513. end;
  514. procedure TReportCacheNode.ResolveCode;
  515. var
  516. sgs: TStrings;
  517. i: Integer;
  518. begin
  519. sgs := TStringList.Create;
  520. try
  521. sgs.Delimiter := '-';
  522. sgs.DelimitedText := FCode;
  523. FXiangCode := '';
  524. FMuCode := '';
  525. FJieCode := '';
  526. FXiMuCode := '';
  527. case sgs.Count of
  528. 1: FXiangCode := '';
  529. 2: FXiangCode := ChinessNum(StrToIntDef(sgs[1], 0));
  530. 3: FMuCode := sgs[2];
  531. 4: FJieCode := sgs[3];
  532. else
  533. begin
  534. for i := 4 to sgs.Count - 1 do
  535. if FXiMuCode = '' then
  536. FXiMuCode := sgs[i]
  537. else
  538. FXiMuCode := FXiMuCode + '-' + sgs[i];
  539. end;
  540. end;
  541. finally
  542. sgs.Free;
  543. end;
  544. end;
  545. procedure TReportCacheNode.SetCode(const Value: string);
  546. begin
  547. FCode := Value;
  548. ResolveCode;
  549. end;
  550. { TReportCacheTree }
  551. function TReportCacheTree.AddNode(AParent,
  552. ANextSibling: TCacheNode): TReportCacheNode;
  553. begin
  554. Result := GetNewNode(FProjectCount);
  555. if Assigned(ANextSibling) then
  556. ANextSibling.InsertPreSibling(Result)
  557. else if Assigned(AParent) then
  558. AParent.InsertChild(Result)
  559. else
  560. Root.InsertChild(Result);
  561. end;
  562. constructor TReportCacheTree.Create(AProjectCount: Integer);
  563. begin
  564. inherited Create;
  565. FProjectCount := AProjectCount;
  566. FGatherCacheNode := TReportCacheNode.Create(nil, -2, AProjectCount);
  567. SetLength(FProjectName, AProjectCount);
  568. end;
  569. destructor TReportCacheTree.Destroy;
  570. begin
  571. FGatherCacheNode.Free;
  572. inherited;
  573. end;
  574. function TReportCacheTree.FindNextSibling(AParent: TCacheNode; ACode,
  575. AB_Code: string): TReportCacheNode;
  576. var
  577. Node: TReportCacheNode;
  578. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  579. begin
  580. if Assigned(AParent) then
  581. Node := TReportCacheNode(AParent.FirstChild)
  582. else
  583. Node := TReportCacheNode(Root.FirstChild);
  584. Result := nil;
  585. if (ACode = '') and (AB_Code = '') then Exit;
  586. sCodeID := ConvertDigitCode(ACode, 3, '-');
  587. sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');
  588. while Assigned(Node) do
  589. begin
  590. sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');
  591. sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');
  592. if sCodeID < sCodeID2 then
  593. begin
  594. Result := Node;
  595. Break;
  596. end
  597. else if sB_CodeID < sB_CodeID2 then
  598. begin
  599. Result := Node;
  600. Break;
  601. end;
  602. Node := TReportCacheNode(Node.NextSibling);
  603. end;
  604. end;
  605. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode,
  606. AB_Code: string): TReportCacheNode;
  607. var
  608. Node: TReportCacheNode;
  609. begin
  610. if Assigned(AParent) then
  611. Node := TReportCacheNode(AParent.FirstChild)
  612. else
  613. Node := TReportCacheNode(Root.FirstChild);
  614. Result := nil;
  615. while Assigned(Node) do
  616. begin
  617. if (Node.Code = ACode) and (Node.B_Code = AB_Code) then
  618. begin
  619. Result := Node;
  620. Break;
  621. end;
  622. Node := TReportCacheNode(Node.NextSibling);
  623. end;
  624. end;
  625. function TReportCacheTree.FindNode(AParent: TCacheNode;
  626. AName: string): TReportCacheNode;
  627. var
  628. Node: TReportCacheNode;
  629. begin
  630. if Assigned(AParent) then
  631. Node := TReportCacheNode(AParent.FirstChild)
  632. else
  633. Node := TReportCacheNode(Root.FirstChild);
  634. Result := nil;
  635. while Assigned(Node) do
  636. begin
  637. if SameText(Node.Name, AName) then
  638. begin
  639. Result := Node;
  640. Break;
  641. end;
  642. Node := TReportCacheNode(Node.NextSibling);
  643. end;
  644. end;
  645. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,
  646. AName: string): TReportCacheNode;
  647. var
  648. Node: TReportCacheNode;
  649. begin
  650. if Assigned(AParent) then
  651. Node := TReportCacheNode(AParent.FirstChild)
  652. else
  653. Node := TReportCacheNode(Root.FirstChild);
  654. Result := nil;
  655. while Assigned(Node) do
  656. begin
  657. if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)
  658. and SameText(Node.Name, AName) then
  659. begin
  660. Result := Node;
  661. Break;
  662. end;
  663. Node := TReportCacheNode(Node.NextSibling);
  664. end;
  665. end;
  666. function TReportCacheTree.GetNewNode(
  667. AProjectCount: Integer): TReportCacheNode;
  668. begin
  669. Result := TReportCacheNode.Create(Self, GetNewNodeID, AProjectCount);
  670. CacheNodes.Add(Result);
  671. end;
  672. procedure TReportCacheTree.ReCalcGatherData;
  673. var
  674. i: Integer;
  675. CacheNode: TReportCacheNode;
  676. begin
  677. FGatherCacheNode.Free;
  678. FGatherCacheNode := TReportCacheNode.Create(nil, -2, FProjectCount);
  679. CacheNode := TReportCacheNode(FirstNode);
  680. while Assigned(CacheNode) do
  681. begin
  682. FGatherCacheNode.TotalPrice := FGatherCacheNode.TotalPrice + CacheNode.TotalPrice;
  683. FGatherCacheNode.AddDealTotalPrice := FGatherCacheNode.AddDealTotalPrice + CacheNode.AddDealTotalPrice;
  684. FGatherCacheNode.AddQcTotalPrice := FGatherCacheNode.AddQcTotalPrice + CacheNode.AddQcTotalPrice;
  685. FGatherCacheNode.AddPcTotalPrice := FGatherCacheNode.AddPcTotalPrice + CacheNode.AddPcTotalPrice;
  686. FGatherCacheNode.PDTotalPrice := FGatherCacheNode.PDTotalPrice + CacheNode.PDTotalPrice;
  687. FGatherCacheNode.CDDTotalPrice := FGatherCacheNode.CDDTotalPrice + CacheNode.CDDTotalPrice;
  688. FGatherCacheNode.ABTotalPrice := FGatherCacheNode.ABTotalPrice + CacheNode.ABTotalPrice;
  689. for i := 0 to FProjectCount - 1 do
  690. FGatherCacheNode.P_TotalPrice[i] := FGatherCacheNode.P_TotalPrice[i] + CacheNode.P_TotalPrice[i];
  691. CacheNode := TReportCacheNode(CacheNode.NextSibling);
  692. end;
  693. end;
  694. procedure TReportCacheTree.ReCalcRatioPercent;
  695. var
  696. i: Integer;
  697. CacheNode: TReportCacheNode;
  698. begin
  699. for i := 0 to CacheNodes.Count - 1 do
  700. begin
  701. CacheNode := TReportCacheNode(CacheNodes.Items[i]);
  702. if GatherCacheNode.TotalPrice <> 0 then
  703. CacheNode.RatioPercent := AdvRoundTo(CacheNode.TotalPrice/GatherCacheNode.TotalPrice*100);
  704. if GatherCacheNode.AddGatherTotalPrice <> 0 then
  705. CacheNode.AddRatioPercent := AdvRoundTo(CacheNode.AddGatherTotalPrice/GatherCacheNode.AddGatherTotalPrice*100);
  706. end;
  707. end;
  708. procedure TReportCacheTree.SaveTreeToFile(const AFileName: string);
  709. var
  710. sgs: TStringList;
  711. I: Integer;
  712. Node: TReportCacheNode;
  713. begin
  714. sgs := TStringList.Create;
  715. try
  716. for I := 0 to CacheNodes.Count - 1 do
  717. begin
  718. Node := TReportCacheNode(CacheNodes.Items[I]);
  719. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  720. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  721. end;
  722. sgs.SaveToFile(AFileName);
  723. finally
  724. sgs.Free;
  725. end;
  726. end;
  727. { TAllPhaseCacheTree }
  728. function TAllPhaseCacheTree.AddNode(AID: Integer; AParent,
  729. ANextSibling: TCacheNode): TAllPhaseCacheNode;
  730. begin
  731. Result := GetNewNode(AID);
  732. if Assigned(ANextSibling) then
  733. ANextSibling.InsertPreSibling(Result)
  734. else if Assigned(AParent) then
  735. AParent.InsertChild(Result)
  736. else
  737. Root.InsertChild(Result);
  738. end;
  739. function TAllPhaseCacheTree.FindNode(AID: Integer): TAllPhaseCacheNode;
  740. var
  741. i: Integer;
  742. Node: TAllPhaseCacheNode;
  743. begin
  744. Result := nil;
  745. for i := 0 to CacheNodes.Count - 1 do
  746. begin
  747. Node := TAllPhaseCacheNode(CacheNodes.Items[i]);
  748. if Node.ID = AID then
  749. begin
  750. Result := Node;
  751. Break;
  752. end;
  753. end;
  754. end;
  755. function TAllPhaseCacheTree.GetNewNode(
  756. AID: Integer): TAllPhaseCacheNode;
  757. begin
  758. Result := TAllPhaseCacheNode.Create(Self, AID);
  759. CacheNodes.Add(Result);
  760. end;
  761. procedure TAllPhaseCacheTree.SaveTreeToFile(const AFileName: string);
  762. var
  763. sgs: TStringList;
  764. I: Integer;
  765. Node: TAllPhaseCacheNode;
  766. begin
  767. sgs := TStringList.Create;
  768. try
  769. for I := 0 to CacheNodes.Count - 1 do
  770. begin
  771. Node := TAllPhaseCacheNode(CacheNodes.Items[I]);
  772. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  773. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  774. end;
  775. sgs.SaveToFile(AFileName);
  776. finally
  777. sgs.Free;
  778. end;
  779. end;
  780. { TGclCacheTree }
  781. function TGclCacheTree.AddNodeByB_Code(
  782. const AB_Code: string): TGclCacheNode;
  783. function FindParent: TGclCacheNode;
  784. begin
  785. Result := FLastNode;
  786. while Assigned(Result) and (Result <> Root) and (Result.B_Code <> '') and (Pos(Result.B_Code + '-', AB_Code) <> 1) do
  787. Result := TGclCacheNode(Result.Parent);
  788. end;
  789. var
  790. vParent: TGclCacheNode;
  791. begin
  792. vParent := FindParent;
  793. Result := TGclCacheNode(AddNode(vParent));
  794. FLastNode := Result;
  795. end;
  796. function TGclCacheTree.AddNodeByData(const AB_Code,
  797. AName: string): TGclCacheNode;
  798. begin
  799. if AB_Code = '' then
  800. Result := AddNodeByName(AName)
  801. else
  802. Result := AddNodeByB_Code(AB_Code);
  803. end;
  804. function TGclCacheTree.AddNodeByName(const AName: string): TGclCacheNode;
  805. begin
  806. if Pos('第100章至', AName) <> 0 then
  807. begin
  808. Result := TGclCacheNode(AddNode(nil));
  809. FLastBlank1 := Result;
  810. end
  811. else
  812. Result := TGclCacheNode(AddNode(FLastBlank1));
  813. FLastNode := Result;
  814. end;
  815. function TGclCacheTree.GetNewNode: TCacheNode;
  816. begin
  817. Result := TGclCacheNode.Create(Self, GetNewNodeID);
  818. CacheNodes.Add(Result);
  819. end;
  820. procedure TGclCacheTree.SaveTreeToFile(const AFileName: string);
  821. var
  822. sgs: TStringList;
  823. I: Integer;
  824. Node: TGclCacheNode;
  825. begin
  826. sgs := TStringList.Create;
  827. try
  828. for I := 0 to CacheNodes.Count - 1 do
  829. begin
  830. Node := TGclCacheNode(CacheNodes.Items[I]);
  831. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; B_Code: %s; Name: %s;',
  832. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.B_Code, Node.Name]));
  833. end;
  834. sgs.SaveToFile(AFileName);
  835. finally
  836. sgs.Free;
  837. end;
  838. end;
  839. end.