MCacheTree.pas 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  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 GetLastXmjParentOrg: TBillsCacheNode;
  458. begin
  459. Result := TBillsCacheNode(FLastNode);
  460. while Assigned(Result) and ((Result.B_Code <> '') or (Result.Code = '')) do
  461. Result := TBillsCacheNode(Result.Parent);
  462. end;
  463. function GetLastXmjParent: TBillsCacheNode;
  464. begin
  465. Result := TBillsCacheNode(FLastNode);
  466. while Assigned(Result) and Assigned(Result.Parent) and (Result.B_Code <> '') do
  467. Result := TBillsCacheNode(Result.Parent);
  468. end;
  469. function FindParent(AParent: TBillsCacheNode;
  470. const ACode: string): TBillsCacheNode;
  471. var
  472. i: Integer;
  473. sCode: string;
  474. begin
  475. Result := AParent;
  476. sCode := GetPrefixOfCode(ACode, SeparateChar);
  477. while (sCode <> '') do
  478. begin
  479. for i:= 0 to AParent.Children.Count - 1 do
  480. begin
  481. if TBillsCacheNode(AParent.Children.Items[i]).B_Code = ACode then
  482. begin
  483. Result := TBillsCacheNode(AParent.Children.Items[i]);
  484. Break;
  485. end;
  486. end;
  487. sCode := GetPrefixOfCode(sCode, SeparateChar);
  488. end;
  489. end;
  490. function FindNextSibling(AParent: TBillsCacheNode;
  491. const ACode: string): TBillsCacheNode;
  492. var
  493. Node: TBillsCacheNode;
  494. sCodeID, sCodeID2: string;
  495. begin
  496. Node := TBillsCacheNode(AParent.FirstChild);
  497. Result := nil;
  498. sCodeID := ConvertDigitCode(ACode, 3, '-');
  499. while Assigned(Node) do
  500. begin
  501. sCodeID2 := ConvertDigitCode(Node.LevelCode, 3, SeparateChar);
  502. if sCodeID < sCodeID2 then
  503. begin
  504. Result := Node;
  505. Break;
  506. end;
  507. Node := TBillsCacheNode(Node.NextSibling);
  508. end;
  509. end;
  510. function AddNodeByParent(AParent: TBillsCacheNode;
  511. const ACode: string): TBillsCacheNode;
  512. var
  513. Parent, NextSibling: TBillsCacheNode;
  514. begin
  515. Parent := FindParent(AParent, ACode);
  516. if AutoSort then
  517. NextSibling := FindNextSibling(AParent, ACode)
  518. else
  519. NextSibling := nil;
  520. Result := AddNode(Parent, NextSibling);
  521. Result.FLevelCode := ACode;
  522. end;
  523. var
  524. Parent: TBillsCacheNode;
  525. begin
  526. Parent := GetLastXmjParentOrg;
  527. Result := AddNodeByCode(Parent.Code + '-' + AB_Code, -1);
  528. //Parent := GetLastXmjParent;
  529. //Result := AddNodeByParent(Parent, AB_Code);
  530. end;
  531. procedure TBillsCacheTree.SetSeparateChar(const Value: Char);
  532. var
  533. I: Integer;
  534. Node: TBillsCacheNode;
  535. begin
  536. for I := 0 to CacheNodes.Count - 1 do
  537. begin
  538. Node := TBillsCacheNode(CacheNodes.Items[I]);
  539. Node.FLevelCode := StringReplace(Node.FLevelCode, FSeparateChar, Value, [rfReplaceAll]);
  540. end;
  541. FSeparateChar := Value;
  542. end;
  543. procedure TBillsCacheTree.SaveTreeToFile(const AFileName: string);
  544. var
  545. sgs: TStringList;
  546. I: Integer;
  547. Node: TBillsCacheNode;
  548. begin
  549. sgs := TStringList.Create;
  550. try
  551. for I := 0 to CacheNodes.Count - 1 do
  552. begin
  553. Node := TBillsCacheNode(CacheNodes.Items[I]);
  554. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  555. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  556. end;
  557. sgs.SaveToFile(AFileName);
  558. finally
  559. sgs.Free;
  560. end;
  561. end;
  562. function TBillsCacheTree.FindGclChild(AParent: TBillsCacheNode;
  563. const AB_Code, AName, AUnits: string; APrice: Double): TBillsCacheNode;
  564. var
  565. vChild: TBillsCacheNode;
  566. begin
  567. Result := nil;
  568. if Assigned(AParent) then
  569. vChild := TBillsCacheNode(AParent.FirstChild)
  570. else
  571. vChild := TBillsCacheNode(Root.FirstChild);
  572. while Assigned(vChild) and not Assigned(Result) do
  573. begin
  574. if SameText(AB_Code, vChild.B_Code) and
  575. SameText(AName, vChild.Name) and
  576. SameText(AUnits, vChild.Units) and
  577. (APrice = vChild.Price) then
  578. Result := vChild;
  579. vChild := TBillsCacheNode(vChild.NextSibling);
  580. end;
  581. end;
  582. function TBillsCacheTree.FindXmjChild(AParent: TBillsCacheNode;
  583. const ACode, AName: string): TBillsCacheNode;
  584. var
  585. vChild: TBillsCacheNode;
  586. begin
  587. Result := nil;
  588. if Assigned(AParent) then
  589. vChild := TBillsCacheNode(AParent.FirstChild)
  590. else
  591. vChild := TBillsCacheNode(Root.FirstChild);
  592. while Assigned(vChild) and not Assigned(Result) do
  593. begin
  594. if SameText(ACode, vChild.Code) and SameText(AName, vChild.Name) then
  595. Result := vChild;
  596. vChild := TBillsCacheNode(vChild.NextSibling);
  597. end;
  598. end;
  599. constructor TBillsCacheTree.Create;
  600. begin
  601. inherited;
  602. FFixedIDNodes := TList.Create;
  603. end;
  604. destructor TBillsCacheTree.Destroy;
  605. begin
  606. FFixedIDNodes.Free;
  607. inherited;
  608. end;
  609. function TBillsCacheTree.FindFixedIDNode(AID: Integer): TBillsCacheNode;
  610. var
  611. iNode: Integer;
  612. vNode: TCacheNode;
  613. begin
  614. Result := nil;
  615. for iNode := 0 to FFixedIDNodes.Count - 1 do
  616. begin
  617. vNode := TCacheNode(FFixedIDNodes.Items[iNode]);
  618. if vNode.ID = AID then
  619. begin
  620. Result := TBillsCacheNode(vNode);
  621. Break;
  622. end;
  623. end;
  624. end;
  625. function TBillsCacheTree.AddNodeByCodeName(const ACode, AName: string): TBillsCacheNode;
  626. function GetLastXmjParentOrg: TBillsCacheNode;
  627. begin
  628. Result := TBillsCacheNode(FLastNode);
  629. while Assigned(Result) and ((Result.B_Code <> '') or (Result.Code = '')) do
  630. Result := TBillsCacheNode(Result.Parent);
  631. end;
  632. function HasSiblingGclNode(ANode: TBillsCacheNode): Boolean;
  633. var
  634. Sibling: TBillsCacheNode;
  635. begin
  636. Result := False;
  637. Sibling := TBillsCacheNode(ANode.PreSibling);
  638. while Assigned(Sibling) and not Result do
  639. begin
  640. if Sibling.B_Code <> '' then
  641. Result := True;
  642. Sibling := TBillsCacheNode(Sibling.PreSibling);
  643. end;
  644. end;
  645. function GetParentWithBlankNode: TBillsCacheNode;
  646. begin
  647. Result := TBillsCacheNode(FLastBlankNode);
  648. if HasSiblingGclNode(Result) then
  649. Result := TBillsCacheNode(FLastBlankNode.Parent);
  650. end;
  651. var
  652. Parent, NextSibling: TBillsCacheNode;
  653. begin
  654. Result := FindFxNode(ACode, AName);
  655. if Assigned(Result) then
  656. begin
  657. FLastNode := Result;
  658. if (ACode = '') then
  659. FLastBlankNode := Result
  660. else
  661. FLastBlankNode := nil;
  662. Exit;
  663. end;
  664. NextSibling := nil;
  665. if Pos('-', ACode) > 0 then
  666. begin
  667. Parent := FindParent(ACode);
  668. if AutoSort then
  669. NextSibling := FindNextSibling(ACode);
  670. end
  671. else if (AName = '其他费用项目') or (AName = '建设期贷款利息') or (Pos('公路功能以外的工程费用', AName) > 0) then
  672. Parent := TBillsCacheNode(Root)
  673. else if Assigned(FLastBlankNode) then
  674. Parent := GetParentWithBlankNode
  675. else
  676. Parent := GetLastXmjParentOrg;
  677. Result := AddNode(Parent, NextSibling);
  678. Result.FLevelCode := ACode;
  679. FLastNode := Result;
  680. if (ACode = '') then
  681. FLastBlankNode := Result
  682. else
  683. FLastBlankNode := nil;
  684. end;
  685. function TBillsCacheTree.FindFxNode(const ACode,
  686. AName: string): TBillsCacheNode;
  687. var
  688. i: Integer;
  689. begin
  690. if (ACode = '') then
  691. begin
  692. for i := 0 to CacheNodes.Count - 1 do
  693. begin
  694. Result := TBillsCacheNode(CacheNodes.Items[i]);
  695. if (Result.Code = ACode) And (Result.Name = AName) then
  696. Exit;
  697. end;
  698. Result := nil;
  699. end
  700. else
  701. Result := FindFxNode(TBillsCacheNode(Root), ACode, AName);
  702. end;
  703. function TBillsCacheTree.FindFxNode(AParent: TBillsCacheNode; const ACode,
  704. AName: string): TBillsCacheNode;
  705. begin
  706. Result := TBillsCacheNode(AParent.FirstChild);
  707. while Assigned(Result) do
  708. begin
  709. if (Result.Code = ACode) And (Result.Name = AName) then
  710. Break
  711. else if Pos(Result.LevelCode + SeparateChar, ACode) = 1 then
  712. begin
  713. Result := FindNode(Result, ACode);
  714. Break;
  715. end
  716. else
  717. Result := TBillsCacheNode(Result.NextSibling);
  718. end;
  719. end;
  720. { TReportCacheNode }
  721. constructor TReportCacheNode.Create(ACacheTree: TCacheTree; AID,
  722. AProjectCount: Integer);
  723. begin
  724. inherited Create(ACacheTree, AID);
  725. FProjectCount := AProjectCount;
  726. SetLength(FP_Quantity, AProjectCount);
  727. SetLength(FP_Price, AProjectCount);
  728. SetLength(FP_TotalPrice, AProjectCount);
  729. SetLength(FP_DgnQuantity1, AProjectCount);
  730. SetLength(FP_DgnQuantity2, AProjectCount);
  731. end;
  732. function TReportCacheNode.GetAddGatherQuantity: Double;
  733. begin
  734. Result := AddDealQuantity + AddQcQuantity;
  735. end;
  736. function TReportCacheNode.GetAddGatherTotalPrice: Double;
  737. begin
  738. Result := AddDealTotalPrice + AddQcTotalPrice + AddPcTotalPrice;
  739. end;
  740. function TReportCacheNode.GetDesignPrice: Double;
  741. begin
  742. if DesignQuantity1 <> 0 then
  743. Result := TotalPrice / DesignQuantity1
  744. else
  745. Result := 0;
  746. end;
  747. function TReportCacheNode.GetDifferPercent1: Double;
  748. begin
  749. if TotalPrice <> 0 then
  750. Result := (AddGatherTotalPrice - TotalPrice) / TotalPrice * 100
  751. else
  752. Result := 0;
  753. end;
  754. function TReportCacheNode.GetDoubleArrayTotal(
  755. ADoubleArray: TDoubleArray): Double;
  756. var
  757. i: Integer;
  758. begin
  759. Result := 0;
  760. for i := Low(ADoubleArray) to High(ADoubleArray) do
  761. Result := Result + ADoubleArray[i];
  762. end;
  763. function TReportCacheNode.GetFinalDesignPrice: Double;
  764. var
  765. fQuantity: Double;
  766. begin
  767. fQuantity := FDealDesignQuantity1 + FCDesignQuantity1;
  768. if fQuantity <> 0 then
  769. Result := AddGatherTotalPrice / fQuantity
  770. else
  771. Result := 0;
  772. end;
  773. function TReportCacheNode.GetGatherP_TotalPrice: Double;
  774. begin
  775. Result := GetDoubleArrayTotal(FP_TotalPrice);
  776. end;
  777. procedure TReportCacheNode.ResolveCode;
  778. var
  779. sgs: TStrings;
  780. i: Integer;
  781. begin
  782. sgs := TStringList.Create;
  783. try
  784. sgs.Delimiter := '-';
  785. sgs.DelimitedText := FCode;
  786. FXiangCode := '';
  787. FMuCode := '';
  788. FJieCode := '';
  789. FXiMuCode := '';
  790. case sgs.Count of
  791. 1: FXiangCode := '';
  792. 2: FXiangCode := ChinessNum(StrToIntDef(sgs[1], 0));
  793. 3: FMuCode := sgs[2];
  794. 4: FJieCode := sgs[3];
  795. else
  796. begin
  797. for i := 4 to sgs.Count - 1 do
  798. if FXiMuCode = '' then
  799. FXiMuCode := sgs[i]
  800. else
  801. FXiMuCode := FXiMuCode + '-' + sgs[i];
  802. end;
  803. end;
  804. finally
  805. sgs.Free;
  806. end;
  807. end;
  808. procedure TReportCacheNode.SetCode(const Value: string);
  809. begin
  810. FCode := Value;
  811. ResolveCode;
  812. end;
  813. { TReportCacheTree }
  814. function TReportCacheTree.AddNode(AParent,
  815. ANextSibling: TCacheNode): TReportCacheNode;
  816. begin
  817. Result := GetNewNode(FProjectCount);
  818. if Assigned(ANextSibling) then
  819. ANextSibling.InsertPreSibling(Result)
  820. else if Assigned(AParent) then
  821. AParent.InsertChild(Result)
  822. else
  823. Root.InsertChild(Result);
  824. end;
  825. constructor TReportCacheTree.Create(AProjectCount: Integer);
  826. begin
  827. inherited Create;
  828. FProjectCount := AProjectCount;
  829. FGatherCacheNode := TReportCacheNode.Create(nil, -2, AProjectCount);
  830. SetLength(FProjectName, AProjectCount);
  831. end;
  832. destructor TReportCacheTree.Destroy;
  833. begin
  834. FGatherCacheNode.Free;
  835. inherited;
  836. end;
  837. function TReportCacheTree.FindNextSibling(AParent: TCacheNode; ACode,
  838. AB_Code: string): TReportCacheNode;
  839. var
  840. Node: TReportCacheNode;
  841. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  842. begin
  843. if Assigned(AParent) then
  844. Node := TReportCacheNode(AParent.FirstChild)
  845. else
  846. Node := TReportCacheNode(Root.FirstChild);
  847. Result := nil;
  848. if (ACode = '') and (AB_Code = '') then Exit;
  849. sCodeID := ConvertDigitCode(ACode, 3, '-');
  850. sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');
  851. while Assigned(Node) do
  852. begin
  853. sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');
  854. sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');
  855. if (sCodeID <> '') and (sCodeID < sCodeID2) then
  856. begin
  857. Result := Node;
  858. Break;
  859. end
  860. else if sB_CodeID < sB_CodeID2 then
  861. begin
  862. Result := Node;
  863. Break;
  864. end;
  865. Node := TReportCacheNode(Node.NextSibling);
  866. end;
  867. end;
  868. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode,
  869. AB_Code: string): TReportCacheNode;
  870. var
  871. Node: TReportCacheNode;
  872. begin
  873. if Assigned(AParent) then
  874. Node := TReportCacheNode(AParent.FirstChild)
  875. else
  876. Node := TReportCacheNode(Root.FirstChild);
  877. Result := nil;
  878. while Assigned(Node) do
  879. begin
  880. if (Node.Code = ACode) and (Node.B_Code = AB_Code) then
  881. begin
  882. Result := Node;
  883. Break;
  884. end;
  885. Node := TReportCacheNode(Node.NextSibling);
  886. end;
  887. end;
  888. function TReportCacheTree.FindNode(AParent: TCacheNode;
  889. AName: string): TReportCacheNode;
  890. var
  891. Node: TReportCacheNode;
  892. begin
  893. if Assigned(AParent) then
  894. Node := TReportCacheNode(AParent.FirstChild)
  895. else
  896. Node := TReportCacheNode(Root.FirstChild);
  897. Result := nil;
  898. while Assigned(Node) do
  899. begin
  900. if SameText(Node.Name, AName) then
  901. begin
  902. Result := Node;
  903. Break;
  904. end;
  905. Node := TReportCacheNode(Node.NextSibling);
  906. end;
  907. end;
  908. function TReportCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,
  909. AName: string): TReportCacheNode;
  910. var
  911. Node: TReportCacheNode;
  912. begin
  913. if Assigned(AParent) then
  914. Node := TReportCacheNode(AParent.FirstChild)
  915. else
  916. Node := TReportCacheNode(Root.FirstChild);
  917. Result := nil;
  918. while Assigned(Node) do
  919. begin
  920. if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)
  921. and SameText(Node.Name, AName) then
  922. begin
  923. Result := Node;
  924. Break;
  925. end;
  926. Node := TReportCacheNode(Node.NextSibling);
  927. end;
  928. end;
  929. function TReportCacheTree.GetNewNode(
  930. AProjectCount: Integer): TReportCacheNode;
  931. begin
  932. Result := TReportCacheNode.Create(Self, GetNewNodeID, AProjectCount);
  933. CacheNodes.Add(Result);
  934. end;
  935. procedure TReportCacheTree.ReCalcGatherData;
  936. var
  937. i: Integer;
  938. CacheNode: TReportCacheNode;
  939. begin
  940. FGatherCacheNode.Free;
  941. FGatherCacheNode := TReportCacheNode.Create(nil, -2, FProjectCount);
  942. CacheNode := TReportCacheNode(FirstNode);
  943. while Assigned(CacheNode) do
  944. begin
  945. FGatherCacheNode.TotalPrice := FGatherCacheNode.TotalPrice + CacheNode.TotalPrice;
  946. FGatherCacheNode.AddDealTotalPrice := FGatherCacheNode.AddDealTotalPrice + CacheNode.AddDealTotalPrice;
  947. FGatherCacheNode.AddQcTotalPrice := FGatherCacheNode.AddQcTotalPrice + CacheNode.AddQcTotalPrice;
  948. FGatherCacheNode.AddPcTotalPrice := FGatherCacheNode.AddPcTotalPrice + CacheNode.AddPcTotalPrice;
  949. FGatherCacheNode.PASTotalPrice := FGatherCacheNode.PASTotalPrice + CacheNode.PASTotalPrice;
  950. FGatherCacheNode.PDTotalPrice := FGatherCacheNode.PDTotalPrice + CacheNode.PDTotalPrice;
  951. FGatherCacheNode.CDDTotalPrice := FGatherCacheNode.CDDTotalPrice + CacheNode.CDDTotalPrice;
  952. FGatherCacheNode.ABTotalPrice := FGatherCacheNode.ABTotalPrice + CacheNode.ABTotalPrice;
  953. for i := 0 to FProjectCount - 1 do
  954. FGatherCacheNode.P_TotalPrice[i] := FGatherCacheNode.P_TotalPrice[i] + CacheNode.P_TotalPrice[i];
  955. CacheNode := TReportCacheNode(CacheNode.NextSibling);
  956. end;
  957. end;
  958. procedure TReportCacheTree.ReCalcRatioPercent;
  959. var
  960. i: Integer;
  961. CacheNode: TReportCacheNode;
  962. begin
  963. for i := 0 to CacheNodes.Count - 1 do
  964. begin
  965. CacheNode := TReportCacheNode(CacheNodes.Items[i]);
  966. if GatherCacheNode.TotalPrice <> 0 then
  967. CacheNode.RatioPercent := AdvRoundTo(CacheNode.TotalPrice/GatherCacheNode.TotalPrice*100);
  968. if GatherCacheNode.AddGatherTotalPrice <> 0 then
  969. CacheNode.AddRatioPercent := AdvRoundTo(CacheNode.AddGatherTotalPrice/GatherCacheNode.AddGatherTotalPrice*100);
  970. end;
  971. end;
  972. procedure TReportCacheTree.SaveTreeToFile(const AFileName: string);
  973. var
  974. sgs: TStringList;
  975. I: Integer;
  976. Node: TReportCacheNode;
  977. begin
  978. sgs := TStringList.Create;
  979. try
  980. for I := 0 to CacheNodes.Count - 1 do
  981. begin
  982. Node := TReportCacheNode(CacheNodes.Items[I]);
  983. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  984. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  985. end;
  986. sgs.SaveToFile(AFileName);
  987. finally
  988. sgs.Free;
  989. end;
  990. end;
  991. { TAllPhaseCacheTree }
  992. function TAllPhaseCacheTree.AddNode(AID: Integer; AParent,
  993. ANextSibling: TCacheNode): TAllPhaseCacheNode;
  994. begin
  995. Result := GetNewNode(AID);
  996. if Assigned(ANextSibling) then
  997. ANextSibling.InsertPreSibling(Result)
  998. else if Assigned(AParent) then
  999. AParent.InsertChild(Result)
  1000. else
  1001. Root.InsertChild(Result);
  1002. end;
  1003. function TAllPhaseCacheTree.FindNode(AID: Integer): TAllPhaseCacheNode;
  1004. var
  1005. i: Integer;
  1006. Node: TAllPhaseCacheNode;
  1007. begin
  1008. Result := nil;
  1009. for i := 0 to CacheNodes.Count - 1 do
  1010. begin
  1011. Node := TAllPhaseCacheNode(CacheNodes.Items[i]);
  1012. if Node.ID = AID then
  1013. begin
  1014. Result := Node;
  1015. Break;
  1016. end;
  1017. end;
  1018. end;
  1019. function TAllPhaseCacheTree.GetNewNode(
  1020. AID: Integer): TAllPhaseCacheNode;
  1021. begin
  1022. Result := TAllPhaseCacheNode.Create(Self, AID);
  1023. CacheNodes.Add(Result);
  1024. end;
  1025. procedure TAllPhaseCacheTree.SaveTreeToFile(const AFileName: string);
  1026. var
  1027. sgs: TStringList;
  1028. I: Integer;
  1029. Node: TAllPhaseCacheNode;
  1030. begin
  1031. sgs := TStringList.Create;
  1032. try
  1033. for I := 0 to CacheNodes.Count - 1 do
  1034. begin
  1035. Node := TAllPhaseCacheNode(CacheNodes.Items[I]);
  1036. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; Code: %s; B_Code: %s; Name: %s;',
  1037. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.Code, Node.B_Code, Node.Name]));
  1038. end;
  1039. sgs.SaveToFile(AFileName);
  1040. finally
  1041. sgs.Free;
  1042. end;
  1043. end;
  1044. { TGclCacheTree }
  1045. function TGclCacheTree.AddNodeByB_Code(
  1046. const AB_Code: string): TGclCacheNode;
  1047. function FindParent: TGclCacheNode;
  1048. begin
  1049. Result := FLastNode;
  1050. while Assigned(Result) and (Result <> Root) and (Result.B_Code <> '') and (Pos(Result.B_Code + '-', AB_Code) <> 1) do
  1051. Result := TGclCacheNode(Result.Parent);
  1052. end;
  1053. var
  1054. vParent: TGclCacheNode;
  1055. begin
  1056. vParent := FindParent;
  1057. Result := TGclCacheNode(AddNode(vParent));
  1058. FLastNode := Result;
  1059. end;
  1060. function TGclCacheTree.AddNodeByData(const AB_Code,
  1061. AName: string): TGclCacheNode;
  1062. begin
  1063. if AB_Code = '' then
  1064. Result := AddNodeByName(AName)
  1065. else
  1066. Result := AddNodeByB_Code(AB_Code);
  1067. end;
  1068. function TGclCacheTree.AddNodeByName(const AName: string): TGclCacheNode;
  1069. begin
  1070. if Pos('第100章至', AName) <> 0 then
  1071. begin
  1072. Result := TGclCacheNode(AddNode(nil));
  1073. FLastBlank1 := Result;
  1074. end
  1075. else
  1076. Result := TGclCacheNode(AddNode(FLastBlank1));
  1077. FLastNode := Result;
  1078. end;
  1079. function TGclCacheTree.GetNewNode: TCacheNode;
  1080. begin
  1081. Result := TGclCacheNode.Create(Self, GetNewNodeID);
  1082. CacheNodes.Add(Result);
  1083. end;
  1084. procedure TGclCacheTree.SaveTreeToFile(const AFileName: string);
  1085. var
  1086. sgs: TStringList;
  1087. I: Integer;
  1088. Node: TGclCacheNode;
  1089. begin
  1090. sgs := TStringList.Create;
  1091. try
  1092. for I := 0 to CacheNodes.Count - 1 do
  1093. begin
  1094. Node := TGclCacheNode(CacheNodes.Items[I]);
  1095. sgs.Add(Format('ID: %3d; ParentID: %3d; NextID: %3d; B_Code: %s; Name: %s;',
  1096. [Node.ID, Node.ParentID, Node.NextSiblingID, Node.B_Code, Node.Name]));
  1097. end;
  1098. sgs.SaveToFile(AFileName);
  1099. finally
  1100. sgs.Free;
  1101. end;
  1102. end;
  1103. { TSpecPhaseCacheTree }
  1104. function TSpecPhaseCacheTree.AddNode(AParent,
  1105. ANextSibling: TCacheNode): TSpecPhaseCacheNode;
  1106. begin
  1107. Result := GetNewNode();
  1108. if Assigned(ANextSibling) then
  1109. ANextSibling.InsertPreSibling(Result)
  1110. else if Assigned(AParent) then
  1111. AParent.InsertChild(Result)
  1112. else
  1113. Root.InsertChild(Result);
  1114. end;
  1115. function TSpecPhaseCacheTree.FindNextSibling(AParent: TCacheNode; ACode,
  1116. AB_Code: string): TSpecPhaseCacheNode;
  1117. var
  1118. Node: TSpecPhaseCacheNode;
  1119. sCodeID, sCodeID2, sB_CodeID, sB_CodeID2: string;
  1120. begin
  1121. if Assigned(AParent) then
  1122. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1123. else
  1124. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1125. Result := nil;
  1126. if (ACode = '') and (AB_Code = '') then Exit;
  1127. sCodeID := ConvertDigitCode(ACode, 3, '-');
  1128. sB_CodeID := ConvertDigitCode(AB_Code, 4, '-');
  1129. while Assigned(Node) do
  1130. begin
  1131. sCodeID2 := ConvertDigitCode(Node.Code, 3, '-');
  1132. sB_CodeID2 := ConvertDigitCode(Node.B_Code, 4, '-');
  1133. if (sCodeID <> '') and (sCodeID < sCodeID2) then
  1134. begin
  1135. Result := Node;
  1136. Break;
  1137. end
  1138. else if sB_CodeID < sB_CodeID2 then
  1139. begin
  1140. Result := Node;
  1141. Break;
  1142. end;
  1143. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1144. end;
  1145. end;
  1146. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode; ACode,
  1147. AB_Code: string): TSpecPhaseCacheNode;
  1148. var
  1149. Node: TSpecPhaseCacheNode;
  1150. begin
  1151. if Assigned(AParent) then
  1152. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1153. else
  1154. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1155. Result := nil;
  1156. while Assigned(Node) do
  1157. begin
  1158. if (Node.Code = ACode) and (Node.B_Code = AB_Code) then
  1159. begin
  1160. Result := Node;
  1161. Break;
  1162. end;
  1163. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1164. end;
  1165. end;
  1166. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode;
  1167. AName: string): TSpecPhaseCacheNode;
  1168. var
  1169. Node: TSpecPhaseCacheNode;
  1170. begin
  1171. if Assigned(AParent) then
  1172. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1173. else
  1174. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1175. Result := nil;
  1176. while Assigned(Node) do
  1177. begin
  1178. if SameText(Node.Name, AName) then
  1179. begin
  1180. Result := Node;
  1181. Break;
  1182. end;
  1183. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1184. end;
  1185. end;
  1186. function TSpecPhaseCacheTree.FindNode(AParent: TCacheNode; ACode, AB_Code,
  1187. AName: string): TSpecPhaseCacheNode;
  1188. var
  1189. Node: TSpecPhaseCacheNode;
  1190. begin
  1191. if Assigned(AParent) then
  1192. Node := TSpecPhaseCacheNode(AParent.FirstChild)
  1193. else
  1194. Node := TSpecPhaseCacheNode(Root.FirstChild);
  1195. Result := nil;
  1196. while Assigned(Node) do
  1197. begin
  1198. if SameText(Node.Code, ACode) and SameText(Node.B_Code, AB_Code)
  1199. and SameText(Node.Name, AName) then
  1200. begin
  1201. Result := Node;
  1202. Break;
  1203. end;
  1204. Node := TSpecPhaseCacheNode(Node.NextSibling);
  1205. end;
  1206. end;
  1207. function TSpecPhaseCacheTree.GetNewNode: TSpecPhaseCacheNode;
  1208. begin
  1209. Result := TSpecPhaseCacheNode.Create(Self, GetNewNodeID);
  1210. CacheNodes.Add(Result);
  1211. end;
  1212. end.