MCacheTree.pas 38 KB

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