MCacheTree.pas 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  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. FTotalPrice: Double;
  286. FEndDealTotalPrice: Double;
  287. FEndQcTotalPrice: Double;
  288. FhtDgnQty1: Double;
  289. FhtDgnQty2: Double;
  290. FbgDgnQty1: Double;
  291. FbgDgnQty2: Double;
  292. FcbDgnQty1: Double;
  293. FcbDgnQty2: Double;
  294. FcbTotalPrice: Double;
  295. FsscDgnQty1: Double;
  296. FsscDgnQty2: Double;
  297. FsscTotalPrice: Double;
  298. FshtDgnQty1: Double;
  299. FshtDgnQty2: Double;
  300. FshtTotalPrice: Double;
  301. public
  302. property Code: string read FCode write FCode;
  303. property B_Code: string read FB_Code write FB_Code;
  304. property Name: string read FName write FName;
  305. property Units: string read FUnits write FUnits;
  306. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  307. property EndDealTotalPrice: Double read FEndDealTotalPrice write FEndDealTotalPrice;
  308. property EndQcTotalPrice: Double read FEndQcTotalPrice write FEndQcTotalPrice;
  309. property htDgnQty1: Double read FhtDgnQty1 write FhtDgnQty1;
  310. property htDgnQty2: Double read FhtDgnQty2 write FhtDgnQty2;
  311. property bgDgnQty1: Double read FbgDgnQty1 write FbgDgnQty1;
  312. property bgDgnQty2: Double read FbgDgnQty2 write FbgDgnQty2;
  313. property cbDgnQty1: Double read FcbDgnQty1 write FcbDgnQty1;
  314. property cbDgnQty2: Double read FcbDgnQty2 write FcbDgnQty2;
  315. property cbTotalPrice: Double read FcbTotalPrice write FcbTotalPrice;
  316. property sscDgnQty1: Double read FsscDgnQty1 write FsscDgnQty1;
  317. property sscDgnQty2: Double read FsscDgnQty2 write FsscDgnQty2;
  318. property sscTotalPrice: Double read FsscTotalPrice write FsscTotalPrice;
  319. property shtDgnQty1: Double read FshtDgnQty1 write FshtDgnQty1;
  320. property shtDgnQty2: Double read FshtDgnQty2 write FshtDgnQty2;
  321. property shtTotalPrice: Double read FshtTotalPrice write FshtTotalPrice;
  322. end;
  323. TSpecPhaseCacheTree = class(TCacheTree)
  324. private
  325. function GetNewNode: TSpecPhaseCacheNode;
  326. public
  327. function AddNode(AParent: TCacheNode; ANextSibling: TCacheNode = nil): TSpecPhaseCacheNode;
  328. function FindNextSibling(AParent: TCacheNode; ACode, AB_Code: string): TSpecPhaseCacheNode;
  329. function FindNode(AParent: TCacheNode; ACode, AB_Code: string): TSpecPhaseCacheNode; overload;
  330. function FindNode(AParent: TCacheNode; AName: string): TSpecPhaseCacheNode; overload;
  331. function FindNode(AParent: TCacheNode; ACode, AB_Code, AName: string): TSpecPhaseCacheNode; overload;
  332. end;
  333. implementation
  334. uses
  335. SysUtils, UtilMethods;
  336. { TBillsCacheTree }
  337. function TBillsCacheTree.AddNodeByCode(const ACode: string;
  338. AFixedID: Integer): TBillsCacheNode;
  339. var
  340. Parent, NextSibling: TBillsCacheNode;
  341. begin
  342. Result := FindNode(ACode);
  343. if Assigned(Result) then
  344. begin
  345. FLastNode := Result;
  346. Exit;
  347. end;
  348. Parent := FindParent(ACode);
  349. if AutoSort then
  350. NextSibling := FindNextSibling(ACode)
  351. else
  352. NextSibling := nil;
  353. Result := AddNode(Parent, NextSibling, AFixedID);
  354. Result.FLevelCode := ACode;
  355. FLastNode := Result;
  356. end;
  357. function TBillsCacheTree.FindNode(const ACode: string): TBillsCacheNode;
  358. begin
  359. Result := FindNode(TBillsCacheNode(Root), ACode);
  360. end;
  361. function TBillsCacheTree.FindNextSibling(
  362. const ACode: string): TBillsCacheNode;
  363. var
  364. Parent, Node: TBillsCacheNode;
  365. sCodeID, sCodeID2: string;
  366. begin
  367. Parent := FindParent(ACode);
  368. if Assigned(Parent) then
  369. Node := TBillsCacheNode(Parent.FirstChild)
  370. else
  371. Node := TBillsCacheNode(Root.FirstChild);
  372. Result := nil;
  373. sCodeID := ConvertDigitCode(ACode, 3, '-');
  374. while Assigned(Node) do
  375. begin
  376. sCodeID2 := ConvertDigitCode(Node.LevelCode, 3, SeparateChar);
  377. if sCodeID < sCodeID2 then
  378. begin
  379. Result := Node;
  380. Break;
  381. end;
  382. Node := TBillsCacheNode(Node.NextSibling);
  383. end;
  384. end;
  385. function TBillsCacheTree.FindNode(AParent: TBillsCacheNode;
  386. const ACode: string): TBillsCacheNode;
  387. begin
  388. Result := TBillsCacheNode(AParent.FirstChild);
  389. while Assigned(Result) do
  390. begin
  391. if Result.LevelCode = ACode then
  392. Break
  393. else if Pos(Result.LevelCode + SeparateChar, ACode) = 1 then
  394. begin
  395. Result := FindNode(Result, ACode);
  396. Break;
  397. end
  398. else
  399. Result := TBillsCacheNode(Result.NextSibling);
  400. end;
  401. end;
  402. function TBillsCacheTree.FindParent(const ACode: string): TBillsCacheNode;
  403. var
  404. sCode: string;
  405. begin
  406. Result := nil;
  407. sCode := GetPrefixOfCode(ACode, SeparateChar);
  408. while (Result = nil) and (sCode <> '') do
  409. begin
  410. Result := FindNode(sCode);
  411. sCode := GetPrefixOfCode(sCode, SeparateChar);
  412. end;
  413. end;
  414. function TBillsCacheTree.GetNewNode(AID: Integer): TBillsCacheNode;
  415. begin
  416. if AID = -1 then
  417. Result := TBillsCacheNode.Create(Self, GetNewNodeID)
  418. else
  419. Result := TBillsCacheNode.Create(Self, AID);
  420. CacheNodes.Add(Result);
  421. if Result.ID < 100 then
  422. FFixedIDNodes.Add(Result);
  423. end;
  424. function TBillsCacheTree.AddNode(AParent, ANextSibling: TCacheNode;
  425. AFixedID: Integer): TBillsCacheNode;
  426. begin
  427. Result := GetNewNode(AFixedID);
  428. if Assigned(ANextSibling) then
  429. ANextSibling.InsertPreSibling(Result)
  430. else if Assigned(AParent) then
  431. AParent.InsertChild(Result)
  432. else
  433. Root.InsertChild(Result);
  434. end;
  435. function TBillsCacheTree.AddLeafBillsNode(const AB_Code: string): TBillsCacheNode;
  436. function GetLastXmjParent: TBillsCacheNode;
  437. begin
  438. Result := TBillsCacheNode(FLastNode);
  439. while Assigned(Result) and Assigned(Result.Parent) and (Result.B_Code <> '') do
  440. Result := TBillsCacheNode(Result.Parent);
  441. end;
  442. function FindParent(AParent: TBillsCacheNode;
  443. const ACode: string): TBillsCacheNode;
  444. var
  445. i: Integer;
  446. sCode: string;
  447. begin
  448. Result := AParent;
  449. sCode := GetPrefixOfCode(ACode, SeparateChar);
  450. while (sCode <> '') do
  451. begin
  452. for i:= 0 to AParent.Children.Count - 1 do
  453. begin
  454. if TBillsCacheNode(AParent.Children.Items[i]).B_Code = ACode then
  455. begin
  456. Result := TBillsCacheNode(AParent.Children.Items[i]);
  457. Break;
  458. end;
  459. end;
  460. sCode := GetPrefixOfCode(sCode, SeparateChar);
  461. end;
  462. end;
  463. function FindNextSibling(AParent: TBillsCacheNode;
  464. const ACode: string): TBillsCacheNode;
  465. var
  466. Node: TBillsCacheNode;
  467. sCodeID, sCodeID2: string;
  468. begin
  469. Node := TBillsCacheNode(AParent.FirstChild);
  470. Result := nil;
  471. sCodeID := ConvertDigitCode(ACode, 3, '-');
  472. while Assigned(Node) do
  473. begin
  474. sCodeID2 := ConvertDigitCode(Node.LevelCode, 3, SeparateChar);
  475. if sCodeID < sCodeID2 then
  476. begin
  477. Result := Node;
  478. Break;
  479. end;
  480. Node := TBillsCacheNode(Node.NextSibling);
  481. end;
  482. end;
  483. function AddNodeByParent(AParent: TBillsCacheNode;
  484. const ACode: string): TBillsCacheNode;
  485. var
  486. Parent, NextSibling: TBillsCacheNode;
  487. begin
  488. Parent := FindParent(AParent, ACode);
  489. if AutoSort then
  490. NextSibling := FindNextSibling(AParent, ACode)
  491. else
  492. NextSibling := nil;
  493. Result := AddNode(Parent, NextSibling);
  494. Result.FLevelCode := ACode;
  495. end;
  496. var
  497. Parent: TBillsCacheNode;
  498. begin
  499. Parent := GetLastXmjParent;
  500. Result := AddNodeByParent(Parent, AB_Code);
  501. end;
  502. procedure TBillsCacheTree.SetSeparateChar(const Value: Char);
  503. var
  504. I: Integer;
  505. Node: TBillsCacheNode;
  506. begin
  507. for I := 0 to CacheNodes.Count - 1 do
  508. begin
  509. Node := TBillsCacheNode(CacheNodes.Items[I]);
  510. Node.FLevelCode := StringReplace(Node.FLevelCode, FSeparateChar, Value, [rfReplaceAll]);
  511. end;
  512. FSeparateChar := Value;
  513. end;
  514. procedure TBillsCacheTree.SaveTreeToFile(const AFileName: string);
  515. var
  516. sgs: TStringList;
  517. I: Integer;
  518. Node: TBillsCacheNode;
  519. begin
  520. sgs := TStringList.Create;
  521. try
  522. for I := 0 to CacheNodes.Count - 1 do
  523. begin
  524. Node := TBillsCacheNode(CacheNodes.Items[I]);
  525. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  526. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  527. end;
  528. sgs.SaveToFile(AFileName);
  529. finally
  530. sgs.Free;
  531. end;
  532. end;
  533. function TBillsCacheTree.FindGclChild(AParent: TBillsCacheNode;
  534. const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;
  535. var
  536. vChild: TBillsCacheNode;
  537. begin
  538. Result := nil;
  539. if Assigned(AParent) then
  540. vChild := TBillsCacheNode(AParent.FirstChild)
  541. else
  542. vChild := TBillsCacheNode(Root.FirstChild);
  543. while Assigned(vChild) and not Assigned(Result) do
  544. begin
  545. if SameText(AB_Code, vChild.B_Code) and
  546. SameText(AName, vChild.Name) and
  547. SameText(AUnits, vChild.Units) and
  548. (APrice = vChild.Price) then
  549. Result := vChild;
  550. vChild := TBillsCacheNode(vChild.NextSibling);
  551. end;
  552. end;
  553. function TBillsCacheTree.FindXmjChild(AParent: TBillsCacheNode;
  554. const ACode, AName: string): TBillsCacheNode;
  555. var
  556. vChild: TBillsCacheNode;
  557. begin
  558. Result := nil;
  559. if Assigned(AParent) then
  560. vChild := TBillsCacheNode(AParent.FirstChild)
  561. else
  562. vChild := TBillsCacheNode(Root.FirstChild);
  563. while Assigned(vChild) and not Assigned(Result) do
  564. begin
  565. if SameText(ACode, vChild.Code) and SameText(AName, vChild.Name) then
  566. Result := vChild;
  567. vChild := TBillsCacheNode(vChild.NextSibling);
  568. end;
  569. end;
  570. constructor TBillsCacheTree.Create;
  571. begin
  572. inherited;
  573. FFixedIDNodes := TList.Create;
  574. end;
  575. destructor TBillsCacheTree.Destroy;
  576. begin
  577. FFixedIDNodes.Free;
  578. inherited;
  579. end;
  580. function TBillsCacheTree.FindFixedIDNode(AID: Integer): TBillsCacheNode;
  581. var
  582. iNode: Integer;
  583. vNode: TCacheNode;
  584. begin
  585. Result := nil;
  586. for iNode := 0 to FFixedIDNodes.Count - 1 do
  587. begin
  588. vNode := TCacheNode(FFixedIDNodes.Items[iNode]);
  589. if vNode.ID = AID then
  590. begin
  591. Result := TBillsCacheNode(vNode);
  592. Break;
  593. end;
  594. end;
  595. end;
  596. function TBillsCacheTree.AddNodeByCodeName(const ACode, AName: string): TBillsCacheNode;
  597. var
  598. Parent, NextSibling: TBillsCacheNode;
  599. begin
  600. Result := FindFxNode(ACode, AName);
  601. if Assigned(Result) then
  602. begin
  603. FLastNode := Result;
  604. if (ACode = '') then FLastBlankNode := Result;
  605. Exit;
  606. end;
  607. NextSibling := nil;
  608. if Pos('-', ACode) > 0 then
  609. begin
  610. Parent := FindParent(ACode);
  611. if AutoSort then
  612. NextSibling := FindNextSibling(ACode);
  613. end
  614. else if (AName = '其他费用项目') or (AName = '建设期贷款利息') or (Pos('公路功能以外的工程费用', AName) > 0) then
  615. Parent := TBillsCacheNode(Root)
  616. else
  617. Parent := TBillsCacheNode(FLastBlankNode);
  618. Result := AddNode(Parent, NextSibling);
  619. Result.FLevelCode := ACode;
  620. FLastNode := Result;
  621. if (ACode = '') then FLastBlankNode := Result;
  622. end;
  623. function TBillsCacheTree.FindFxNode(const ACode,
  624. AName: string): TBillsCacheNode;
  625. var
  626. i: Integer;
  627. begin
  628. if (ACode = '') then
  629. begin
  630. for i := 0 to CacheNodes.Count - 1 do
  631. begin
  632. Result := TBillsCacheNode(CacheNodes.Items[i]);
  633. if (Result.Code = ACode) And (Result.Name = AName) then
  634. Exit;
  635. end;
  636. Result := nil;
  637. end
  638. else
  639. Result := FindFxNode(TBillsCacheNode(Root), ACode, AName);
  640. end;
  641. function TBillsCacheTree.FindFxNode(AParent: TBillsCacheNode; const ACode,
  642. AName: string): TBillsCacheNode;
  643. begin
  644. Result := TBillsCacheNode(AParent.FirstChild);
  645. while Assigned(Result) do
  646. begin
  647. if (Result.Code = ACode) And (Result.Name = AName) then
  648. Break
  649. else if Pos(Result.LevelCode + SeparateChar, ACode) = 1 then
  650. begin
  651. Result := FindNode(Result, ACode);
  652. Break;
  653. end
  654. else
  655. Result := TBillsCacheNode(Result.NextSibling);
  656. end;
  657. end;
  658. { TReportCacheNode }
  659. constructor TReportCacheNode.Create(ACacheTree: TCacheTree; AID,
  660. AProjectCount: Integer);
  661. begin
  662. inherited Create(ACacheTree, AID);
  663. FProjectCount := AProjectCount;
  664. SetLength(FP_Quantity, AProjectCount);
  665. SetLength(FP_Price, AProjectCount);
  666. SetLength(FP_TotalPrice, AProjectCount);
  667. SetLength(FP_DgnQuantity1, AProjectCount);
  668. SetLength(FP_DgnQuantity2, AProjectCount);
  669. end;
  670. function TReportCacheNode.GetAddGatherQuantity: Double;
  671. begin
  672. Result := AddDealQuantity + AddQcQuantity;
  673. end;
  674. function TReportCacheNode.GetAddGatherTotalPrice: Double;
  675. begin
  676. Result := AddDealTotalPrice + AddQcTotalPrice + AddPcTotalPrice;
  677. end;
  678. function TReportCacheNode.GetDoubleArrayTotal(
  679. ADoubleArray: TDoubleArray): Double;
  680. var
  681. i: Integer;
  682. begin
  683. Result := 0;
  684. for i := Low(ADoubleArray) to High(ADoubleArray) do
  685. Result := Result + ADoubleArray[i];
  686. end;
  687. function TReportCacheNode.GetGatherP_TotalPrice: Double;
  688. begin
  689. Result := GetDoubleArrayTotal(FP_TotalPrice);
  690. end;
  691. procedure TReportCacheNode.ResolveCode;
  692. var
  693. sgs: TStrings;
  694. i: Integer;
  695. begin
  696. sgs := TStringList.Create;
  697. try
  698. sgs.Delimiter := '-';
  699. sgs.DelimitedText := FCode;
  700. FXiangCode := '';
  701. FMuCode := '';
  702. FJieCode := '';
  703. FXiMuCode := '';
  704. case sgs.Count of
  705. 1: FXiangCode := '';
  706. 2: FXiangCode := ChinessNum(StrToIntDef(sgs[1], 0));
  707. 3: FMuCode := sgs[2];
  708. 4: FJieCode := sgs[3];
  709. else
  710. begin
  711. for i := 4 to sgs.Count - 1 do
  712. if FXiMuCode = '' then
  713. FXiMuCode := sgs[i]
  714. else
  715. FXiMuCode := FXiMuCode + '-' + sgs[i];
  716. end;
  717. end;
  718. finally
  719. sgs.Free;
  720. end;
  721. end;
  722. procedure TReportCacheNode.SetCode(const Value: string);
  723. begin
  724. FCode := Value;
  725. ResolveCode;
  726. end;
  727. { TReportCacheTree }
  728. function TReportCacheTree.AddNode(AParent,
  729. ANextSibling: TCacheNode): TReportCacheNode;
  730. begin
  731. Result := GetNewNode(FProjectCount);
  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. constructor TReportCacheTree.Create(AProjectCount: Integer);
  740. begin
  741. inherited Create;
  742. FProjectCount := AProjectCount;
  743. FGatherCacheNode := TReportCacheNode.Create(nil, -2, AProjectCount);
  744. SetLength(FProjectName, AProjectCount);
  745. end;
  746. destructor TReportCacheTree.Destroy;
  747. begin
  748. FGatherCacheNode.Free;
  749. inherited;
  750. end;
  751. function TReportCacheTree.FindNextSibling(AParent: TCacheNode; ACode,
  752. AB_Code: string): TReportCacheNode;
  753. var
  754. Node: TReportCacheNode;
  755. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  756. begin
  757. if Assigned(AParent) then
  758. Node := TReportCacheNode(AParent.FirstChild)
  759. else
  760. Node := TReportCacheNode(Root.FirstChild);
  761. Result := nil;
  762. if (ACode = '') and (AB_Code = '') then Exit;
  763. sCodeID := ConvertDigitCode(ACode, 3, '-');
  764. sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');
  765. while Assigned(Node) do
  766. begin
  767. sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');
  768. sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');
  769. if (sCodeID <> '') and (sCodeID < sCodeID2) then
  770. begin
  771. Result := Node;
  772. Break;
  773. end
  774. else if sB_CodeID < sB_CodeID2 then
  775. begin
  776. Result := Node;
  777. Break;
  778. end;
  779. Node := TReportCacheNode(Node.NextSibling);
  780. end;
  781. end;
  782. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode,
  783. AB_Code: string): TReportCacheNode;
  784. var
  785. Node: TReportCacheNode;
  786. begin
  787. if Assigned(AParent) then
  788. Node := TReportCacheNode(AParent.FirstChild)
  789. else
  790. Node := TReportCacheNode(Root.FirstChild);
  791. Result := nil;
  792. while Assigned(Node) do
  793. begin
  794. if (Node.Code = ACode) and (Node.B_Code = AB_Code) then
  795. begin
  796. Result := Node;
  797. Break;
  798. end;
  799. Node := TReportCacheNode(Node.NextSibling);
  800. end;
  801. end;
  802. function TReportCacheTree.FindNode(AParent: TCacheNode;
  803. AName: string): TReportCacheNode;
  804. var
  805. Node: TReportCacheNode;
  806. begin
  807. if Assigned(AParent) then
  808. Node := TReportCacheNode(AParent.FirstChild)
  809. else
  810. Node := TReportCacheNode(Root.FirstChild);
  811. Result := nil;
  812. while Assigned(Node) do
  813. begin
  814. if SameText(Node.Name, AName) then
  815. begin
  816. Result := Node;
  817. Break;
  818. end;
  819. Node := TReportCacheNode(Node.NextSibling);
  820. end;
  821. end;
  822. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,
  823. AName: string): TReportCacheNode;
  824. var
  825. Node: TReportCacheNode;
  826. begin
  827. if Assigned(AParent) then
  828. Node := TReportCacheNode(AParent.FirstChild)
  829. else
  830. Node := TReportCacheNode(Root.FirstChild);
  831. Result := nil;
  832. while Assigned(Node) do
  833. begin
  834. if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)
  835. and SameText(Node.Name, AName) then
  836. begin
  837. Result := Node;
  838. Break;
  839. end;
  840. Node := TReportCacheNode(Node.NextSibling);
  841. end;
  842. end;
  843. function TReportCacheTree.GetNewNode(
  844. AProjectCount: Integer): TReportCacheNode;
  845. begin
  846. Result := TReportCacheNode.Create(Self, GetNewNodeID, AProjectCount);
  847. CacheNodes.Add(Result);
  848. end;
  849. procedure TReportCacheTree.ReCalcGatherData;
  850. var
  851. i: Integer;
  852. CacheNode: TReportCacheNode;
  853. begin
  854. FGatherCacheNode.Free;
  855. FGatherCacheNode := TReportCacheNode.Create(nil, -2, FProjectCount);
  856. CacheNode := TReportCacheNode(FirstNode);
  857. while Assigned(CacheNode) do
  858. begin
  859. FGatherCacheNode.TotalPrice := FGatherCacheNode.TotalPrice + CacheNode.TotalPrice;
  860. FGatherCacheNode.AddDealTotalPrice := FGatherCacheNode.AddDealTotalPrice + CacheNode.AddDealTotalPrice;
  861. FGatherCacheNode.AddQcTotalPrice := FGatherCacheNode.AddQcTotalPrice + CacheNode.AddQcTotalPrice;
  862. FGatherCacheNode.AddPcTotalPrice := FGatherCacheNode.AddPcTotalPrice + CacheNode.AddPcTotalPrice;
  863. FGatherCacheNode.PDTotalPrice := FGatherCacheNode.PDTotalPrice + CacheNode.PDTotalPrice;
  864. FGatherCacheNode.CDDTotalPrice := FGatherCacheNode.CDDTotalPrice + CacheNode.CDDTotalPrice;
  865. FGatherCacheNode.ABTotalPrice := FGatherCacheNode.ABTotalPrice + CacheNode.ABTotalPrice;
  866. for i := 0 to FProjectCount - 1 do
  867. FGatherCacheNode.P_TotalPrice[i] := FGatherCacheNode.P_TotalPrice[i] + CacheNode.P_TotalPrice[i];
  868. CacheNode := TReportCacheNode(CacheNode.NextSibling);
  869. end;
  870. end;
  871. procedure TReportCacheTree.ReCalcRatioPercent;
  872. var
  873. i: Integer;
  874. CacheNode: TReportCacheNode;
  875. begin
  876. for i := 0 to CacheNodes.Count - 1 do
  877. begin
  878. CacheNode := TReportCacheNode(CacheNodes.Items[i]);
  879. if GatherCacheNode.TotalPrice <> 0 then
  880. CacheNode.RatioPercent := AdvRoundTo(CacheNode.TotalPrice/GatherCacheNode.TotalPrice*100);
  881. if GatherCacheNode.AddGatherTotalPrice <> 0 then
  882. CacheNode.AddRatioPercent := AdvRoundTo(CacheNode.AddGatherTotalPrice/GatherCacheNode.AddGatherTotalPrice*100);
  883. end;
  884. end;
  885. procedure TReportCacheTree.SaveTreeToFile(const AFileName: string);
  886. var
  887. sgs: TStringList;
  888. I: Integer;
  889. Node: TReportCacheNode;
  890. begin
  891. sgs := TStringList.Create;
  892. try
  893. for I := 0 to CacheNodes.Count - 1 do
  894. begin
  895. Node := TReportCacheNode(CacheNodes.Items[I]);
  896. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  897. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  898. end;
  899. sgs.SaveToFile(AFileName);
  900. finally
  901. sgs.Free;
  902. end;
  903. end;
  904. { TAllPhaseCacheTree }
  905. function TAllPhaseCacheTree.AddNode(AID: Integer; AParent,
  906. ANextSibling: TCacheNode): TAllPhaseCacheNode;
  907. begin
  908. Result := GetNewNode(AID);
  909. if Assigned(ANextSibling) then
  910. ANextSibling.InsertPreSibling(Result)
  911. else if Assigned(AParent) then
  912. AParent.InsertChild(Result)
  913. else
  914. Root.InsertChild(Result);
  915. end;
  916. function TAllPhaseCacheTree.FindNode(AID: Integer): TAllPhaseCacheNode;
  917. var
  918. i: Integer;
  919. Node: TAllPhaseCacheNode;
  920. begin
  921. Result := nil;
  922. for i := 0 to CacheNodes.Count - 1 do
  923. begin
  924. Node := TAllPhaseCacheNode(CacheNodes.Items[i]);
  925. if Node.ID = AID then
  926. begin
  927. Result := Node;
  928. Break;
  929. end;
  930. end;
  931. end;
  932. function TAllPhaseCacheTree.GetNewNode(
  933. AID: Integer): TAllPhaseCacheNode;
  934. begin
  935. Result := TAllPhaseCacheNode.Create(Self, AID);
  936. CacheNodes.Add(Result);
  937. end;
  938. procedure TAllPhaseCacheTree.SaveTreeToFile(const AFileName: string);
  939. var
  940. sgs: TStringList;
  941. I: Integer;
  942. Node: TAllPhaseCacheNode;
  943. begin
  944. sgs := TStringList.Create;
  945. try
  946. for I := 0 to CacheNodes.Count - 1 do
  947. begin
  948. Node := TAllPhaseCacheNode(CacheNodes.Items[I]);
  949. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  950. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  951. end;
  952. sgs.SaveToFile(AFileName);
  953. finally
  954. sgs.Free;
  955. end;
  956. end;
  957. { TGclCacheTree }
  958. function TGclCacheTree.AddNodeByB_Code(
  959. const AB_Code: string): TGclCacheNode;
  960. function FindParent: TGclCacheNode;
  961. begin
  962. Result := FLastNode;
  963. while Assigned(Result) and (Result <> Root) and (Result.B_Code <> '') and (Pos(Result.B_Code + '-', AB_Code) <> 1) do
  964. Result := TGclCacheNode(Result.Parent);
  965. end;
  966. var
  967. vParent: TGclCacheNode;
  968. begin
  969. vParent := FindParent;
  970. Result := TGclCacheNode(AddNode(vParent));
  971. FLastNode := Result;
  972. end;
  973. function TGclCacheTree.AddNodeByData(const AB_Code,
  974. AName: string): TGclCacheNode;
  975. begin
  976. if AB_Code = '' then
  977. Result := AddNodeByName(AName)
  978. else
  979. Result := AddNodeByB_Code(AB_Code);
  980. end;
  981. function TGclCacheTree.AddNodeByName(const AName: string): TGclCacheNode;
  982. begin
  983. if Pos('第100章至', AName) <> 0 then
  984. begin
  985. Result := TGclCacheNode(AddNode(nil));
  986. FLastBlank1 := Result;
  987. end
  988. else
  989. Result := TGclCacheNode(AddNode(FLastBlank1));
  990. FLastNode := Result;
  991. end;
  992. function TGclCacheTree.GetNewNode: TCacheNode;
  993. begin
  994. Result := TGclCacheNode.Create(Self, GetNewNodeID);
  995. CacheNodes.Add(Result);
  996. end;
  997. procedure TGclCacheTree.SaveTreeToFile(const AFileName: string);
  998. var
  999. sgs: TStringList;
  1000. I: Integer;
  1001. Node: TGclCacheNode;
  1002. begin
  1003. sgs := TStringList.Create;
  1004. try
  1005. for I := 0 to CacheNodes.Count - 1 do
  1006. begin
  1007. Node := TGclCacheNode(CacheNodes.Items[I]);
  1008. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; B_Code: %s; Name: %s;',
  1009. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.B_Code, Node.Name]));
  1010. end;
  1011. sgs.SaveToFile(AFileName);
  1012. finally
  1013. sgs.Free;
  1014. end;
  1015. end;
  1016. { TSpecPhaseCacheTree }
  1017. function TSpecPhaseCacheTree.AddNode(AParent,
  1018. ANextSibling: TCacheNode): TSpecPhaseCacheNode;
  1019. begin
  1020. Result := GetNewNode();
  1021. if Assigned(ANextSibling) then
  1022. ANextSibling.InsertPreSibling(Result)
  1023. else if Assigned(AParent) then
  1024. AParent.InsertChild(Result)
  1025. else
  1026. Root.InsertChild(Result);
  1027. end;
  1028. function TSpecPhaseCacheTree.FindNextSibling(AParent: TCacheNode; ACode,
  1029. AB_Code: string): TSpecPhaseCacheNode;
  1030. var
  1031. Node: TSpecPhaseCacheNode;
  1032. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  1033. begin
  1034. if Assigned(AParent) then
  1035. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1036. else
  1037. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1038. Result := nil;
  1039. if (ACode = '') and (AB_Code = '') then Exit;
  1040. sCodeID := ConvertDigitCode(ACode, 3, '-');
  1041. sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');
  1042. while Assigned(Node) do
  1043. begin
  1044. sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');
  1045. sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');
  1046. if (sCodeID <> '') and (sCodeID < sCodeID2) then
  1047. begin
  1048. Result := Node;
  1049. Break;
  1050. end
  1051. else if sB_CodeID < sB_CodeID2 then
  1052. begin
  1053. Result := Node;
  1054. Break;
  1055. end;
  1056. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1057. end;
  1058. end;
  1059. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode; ACode,
  1060. AB_Code: string): TSpecPhaseCacheNode;
  1061. var
  1062. Node: TSpecPhaseCacheNode;
  1063. begin
  1064. if Assigned(AParent) then
  1065. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1066. else
  1067. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1068. Result := nil;
  1069. while Assigned(Node) do
  1070. begin
  1071. if (Node.Code = ACode) and (Node.B_Code = AB_Code) then
  1072. begin
  1073. Result := Node;
  1074. Break;
  1075. end;
  1076. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1077. end;
  1078. end;
  1079. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode;
  1080. AName: string): TSpecPhaseCacheNode;
  1081. var
  1082. Node: TSpecPhaseCacheNode;
  1083. begin
  1084. if Assigned(AParent) then
  1085. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1086. else
  1087. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1088. Result := nil;
  1089. while Assigned(Node) do
  1090. begin
  1091. if SameText(Node.Name, AName) then
  1092. begin
  1093. Result := Node;
  1094. Break;
  1095. end;
  1096. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1097. end;
  1098. end;
  1099. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,
  1100. AName: string): TSpecPhaseCacheNode;
  1101. var
  1102. Node: TSpecPhaseCacheNode;
  1103. begin
  1104. if Assigned(AParent) then
  1105. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1106. else
  1107. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1108. Result := nil;
  1109. while Assigned(Node) do
  1110. begin
  1111. if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)
  1112. and SameText(Node.Name, AName) then
  1113. begin
  1114. Result := Node;
  1115. Break;
  1116. end;
  1117. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1118. end;
  1119. end;
  1120. function TSpecPhaseCacheTree.GetNewNode: TSpecPhaseCacheNode;
  1121. begin
  1122. Result := TSpecPhaseCacheNode.Create(Self, GetNewNodeID);
  1123. CacheNodes.Add(Result);
  1124. end;
  1125. end.