MCacheTree.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  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. FLastBlankNode: TCacheNode;
  44. FSeparateChar: Char;
  45. FAutoSort: Boolean;
  46. FFixedIDNodes: TList;
  47. function GetNewNode(AID: Integer = -1): TBillsCacheNode; overload;
  48. function FindNode(const ACode: string): TBillsCacheNode; overload;
  49. function FindNode(AParent: TBillsCacheNode; const ACode: string): TBillsCacheNode; overload;
  50. function FindFxNode(const ACode, AName: string): TBillsCacheNode; overload;
  51. function FindFxNode(AParent: TBillsCacheNode; const ACode, AName: string): TBillsCacheNode; overload;
  52. function FindParent(const ACode: string): TBillsCacheNode;
  53. function FindNextSibling(const ACode: string): TBillsCacheNode;
  54. procedure SetSeparateChar(const Value: Char);
  55. public
  56. constructor Create; override;
  57. destructor Destroy; override;
  58. function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil; AFixedID: Integer = -1): TBillsCacheNode;
  59. function AddNodeByCode(const ACode: string; AFixedID: Integer = -1): TBillsCacheNode;
  60. function AddNodeByCodeName(const ACode, AName: string): TBillsCacheNode;
  61. function AddLeafBillsNode(const AB_Code: string): TBillsCacheNode;
  62. function FindXmjChild(AParent: TBillsCacheNode; const ACode, AName: string): TBillsCacheNode;
  63. function FindGclChild(AParent: TBillsCacheNode; const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;
  64. function FindFixedIDNode(AID: Integer): TBillsCacheNode;
  65. // Only for Debugging lot of Data
  66. procedure SaveTreeToFile(const AFileName: string);
  67. property SeparateChar: Char read FSeparateChar write SetSeparateChar;
  68. property AutoSort: Boolean read FAutoSort write FAutoSort;
  69. property FixedIDNodes: TList read FFixedIDNodes;
  70. end;
  71. // 此树仅用于导入工程量清单,禁止作为它用
  72. // 如须使用应遵守以下两点:1.完全清楚相关的导入方法类及需求 2.派生子类。
  73. TGclCacheNode = class(TCacheNode)
  74. private
  75. FB_Code: string;
  76. FName: string;
  77. FUnits: string;
  78. FPrice: Double;
  79. FQuantity: Double;
  80. public
  81. property B_Code: string read FB_Code write FB_Code;
  82. property Name: string read FName write FName;
  83. property Units: string read FUnits write FUnits;
  84. property Price: Double read FPrice write FPrice;
  85. property Quantity: Double read FQuantity write FQuantity;
  86. end;
  87. TGclCacheTree = class(TCacheTree)
  88. private
  89. FLastBlank1: TGclCacheNode;
  90. FLastNode: TGclCacheNode;
  91. function AddNodeByName(const AName: string): TGclCacheNode;
  92. function AddNodeByB_Code(const AB_Code: string): TGclCacheNode;
  93. protected
  94. function GetNewNode: TCacheNode; override;
  95. public
  96. function AddNodeByData(const AB_Code, AName: string): TGclCacheNode;
  97. procedure SaveTreeToFile(const AFileName: string);
  98. end;
  99. {For Report Memory(Gather or Compare Projects)}
  100. TDoubleArray = array of Double;
  101. TReportCacheNode = class(TCacheNode)
  102. private
  103. FCode: string;
  104. FB_Code: string;
  105. FName: string;
  106. FUnits: string;
  107. FMemoStr: string;
  108. FXiangCode: string;
  109. FMuCode: string;
  110. FJieCode: string;
  111. FXiMuCode: string;
  112. FPrice: Double;
  113. FQuantity: Double;
  114. FTotalPrice: Double;
  115. FRatioPercent: Double; // 0号台账 - 各项费用所占比例
  116. FDesignQuantity1: Double;
  117. FDesignQuantity2: Double;
  118. FAddQcQuantity: Double;
  119. FAddPcTotalPrice: Double;
  120. FAddQcTotalPrice: Double;
  121. FAddDealQuantity: Double;
  122. FAddDealTotalPrice: Double;
  123. FAddPcQuantity: Double;
  124. FAddRatioPercent: Double; // 决算 - 各项费用所占比例
  125. FDealDesignQuantity1: Double;
  126. FDealDesignQuantity2: Double;
  127. FCDesignQuantity1: Double;
  128. FCDesignQuantity2: Double;
  129. FPDQuantity: Double;
  130. FPDTotalPrice: Double;
  131. FPDDesignQuantity1: Double;
  132. FPDDesignQuantity2: Double;
  133. FPDDesignPrice: Double;
  134. FCDDQuantity: Double;
  135. FCDDTotalPrice: Double;
  136. FCDDDesignQuantity1: Double;
  137. FCDDDesignQuantity2: Double;
  138. FCDDDesignPrice: Double;
  139. FABTotalPrice: Double;
  140. FABQuantity: Double;
  141. FABDesignQuantity1: Double;
  142. FABDesignQuantity2: Double;
  143. FABDesignPrice: Double;
  144. FProjectCount: Integer;
  145. FP_TotalPrice: TDoubleArray;
  146. FP_Quantity: TDoubleArray;
  147. FP_Price: TDoubleArray;
  148. FP_DgnQuantity1: TDoubleArray;
  149. FP_DgnQuantity2: TDoubleArray;
  150. procedure ResolveCode;
  151. function GetDoubleArrayTotal(ADoubleArray: TDoubleArray): Double;
  152. procedure SetCode(const Value: string);
  153. function GetGatherP_TotalPrice: Double;
  154. function GetAddGatherQuantity: Double;
  155. function GetAddGatherTotalPrice: Double;
  156. public
  157. constructor Create(ACacheTree: TCacheTree; AID, AProjectCount: Integer);
  158. property Code: string read FCode write SetCode;
  159. property B_Code: string read FB_Code write FB_Code;
  160. property Name: string read FName write FName;
  161. property Units: string read FUnits write FUnits;
  162. property MemoStr: string read FMemoStr write FMemoStr;
  163. property XiangCode: string read FXiangCode;
  164. property MuCode: string read FMuCode;
  165. property JieCode: string read FJieCode;
  166. property XiMuCode: string read FXiMuCode;
  167. // 用于汇总多个项目的合同、变更(数量、金额)
  168. property Price: Double read FPrice write FPrice;
  169. // 0号台账合同
  170. property Quantity: Double read FQuantity write FQuantity;
  171. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  172. property RatioPercent: Double read FRatioPercent write FRatioPercent;
  173. property DesignQuantity1: Double read FDesignQuantity1 write FDesignQuantity1;
  174. property DesignQuantity2: Double read FDesignQuantity2 write FDesignQuantity2;
  175. // 累计各值
  176. property AddDealQuantity: Double read FAddDealQuantity write FAddDealQuantity;
  177. property AddDealTotalPrice: Double read FAddDealTotalPrice write FAddDealTotalPrice;
  178. property AddQcQuantity: Double read FAddQcQuantity write FAddQcQuantity;
  179. property AddQcTotalPrice: Double read FAddQcTotalPrice write FAddQcTotalPrice;
  180. property AddPcQuantity: Double read FAddPcQuantity write FAddPcQuantity;
  181. property AddPcTotalPrice: Double read FAddPcTotalPrice write FAddPcTotalPrice;
  182. property AddGatherQuantity: Double read GetAddGatherQuantity;
  183. property AddGatherTotalPrice: Double read GetAddGatherTotalPrice;
  184. property AddRatioPercent: Double read FAddRatioPercent write FAddRatioPercent;
  185. // 合同&变更 设计数量
  186. property DealDesignQuantity1: Double read FDealDesignQuantity1 write FDealDesignQuantity1;
  187. property DealDesignQuantity2: Double read FDealDesignQuantity2 write FDealDesignQuantity2;
  188. property CDesignQuantity1: Double read FCDesignQuantity1 write FCDesignQuantity1;
  189. property CDesignQuantity2: Double read FCDesignQuantity2 write FCDesignQuantity2;
  190. // ----仅用于汇总生成决算02表----
  191. // 初步设计 Preliminary Design
  192. property PDQuantity: Double read FPDQuantity write FPDQuantity;
  193. property PDTotalPrice: Double read FPDTotalPrice write FPDTotalPrice;
  194. property PDDesignQuantity1: Double read FPDDesignQuantity1 write FPDDesignQuantity1;
  195. property PDDesignQuantity2: Double read FPDDesignQuantity2 write FPDDesignQuantity2;
  196. property PDDesignPrice: Double read FPDDesignPrice write FPDDesignPrice;
  197. // 施工图设计 Construction Drawing Design
  198. property CDDQuantity: Double read FCDDQuantity write FCDDQuantity;
  199. property CDDTotalPrice: Double read FCDDTotalPrice write FCDDTotalPrice;
  200. property CDDDesignQuantity1: Double read FCDDDesignQuantity1 write FCDDDesignQuantity1;
  201. property CDDDesignQuantity2: Double read FCDDDesignQuantity2 write FCDDDesignQuantity2;
  202. property CDDDesignPrice: Double read FCDDDesignPrice write FCDDDesignPrice;
  203. // ------------------------------
  204. // ----仅用于汇总生成决算02表(部颁)----
  205. // 批准概(预算)算 Approved Budget
  206. property ABQuantity: Double read FABQuantity write FABQuantity;
  207. property ABTotalPrice: Double read FABTotalPrice write FABTotalPrice;
  208. property ABDesignQuantity1: Double read FABDesignQuantity1 write FABDesignQuantity1;
  209. property ABDesignQuantity2: Double read FABDesignQuantity2 write FABDesignQuantity2;
  210. property ABDesignPrice: Double read FABDesignPrice write FABDesignPrice;
  211. // ------------------------------------
  212. // 用于记录多个项目的数量、单价、金额、设计数量
  213. property P_Price: TDoubleArray read FP_Price write FP_Price;
  214. property P_Quantity: TDoubleArray read FP_Quantity write FP_Quantity;
  215. property P_TotalPrice: TDoubleArray read FP_TotalPrice write FP_TotalPrice;
  216. property P_DgnQuantity1: TDoubleArray read FP_DgnQuantity1 write FP_DgnQuantity1;
  217. property P_DgnQuantity2: TDoubleArray read FP_DgnQuantity2 write FP_DgnQuantity2;
  218. property GatherP_TotalPrice: Double read GetGatherP_TotalPrice;
  219. property ProjectCount: Integer read FProjectCount;
  220. end;
  221. TStringArray = array of string;
  222. TReportCacheTree = class(TCacheTree)
  223. private
  224. FProjectCount: Integer;
  225. FGatherCacheNode: TReportCacheNode;
  226. FProjectName: TStringArray;
  227. function GetNewNode(AProjectCount: Integer): TReportCacheNode; overload;
  228. public
  229. constructor Create(AProjectCount: Integer);
  230. destructor Destroy; override;
  231. function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil): TReportCacheNode;
  232. function FindNextSibling(AParent: TCacheNode; ACode, AB_Code: string): TReportCacheNode;
  233. function FindNode(AParent: TCacheNode; ACode, AB_Code: string): TReportCacheNode; overload;
  234. function FindNode(AParent: TCacheNode; AName: string): TReportCacheNode; overload;
  235. function FindNode(AParent: TCacheNode; ACode, AB_Code, AName: string): TReportCacheNode; overload;
  236. procedure ReCalcGatherData;
  237. // 调用此方法先须先调用ReCalcGatherData
  238. // RatioPercent = 金额/总金额,这里的总金额取GatherCacheNode的金额,故须先汇总计算GatherCacheNode。
  239. procedure ReCalcRatioPercent;
  240. // Only for Debugging lot of Data
  241. procedure SaveTreeToFile(const AFileName: string);
  242. property ProjectCount: Integer read FProjectCount;
  243. property GatherCacheNode: TReportCacheNode read FGatherCacheNode;
  244. property ProjectName: TStringArray read FProjectName write FProjectName;
  245. end;
  246. TapDoubleArray = array [1..50] of Double;
  247. TAllPhaseCacheNode = class(TCacheNode)
  248. private
  249. FCode: string;
  250. FB_Code: string;
  251. FName: string;
  252. FUnits: string;
  253. FPrice: Double;
  254. FQuantity: Double;
  255. FTotalPrice: Double;
  256. FMemoStr: string;
  257. public
  258. FP_Quantity: TapDoubleArray;
  259. FP_TotalPrice: TapDoubleArray;
  260. property Code: string read FCode write FCode;
  261. property B_Code: string read FB_Code write FB_Code;
  262. property Name: string read FName write FName;
  263. property Units: string read FUnits write FUnits;
  264. property Price: Double read FPrice write FPrice;
  265. property Quantity: Double read FQuantity write FQuantity;
  266. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  267. property MemoStr: string read FMemoStr write FMemoStr;
  268. end;
  269. // 仅用于汇总同一项目的不同期数据
  270. TAllPhaseCacheTree = class(TCacheTree)
  271. private
  272. function GetNewNode(AID: Integer): TAllPhaseCacheNode;
  273. public
  274. function AddNode(AID: Integer; AParent: TCacheNode; ANextSibling: TCacheNode = nil): TAllPhaseCacheNode;
  275. function FindNode(AID: Integer): TAllPhaseCacheNode;
  276. // Only for Debugging lot of Data
  277. procedure SaveTreeToFile(const AFileName: string);
  278. end;
  279. TSpecPhaseCacheNode = class(TCacheNode)
  280. private
  281. FCode: string;
  282. FB_Code: string;
  283. FName: string;
  284. FUnits: string;
  285. FDgnQty1: Double;
  286. FDgnQty2: Double;
  287. FTotalPrice: Double;
  288. FEndDealTotalPrice: Double;
  289. FEndQcTotalPrice: Double;
  290. FhtDgnQty1: Double;
  291. FhtDgnQty2: Double;
  292. FbgDgnQty1: Double;
  293. FbgDgnQty2: Double;
  294. FcbDgnQty1: Double;
  295. FcbDgnQty2: Double;
  296. FcbTotalPrice: Double;
  297. FsscDgnQty1: Double;
  298. FsscDgnQty2: Double;
  299. FsscTotalPrice: Double;
  300. FshtDgnQty1: Double;
  301. FshtDgnQty2: Double;
  302. FshtTotalPrice: Double;
  303. public
  304. property Code: string read FCode write FCode;
  305. property B_Code: string read FB_Code write FB_Code;
  306. property Name: string read FName write FName;
  307. property Units: string read FUnits write FUnits;
  308. property DgnQty1: Double read FDgnQty1 write FDgnQty1;
  309. property DgnQty2: Double read FDgnQty2 write FDgnQty2;
  310. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  311. property EndDealTotalPrice: Double read FEndDealTotalPrice write FEndDealTotalPrice;
  312. property EndQcTotalPrice: Double read FEndQcTotalPrice write FEndQcTotalPrice;
  313. property htDgnQty1: Double read FhtDgnQty1 write FhtDgnQty1;
  314. property htDgnQty2: Double read FhtDgnQty2 write FhtDgnQty2;
  315. property bgDgnQty1: Double read FbgDgnQty1 write FbgDgnQty1;
  316. property bgDgnQty2: Double read FbgDgnQty2 write FbgDgnQty2;
  317. property cbDgnQty1: Double read FcbDgnQty1 write FcbDgnQty1;
  318. property cbDgnQty2: Double read FcbDgnQty2 write FcbDgnQty2;
  319. property cbTotalPrice: Double read FcbTotalPrice write FcbTotalPrice;
  320. property sscDgnQty1: Double read FsscDgnQty1 write FsscDgnQty1;
  321. property sscDgnQty2: Double read FsscDgnQty2 write FsscDgnQty2;
  322. property sscTotalPrice: Double read FsscTotalPrice write FsscTotalPrice;
  323. property shtDgnQty1: Double read FshtDgnQty1 write FshtDgnQty1;
  324. property shtDgnQty2: Double read FshtDgnQty2 write FshtDgnQty2;
  325. property shtTotalPrice: Double read FshtTotalPrice write FshtTotalPrice;
  326. end;
  327. TSpecPhaseCacheTree = class(TCacheTree)
  328. private
  329. function GetNewNode: TSpecPhaseCacheNode;
  330. public
  331. function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil): TSpecPhaseCacheNode;
  332. function FindNextSibling(AParent: TCacheNode; ACode, AB_Code: string): TSpecPhaseCacheNode;
  333. function FindNode(AParent: TCacheNode; ACode, AB_Code: string): TSpecPhaseCacheNode; overload;
  334. function FindNode(AParent: TCacheNode; AName: string): TSpecPhaseCacheNode; overload;
  335. function FindNode(AParent: TCacheNode; ACode, AB_Code, AName: string): TSpecPhaseCacheNode; overload;
  336. end;
  337. implementation
  338. uses
  339. SysUtils, UtilMethods;
  340. { TBillsCacheTree }
  341. function TBillsCacheTree.AddNodeByCode(const ACode: string;
  342. AFixedID: Integer): TBillsCacheNode;
  343. var
  344. Parent, NextSibling: TBillsCacheNode;
  345. begin
  346. Result := FindNode(ACode);
  347. if Assigned(Result) then
  348. begin
  349. FLastNode := Result;
  350. Exit;
  351. end;
  352. Parent := FindParent(ACode);
  353. if AutoSort then
  354. NextSibling := FindNextSibling(ACode)
  355. else
  356. NextSibling := nil;
  357. Result := AddNode(Parent, NextSibling, AFixedID);
  358. Result.FLevelCode := ACode;
  359. FLastNode := Result;
  360. end;
  361. function TBillsCacheTree.FindNode(const ACode: string): TBillsCacheNode;
  362. begin
  363. Result := FindNode(TBillsCacheNode(Root), ACode);
  364. end;
  365. function TBillsCacheTree.FindNextSibling(
  366. const ACode: string): TBillsCacheNode;
  367. var
  368. Parent, Node: TBillsCacheNode;
  369. sCodeID, sCodeID2: string;
  370. begin
  371. Parent := FindParent(ACode);
  372. if Assigned(Parent) then
  373. Node := TBillsCacheNode(Parent.FirstChild)
  374. else
  375. Node := TBillsCacheNode(Root.FirstChild);
  376. Result := nil;
  377. sCodeID := ConvertDigitCode(ACode, 3, '-');
  378. while Assigned(Node) do
  379. begin
  380. sCodeID2 := ConvertDigitCode(Node.LevelCode, 3, SeparateChar);
  381. if sCodeID < sCodeID2 then
  382. begin
  383. Result := Node;
  384. Break;
  385. end;
  386. Node := TBillsCacheNode(Node.NextSibling);
  387. end;
  388. end;
  389. function TBillsCacheTree.FindNode(AParent: TBillsCacheNode;
  390. const ACode: string): TBillsCacheNode;
  391. begin
  392. Result := TBillsCacheNode(AParent.FirstChild);
  393. while Assigned(Result) do
  394. begin
  395. if Result.LevelCode = ACode then
  396. Break
  397. else if Pos(Result.LevelCode + SeparateChar, ACode) = 1 then
  398. begin
  399. Result := FindNode(Result, ACode);
  400. Break;
  401. end
  402. else
  403. Result := TBillsCacheNode(Result.NextSibling);
  404. end;
  405. end;
  406. function TBillsCacheTree.FindParent(const ACode: string): TBillsCacheNode;
  407. var
  408. sCode: string;
  409. begin
  410. Result := nil;
  411. sCode := GetPrefixOfCode(ACode, SeparateChar);
  412. while (Result = nil) and (sCode <> '') do
  413. begin
  414. Result := FindNode(sCode);
  415. sCode := GetPrefixOfCode(sCode, SeparateChar);
  416. end;
  417. end;
  418. function TBillsCacheTree.GetNewNode(AID: Integer): TBillsCacheNode;
  419. begin
  420. if AID = -1 then
  421. Result := TBillsCacheNode.Create(Self, GetNewNodeID)
  422. else
  423. Result := TBillsCacheNode.Create(Self, AID);
  424. CacheNodes.Add(Result);
  425. if Result.ID < 100 then
  426. FFixedIDNodes.Add(Result);
  427. end;
  428. function TBillsCacheTree.AddNode(AParent, ANextSibling: TCacheNode;
  429. AFixedID: Integer): TBillsCacheNode;
  430. begin
  431. Result := GetNewNode(AFixedID);
  432. if Assigned(ANextSibling) then
  433. ANextSibling.InsertPreSibling(Result)
  434. else if Assigned(AParent) then
  435. AParent.InsertChild(Result)
  436. else
  437. Root.InsertChild(Result);
  438. end;
  439. function TBillsCacheTree.AddLeafBillsNode(const AB_Code: string): TBillsCacheNode;
  440. function GetLastXmjParent: TBillsCacheNode;
  441. begin
  442. Result := TBillsCacheNode(FLastNode);
  443. while Assigned(Result) and Assigned(Result.Parent) and (Result.B_Code <> '') do
  444. Result := TBillsCacheNode(Result.Parent);
  445. end;
  446. function FindParent(AParent: TBillsCacheNode;
  447. const ACode: string): TBillsCacheNode;
  448. var
  449. i: Integer;
  450. sCode: string;
  451. begin
  452. Result := AParent;
  453. sCode := GetPrefixOfCode(ACode, SeparateChar);
  454. while (sCode <> '') do
  455. begin
  456. for i:= 0 to AParent.Children.Count - 1 do
  457. begin
  458. if TBillsCacheNode(AParent.Children.Items[i]).B_Code = ACode then
  459. begin
  460. Result := TBillsCacheNode(AParent.Children.Items[i]);
  461. Break;
  462. end;
  463. end;
  464. sCode := GetPrefixOfCode(sCode, SeparateChar);
  465. end;
  466. end;
  467. function FindNextSibling(AParent: TBillsCacheNode;
  468. const ACode: string): TBillsCacheNode;
  469. var
  470. Node: TBillsCacheNode;
  471. sCodeID, sCodeID2: string;
  472. begin
  473. Node := TBillsCacheNode(AParent.FirstChild);
  474. Result := nil;
  475. sCodeID := ConvertDigitCode(ACode, 3, '-');
  476. while Assigned(Node) do
  477. begin
  478. sCodeID2 := ConvertDigitCode(Node.LevelCode, 3, SeparateChar);
  479. if sCodeID < sCodeID2 then
  480. begin
  481. Result := Node;
  482. Break;
  483. end;
  484. Node := TBillsCacheNode(Node.NextSibling);
  485. end;
  486. end;
  487. function AddNodeByParent(AParent: TBillsCacheNode;
  488. const ACode: string): TBillsCacheNode;
  489. var
  490. Parent, NextSibling: TBillsCacheNode;
  491. begin
  492. Parent := FindParent(AParent, ACode);
  493. if AutoSort then
  494. NextSibling := FindNextSibling(AParent, ACode)
  495. else
  496. NextSibling := nil;
  497. Result := AddNode(Parent, NextSibling);
  498. Result.FLevelCode := ACode;
  499. end;
  500. var
  501. Parent: TBillsCacheNode;
  502. begin
  503. Parent := GetLastXmjParent;
  504. Result := AddNodeByParent(Parent, AB_Code);
  505. end;
  506. procedure TBillsCacheTree.SetSeparateChar(const Value: Char);
  507. var
  508. I: Integer;
  509. Node: TBillsCacheNode;
  510. begin
  511. for I := 0 to CacheNodes.Count - 1 do
  512. begin
  513. Node := TBillsCacheNode(CacheNodes.Items[I]);
  514. Node.FLevelCode := StringReplace(Node.FLevelCode, FSeparateChar, Value, [rfReplaceAll]);
  515. end;
  516. FSeparateChar := Value;
  517. end;
  518. procedure TBillsCacheTree.SaveTreeToFile(const AFileName: string);
  519. var
  520. sgs: TStringList;
  521. I: Integer;
  522. Node: TBillsCacheNode;
  523. begin
  524. sgs := TStringList.Create;
  525. try
  526. for I := 0 to CacheNodes.Count - 1 do
  527. begin
  528. Node := TBillsCacheNode(CacheNodes.Items[I]);
  529. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  530. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  531. end;
  532. sgs.SaveToFile(AFileName);
  533. finally
  534. sgs.Free;
  535. end;
  536. end;
  537. function TBillsCacheTree.FindGclChild(AParent: TBillsCacheNode;
  538. const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;
  539. var
  540. vChild: TBillsCacheNode;
  541. begin
  542. Result := nil;
  543. if Assigned(AParent) then
  544. vChild := TBillsCacheNode(AParent.FirstChild)
  545. else
  546. vChild := TBillsCacheNode(Root.FirstChild);
  547. while Assigned(vChild) and not Assigned(Result) do
  548. begin
  549. if SameText(AB_Code, vChild.B_Code) and
  550. SameText(AName, vChild.Name) and
  551. SameText(AUnits, vChild.Units) and
  552. (APrice = vChild.Price) then
  553. Result := vChild;
  554. vChild := TBillsCacheNode(vChild.NextSibling);
  555. end;
  556. end;
  557. function TBillsCacheTree.FindXmjChild(AParent: TBillsCacheNode;
  558. const ACode, AName: string): TBillsCacheNode;
  559. var
  560. vChild: TBillsCacheNode;
  561. begin
  562. Result := nil;
  563. if Assigned(AParent) then
  564. vChild := TBillsCacheNode(AParent.FirstChild)
  565. else
  566. vChild := TBillsCacheNode(Root.FirstChild);
  567. while Assigned(vChild) and not Assigned(Result) do
  568. begin
  569. if SameText(ACode, vChild.Code) and SameText(AName, vChild.Name) then
  570. Result := vChild;
  571. vChild := TBillsCacheNode(vChild.NextSibling);
  572. end;
  573. end;
  574. constructor TBillsCacheTree.Create;
  575. begin
  576. inherited;
  577. FFixedIDNodes := TList.Create;
  578. end;
  579. destructor TBillsCacheTree.Destroy;
  580. begin
  581. FFixedIDNodes.Free;
  582. inherited;
  583. end;
  584. function TBillsCacheTree.FindFixedIDNode(AID: Integer): TBillsCacheNode;
  585. var
  586. iNode: Integer;
  587. vNode: TCacheNode;
  588. begin
  589. Result := nil;
  590. for iNode := 0 to FFixedIDNodes.Count - 1 do
  591. begin
  592. vNode := TCacheNode(FFixedIDNodes.Items[iNode]);
  593. if vNode.ID = AID then
  594. begin
  595. Result := TBillsCacheNode(vNode);
  596. Break;
  597. end;
  598. end;
  599. end;
  600. function TBillsCacheTree.AddNodeByCodeName(const ACode, AName: string): TBillsCacheNode;
  601. var
  602. Parent, NextSibling: TBillsCacheNode;
  603. begin
  604. Result := FindFxNode(ACode, AName);
  605. if Assigned(Result) then
  606. begin
  607. FLastNode := Result;
  608. if (ACode = '') then FLastBlankNode := Result;
  609. Exit;
  610. end;
  611. NextSibling := nil;
  612. if Pos('-', ACode) > 0 then
  613. begin
  614. Parent := FindParent(ACode);
  615. if AutoSort then
  616. NextSibling := FindNextSibling(ACode);
  617. end
  618. else if (AName = '其他费用项目') or (AName = '建设期贷款利息') or (Pos('公路功能以外的工程费用', AName) > 0) then
  619. Parent := TBillsCacheNode(Root)
  620. else
  621. Parent := TBillsCacheNode(FLastBlankNode);
  622. Result := AddNode(Parent, NextSibling);
  623. Result.FLevelCode := ACode;
  624. FLastNode := Result;
  625. if (ACode = '') then FLastBlankNode := Result;
  626. end;
  627. function TBillsCacheTree.FindFxNode(const ACode,
  628. AName: string): TBillsCacheNode;
  629. var
  630. i: Integer;
  631. begin
  632. if (ACode = '') then
  633. begin
  634. for i := 0 to CacheNodes.Count - 1 do
  635. begin
  636. Result := TBillsCacheNode(CacheNodes.Items[i]);
  637. if (Result.Code = ACode) And (Result.Name = AName) then
  638. Exit;
  639. end;
  640. Result := nil;
  641. end
  642. else
  643. Result := FindFxNode(TBillsCacheNode(Root), ACode, AName);
  644. end;
  645. function TBillsCacheTree.FindFxNode(AParent: TBillsCacheNode; const ACode,
  646. AName: string): TBillsCacheNode;
  647. begin
  648. Result := TBillsCacheNode(AParent.FirstChild);
  649. while Assigned(Result) do
  650. begin
  651. if (Result.Code = ACode) And (Result.Name = AName) then
  652. Break
  653. else if Pos(Result.LevelCode + SeparateChar, ACode) = 1 then
  654. begin
  655. Result := FindNode(Result, ACode);
  656. Break;
  657. end
  658. else
  659. Result := TBillsCacheNode(Result.NextSibling);
  660. end;
  661. end;
  662. { TReportCacheNode }
  663. constructor TReportCacheNode.Create(ACacheTree: TCacheTree; AID,
  664. AProjectCount: Integer);
  665. begin
  666. inherited Create(ACacheTree, AID);
  667. FProjectCount := AProjectCount;
  668. SetLength(FP_Quantity, AProjectCount);
  669. SetLength(FP_Price, AProjectCount);
  670. SetLength(FP_TotalPrice, AProjectCount);
  671. SetLength(FP_DgnQuantity1, AProjectCount);
  672. SetLength(FP_DgnQuantity2, AProjectCount);
  673. end;
  674. function TReportCacheNode.GetAddGatherQuantity: Double;
  675. begin
  676. Result := AddDealQuantity + AddQcQuantity;
  677. end;
  678. function TReportCacheNode.GetAddGatherTotalPrice: Double;
  679. begin
  680. Result := AddDealTotalPrice + AddQcTotalPrice + AddPcTotalPrice;
  681. end;
  682. function TReportCacheNode.GetDoubleArrayTotal(
  683. ADoubleArray: TDoubleArray): Double;
  684. var
  685. i: Integer;
  686. begin
  687. Result := 0;
  688. for i := Low(ADoubleArray) to High(ADoubleArray) do
  689. Result := Result + ADoubleArray[i];
  690. end;
  691. function TReportCacheNode.GetGatherP_TotalPrice: Double;
  692. begin
  693. Result := GetDoubleArrayTotal(FP_TotalPrice);
  694. end;
  695. procedure TReportCacheNode.ResolveCode;
  696. var
  697. sgs: TStrings;
  698. i: Integer;
  699. begin
  700. sgs := TStringList.Create;
  701. try
  702. sgs.Delimiter := '-';
  703. sgs.DelimitedText := FCode;
  704. FXiangCode := '';
  705. FMuCode := '';
  706. FJieCode := '';
  707. FXiMuCode := '';
  708. case sgs.Count of
  709. 1: FXiangCode := '';
  710. 2: FXiangCode := ChinessNum(StrToIntDef(sgs[1], 0));
  711. 3: FMuCode := sgs[2];
  712. 4: FJieCode := sgs[3];
  713. else
  714. begin
  715. for i := 4 to sgs.Count - 1 do
  716. if FXiMuCode = '' then
  717. FXiMuCode := sgs[i]
  718. else
  719. FXiMuCode := FXiMuCode + '-' + sgs[i];
  720. end;
  721. end;
  722. finally
  723. sgs.Free;
  724. end;
  725. end;
  726. procedure TReportCacheNode.SetCode(const Value: string);
  727. begin
  728. FCode := Value;
  729. ResolveCode;
  730. end;
  731. { TReportCacheTree }
  732. function TReportCacheTree.AddNode(AParent,
  733. ANextSibling: TCacheNode): TReportCacheNode;
  734. begin
  735. Result := GetNewNode(FProjectCount);
  736. if Assigned(ANextSibling) then
  737. ANextSibling.InsertPreSibling(Result)
  738. else if Assigned(AParent) then
  739. AParent.InsertChild(Result)
  740. else
  741. Root.InsertChild(Result);
  742. end;
  743. constructor TReportCacheTree.Create(AProjectCount: Integer);
  744. begin
  745. inherited Create;
  746. FProjectCount := AProjectCount;
  747. FGatherCacheNode := TReportCacheNode.Create(nil, -2, AProjectCount);
  748. SetLength(FProjectName, AProjectCount);
  749. end;
  750. destructor TReportCacheTree.Destroy;
  751. begin
  752. FGatherCacheNode.Free;
  753. inherited;
  754. end;
  755. function TReportCacheTree.FindNextSibling(AParent: TCacheNode; ACode,
  756. AB_Code: string): TReportCacheNode;
  757. var
  758. Node: TReportCacheNode;
  759. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  760. begin
  761. if Assigned(AParent) then
  762. Node := TReportCacheNode(AParent.FirstChild)
  763. else
  764. Node := TReportCacheNode(Root.FirstChild);
  765. Result := nil;
  766. if (ACode = '') and (AB_Code = '') then Exit;
  767. sCodeID := ConvertDigitCode(ACode, 3, '-');
  768. sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');
  769. while Assigned(Node) do
  770. begin
  771. sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');
  772. sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');
  773. if (sCodeID <> '') and (sCodeID < sCodeID2) then
  774. begin
  775. Result := Node;
  776. Break;
  777. end
  778. else if sB_CodeID < sB_CodeID2 then
  779. begin
  780. Result := Node;
  781. Break;
  782. end;
  783. Node := TReportCacheNode(Node.NextSibling);
  784. end;
  785. end;
  786. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode,
  787. AB_Code: string): TReportCacheNode;
  788. var
  789. Node: TReportCacheNode;
  790. begin
  791. if Assigned(AParent) then
  792. Node := TReportCacheNode(AParent.FirstChild)
  793. else
  794. Node := TReportCacheNode(Root.FirstChild);
  795. Result := nil;
  796. while Assigned(Node) do
  797. begin
  798. if (Node.Code = ACode) and (Node.B_Code = AB_Code) then
  799. begin
  800. Result := Node;
  801. Break;
  802. end;
  803. Node := TReportCacheNode(Node.NextSibling);
  804. end;
  805. end;
  806. function TReportCacheTree.FindNode(AParent: TCacheNode;
  807. AName: string): TReportCacheNode;
  808. var
  809. Node: TReportCacheNode;
  810. begin
  811. if Assigned(AParent) then
  812. Node := TReportCacheNode(AParent.FirstChild)
  813. else
  814. Node := TReportCacheNode(Root.FirstChild);
  815. Result := nil;
  816. while Assigned(Node) do
  817. begin
  818. if SameText(Node.Name, AName) then
  819. begin
  820. Result := Node;
  821. Break;
  822. end;
  823. Node := TReportCacheNode(Node.NextSibling);
  824. end;
  825. end;
  826. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,
  827. AName: string): TReportCacheNode;
  828. var
  829. Node: TReportCacheNode;
  830. begin
  831. if Assigned(AParent) then
  832. Node := TReportCacheNode(AParent.FirstChild)
  833. else
  834. Node := TReportCacheNode(Root.FirstChild);
  835. Result := nil;
  836. while Assigned(Node) do
  837. begin
  838. if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)
  839. and SameText(Node.Name, AName) then
  840. begin
  841. Result := Node;
  842. Break;
  843. end;
  844. Node := TReportCacheNode(Node.NextSibling);
  845. end;
  846. end;
  847. function TReportCacheTree.GetNewNode(
  848. AProjectCount: Integer): TReportCacheNode;
  849. begin
  850. Result := TReportCacheNode.Create(Self, GetNewNodeID, AProjectCount);
  851. CacheNodes.Add(Result);
  852. end;
  853. procedure TReportCacheTree.ReCalcGatherData;
  854. var
  855. i: Integer;
  856. CacheNode: TReportCacheNode;
  857. begin
  858. FGatherCacheNode.Free;
  859. FGatherCacheNode := TReportCacheNode.Create(nil, -2, FProjectCount);
  860. CacheNode := TReportCacheNode(FirstNode);
  861. while Assigned(CacheNode) do
  862. begin
  863. FGatherCacheNode.TotalPrice := FGatherCacheNode.TotalPrice + CacheNode.TotalPrice;
  864. FGatherCacheNode.AddDealTotalPrice := FGatherCacheNode.AddDealTotalPrice + CacheNode.AddDealTotalPrice;
  865. FGatherCacheNode.AddQcTotalPrice := FGatherCacheNode.AddQcTotalPrice + CacheNode.AddQcTotalPrice;
  866. FGatherCacheNode.AddPcTotalPrice := FGatherCacheNode.AddPcTotalPrice + CacheNode.AddPcTotalPrice;
  867. FGatherCacheNode.PDTotalPrice := FGatherCacheNode.PDTotalPrice + CacheNode.PDTotalPrice;
  868. FGatherCacheNode.CDDTotalPrice := FGatherCacheNode.CDDTotalPrice + CacheNode.CDDTotalPrice;
  869. FGatherCacheNode.ABTotalPrice := FGatherCacheNode.ABTotalPrice + CacheNode.ABTotalPrice;
  870. for i := 0 to FProjectCount - 1 do
  871. FGatherCacheNode.P_TotalPrice[i] := FGatherCacheNode.P_TotalPrice[i] + CacheNode.P_TotalPrice[i];
  872. CacheNode := TReportCacheNode(CacheNode.NextSibling);
  873. end;
  874. end;
  875. procedure TReportCacheTree.ReCalcRatioPercent;
  876. var
  877. i: Integer;
  878. CacheNode: TReportCacheNode;
  879. begin
  880. for i := 0 to CacheNodes.Count - 1 do
  881. begin
  882. CacheNode := TReportCacheNode(CacheNodes.Items[i]);
  883. if GatherCacheNode.TotalPrice <> 0 then
  884. CacheNode.RatioPercent := AdvRoundTo(CacheNode.TotalPrice/GatherCacheNode.TotalPrice*100);
  885. if GatherCacheNode.AddGatherTotalPrice <> 0 then
  886. CacheNode.AddRatioPercent := AdvRoundTo(CacheNode.AddGatherTotalPrice/GatherCacheNode.AddGatherTotalPrice*100);
  887. end;
  888. end;
  889. procedure TReportCacheTree.SaveTreeToFile(const AFileName: string);
  890. var
  891. sgs: TStringList;
  892. I: Integer;
  893. Node: TReportCacheNode;
  894. begin
  895. sgs := TStringList.Create;
  896. try
  897. for I := 0 to CacheNodes.Count - 1 do
  898. begin
  899. Node := TReportCacheNode(CacheNodes.Items[I]);
  900. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  901. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  902. end;
  903. sgs.SaveToFile(AFileName);
  904. finally
  905. sgs.Free;
  906. end;
  907. end;
  908. { TAllPhaseCacheTree }
  909. function TAllPhaseCacheTree.AddNode(AID: Integer; AParent,
  910. ANextSibling: TCacheNode): TAllPhaseCacheNode;
  911. begin
  912. Result := GetNewNode(AID);
  913. if Assigned(ANextSibling) then
  914. ANextSibling.InsertPreSibling(Result)
  915. else if Assigned(AParent) then
  916. AParent.InsertChild(Result)
  917. else
  918. Root.InsertChild(Result);
  919. end;
  920. function TAllPhaseCacheTree.FindNode(AID: Integer): TAllPhaseCacheNode;
  921. var
  922. i: Integer;
  923. Node: TAllPhaseCacheNode;
  924. begin
  925. Result := nil;
  926. for i := 0 to CacheNodes.Count - 1 do
  927. begin
  928. Node := TAllPhaseCacheNode(CacheNodes.Items[i]);
  929. if Node.ID = AID then
  930. begin
  931. Result := Node;
  932. Break;
  933. end;
  934. end;
  935. end;
  936. function TAllPhaseCacheTree.GetNewNode(
  937. AID: Integer): TAllPhaseCacheNode;
  938. begin
  939. Result := TAllPhaseCacheNode.Create(Self, AID);
  940. CacheNodes.Add(Result);
  941. end;
  942. procedure TAllPhaseCacheTree.SaveTreeToFile(const AFileName: string);
  943. var
  944. sgs: TStringList;
  945. I: Integer;
  946. Node: TAllPhaseCacheNode;
  947. begin
  948. sgs := TStringList.Create;
  949. try
  950. for I := 0 to CacheNodes.Count - 1 do
  951. begin
  952. Node := TAllPhaseCacheNode(CacheNodes.Items[I]);
  953. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  954. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  955. end;
  956. sgs.SaveToFile(AFileName);
  957. finally
  958. sgs.Free;
  959. end;
  960. end;
  961. { TGclCacheTree }
  962. function TGclCacheTree.AddNodeByB_Code(
  963. const AB_Code: string): TGclCacheNode;
  964. function FindParent: TGclCacheNode;
  965. begin
  966. Result := FLastNode;
  967. while Assigned(Result) and (Result <> Root) and (Result.B_Code <> '') and (Pos(Result.B_Code + '-', AB_Code) <> 1) do
  968. Result := TGclCacheNode(Result.Parent);
  969. end;
  970. var
  971. vParent: TGclCacheNode;
  972. begin
  973. vParent := FindParent;
  974. Result := TGclCacheNode(AddNode(vParent));
  975. FLastNode := Result;
  976. end;
  977. function TGclCacheTree.AddNodeByData(const AB_Code,
  978. AName: string): TGclCacheNode;
  979. begin
  980. if AB_Code = '' then
  981. Result := AddNodeByName(AName)
  982. else
  983. Result := AddNodeByB_Code(AB_Code);
  984. end;
  985. function TGclCacheTree.AddNodeByName(const AName: string): TGclCacheNode;
  986. begin
  987. if Pos('第100章至', AName) <> 0 then
  988. begin
  989. Result := TGclCacheNode(AddNode(nil));
  990. FLastBlank1 := Result;
  991. end
  992. else
  993. Result := TGclCacheNode(AddNode(FLastBlank1));
  994. FLastNode := Result;
  995. end;
  996. function TGclCacheTree.GetNewNode: TCacheNode;
  997. begin
  998. Result := TGclCacheNode.Create(Self, GetNewNodeID);
  999. CacheNodes.Add(Result);
  1000. end;
  1001. procedure TGclCacheTree.SaveTreeToFile(const AFileName: string);
  1002. var
  1003. sgs: TStringList;
  1004. I: Integer;
  1005. Node: TGclCacheNode;
  1006. begin
  1007. sgs := TStringList.Create;
  1008. try
  1009. for I := 0 to CacheNodes.Count - 1 do
  1010. begin
  1011. Node := TGclCacheNode(CacheNodes.Items[I]);
  1012. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; B_Code: %s; Name: %s;',
  1013. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.B_Code, Node.Name]));
  1014. end;
  1015. sgs.SaveToFile(AFileName);
  1016. finally
  1017. sgs.Free;
  1018. end;
  1019. end;
  1020. { TSpecPhaseCacheTree }
  1021. function TSpecPhaseCacheTree.AddNode(AParent,
  1022. ANextSibling: TCacheNode): TSpecPhaseCacheNode;
  1023. begin
  1024. Result := GetNewNode();
  1025. if Assigned(ANextSibling) then
  1026. ANextSibling.InsertPreSibling(Result)
  1027. else if Assigned(AParent) then
  1028. AParent.InsertChild(Result)
  1029. else
  1030. Root.InsertChild(Result);
  1031. end;
  1032. function TSpecPhaseCacheTree.FindNextSibling(AParent: TCacheNode; ACode,
  1033. AB_Code: string): TSpecPhaseCacheNode;
  1034. var
  1035. Node: TSpecPhaseCacheNode;
  1036. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  1037. begin
  1038. if Assigned(AParent) then
  1039. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1040. else
  1041. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1042. Result := nil;
  1043. if (ACode = '') and (AB_Code = '') then Exit;
  1044. sCodeID := ConvertDigitCode(ACode, 3, '-');
  1045. sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');
  1046. while Assigned(Node) do
  1047. begin
  1048. sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');
  1049. sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');
  1050. if (sCodeID <> '') and (sCodeID < sCodeID2) then
  1051. begin
  1052. Result := Node;
  1053. Break;
  1054. end
  1055. else if sB_CodeID < sB_CodeID2 then
  1056. begin
  1057. Result := Node;
  1058. Break;
  1059. end;
  1060. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1061. end;
  1062. end;
  1063. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode; ACode,
  1064. AB_Code: string): TSpecPhaseCacheNode;
  1065. var
  1066. Node: TSpecPhaseCacheNode;
  1067. begin
  1068. if Assigned(AParent) then
  1069. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1070. else
  1071. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1072. Result := nil;
  1073. while Assigned(Node) do
  1074. begin
  1075. if (Node.Code = ACode) and (Node.B_Code = AB_Code) then
  1076. begin
  1077. Result := Node;
  1078. Break;
  1079. end;
  1080. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1081. end;
  1082. end;
  1083. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode;
  1084. AName: string): TSpecPhaseCacheNode;
  1085. var
  1086. Node: TSpecPhaseCacheNode;
  1087. begin
  1088. if Assigned(AParent) then
  1089. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1090. else
  1091. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1092. Result := nil;
  1093. while Assigned(Node) do
  1094. begin
  1095. if SameText(Node.Name, AName) then
  1096. begin
  1097. Result := Node;
  1098. Break;
  1099. end;
  1100. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1101. end;
  1102. end;
  1103. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,
  1104. AName: string): TSpecPhaseCacheNode;
  1105. var
  1106. Node: TSpecPhaseCacheNode;
  1107. begin
  1108. if Assigned(AParent) then
  1109. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1110. else
  1111. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1112. Result := nil;
  1113. while Assigned(Node) do
  1114. begin
  1115. if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)
  1116. and SameText(Node.Name, AName) then
  1117. begin
  1118. Result := Node;
  1119. Break;
  1120. end;
  1121. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1122. end;
  1123. end;
  1124. function TSpecPhaseCacheTree.GetNewNode: TSpecPhaseCacheNode;
  1125. begin
  1126. Result := TSpecPhaseCacheNode.Create(Self, GetNewNodeID);
  1127. CacheNodes.Add(Result);
  1128. end;
  1129. end.