ScKindsOfTrees.pas 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723
  1. unit ScKindsOfTrees;
  2. interface
  3. uses
  4. Contnrs,
  5. Classes,
  6. DB,
  7. ZjIDTree,
  8. ADODB,
  9. DBClient,
  10. ConstVarUnit,
  11. Windows;
  12. type
  13. TDrawingQuantityItem = class
  14. private
  15. FID: Integer;
  16. FBillsID: Integer;
  17. FSerinalNo: Integer;
  18. FName: string;
  19. FUnits: string;
  20. FDesignQuantity1: Double;
  21. FDesignQuantity2: Double;
  22. FMemoContext: string;
  23. public
  24. procedure Assign(aSrcItem: TDrawingQuantityItem);
  25. property ID: Integer read FID write FID;
  26. property BillsID: Integer read FBillsID write FBillsID;
  27. property SerinalNo: Integer read FSerinalNo write FSerinalNo;
  28. property Name: string read FName write FName;
  29. property Units: string read FUnits write FUnits;
  30. property DesignQuantity1: Double read FDesignQuantity1 write FDesignQuantity1;
  31. property DesignQuantity2: Double read FDesignQuantity2 write FDesignQuantity2;
  32. property MemoContext: string read FMemoContext write FMemoContext;
  33. end;
  34. TExprsNode = class
  35. private
  36. FMajorID: Integer;
  37. FMinorID: Integer;
  38. FRecdID: Integer;
  39. FExprs: string;
  40. FExprs1: string;
  41. public
  42. end;
  43. {导入Excel用的树}
  44. TScExcelItem = class
  45. private
  46. FID: Integer;
  47. FParent: TScExcelItem;
  48. FNextSibling: TScExcelItem;
  49. FFirstChild: TScExcelItem;
  50. FLastChild: TScExcelItem;
  51. FCode: string;
  52. FBCode: string;
  53. FName: string;
  54. FUnits: string;
  55. FQuantity: Double;
  56. FQuantity1: Double;
  57. FQuantity2: Double;
  58. FPrice: Double;
  59. FTotalPrice: Double;
  60. FMemoString: string;
  61. {父节点的编号, 以'-'结尾的字符串, 如:'1-1-'}
  62. FParentCode: string;
  63. function GetParentID: Integer;
  64. function GetNextSiblingID: Integer;
  65. public
  66. function HasChildren: Boolean;
  67. procedure AssignFirstChild(ANode: TScExcelItem);
  68. procedure MoveLastChild(ANode: TScExcelItem);
  69. property ParentCode: string read FParentCode write FParentCode;
  70. property ID: Integer read FID write FID;
  71. property ParentID: Integer read GetParentID;
  72. property NextSiblingID: Integer read GetNextSiblingID;
  73. property Parent: TScExcelItem read FParent write FParent;
  74. property NextSibling: TScExcelItem read FNextSibling write FNextSibling;
  75. property FirstChild: TScExcelItem read FFirstChild;
  76. property LastChild: TScExcelItem read FLastChild;
  77. property Code: string read FCode write FCode;
  78. property BCode: string read FBCode write FBCode;
  79. property Name: string read FName write FName;
  80. property Units: string read FUnits write FUnits;
  81. property Quantity: Double read FQuantity write FQuantity;
  82. property Quantity1: Double read FQuantity1 write FQuantity1;
  83. property Quantity2: Double read FQuantity2 write FQuantity2;
  84. property Price: Double read FPrice write FPrice;
  85. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  86. property MemoString: string read FMemoString write FMemoString;
  87. end;
  88. TScExcelItemTree = class
  89. private
  90. FRoot: TScExcelItem;
  91. FList: TObjectList;
  92. FDrawQList: TObjectList;
  93. FBillsData: TObject;
  94. FPartID: Integer;
  95. {指向项目列的最后一个节点}
  96. FPNode: TScExcelItem;
  97. {指向清单列的最后一个节点}
  98. FBNode: TScExcelItem;
  99. FMaxNodeID: Integer;
  100. FMaxDrawQID: Integer;
  101. // 保存所有子节点列表
  102. FPartOne: TStringList;
  103. FPartTwo: TStringList;
  104. FPartThree: TStringList;
  105. function GetFirstNode: TScExcelItem;
  106. function InsertOmissionCode(const ACode: string): TScExcelItem;
  107. function InsertOmissionBCode(const ABCode: string): TScExcelItem;
  108. function InsertCode(const ACode: string): TScExcelItem;
  109. function InsertBCode(const ABCode: string): TScExcelItem;
  110. function InsertNull(const AIsPreDefine: Boolean = False): TScExcelItem;
  111. function FindNode(const AID: Integer): TScExcelItem;
  112. procedure ModifyNodePosition(ANode: TScExcelItem; const AParentID, ANextSiblingID: Integer);
  113. function Add(const AID, AParentID, ANextSiblingID: Integer): TScExcelItem;
  114. procedure InternalInsertNode(ANode: TScExcelItem);
  115. procedure RefreshBills;
  116. procedure RefreshDrawingQuantity;
  117. public
  118. constructor Create(aBillsData: TObject);
  119. destructor Destroy; override;
  120. function AddNodeByCode(const ACode: string; const ABCode: string = '';
  121. const AName: string = ''): TScExcelItem;
  122. function AddDrawQuantity: TDrawingQuantityItem;
  123. procedure RefreshDataBase;
  124. {添加一二三部分高端节点}
  125. procedure AddFirstNode(const AID: Integer);
  126. function LastNextSiblingID: Integer;
  127. procedure ViewBillTreeParts;
  128. procedure DeleteNode(AObject: TObject);
  129. property FirstNode: TScExcelItem read GetFirstNode;
  130. property PNode: TScExcelItem read FPNode write FPNode;
  131. property BNode: TScExcelItem read FBNode write FBNode;
  132. property MaxNodeID: Integer read FMaxNodeID write FMaxNodeID;
  133. property MaxDrawQID: Integer read FMaxDrawQID write FMaxDrawQID;
  134. property PartOne: TStringList read FPartOne;
  135. property PartTwo: TStringList read FPartTwo;
  136. property PartThree: TStringList read FPartThree;
  137. end;
  138. {汇总用的树}
  139. TCacheGatherTree = class;
  140. TCacheGatherNode = class
  141. private
  142. FID: Integer;
  143. FCode: string;
  144. FBCode: string;
  145. FName: string;
  146. FUnits: string;
  147. FUnitPrice: Double;
  148. FTotalPrice: Double;
  149. FMemostring: string;
  150. FQuantity: Double;
  151. FDesignPrice: Double;
  152. FDesignQuantity1: Double;
  153. FDesignQuantity2: Double;
  154. FOldCode: string;
  155. FOldBCode: string;
  156. FIsPreDefine: Boolean;
  157. FOwner: TCacheGatherTree;
  158. FDQList: TList;
  159. FExprsList: TList;
  160. FParent: TCacheGatherNode;
  161. FNextSibling: TCacheGatherNode;
  162. FPreSibling: TCacheGatherNode;
  163. FFirstChild: TCacheGatherNode;
  164. FLastChild: TCacheGatherNode;
  165. procedure DeleteDQItems;
  166. function GetParentID: Integer;
  167. function GetNextSiblingID: Integer;
  168. public
  169. constructor Create(aOwner: TCacheGatherTree);
  170. destructor Destroy; override;
  171. procedure DeleteChildren;
  172. procedure RemoveFromParent;
  173. { Assign }
  174. procedure AssignDraw(aNode: TCacheGatherNode);
  175. procedure Assign(aNode: TCacheGatherNode; aIncludeDraw: Boolean = True);
  176. procedure MoveFirstChild(ANode: TCacheGatherNode);
  177. procedure MoveLastChild(ANode: TCacheGatherNode);
  178. procedure MovePreSibling(ANode: TCacheGatherNode);
  179. function HasChildren: Boolean;
  180. property Parent: TCacheGatherNode read FParent;
  181. property NextSibling: TCacheGatherNode read FNextSibling;
  182. property FirstChild: TCacheGatherNode read FFirstChild;
  183. property LastChild: TCacheGatherNode read FLastChild;
  184. property DQList: TList read FDQList write FDQList;
  185. property ID: Integer read FID write FID;
  186. property ParentID: Integer read GetParentID;
  187. property NextSiblingID: Integer read GetNextSiblingID;
  188. property Code: string read FCode write FCode;
  189. property BCode: string read FBCode write FBCode;
  190. property Name: string read FName write FName;
  191. property Units: string read FUnits write FUnits;
  192. property Quantity: Double read FQuantity write FQuantity;
  193. property DesignQuantity1: Double read FDesignQuantity1 write FDesignQuantity1;
  194. property DesignQuantity2: Double read FDesignQuantity2 write FDesignQuantity2;
  195. property UnitPrice: Double read FUnitPrice write FUnitPrice;
  196. property DesignPrice: Double read FDesignPrice write FDesignPrice;
  197. property TotalPrice: Double read FTotalPrice write FTotalPrice;
  198. property MemoString: string read FMemostring write FMemostring;
  199. property OldCode: string read FOldCode write FOldCode;
  200. property OldBCode: string read FOldBCode write FOldBCode;
  201. property IsPreDefined: Boolean read FIsPreDefine write FIsPreDefine;
  202. end;
  203. TCacheGatherTree = class
  204. private
  205. FMinIDList: TList;
  206. FCacheList: TObjectList;
  207. FRoot: TCacheGatherNode;
  208. FProject: TObject;
  209. FMaxID: Integer;
  210. FMaxDQID: Integer;
  211. FBillsCode: string;
  212. FTokenID: Integer;
  213. function GetFirstNode: TCacheGatherNode;
  214. procedure MergeCacheList;
  215. function SerialSearch(const AID: Integer): TCacheGatherNode;
  216. function DichotomySearch(const AID: Integer): TCacheGatherNode;
  217. function FindCacheNode(const AID: Integer): TCacheGatherNode;
  218. // 按编号排序节点 [Litao 2012.1.12]
  219. procedure SortCacheTreeNodes(AParent: TCacheGatherNode);
  220. procedure AddChildren(AParent: TCacheGatherNode; AList: TList);
  221. procedure MoveChildren(AParent: TCacheGatherNode; AList: TList);
  222. procedure SortChildren(AParent: TCacheGatherNode);
  223. procedure DeleteBySerialSearch(const ANode: TCacheGatherNode);
  224. procedure DeleteByDichotomySearch(const ANode: TCacheGatherNode);
  225. procedure DeleteNode(ANode: TCacheGatherNode);
  226. {合并两个节点}
  227. procedure CombineDrawQ(ASrcQList, ADestQList: TList; aDestID: Integer);
  228. procedure CombineNodeQuantity(ASrc, ADest: TCacheGatherNode);
  229. {Asrc移到ADest前面}
  230. procedure MovePreNode(ASrc, ADest: TCacheGatherNode);
  231. function IncludeToken(const aCode: string): Boolean;
  232. function ConvertCode(const aCode, aGCode: string): string;
  233. function SplitAndConvertCode(const aCode, aGCode: string; ASpliter: Char = '-'): string;
  234. procedure AddBillsExprs(ABillsID: Integer; ACacheNode: TCacheGatherNode);
  235. {汇总部分}
  236. function ModifyBillsCode(const ACode: string): string; overload;
  237. procedure ModifyBillsCode(GNode: TCacheGatherNode; const aParentCode: string); overload;
  238. procedure PlusItems(xNode: TZjIDTreeNode; GNode: TCacheGatherNode; aLevel: Integer; IsCode: Boolean);
  239. procedure InternalDetail(AGNode: TCacheGatherNode; ANode: TZjIDTreeNode; const AParentCode: string);
  240. procedure AddGatherNode(AGatherNode: TCacheGatherNode;
  241. AZjNode: TZjIDTreeNode; aLevel: Integer; const aBCode, aName: string);
  242. procedure AdjustStructor(AParNode, AChdNode: TCacheGatherNode);
  243. procedure AddBillsNode(ANode: TZjIDTreeNode; AGatherParent: TCacheGatherNode);
  244. procedure GatherCurNode(ANode: TZjIDTreeNode; AGatherParent: TCacheGatherNode; aLevel: Integer);
  245. public
  246. constructor Create;
  247. destructor Destroy; override;
  248. function AddCacheNode(const AID, AParentID, ANextSiblingID: Integer): TCacheGatherNode;
  249. function TraverseDBIntoSelf(AProject: TObject): Boolean;
  250. procedure TraverseOwnerIntoDB(AProject: TObject);
  251. property FirstNode: TCacheGatherNode read GetFirstNode;
  252. end;
  253. { Merge Gather Tree }
  254. TMergeGatherTree = class(TCacheGatherTree)
  255. private
  256. FIsOpen1: Boolean;
  257. FIsOpen2: Boolean;
  258. FBillsTree1: TZjIDTree;
  259. FBillsTree2: TZjIDTree;
  260. FCdsDraw1: TClientDataSet;
  261. FCdsDraw2: TClientDataSet;
  262. FCdsExprs: TClientDataSet;
  263. FMergeByCode: Boolean;
  264. procedure InitMaxID;
  265. // 为桩号重新编号
  266. procedure ReCodeNode(ANode: TCacheGatherNode);
  267. { Add Bills }
  268. procedure AddDrawItems(aCdsDraw: TClientDataSet; aBillsID: Integer; aCGNode: TCacheGatherNode);
  269. procedure AddExprs(AORecID: Integer; AGNode: TCacheGatherNode);
  270. procedure AssignTo(aNode: TZjIDTreeNode; aGatherNode: TCacheGatherNode);
  271. procedure AssignByOpened(aBillsTree: TObject; aNode: TZjIDTreeNode; aGatherNode: TCacheGatherNode);
  272. procedure AddNode(aNode: TZjIDTreeNode; aGatherNode: TCacheGatherNode; aBillsTree: TZjIDTree;
  273. aCdsDraw: TClientDataSet; aIsOpened: Boolean);
  274. function AddSingleNode(aNode: TZjIDTreeNode; aGatherNode: TCacheGatherNode; aBillsTree: TZjIDTree;
  275. aCdsDraw: TClientDataSet; aIsOpened: Boolean): TCacheGatherNode;
  276. { Update Bills }
  277. procedure UpdateDrawItems(aBillsID: Integer; aCGNode: TCacheGatherNode);
  278. procedure UpdateQuantity(aNode: TZjIDTreeNode; aGatherNode: TCacheGatherNode);
  279. procedure UpdateQuantityByOpened(aNode: TZjIDTreeNode; aGatherNode: TCacheGatherNode);
  280. procedure UpdateNode(aNode: TZjIDTreeNode; aGatherNode: TCacheGatherNode);
  281. { Update Gather }
  282. function AddSingleGatherNode(aSrcNode, aDstNode: TCacheGatherNode): TCacheGatherNode;
  283. procedure AddGatherNode(aSrcNode, aDstNode: TCacheGatherNode);
  284. procedure UpdateGatherDrawItems(aSrcNode, aDstNode: TCacheGatherNode);
  285. procedure UpdateGatherQuantity(aSrcNode, aDstNode: TCacheGatherNode);
  286. procedure UpdateGatherNode(aSrcNode, aDstNode: TCacheGatherNode);
  287. { write }
  288. procedure WriteBills(aNode: TCacheGatherNode; aTable: TDataSet);
  289. procedure WriteDraw(aNode: TCacheGatherNode; aTable: TDataSet);
  290. procedure WriteExprs(aNode: TCacheGatherNode; ADataset: TDataSet);
  291. public
  292. procedure GatherBillsTree(aBillsTree: TZjIDTree);
  293. procedure UpdateBillsTree(aBillsTree: TZjIDTree);
  294. procedure GatherTree(aGatherTree: TMergeGatherTree);
  295. procedure WriteTo(aBillsTable, aDrawTable, aExprsTable: TDataSet);
  296. property IsOpen1: Boolean read FIsOpen1 write FIsOpen1;
  297. property IsOpen2: Boolean read FIsOpen2 write FIsOpen2;
  298. property CdsDraw1: TClientDataSet read FCdsDraw1 write FCdsDraw1;
  299. property CdsDraw2: TClientDataSet read FCdsDraw2 write FCdsDraw2;
  300. property BillsTree1: TZjIDTree read FBillsTree1 write FBillsTree1;
  301. property BillsTree2: TZjIDTree read FBillsTree2 write FBillsTree2;
  302. property CdsExprs: TClientDataSet read FCdsExprs write FCdsExprs;
  303. property MergeByCode: Boolean read FMergeByCode write FMergeByCode;
  304. end;
  305. TSplitGatherTree = Class(TMergeGatherTree)
  306. private
  307. FOwnerName: string;
  308. procedure SearchParents(aNode: TZjIDTreeNode; aParList: TList);
  309. function FindChildNode(aNode: TZjIDTreeNode; aCgnNode: TCacheGatherNode): TCacheGatherNode;
  310. function AddSingleNode(aNode: TZjIDTreeNode; aCgnNode: TCacheGatherNode): TCacheGatherNode; overload;
  311. function AddParent(aNode: TZjIDTreeNode): TCacheGatherNode;
  312. procedure GenerateGatherTree(aNode: TZjIDTreeNode);
  313. public
  314. procedure SplitBillsTree(aBillsTree: TZjIDTree; aCdsDraw: TClientDataSet; const aOwnerName: string);
  315. end;
  316. implementation
  317. uses
  318. SysUtils,
  319. DataBase,
  320. ScProjectManager,
  321. ConstMethodUnit,
  322. Math,
  323. ScBillsTree,
  324. ScExprsDM,
  325. ScConfig,
  326. ScProgressFrm;
  327. const
  328. TokenArray: array [0..10] of Char = ('N', 'M', 'Q', 'L', 'P', 'R', 'S', 'T', 'X', 'Y', 'Z');
  329. { TScExcelItemTree }
  330. function TScExcelItemTree.Add(const AID, AParentID,
  331. ANextSiblingID: Integer): TScExcelItem;
  332. var
  333. paNode: TScExcelItem;
  334. begin
  335. Result := TScExcelItem.Create;
  336. Result.ID := AID;
  337. {修改节点关系}
  338. ModifyNodePosition(Result, AParentID, ANextSiblingID);
  339. FList.Add(Result);
  340. end;
  341. function TScExcelItemTree.AddDrawQuantity: TDrawingQuantityItem;
  342. begin
  343. Result := TDrawingQuantityItem.Create;
  344. Result.ID := FMaxDrawQID;
  345. if Assigned(FBNode) then
  346. Result.BillsID := FBNode.ID
  347. else Result.BillsID := FPNode.ID;
  348. FDrawQList.Add(Result);
  349. Inc(FMaxDrawQID);
  350. end;
  351. procedure TScExcelItemTree.AddFirstNode(const AID: Integer);
  352. function AddPartNode(const ID: Integer): TScExcelItem;
  353. begin
  354. Result := Add(ID, -1, -1);
  355. Result.ParentCode := '';
  356. Result.Code := IntToStr(ID);
  357. end;
  358. begin
  359. PNode := AddPartNode(1);
  360. AddPartNode(2);
  361. AddPartNode(3);
  362. FPartID := 2;
  363. end;
  364. function TScExcelItemTree.AddNodeByCode(const ACode,
  365. ABCode, AName: string): TScExcelItem;
  366. begin
  367. if not SameText(ACode, '') then {Code}
  368. begin
  369. if Pos('…', ACode) = 0 then
  370. begin
  371. if FPNode = nil then
  372. begin
  373. Result := nil;
  374. Exit;
  375. end;
  376. Result := InsertCode(ACode);
  377. if Assigned(FBNode) then FBNode := nil;
  378. end
  379. else Result := nil;
  380. end
  381. else if not SameText(ABCode, '') then {BCode}
  382. begin
  383. if Pos('…', ABCode) = 0 then
  384. Result := InsertBCode(ABCode)
  385. else Result := nil;
  386. end
  387. else {...}
  388. begin
  389. Result := InsertNull;
  390. if Assigned(FBNode) then FBNode := nil;
  391. end;
  392. Inc(FMaxNodeID);
  393. end;
  394. constructor TScExcelItemTree.Create(aBillsData: TObject);
  395. begin
  396. FBillsData := aBillsData;
  397. FList := TObjectList.Create;
  398. FRoot := TScExcelItem.Create;
  399. FRoot.ID := -1;
  400. FPartOne := TStringList.Create;
  401. FPartTwo := TStringList.Create;
  402. FPartThree := TStringList.Create;
  403. FPartID := 1;
  404. FDrawQList := TObjectList.Create;
  405. end;
  406. procedure TScExcelItemTree.DeleteNode(AObject: TObject);
  407. begin
  408. FList.Remove(AObject);
  409. AObject.Free;
  410. end;
  411. destructor TScExcelItemTree.Destroy;
  412. begin
  413. FreeAndNil(FDrawQList);
  414. FreeAndNil(FList);
  415. FreeAndNil(FRoot);
  416. FreeAndNil(FPartOne);
  417. FreeAndNil(FPartTwo);
  418. FreeAndNil(FPartThree);
  419. inherited;
  420. end;
  421. function TScExcelItemTree.FindNode(const AID: Integer): TScExcelItem;
  422. var
  423. ilow, ihigh, imid: Integer;
  424. eNode: TScExcelItem;
  425. begin
  426. Result := nil;
  427. ilow := 0;
  428. ihigh := FList.Count - 1;
  429. while ilow <= ihigh do
  430. begin
  431. imid := (ilow + ihigh) div 2;
  432. eNode := TScExcelItem(FList[imid]);
  433. if eNode.ID = AID then
  434. begin
  435. Result := eNode;
  436. Break;
  437. end;
  438. if eNode.ID < AID then ilow := imid + 1
  439. else ihigh := imid - 1;
  440. end;
  441. end;
  442. function TScExcelItemTree.GetFirstNode: TScExcelItem;
  443. begin
  444. Result := FRoot.FirstChild;
  445. end;
  446. function TScExcelItemTree.InsertBCode(const ABCode: string): TScExcelItem;
  447. begin
  448. if not Assigned(FBNode) or (FBNode = FPNode) then
  449. begin
  450. Result := Add(FMaxNodeID, FPNode.ID, -1);
  451. Result.ParentCode := Format('%s-', [ABCode]);
  452. Result.BCode := ABCode;
  453. FBNode := Result;
  454. end
  455. else
  456. begin
  457. if Pos(FBNode.ParentCode, ABCode) = 1 then
  458. begin
  459. if Pos(Format('%s-', [FBNode.BCode]), ABCode) <> 1 then
  460. begin
  461. Result := Add(FMaxNodeID, FBNode.ParentID, -1);
  462. Result.ParentCode := FBNode.ParentCode;
  463. Result.BCode := ABCode;
  464. FBNode := Result;
  465. end
  466. else
  467. begin
  468. Result := Add(FMaxNodeID, FBNode.ID, -1);
  469. Result.ParentCode := Format('%s-', [FBNode.BCode]);
  470. Result.BCode := ABCode;
  471. FBNode := Result;
  472. end;
  473. end
  474. else
  475. begin
  476. FBNode := FBNode.Parent;
  477. Result := InsertBCode(ABCode);
  478. end;
  479. end;
  480. end;
  481. function TScExcelItemTree.InsertCode(const ACode: string): TScExcelItem;
  482. var
  483. iErr: Integer;
  484. sCode: string;
  485. begin
  486. if Pos(FPNode.ParentCode, ACode) = 1 then
  487. begin
  488. if (Pos(FPNode.Code + '-', ACode) <> 1) or (FPNode.Code = ACode) then
  489. begin
  490. Result := Add(FMaxNodeID, FPNode.ParentID, -1);
  491. Result.ParentCode := FPNode.ParentCode;
  492. Result.Code := ACode;
  493. FPNode := Result;
  494. end
  495. else
  496. begin
  497. Result := Add(FMaxNodeID, FPNode.ID, -1);
  498. Result.ParentCode := Format('%s-', [FPNode.Code]);
  499. Result.Code := ACode;
  500. FPNode := Result;
  501. end;
  502. end
  503. else
  504. begin
  505. if SameText(FPNode.ParentCode, '') then
  506. begin
  507. if Pos('-', ACode) <> 0 then
  508. begin
  509. Result := Add(FMaxNodeID, FPNode.ID, -1);
  510. sCode := Format('%s-', [FPNode.Code]);
  511. {1部分下面有3-1时情况}
  512. if Pos(sCode, ACode) = 0 then
  513. sCode := Format('%s-', [ACode]);
  514. Result.ParentCode := sCode;
  515. Result.Code := ACode;
  516. FPNode := Result;
  517. end
  518. else
  519. begin
  520. Val(ACode, FPartID, iErr);
  521. Result := FindNode(FPartID);
  522. FPNode := Result;
  523. Inc(FPartID);
  524. end;
  525. end
  526. else
  527. begin
  528. FPNode := FPNode.Parent;
  529. Result := InsertCode(ACode);
  530. end;
  531. end;
  532. end;
  533. function TScExcelItemTree.InsertNull(
  534. const AIsPreDefine: Boolean): TScExcelItem;
  535. begin
  536. case AIsPreDefine of
  537. False:
  538. if Assigned(FBNode) then
  539. Result := Add(FMaxNodeID, FBNode.ParentID, -1)
  540. else
  541. Result := Add(FMaxNodeID, FPNode.ID, -1);
  542. True: Result := Add(FMaxNodeID, -1, -1);
  543. end;
  544. end;
  545. function TScExcelItemTree.InsertOmissionBCode(
  546. const ABCode: string): TScExcelItem;
  547. begin
  548. if Assigned(FBNode) then
  549. Result := Add(FMaxNodeID, FBNode.ParentID, -1)
  550. else Result := Add(FMaxNodeID, FPNode.ID, -1);
  551. Result.ParentCode := '…';
  552. Result.Code := ABCode;
  553. FBNode := Result;
  554. end;
  555. function TScExcelItemTree.InsertOmissionCode(
  556. const ACode: string): TScExcelItem;
  557. begin
  558. Result := Add(FMaxNodeID, FPNode.ParentID, -1);
  559. Result.ParentCode := '…';
  560. Result.Code := ACode;
  561. FPNode := Result;
  562. end;
  563. procedure TScExcelItemTree.InternalInsertNode(ANode: TScExcelItem);
  564. begin
  565. TDMDataBase(FBillsData).AddBillsItem(ANode);
  566. if ANode.HasChildren then
  567. InternalInsertNode(ANode.FirstChild);
  568. if Assigned(ANode.NextSibling) then
  569. InternalInsertNode(ANode.NextSibling);
  570. end;
  571. function TScExcelItemTree.LastNextSiblingID: Integer;
  572. var
  573. xlsItem: TScExcelItem;
  574. begin
  575. xlsItem := FirstNode;
  576. Result := -1;
  577. while Assigned(xlsItem) do
  578. begin
  579. Result := xlsItem.FID;
  580. xlsItem := xlsItem.NextSibling;
  581. end;
  582. end;
  583. procedure TScExcelItemTree.ModifyNodePosition(ANode: TScExcelItem;
  584. const AParentID, ANextSiblingID: Integer);
  585. var
  586. atNode, etNode: TScExcelItem;
  587. begin
  588. {没考滤NextSibling为非-1情况}
  589. if AParentID = -1 then
  590. begin
  591. if Assigned(FRoot.FFirstChild) then
  592. FRoot.MoveLastChild(ANode)
  593. else
  594. FRoot.AssignFirstChild(ANode);
  595. end
  596. else
  597. begin
  598. atNode := FindNode(AParentID);
  599. ANode.Parent := atNode;
  600. if Assigned(atNode.FirstChild) then
  601. atNode.MoveLastChild(ANode)
  602. else atNode.AssignFirstChild(ANode);
  603. end;
  604. end;
  605. procedure TScExcelItemTree.RefreshBills;
  606. var
  607. xlsNode, temNode: TScExcelItem;
  608. begin
  609. {取第一个节点,即建安费节点}
  610. xlsNode := FirstNode;
  611. {如果第一个节点不为空,并且有子节点,则读取并写入数据}
  612. if Assigned(xlsNode) then
  613. begin
  614. TDMDataBase(FBillsData).EnabledUITreeEvt(False);
  615. TDMDataBase(FBillsData).DisconnectBillsTree;
  616. try
  617. if xlsNode.HasChildren then
  618. begin
  619. TDMDataBase(FBillsData).DeletePartSubItem(PartOne);
  620. InternalInsertNode(xlsNode.FirstChild);
  621. end;
  622. temNode := xlsNode;
  623. xlsNode := xlsNode.NextSibling;
  624. // 添加兄弟节点情况
  625. while Assigned(xlsNode) do
  626. begin
  627. if xlsNode.HasChildren then
  628. begin
  629. if xlsNode.ID = 2 then
  630. begin
  631. TDMDataBase(FBillsData).DeletePartSubItem(PartTwo);
  632. end
  633. else if xlsNode.ID = 3 then
  634. begin
  635. TDMDataBase(FBillsData).DeletePartSubItem(PartThree);
  636. end;
  637. InternalInsertNode(TScExcelItem(xlsNode).FirstChild);
  638. end;
  639. temNode := xlsNode;
  640. xlsNode := xlsNode.NextSibling;
  641. end;
  642. finally
  643. TDMDataBase(FBillsData).ConnectionBillsTree;
  644. TDMDataBase(FBillsData).EnabledUITreeEvt(True);
  645. end;
  646. end;
  647. end;
  648. procedure TScExcelItemTree.RefreshDataBase;
  649. begin
  650. RefreshBills;
  651. RefreshDrawingQuantity;
  652. end;
  653. procedure TScExcelItemTree.RefreshDrawingQuantity;
  654. var
  655. I: Integer;
  656. DQItem: TDrawingQuantityItem;
  657. begin
  658. with TDMDataBase(FBillsData) do
  659. begin
  660. for I := 0 to FDrawQList.Count - 1 do
  661. begin
  662. DQItem := TDrawingQuantityItem(FDrawQList[I]);
  663. AddDrawQItem(DQItem);
  664. end;
  665. end;
  666. end;
  667. procedure TScExcelItemTree.ViewBillTreeParts;
  668. var
  669. I: Integer;
  670. strIDList: string;
  671. procedure AddToList(ANode: TZjIDTreeNode; AStrList: TStringList);
  672. begin
  673. if not SameText(strIDList, '') then
  674. begin
  675. strIDList := Format('%s or ID=%d', [strIDList, ANode.ID]);
  676. Inc(I);
  677. if I = 500 then
  678. begin
  679. AStrList.Add(strIDList);
  680. strIDList := '';
  681. I := 1;
  682. end;
  683. end
  684. else
  685. begin
  686. strIDList := Format('ID=%d', [ANode.ID]);
  687. Inc(I);
  688. end;
  689. if Assigned(ANode.FirstChild) then AddToList(ANode.FirstChild, AStrList);
  690. if Assigned(ANode.NextSibling) then AddToList(ANode.NextSibling, AStrList);
  691. end;
  692. procedure AddIDToList(ANode: TZjIDTreeNode; AID: Integer);
  693. begin
  694. case AID of
  695. 1: if Assigned(ANode.FirstChild) then AddToList(ANode.FirstChild, FPartOne);
  696. 2: if Assigned(ANode.FirstChild) then AddToList(ANode.FirstChild, FPartTwo);
  697. 3: if Assigned(ANode.FirstChild) then AddToList(ANode.FirstChild, FPartThree);
  698. end;
  699. end;
  700. var
  701. zNode: TZjIDTreeNode;
  702. begin
  703. with TDMDataBase(FBillsData) do
  704. begin
  705. zNode := BillsTree.FirstNode;
  706. if Assigned(zNode) then
  707. begin
  708. // 1
  709. I := 1;
  710. strIDList := '';
  711. AddIDToList(zNode, 1);
  712. if not SameText(strIDList, '') then FPartOne.Add(strIDList);
  713. // 2
  714. if Assigned(zNode.NextSibling) then
  715. begin
  716. I := 1;
  717. strIDList := '';
  718. AddIDToList(zNode.NextSibling, 2);
  719. if not SameText(strIDList, '') then FPartTwo.Add(strIDList);
  720. zNode := zNode.NextSibling;
  721. end;
  722. // 3
  723. if Assigned(zNode.NextSibling) then
  724. begin
  725. I := 1;
  726. strIDList := '';
  727. AddIDToList(zNode.NextSibling, 3);
  728. if not SameText(strIDList, '') then FPartThree.Add(strIDList);
  729. end;
  730. end;
  731. end;
  732. end;
  733. { TScExcelItem }
  734. procedure TScExcelItem.AssignFirstChild(ANode: TScExcelItem);
  735. begin
  736. FFirstChild := ANode;
  737. FLastChild := ANode;
  738. end;
  739. function TScExcelItem.GetNextSiblingID: Integer;
  740. begin
  741. if Assigned(FNextSibling) then Result := FNextSibling.ID
  742. else Result := -1;
  743. end;
  744. function TScExcelItem.GetParentID: Integer;
  745. begin
  746. if Assigned(FParent) then Result := FParent.ID
  747. else Result := -1;
  748. end;
  749. function TScExcelItem.HasChildren: Boolean;
  750. begin
  751. if Assigned(FirstChild) then Result := True
  752. else Result := False;
  753. end;
  754. procedure TScExcelItem.MoveLastChild(ANode: TScExcelItem);
  755. begin
  756. FLastChild.NextSibling := ANode;
  757. FLastChild := ANode;
  758. end;
  759. { TCacheGatherNode }
  760. procedure TCacheGatherNode.Assign(aNode: TCacheGatherNode; aIncludeDraw: Boolean);
  761. begin
  762. FCode := aNode.FCode;
  763. FBCode := aNode.FBCode;
  764. FName := aNode.FName;
  765. FUnits := aNode.FUnits;
  766. FUnitPrice := aNode.FUnitPrice;
  767. FTotalPrice := aNode.FTotalPrice;
  768. FMemostring := aNode.FMemostring;
  769. FQuantity := aNode.FQuantity;
  770. FDesignPrice := aNode.FDesignPrice;
  771. FDesignQuantity1 := aNode.FDesignQuantity1;
  772. FDesignQuantity2 := aNode.FDesignQuantity2;
  773. if aIncludeDraw then AssignDraw(aNode);
  774. end;
  775. procedure TCacheGatherNode.AssignDraw(aNode: TCacheGatherNode);
  776. var
  777. I: Integer;
  778. dqiItem: TDrawingQuantityItem;
  779. dqiNewItem: TDrawingQuantityItem;
  780. begin
  781. for I := 0 to aNode.DQList.Count - 1 do
  782. begin
  783. dqiItem := TDrawingQuantityItem(aNode.DQList.List^[I]);
  784. dqiNewItem := TDrawingQuantityItem.Create;
  785. dqiNewItem.ID := FOwner.FMaxDQID;
  786. dqiNewItem.FBillsID := FID;
  787. dqiNewItem.Assign(dqiItem);
  788. FDQList.Add(dqiNewItem);
  789. Inc(FOwner.FMaxDQID);
  790. end;
  791. end;
  792. constructor TCacheGatherNode.Create(aOwner: TCacheGatherTree);
  793. begin
  794. FOwner := aOwner;
  795. FDQList := TList.Create;
  796. FExprsList := TList.Create;
  797. end;
  798. procedure TCacheGatherNode.DeleteChildren;
  799. var
  800. vNode, xNode: TCacheGatherNode;
  801. begin
  802. vNode := FirstChild;
  803. while Assigned(vNode) do
  804. begin
  805. xNode := vNode.NextSibling;
  806. vNode.DeleteChildren;
  807. vNode.DeleteDQItems;
  808. vNode.Free;
  809. vNode := xNode;
  810. end;
  811. end;
  812. procedure TCacheGatherNode.DeleteDQItems;
  813. var
  814. I: Integer;
  815. DQItem: TDrawingQuantityItem;
  816. begin
  817. for I := 0 to FDQList.Count - 1 do
  818. begin
  819. DQItem := TDrawingQuantityItem(FDQList.List^[I]);
  820. DQItem.Free;
  821. end;
  822. end;
  823. destructor TCacheGatherNode.Destroy;
  824. begin
  825. ClearObjectList(FDQList);
  826. FDQList.Free;
  827. ClearObjectList(FExprsList);
  828. FExprsList.Free;
  829. inherited;
  830. end;
  831. function TCacheGatherNode.GetNextSiblingID: Integer;
  832. begin
  833. if Assigned(FNextSibling) then
  834. Result := FNextSibling.ID
  835. else Result := -1;
  836. end;
  837. function TCacheGatherNode.GetParentID: Integer;
  838. begin
  839. if Assigned(FParent) then
  840. Result := FParent.ID
  841. else Result := -1;
  842. end;
  843. function TCacheGatherNode.HasChildren: Boolean;
  844. begin
  845. Result := Assigned(FFirstChild);
  846. end;
  847. procedure TCacheGatherNode.MoveFirstChild(ANode: TCacheGatherNode);
  848. begin
  849. FFirstChild := ANode;
  850. ANode.FParent := Self;
  851. FFirstChild.FParent := Self;
  852. if not Assigned(FLastChild) then
  853. FLastChild := FFirstChild;
  854. end;
  855. procedure TCacheGatherNode.MoveLastChild(ANode: TCacheGatherNode);
  856. begin
  857. FLastChild.FNextSibling := ANode;
  858. ANode.FParent := Self;
  859. ANode.FPreSibling := FLastChild;
  860. FLastChild := ANode;
  861. end;
  862. procedure TCacheGatherNode.MovePreSibling(ANode: TCacheGatherNode);
  863. begin
  864. if Assigned(FPreSibling) then
  865. begin
  866. FPreSibling.FNextSibling := ANode;
  867. ANode.FPreSibling := FPreSibling;
  868. end
  869. else if Assigned(FParent) then
  870. FParent.MoveFirstChild(ANode);
  871. FPreSibling := ANode;
  872. ANode.FParent := Self.FParent;
  873. end;
  874. procedure TCacheGatherNode.RemoveFromParent;
  875. begin
  876. if FParent <> nil then
  877. begin
  878. if FParent.FFirstChild = Self then
  879. FParent.FFirstChild := FNextSibling;
  880. if FParent.FLastChild = Self then
  881. FParent.FLastChild := FPreSibling;
  882. end;
  883. if Assigned(FPreSibling) then
  884. FPreSibling.FNextSibling := FNextSibling;
  885. if Assigned(FNextSibling) then
  886. FNextSibling.FPreSibling := FPreSibling;
  887. FPreSibling := nil;
  888. FNextSibling := nil;
  889. FParent := nil;
  890. end;
  891. { TCacheGatherTree }
  892. procedure TCacheGatherTree.AddBillsNode(ANode: TZjIDTreeNode; AGatherParent: TCacheGatherNode);
  893. var
  894. iID: Integer;
  895. blSelected: Boolean;
  896. gNode: TCacheGatherNode;
  897. begin
  898. blSelected := False;
  899. if TScBillsItem(ANode).Selected then
  900. begin
  901. if Assigned(AGatherParent) then
  902. begin
  903. FTokenID := 0;
  904. GatherCurNode(ANode, AGatherParent, 0);
  905. blSelected := True;
  906. end
  907. else Abort;
  908. end
  909. else
  910. begin
  911. iID := ANode.ID;
  912. if iID >= 100 then iID := FMaxID;
  913. if ANode.ParentID = -1 then
  914. gNode := AddCacheNode(iID, -1, -1)
  915. else
  916. begin
  917. if not Assigned(AGatherParent) then
  918. gNode := AddCacheNode(iID, -1, -1)
  919. else
  920. gNode := AddCacheNode(iID, AGatherParent.ID, -1);
  921. end;
  922. TProject(FProject).BillsData.ExtractBillsRecord(ANode.ID, gNode);
  923. if ANode.ID < 100 then
  924. AddBillsExprs(ANode.ID, gNode);
  925. if not ANode.HasChildren then
  926. TProject(FProject).BillsData.GetDQListByBillsID(ANode.ID, gNode, FMaxDQID);
  927. Inc(FMaxID);
  928. end;
  929. if Assigned(ANode.FirstChild) and not blSelected then AddBillsNode(ANode.FirstChild, gNode);
  930. if Assigned(ANode.NextSibling) then AddBillsNode(ANode.NextSibling, AGatherParent);
  931. end;
  932. function TCacheGatherTree.AddCacheNode(const AID, AParentID,
  933. ANextSiblingID: Integer): TCacheGatherNode;
  934. var
  935. vNode: TCacheGatherNode;
  936. begin
  937. Result := TCacheGatherNode.Create(Self);
  938. Result.ID := AID;
  939. if AParentID <> -1 then
  940. begin
  941. vNode := FindCacheNode(AParentID);
  942. Result.FParent := vNode;
  943. if (ANextSiblingID = -1) and vNode.HasChildren then vNode.MoveLastChild(Result)
  944. else if not vNode.HasChildren or (vNode.FirstChild.ID = ANextSiblingID) then
  945. vNode.MoveFirstChild(Result);
  946. end
  947. else
  948. begin
  949. Result.FParent := nil;
  950. if (ANextSiblingID = -1) and FRoot.HasChildren then FRoot.MoveLastChild(Result)
  951. else if not FRoot.HasChildren or (FRoot.FirstChild.ID = ANextSiblingID) then
  952. FRoot.MoveFirstChild(Result);
  953. end;
  954. if ANextSiblingID = -1 then
  955. Result.FNextSibling := nil
  956. else
  957. begin
  958. vNode := FindCacheNode(ANextSiblingID);
  959. Result.FNextSibling := vNode;
  960. vNode.MovePreSibling(Result);
  961. end;
  962. if AID < 100 then FMinIDList.Add(Result)
  963. else FCacheList.Add(Result);
  964. end;
  965. procedure TCacheGatherTree.CombineNodeQuantity(ASrc,
  966. ADest: TCacheGatherNode);
  967. begin
  968. ADest.Quantity := ADest.Quantity + ASrc.Quantity;
  969. ADest.DesignQuantity1 := ADest.DesignQuantity1 + ASrc.DesignQuantity1;
  970. ADest.DesignQuantity2 := ADest.DesignQuantity2 + ASrc.DesignQuantity2;
  971. ADest.TotalPrice := ADest.TotalPrice + ASrc.TotalPrice;
  972. // 2012.3.5 16:20 何晓勇修改
  973. ADest.Name := ASrc.Name;
  974. if Assigned(ASrc.DQList) and Assigned(ADest.DQList) then
  975. CombineDrawQ(ASrc.DQList, ADest.DQList, ADest.ID);
  976. end;
  977. constructor TCacheGatherTree.Create;
  978. begin
  979. FCacheList := TObjectList.Create;
  980. FMinIDList := TList.Create;
  981. FRoot := TCacheGatherNode.Create(Self);
  982. FRoot.ID := -1;
  983. FMaxID := 400;
  984. FMaxDQID := 1;
  985. end;
  986. procedure TCacheGatherTree.DeleteNode(ANode: TCacheGatherNode);
  987. var
  988. vNext, vPre: TCacheGatherNode;
  989. begin
  990. { ANode.RemoveFromParent;
  991. if Assigned(ANode.FPreSibling) then
  992. ANode.FPreSibling.FNextSibling := ANode.NextSibling;
  993. if Assigned(ANode.FNextSibling) then
  994. ANode.FNextSibling.FPreSibling := ANode.FPreSibling; }
  995. ANode.DeleteChildren;
  996. if ANode.ID < 100 then
  997. begin
  998. DeleteBySerialSearch(ANode);
  999. ANode.Free;
  1000. end
  1001. else DeleteByDichotomySearch(ANode);
  1002. end;
  1003. destructor TCacheGatherTree.Destroy;
  1004. begin
  1005. FCacheList.Free;
  1006. FMinIDList.Free;
  1007. FRoot.Free;
  1008. inherited;
  1009. end;
  1010. function TCacheGatherTree.DichotomySearch(
  1011. const AID: Integer): TCacheGatherNode;
  1012. var
  1013. ilow, ihigh, imid: Integer;
  1014. eNode: TCacheGatherNode;
  1015. begin
  1016. Result := nil;
  1017. ilow := 0;
  1018. ihigh := FCacheList.Count - 1;
  1019. while ilow <= ihigh do
  1020. begin
  1021. imid := (ilow + ihigh) div 2;
  1022. eNode := TCacheGatherNode(FCacheList[imid]);
  1023. if eNode.ID = AID then
  1024. begin
  1025. Result := eNode;
  1026. Break;
  1027. end;
  1028. if eNode.ID < AID then ilow := imid + 1
  1029. else ihigh := imid - 1;
  1030. end;
  1031. end;
  1032. procedure TCacheGatherTree.DeleteByDichotomySearch(const ANode: TCacheGatherNode);
  1033. var
  1034. ilow, ihigh, imid: Integer;
  1035. eNode: TCacheGatherNode;
  1036. begin
  1037. ilow := 0;
  1038. ihigh := FCacheList.Count - 1;
  1039. while ilow <= ihigh do
  1040. begin
  1041. imid := (ilow + ihigh) div 2;
  1042. eNode := TCacheGatherNode(FCacheList[imid]);
  1043. if eNode.ID = ANode.ID then
  1044. begin
  1045. FCacheList.Delete(imid);
  1046. Break;
  1047. end;
  1048. if eNode.ID < ANode.ID then ilow := imid + 1
  1049. else ihigh := imid - 1;
  1050. end;
  1051. end;
  1052. function TCacheGatherTree.FindCacheNode(
  1053. const AID: Integer): TCacheGatherNode;
  1054. begin
  1055. if AID < 100 then Result := SerialSearch(AID)
  1056. else Result := DichotomySearch(AID);
  1057. end;
  1058. procedure TCacheGatherTree.GatherCurNode(ANode: TZjIDTreeNode;
  1059. AGatherParent: TCacheGatherNode; aLevel: Integer);
  1060. var
  1061. I, cValue: Integer;
  1062. sCode, sBCode, sName, sParentCode: string;
  1063. blHasOldCode, blIsCode, blFlag: Boolean;
  1064. cNode, zNode: TZjIDTreeNode;
  1065. gNode, gNextNode, gParNode: TCacheGatherNode;
  1066. begin
  1067. for I := 0 to ANode.ChildCount - 1 do
  1068. begin
  1069. blHasOldCode := False;
  1070. blFlag := False;
  1071. cNode := ANode.ChildNodes[I];
  1072. if Assigned(AGatherParent) then
  1073. begin
  1074. sBCode := AGatherParent.BCode;
  1075. if (aLevel = 0) and Assigned(ANode.Parent) and
  1076. TScBillsItem(ANode.Parent).Selected then
  1077. begin
  1078. sParentCode := FBillsCode + '-' + TokenArray[FTokenID];
  1079. end
  1080. else
  1081. begin
  1082. sParentCode := AGatherParent.Code;
  1083. if (aLevel = 0) and (AGatherParent.Code <> '') then
  1084. begin
  1085. if IncludeToken(AGatherParent.Code) then
  1086. sParentCode := AGatherParent.Code + '-' + TokenArray[FTokenID]
  1087. else
  1088. TProject(FProject).BillsData.ExtractBillsCode(ANode.ID, sParentCode, sBCode, sName);
  1089. sParentCode := ModifyBillsCode(sParentCode);
  1090. end;
  1091. end;
  1092. end
  1093. else
  1094. TProject(FProject).BillsData.ExtractBillsCode(ANode.ID, sParentCode, sBCode, sName);
  1095. if TScBillsItem(cNode).Selected then
  1096. begin
  1097. Inc(FTokenID);
  1098. FBillsCode := sParentCode;
  1099. GatherCurNode(cNode, AGatherParent, 0);
  1100. Dec(FTokenID);
  1101. Continue;
  1102. end;
  1103. TProject(FProject).BillsData.ExtractBillsCode(cNode.ID, sCode, sBCode, sName);
  1104. gNode := AGatherParent.FirstChild;
  1105. while Assigned(gNode) do
  1106. begin
  1107. // if (gNode.Code <> '') or (gNode.BCode <> '') then
  1108. // begin
  1109. if (gNode.Code <> '') and (sCode <> '') then
  1110. begin
  1111. // 1-6-1-2-1 : 1-6-1-N-1
  1112. //sCode := ConvertCode(sCode, gNode.Code);
  1113. sCode := SplitAndConvertCode(sCode, gNode.Code);
  1114. if ScConfigInfo.MatchCodeOnly then
  1115. cValue := CompareCodes(sCode, '', '', gNode.Code, '', '')
  1116. else
  1117. cValue := CompareCodes(sCode, '', sName, gNode.Code, '', gNode.Name);
  1118. blIsCode := True;
  1119. end
  1120. else if (gNode.BCode <> '') and (sBCode <> '') then
  1121. begin
  1122. blIsCode := False;
  1123. if ScConfigInfo.MatchCodeOnly then
  1124. cValue := CompareCodes('', sBCode, '', '', gNode.BCode, '')
  1125. else
  1126. cValue := CompareCodes('', sBCode, sName, '', gNode.BCode, gNode.Name);
  1127. if cValue <> 0 then
  1128. begin
  1129. if Pos(gNode.BCode + '-', sBCode) = 1 then
  1130. begin
  1131. // 101-1与101-1-1 cNode作为gnode的子项添加
  1132. //GatherCurNode(cNode, gNode, aLevel + 1);
  1133. AddGatherNode(gNode, cNode, aLevel + 1, sBCode, sName);
  1134. blHasOldCode := True;
  1135. Break;
  1136. end;
  1137. end;
  1138. end
  1139. { TODO : gnode.code = scode = gnode.bcode = sbcode = '' }
  1140. else if (gNode.Code = sCode) and (gNode.BCode = sBCode) then
  1141. begin
  1142. { TODO : 只有名称的默认当清单加设计数量 }
  1143. blIsCode := False;
  1144. cValue := CompareCodes('', '', sName, '', '', gNode.Name);
  1145. end
  1146. else cValue := 1;
  1147. if cValue = 0 then
  1148. begin
  1149. PlusItems(cNode, gNode, aLevel + 1, blIsCode);
  1150. blHasOldCode := True;
  1151. Break;
  1152. end
  1153. else if cValue < 0 then
  1154. begin
  1155. if ((sBCode <> '') and (Pos(sBCode + '-', gNode.BCode) = 1)) or
  1156. ((sCode <> '') and (Pos(sCode + '-', gNode.Code) = 1)) then
  1157. begin
  1158. gParNode := gNode;
  1159. blFlag := True;
  1160. Break;
  1161. end;
  1162. end;
  1163. // end;
  1164. gNode := gNode.NextSibling;
  1165. end;
  1166. if not blHasOldCode then
  1167. begin
  1168. gNode := AddCacheNode(FMaxID, AGatherParent.ID, -1);
  1169. InternalDetail(gNode, cNode, sParentCode);
  1170. Inc(FMaxID);
  1171. if cNode.HasChildren then
  1172. GatherCurNode(cNode, gNode, aLevel + 1);
  1173. {调整结构,如:207-1-6在207-1前面, 把207-1-6调整为207-1的子节点}
  1174. if blFlag then
  1175. begin
  1176. while Assigned(gParNode) do
  1177. begin
  1178. gNextNode := gParNode.NextSibling;
  1179. if (gNode.ID <> gParNode.ID)
  1180. and
  1181. (
  1182. (Pos(gNode.BCode + '-', gParNode.BCode) = 1)
  1183. or
  1184. (Pos(gNode.Code + '-', gParNode.Code) = 1)
  1185. )
  1186. then
  1187. AdjustStructor(gNode, gParNode);
  1188. gParNode := gNextNode;
  1189. end;
  1190. end;
  1191. end;
  1192. end;
  1193. end;
  1194. function TCacheGatherTree.GetFirstNode: TCacheGatherNode;
  1195. begin
  1196. Result := FRoot.FirstChild;
  1197. end;
  1198. procedure TCacheGatherTree.MergeCacheList;
  1199. var
  1200. I: Integer;
  1201. vNode: TCacheGatherNode;
  1202. begin
  1203. for I := FMinIDList.Count -1 downto 0 do
  1204. begin
  1205. vNode := TCacheGatherNode(FMinIDList[I]);
  1206. FCacheList.Add(vNode);
  1207. end;
  1208. end;
  1209. procedure TCacheGatherTree.MovePreNode(ASrc, ADest: TCacheGatherNode);
  1210. begin
  1211. ASrc.FPreSibling := ADest.FPreSibling;
  1212. if Assigned(ADest.FPreSibling) then
  1213. ADest.FPreSibling.FNextSibling := ASrc;
  1214. ASrc.FParent := ADest.FParent;
  1215. ASrc.FNextSibling := ADest;
  1216. ADest.FPreSibling := ASrc;
  1217. end;
  1218. function TCacheGatherTree.SerialSearch(
  1219. const AID: Integer): TCacheGatherNode;
  1220. var
  1221. I: Integer;
  1222. vNode: TCacheGatherNode;
  1223. begin
  1224. Result := nil;
  1225. for I := 0 to FMinIDList.Count - 1 do
  1226. begin
  1227. vNode := TCacheGatherNode(FMinIDList[I]);
  1228. if vNode.ID = AID then
  1229. begin
  1230. Result := vNode;
  1231. Break;
  1232. end;
  1233. end;
  1234. end;
  1235. procedure TCacheGatherTree.DeleteBySerialSearch(const ANode: TCacheGatherNode);
  1236. var
  1237. I: Integer;
  1238. vNode: TCacheGatherNode;
  1239. begin
  1240. for I := 0 to FMinIDList.Count - 1 do
  1241. begin
  1242. vNode := TCacheGatherNode(FMinIDList[I]);
  1243. if vNode.ID = ANode.ID then
  1244. begin
  1245. FMinIDList.Delete(I);
  1246. Break;
  1247. end;
  1248. end;
  1249. end;
  1250. function TCacheGatherTree.TraverseDBIntoSelf(AProject: TObject): Boolean;
  1251. begin
  1252. Result := True;
  1253. FProject := AProject;
  1254. if TProject(FProject).BillsData.BillsTree.FirstNode <> nil then
  1255. begin
  1256. try
  1257. AddBillsNode(TProject(FProject).BillsData.BillsTree.FirstNode, nil);
  1258. except
  1259. Result := False;
  1260. end;
  1261. end;
  1262. end;
  1263. procedure TCacheGatherTree.TraverseOwnerIntoDB(AProject: TObject);
  1264. var
  1265. project: TProject;
  1266. procedure AddDQItem(ANode: TCacheGatherNode);
  1267. var
  1268. I: Integer;
  1269. DQItem: TDrawingQuantityItem;
  1270. begin
  1271. for I := 0 to ANode.FDQList.Count - 1 do
  1272. begin
  1273. DQItem := TDrawingQuantityItem(ANode.FDQList[I]);
  1274. project.BillsData.AddDrawQItem(DQItem, I + 1);
  1275. end;
  1276. end;
  1277. procedure AddExprs(ANode: TCacheGatherNode);
  1278. var
  1279. I: Integer;
  1280. expNode: TExprsNode;
  1281. begin
  1282. for I := 0 to ANode.FExprsList.Count - 1 do
  1283. begin
  1284. expNode := TExprsNode(ANode.FExprsList[I]);
  1285. with project.BillsData.DMExprs do
  1286. begin
  1287. cdsExprs.Append;
  1288. cdsExprsMajorID.Value := expNode.FMajorID;
  1289. cdsExprsMinorID.Value := expNode.FMinorID;
  1290. cdsExprsRecdID.Value := expNode.FRecdID;
  1291. cdsExprsExprs.Value := expNode.FExprs;
  1292. cdsExprsExprs1.Value := expNode.FExprs1;
  1293. cdsExprs.Post;
  1294. end;
  1295. end;
  1296. end;
  1297. procedure AddBillsAndDrawingItemAndExprs(ANode: TCacheGatherNode);
  1298. begin
  1299. project.BillsData.AddBillsItem(ANode);
  1300. AddDQItem(ANode);
  1301. AddExprs(ANode);
  1302. end;
  1303. procedure AddCacheNodes;
  1304. var
  1305. I: Integer;
  1306. begin
  1307. for I := 0 to FCacheList.Count - 1 do
  1308. AddBillsAndDrawingItemAndExprs(TCacheGatherNode(FCacheList.List^[I]));
  1309. end;
  1310. begin
  1311. project := TProject(AProject);
  1312. project.BillsData.DisconnectBillsTree;
  1313. try
  1314. project.BillsData.DeleteAllBills;
  1315. MergeCacheList;
  1316. SortCacheTreeNodes(FRoot.FFirstChild);
  1317. AddCacheNodes;
  1318. project.Save(False);
  1319. finally
  1320. project.BillsData.ConnectionBillsTree;
  1321. project.BillsData.SaveSerialNo;
  1322. end;
  1323. end;
  1324. function TCacheGatherTree.ModifyBillsCode(const ACode: string): string;
  1325. var
  1326. I: Integer;
  1327. begin
  1328. Result := ACode;
  1329. for I := Length(ACode) downto 1 do
  1330. begin
  1331. if ACode[I] = '-' then
  1332. begin
  1333. Result := Copy(Result, 1, I);
  1334. Break;
  1335. end;
  1336. end;
  1337. if Result[Length(Result)] = '-' then
  1338. Result := Result + TokenArray[FTokenID]
  1339. else
  1340. Result := Result + '-' + TokenArray[FTokenID];
  1341. end;
  1342. procedure TCacheGatherTree.ModifyBillsCode(GNode: TCacheGatherNode;
  1343. const aParentCode: string);
  1344. var
  1345. I, iLen: Integer;
  1346. sCode: string;
  1347. begin
  1348. iLen := 0;
  1349. for I := 1 to Length(aParentCode) do
  1350. begin
  1351. if aParentCode[I] = '-' then Inc(iLen);
  1352. end;
  1353. Inc(iLen);
  1354. sCode := GNode.Code;
  1355. for I := 1 to Length(sCode) do
  1356. begin
  1357. if sCode[I] = '-' then
  1358. begin
  1359. Dec(iLen);
  1360. if iLen = 0 then
  1361. begin
  1362. Delete(sCode, 1, I - 1);
  1363. Break;
  1364. end;
  1365. end;
  1366. end;
  1367. GNode.Code := aParentCode + sCode;
  1368. end;
  1369. procedure TCacheGatherTree.PlusItems(xNode: TZjIDTreeNode;
  1370. GNode: TCacheGatherNode; aLevel: Integer; IsCode: Boolean);
  1371. begin
  1372. with TProject(FProject).BillsData do
  1373. begin
  1374. if IsCode then
  1375. PlusDesignQuantitys(xNode.ID, GNode)
  1376. else
  1377. begin
  1378. PlusBillsQuantity(xNode.ID, GNode);
  1379. if not xNode.HasChildren then
  1380. PlusDQDesignQuantitys(xNode.ID, GNode, FMaxDQID);
  1381. end;
  1382. if xNode.HasChildren then GatherCurNode(xNode, GNode, aLevel);
  1383. end;
  1384. end;
  1385. procedure TCacheGatherTree.InternalDetail(
  1386. AGNode: TCacheGatherNode; ANode: TZjIDTreeNode;
  1387. const AParentCode: string);
  1388. begin
  1389. TProject(FProject).BillsData.ExtractBillsRecord(ANode.ID, AGNode);
  1390. if Assigned(ANode) and (AGNode.Code <> '') then
  1391. ModifyBillsCode(AGNode, AParentCode);
  1392. if not ANode.HasChildren then
  1393. TProject(FProject).BillsData.GetDQListByBillsID(ANode.ID, AGNode, FMaxDQID);
  1394. end;
  1395. procedure TCacheGatherTree.AddGatherNode(AGatherNode: TCacheGatherNode;
  1396. AZjNode: TZjIDTreeNode; aLevel: Integer; const aBCode, aName: string);
  1397. var
  1398. cValue: Integer;
  1399. blFlag: Boolean;
  1400. gNode: TCacheGatherNode;
  1401. begin
  1402. blFlag := False;
  1403. gNode := AGatherNode.FirstChild;
  1404. while Assigned(gNode) do
  1405. begin
  1406. if ScConfigInfo.MatchCodeOnly then
  1407. cValue := CompareCodes('', aBCode, '', '', gNode.BCode, '')
  1408. else
  1409. cValue := CompareCodes('', aBCode, aName, '', gNode.BCode, gNode.Name);
  1410. if cValue = 0 then
  1411. begin
  1412. PlusItems(AZjNode, gNode, aLevel, False);
  1413. blFlag := True;
  1414. Break;
  1415. end;
  1416. if Pos(gNode.BCode + '-', aBCode) = 1 then
  1417. begin
  1418. AddGatherNode(gNode, AZjNode, aLevel, aBCode, aName);
  1419. blFlag := True;
  1420. Break;
  1421. end;
  1422. gNode := gNode.NextSibling;
  1423. end;
  1424. if not blFlag then
  1425. begin
  1426. gNode := AddCacheNode(FMaxID, AGatherNode.ID, -1);
  1427. InternalDetail(gNode, AZjNode, '');
  1428. Inc(FMaxID);
  1429. if AZjNode.HasChildren then
  1430. {GatherCurNode(AZjNode, gNode, aLevel);//} AddBillsNode(AZjNode.FirstChild, gNode);
  1431. end;
  1432. end;
  1433. procedure TCacheGatherTree.AdjustStructor(AParNode,
  1434. AChdNode: TCacheGatherNode);
  1435. var
  1436. xValue: Integer;
  1437. blFlag: Boolean;
  1438. ChildNode, SecChdNode, SecNextNode: TCacheGatherNode;
  1439. begin
  1440. AChdNode.RemoveFromParent;
  1441. if Assigned(AChdNode) then
  1442. begin
  1443. blFlag := False;
  1444. ChildNode := AParNode.FirstChild;
  1445. while Assigned(ChildNode) do
  1446. begin
  1447. xValue := CompareCodes('', AChdNode.BCode, '', '', ChildNode.BCode, '');
  1448. if xValue = 0 then
  1449. begin
  1450. {两节点相加数据,合并}
  1451. CombineNodeQuantity(AChdNode, ChildNode);
  1452. SecChdNode := AChdNode.FirstChild;
  1453. while Assigned(SecChdNode) do
  1454. begin
  1455. SecNextNode := SecChdNode.NextSibling;
  1456. AdjustStructor(ChildNode, SecChdNode);
  1457. SecChdNode := SecNextNode;
  1458. end;
  1459. // 这里2012.3.5.16.20
  1460. DeleteNode(AChdNode);
  1461. //DeleteNode(ChildNode);
  1462. blFlag := True;
  1463. Break;
  1464. end;
  1465. if Pos(ChildNode.BCode + '-', AChdNode.BCode) = 1 then
  1466. begin
  1467. AdjustStructor(ChildNode, AChdNode);
  1468. blFlag := True;
  1469. Break;
  1470. end;
  1471. ChildNode := ChildNode.NextSibling;
  1472. end;
  1473. if not blFlag then
  1474. begin
  1475. // AChdNode.RemoveFromParent;
  1476. if AParNode.HasChildren then
  1477. AParNode.MoveLastChild(AChdNode)
  1478. else
  1479. AParNode.MoveFirstChild(AChdNode);
  1480. end;
  1481. end;
  1482. end;
  1483. function TCacheGatherTree.IncludeToken(const aCode: string): Boolean;
  1484. var
  1485. I: Integer;
  1486. begin
  1487. Result := False;
  1488. for I := 1 to Length(aCode) do
  1489. begin
  1490. if aCode[I] in ['N', 'M', 'Q', 'L', 'P', 'R', 'S', 'T', 'X', 'Y', 'Z'] then
  1491. begin
  1492. Result := True;
  1493. Break;
  1494. end;
  1495. end;
  1496. end;
  1497. function TCacheGatherTree.ConvertCode(const aCode, aGCode: string): string;
  1498. var
  1499. I, J, iDelLen: Integer;
  1500. begin
  1501. Result := aCode;
  1502. for I := 1 to Length(aGCode) do
  1503. begin
  1504. if aGCode[I] in ['N', 'M', 'Q', 'L', 'P', 'R', 'S', 'T', 'X', 'Y', 'Z'] then
  1505. begin
  1506. if I >= Length(Result) then Exit;
  1507. Result[I] := aGCode[I];
  1508. J := I + 1;
  1509. iDelLen := 0;
  1510. while Result[J] <> '-' do
  1511. begin
  1512. Inc(iDelLen);
  1513. Inc(J);
  1514. end;
  1515. Delete(Result, I + 1, iDelLen);
  1516. end;
  1517. end;
  1518. end;
  1519. procedure TCacheGatherTree.CombineDrawQ(ASrcQList, ADestQList: TList; aDestID: Integer);
  1520. var
  1521. I, J: Integer;
  1522. blFlag: Boolean;
  1523. srcQItem, destQItem, newItem: TDrawingQuantityItem;
  1524. begin
  1525. for I := 0 to ASrcQList.Count - 1 do
  1526. begin
  1527. blFlag := False;
  1528. srcQItem := TDrawingQuantityItem(ASrcQList.List^[I]);
  1529. for J := 0 to ADestQList.Count - 1 do
  1530. begin
  1531. destQItem := TDrawingQuantityItem(ADestQList.List^[J]);
  1532. if SameText(destQItem.Name, srcQItem.Name) then
  1533. begin
  1534. destQItem.DesignQuantity1 := srcQItem.DesignQuantity1 + destQItem.DesignQuantity1;
  1535. destQItem.DesignQuantity2 := srcQItem.DesignQuantity2 + destQItem.DesignQuantity2;
  1536. blFlag := True;
  1537. Break;
  1538. end;
  1539. end;
  1540. if not blFlag then
  1541. begin
  1542. newItem := TDrawingQuantityItem.Create;
  1543. newItem.ID := srcQItem.ID;
  1544. newItem.BillsID := aDestID;
  1545. newItem.Name := srcQItem.Name;
  1546. newItem.Units := srcQItem.Units;
  1547. newItem.DesignQuantity1 := srcQItem.DesignQuantity1;
  1548. newItem.DesignQuantity2 := srcQItem.DesignQuantity2;
  1549. newItem.MemoContext := srcQItem.MemoContext;
  1550. ADestQList.Add(newItem);
  1551. end;
  1552. end;
  1553. end;
  1554. procedure TCacheGatherTree.AddBillsExprs(ABillsID: Integer;
  1555. ACacheNode: TCacheGatherNode);
  1556. var
  1557. expNode: TExprsNode;
  1558. begin
  1559. if ACacheNode.FExprsList.Count > 0 then Exit;
  1560. with TProject(FProject).BillsData.DMExprs do
  1561. begin
  1562. if cdsExprs.FindKey([1, 3, ABillsID]) then
  1563. begin
  1564. expNode := TExprsNode.Create;
  1565. expNode.FMajorID := 1;
  1566. expNode.FMinorID := 3;
  1567. expNode.FRecdID := ACacheNode.FID;
  1568. expNode.FExprs := cdsExprsExprs.AsString;
  1569. expNode.FExprs1 := cdsExprsExprs1.AsString;
  1570. ACacheNode.FExprsList.Add(expNode);
  1571. end;
  1572. end;
  1573. end;
  1574. function CompareCacheNode(AItem1, AItem2: Pointer): Integer;
  1575. var
  1576. Node1: TCacheGatherNode absolute AItem1;
  1577. Node2: TCacheGatherNode absolute AItem2;
  1578. begin
  1579. if Node1.FCode <> '' then
  1580. Result := CompareCode(Node1.FCode, Node2.FCode)
  1581. else
  1582. Result := CompareCode(Node1.FBCode, Node2.FBCode);
  1583. end;
  1584. procedure TCacheGatherTree.SortCacheTreeNodes(AParent: TCacheGatherNode);
  1585. var
  1586. lstChildren: TList;
  1587. begin
  1588. if AParent = nil then Exit;
  1589. lstChildren := TList.Create;
  1590. try
  1591. AddChildren(AParent, lstChildren);
  1592. lstChildren.Sort(CompareCacheNode);
  1593. MoveChildren(AParent, lstChildren);
  1594. SortChildren(AParent);
  1595. finally
  1596. lstChildren.Free;
  1597. end;
  1598. end;
  1599. procedure TCacheGatherTree.AddChildren(AParent: TCacheGatherNode;
  1600. AList: TList);
  1601. var
  1602. Node: TCacheGatherNode;
  1603. begin
  1604. Node := AParent.FirstChild;
  1605. while Assigned(Node) do
  1606. begin
  1607. AList.Add(Node);
  1608. Node := Node.NextSibling;
  1609. end;
  1610. end;
  1611. procedure TCacheGatherTree.MoveChildren(AParent: TCacheGatherNode;
  1612. AList: TList);
  1613. var
  1614. iIndex: Integer;
  1615. Node, NextNode: TCacheGatherNode;
  1616. begin
  1617. iIndex := 0;
  1618. while iIndex < AList.Count do
  1619. begin
  1620. Node := TCacheGatherNode(AList[iIndex]);
  1621. if iIndex = 0 then
  1622. begin
  1623. AParent.FFirstChild := Node;
  1624. Node.FPreSibling := nil;
  1625. end;
  1626. if iIndex = AList.Count - 1 then
  1627. begin
  1628. AParent.FLastChild := Node;
  1629. Node.FNextSibling := nil;
  1630. end;
  1631. if iIndex + 1 < AList.Count then
  1632. begin
  1633. NextNode := TCacheGatherNode(AList[iIndex + 1]);
  1634. Node.FNextSibling := NextNode;
  1635. NextNode.FPreSibling := Node;
  1636. end;
  1637. Inc(iIndex);
  1638. end;
  1639. end;
  1640. procedure TCacheGatherTree.SortChildren(AParent: TCacheGatherNode);
  1641. var
  1642. Node: TCacheGatherNode;
  1643. begin
  1644. Node := AParent.FirstChild;
  1645. while Assigned(Node) do
  1646. begin
  1647. SortCacheTreeNodes(Node);
  1648. Node := Node.NextSibling;
  1649. end;
  1650. end;
  1651. function TCacheGatherTree.SplitAndConvertCode(const aCode, aGCode: string;
  1652. ASpliter: Char): string;
  1653. var
  1654. sgsCode, sgsGCode: TStrings;
  1655. iNum: Integer;
  1656. sCurCodeNum: string;
  1657. begin
  1658. sgsCode := TStringList.Create;
  1659. sgsGCode := TStringList.Create;
  1660. try
  1661. sgsCode.Delimiter := ASpliter;
  1662. sgsCode.DelimitedText := aCode;
  1663. sgsGCode.Delimiter := ASpliter;
  1664. sgsGCode.DelimitedText := aGCode;
  1665. for iNum := 0 to Min(sgsGCode.Count, sgsCode.Count) - 1 do
  1666. begin
  1667. sCurCodeNum := sgsGCode[iNum];
  1668. if sCurCodeNum[1] in ['N', 'M', 'Q', 'L', 'P', 'R', 'S', 'T', 'X', 'Y', 'Z'] then
  1669. sgsCode[iNum] := sgsGCode[iNum];
  1670. end;
  1671. finally
  1672. Result := sgsCode.DelimitedText;
  1673. sgsCode.Free;
  1674. sgsGCode.Free;
  1675. end;
  1676. end;
  1677. { TMergeGatherTree }
  1678. procedure TMergeGatherTree.AddDrawItems(aCdsDraw: TClientDataSet; aBillsID: Integer;
  1679. aCGNode: TCacheGatherNode);
  1680. var
  1681. dqiItem: TDrawingQuantityItem;
  1682. begin
  1683. with aCdsDraw do
  1684. begin
  1685. SetRange([aBillsID], [aBillsID]);
  1686. while not Eof do
  1687. begin
  1688. dqiItem := TDrawingQuantityItem.Create;
  1689. dqiItem.ID := FMaxDQID;
  1690. dqiItem.BillsID := aCGNode.ID;
  1691. dqiItem.Name := FieldByName(sName).AsString;
  1692. dqiItem.Units := FieldByName(sUnits).AsString;
  1693. dqiItem.DesignQuantity1 := FieldByName(sDQuantity1).AsFloat;
  1694. dqiItem.DesignQuantity2 := FieldByName(sDQuantity2).AsFloat;
  1695. dqiItem.MemoContext := FieldByName(sMemoContext).AsString;
  1696. aCGNode.DQList.Add(dqiItem);
  1697. Inc(FMaxDQID);
  1698. Next;
  1699. end;
  1700. CancelRange;
  1701. end;
  1702. end;
  1703. procedure TMergeGatherTree.AddExprs(AORecID: Integer; AGNode: TCacheGatherNode);
  1704. var
  1705. expNode: TExprsNode;
  1706. begin
  1707. if AGNode.FExprsList.Count > 0 then Exit;
  1708. if CdsExprs.FindKey([1, 3, AORecID]) then
  1709. begin
  1710. expNode := TExprsNode.Create;
  1711. expNode.FMajorID := 1;
  1712. expNode.FMinorID := 3;
  1713. expNode.FRecdID := AGNode.FID;
  1714. expNode.FExprs := CdsExprs.FieldByName('Exprs').AsString;
  1715. expNode.FExprs1 := CdsExprs.FieldByName('Exprs1').AsString;
  1716. AGNode.FExprsList.Add(expNode);
  1717. end;
  1718. end;
  1719. procedure TMergeGatherTree.AddGatherNode(aSrcNode,
  1720. aDstNode: TCacheGatherNode);
  1721. var
  1722. cgnNode: TCacheGatherNode;
  1723. begin
  1724. cgnNode := AddSingleGatherNode(aSrcNode, aDstNode);
  1725. if cgnNode = nil then Exit;
  1726. AddGatherNode(aSrcNode.FirstChild, cgnNode);
  1727. AddGatherNode(aSrcNode.NextSibling, aDstNode);
  1728. end;
  1729. procedure TMergeGatherTree.AddNode(aNode: TZjIDTreeNode;
  1730. aGatherNode: TCacheGatherNode; aBillsTree: TZjIDTree;
  1731. aCdsDraw: TClientDataSet;
  1732. aIsOpened: Boolean);
  1733. var
  1734. cgnNode: TCacheGatherNode;
  1735. begin
  1736. cgnNode := AddSingleNode(aNode, aGatherNode, aBillsTree, aCdsDraw, aIsOpened);
  1737. if cgnNode = nil then Exit;
  1738. AddNode(aNode.FirstChild, cgnNode, aBillsTree, aCdsDraw, aIsOpened);
  1739. AddNode(aNode.NextSibling, aGatherNode, aBillsTree, aCdsDraw, aIsOpened);
  1740. end;
  1741. function TMergeGatherTree.AddSingleGatherNode(aSrcNode,
  1742. aDstNode: TCacheGatherNode): TCacheGatherNode;
  1743. var
  1744. iID: Integer;
  1745. begin
  1746. Result := nil;
  1747. if aSrcNode = nil then Exit;
  1748. if aSrcNode.ID < 100 then
  1749. iID := aSrcNode.ID
  1750. else
  1751. begin
  1752. iID := FMaxID;
  1753. Inc(FMaxID);
  1754. end;
  1755. if Assigned(aDstNode) then
  1756. Result := AddCacheNode(iID, aDstNode.ID, -1)
  1757. else
  1758. Result := AddCacheNode(iID, -1, -1);
  1759. Result.Assign(aSrcNode);
  1760. end;
  1761. function TMergeGatherTree.AddSingleNode(aNode: TZjIDTreeNode;
  1762. aGatherNode: TCacheGatherNode; aBillsTree: TZjIDTree;
  1763. aCdsDraw: TClientDataSet; aIsOpened: Boolean): TCacheGatherNode;
  1764. var
  1765. iID: Integer;
  1766. begin
  1767. Result := nil;
  1768. if aNode = nil then Exit;
  1769. if aNode.ID < 100 then
  1770. iID := aNode.ID
  1771. else
  1772. begin
  1773. iID := FMaxID;
  1774. Inc(FMaxID);
  1775. end;
  1776. if Assigned(aGatherNode) then
  1777. Result := AddCacheNode(iID, aGatherNode.ID, -1)
  1778. else
  1779. Result := AddCacheNode(iID, -1, -1);
  1780. if aIsOpened then
  1781. begin
  1782. AssignByOpened(aBillsTree, aNode, Result);
  1783. TDMDataBase(TAdditinalTree(aBillsTree).Bills).GetDQListByBillsID(aNode.ID, Result, FMaxDQID);
  1784. end
  1785. else
  1786. begin
  1787. AssignTo(aNode, Result);
  1788. AddDrawItems(aCdsDraw, aNode.ID, Result);
  1789. end;
  1790. AddExprs(aNode.ID, Result);
  1791. ReCodeNode(Result);
  1792. end;
  1793. procedure TMergeGatherTree.AssignByOpened(aBillsTree: TObject; aNode: TZjIDTreeNode;
  1794. aGatherNode: TCacheGatherNode);
  1795. begin
  1796. with TDMDataBase(TAdditinalTree(aBillsTree).Bills) do
  1797. begin
  1798. if cdsBills.FindKey([aNode.ID]) then
  1799. begin
  1800. aGatherNode.FCode := cdsBillsCode.AsString;
  1801. aGatherNode.FBCode := cdsBillsB_Code.AsString;
  1802. aGatherNode.FName := cdsBillsName.AsString;
  1803. aGatherNode.FUnits := cdsBillsUnits.AsString;
  1804. aGatherNode.FUnitPrice := cdsBillsUnitPrice.AsFloat;
  1805. aGatherNode.FTotalPrice := cdsBillsTotalPrice.AsFloat;
  1806. aGatherNode.FMemostring := cdsBillsMemoStr.AsString;
  1807. aGatherNode.FQuantity := cdsBillsQuantity.AsFloat;
  1808. aGatherNode.FDesignQuantity1 := cdsBillsDesignQuantity.AsFloat;
  1809. aGatherNode.FDesignQuantity2 := cdsBillsDesignQuantity2.AsFloat;
  1810. aGatherNode.FDesignPrice := cdsBillsDesignPrice.AsFloat;
  1811. end;
  1812. end;
  1813. end;
  1814. procedure TMergeGatherTree.AssignTo(aNode: TZjIDTreeNode;
  1815. aGatherNode: TCacheGatherNode);
  1816. begin
  1817. aGatherNode.FCode := TAdditionalItem(aNode).Code;
  1818. aGatherNode.FBCode := TAdditionalItem(aNode).B_Code;
  1819. aGatherNode.FName := TAdditionalItem(aNode).Name;
  1820. aGatherNode.FUnits := TAdditionalItem(aNode).Units;
  1821. aGatherNode.FUnitPrice := TAdditionalItem(aNode).UnitPrice;
  1822. aGatherNode.FTotalPrice := TAdditionalItem(aNode).TotalPrice;
  1823. aGatherNode.FMemostring := TAdditionalItem(aNode).MemoStr;
  1824. aGatherNode.FQuantity := TAdditionalItem(aNode).Quantity;
  1825. aGatherNode.FDesignQuantity1 := TAdditionalItem(aNode).DesignQuantity;
  1826. aGatherNode.FDesignQuantity2 := TAdditionalItem(aNode).DesignQuantity2;
  1827. aGatherNode.FDesignPrice := TAdditionalItem(aNode).DesignPrice;
  1828. end;
  1829. procedure TMergeGatherTree.GatherBillsTree(aBillsTree: TZjIDTree);
  1830. begin
  1831. FBillsTree1 := aBillsTree;
  1832. InitMaxID;
  1833. if Assigned(FBillsTree1) then
  1834. AddNode(FBillsTree1.FirstNode, nil, FBillsTree1, FCdsDraw1, FIsOpen1);
  1835. { if Assigned(FBillsTree2) and (FBillsTree1 <> FBillsTree2) then
  1836. UpdateNode(FBillsTree2.FirstNode, nil); }
  1837. end;
  1838. procedure TMergeGatherTree.GatherTree(aGatherTree: TMergeGatherTree);
  1839. begin
  1840. if Self <> aGatherTree then
  1841. UpdateGatherNode(aGatherTree.FirstNode, nil);
  1842. end;
  1843. procedure TMergeGatherTree.InitMaxID;
  1844. begin
  1845. FMaxID := 100;
  1846. FMaxDQID := 1;
  1847. end;
  1848. procedure TMergeGatherTree.ReCodeNode(ANode: TCacheGatherNode);
  1849. function GetPreSiblingCount: Integer;
  1850. var
  1851. cgnNode: TCacheGatherNode;
  1852. begin
  1853. Result := 0;
  1854. cgnNode := ANode.FPreSibling;
  1855. while Assigned(cgnNode) do
  1856. begin
  1857. Inc(Result);
  1858. cgnNode := cgnNode.FPreSibling;
  1859. end;
  1860. end;
  1861. function GetPosition(const AName, AStr, AStrSpare: string): Integer;
  1862. begin
  1863. Result := Pos(AStr, AName);
  1864. if Result = 0 then
  1865. Result := Pos(AStrSpare, AName);
  1866. end;
  1867. function CheckNameIsPeg(const AName: string): Boolean;
  1868. var
  1869. iPosK, iPosPlus: Integer;
  1870. fNum: Double;
  1871. begin
  1872. Result := False;
  1873. iPosK := GetPosition(AName, 'K', 'k');
  1874. iPosPlus := GetPosition(AName, '+', '+');
  1875. if (iPosK = 0) or (iPosPlus = 0) or (iPosPlus < iPosK) then Exit;
  1876. Result := TryStrToFloat(Copy(AName, iPosK + 1, iPosPlus - iPosK - 1), fNum);
  1877. end;
  1878. var
  1879. cgnNode: TCacheGatherNode;
  1880. strCode: string;
  1881. begin
  1882. if ANode = nil then Exit;
  1883. if CheckNameIsPeg(ANode.FName) then
  1884. begin
  1885. cgnNode := ANode.FParent;
  1886. if cgnNode <> nil then
  1887. begin
  1888. strCode := cgnNode.FCode;
  1889. ANode.FCode := strCode + '-' + IntToStr(GetPreSiblingCount + 1);
  1890. end
  1891. else
  1892. ANode.FCode := IntToStr(GetPreSiblingCount + 1);
  1893. end;
  1894. end;
  1895. procedure TMergeGatherTree.UpdateBillsTree(aBillsTree: TZjIDTree);
  1896. begin
  1897. FBillsTree2 := aBillsTree;
  1898. if Assigned(FBillsTree2) and (FBillsTree1 <> FBillsTree2) then
  1899. UpdateNode(FBillsTree2.FirstNode, nil);
  1900. end;
  1901. procedure TMergeGatherTree.UpdateDrawItems(aBillsID: Integer;
  1902. aCGNode: TCacheGatherNode);
  1903. var
  1904. I: Integer;
  1905. bFounded: Boolean;
  1906. dqiItem: TDrawingQuantityItem;
  1907. begin
  1908. with FCdsDraw2 do
  1909. begin
  1910. SetRange([aBillsID], [aBillsID]);
  1911. while not Eof do
  1912. begin
  1913. bFounded := False;
  1914. for I := 0 to aCGNode.DQList.Count - 1 do
  1915. begin
  1916. dqiItem := TDrawingQuantityItem(aCGNode.DQList.List^[I]);
  1917. if SameText(dqiItem.Name, FieldByName(sName).AsString) then
  1918. begin
  1919. dqiItem.DesignQuantity1 := dqiItem.DesignQuantity1 + FieldByName(sDQuantity1).AsFloat;
  1920. dqiItem.DesignQuantity2 := dqiItem.DesignQuantity2 + FieldByName(sDQuantity2).AsFloat;
  1921. bFounded := True;
  1922. Break;
  1923. end;
  1924. end;
  1925. if not bFounded then
  1926. begin
  1927. dqiItem := TDrawingQuantityItem.Create;
  1928. dqiItem.ID := FMaxDQID;
  1929. dqiItem.BillsID := aCGNode.ID;
  1930. dqiItem.Name := FieldByName(sName).AsString;
  1931. dqiItem.Units := FieldByName(sUnits).AsString;
  1932. dqiItem.DesignQuantity1 := FieldByName(sDQuantity1).AsFloat;
  1933. dqiItem.DesignQuantity2 := FieldByName(sDQuantity2).AsFloat;
  1934. dqiItem.MemoContext := FieldByName(sMemoContext).AsString;
  1935. aCGNode.DQList.Add(dqiItem);
  1936. Inc(FMaxDQID);
  1937. end;
  1938. Next;
  1939. end;
  1940. CancelRange;
  1941. end;
  1942. end;
  1943. procedure TMergeGatherTree.UpdateGatherDrawItems(aSrcNode,
  1944. aDstNode: TCacheGatherNode);
  1945. var
  1946. I : Integer;
  1947. J : Integer;
  1948. bFounded : Boolean;
  1949. dqiSrcItem: TDrawingQuantityItem;
  1950. dqiDstItem: TDrawingQuantityItem;
  1951. begin
  1952. for I := 0 to aSrcNode.DQList.Count - 1 do
  1953. begin
  1954. bFounded := False;
  1955. dqiSrcItem := TDrawingQuantityItem(aSrcNode.DQList.List^[I]);
  1956. for J := 0 to aDstNode.DQList.Count - 1 do
  1957. begin
  1958. dqiDstItem := TDrawingQuantityItem(aDstNode.DQList.List^[J]);
  1959. if SameText(dqiSrcItem.FName, dqiDstItem.FName) then
  1960. begin
  1961. dqiDstItem.DesignQuantity1 := dqiDstItem.DesignQuantity1 + dqiSrcItem.DesignQuantity1;
  1962. dqiDstItem.DesignQuantity2 := dqiDstItem.DesignQuantity2 + dqiSrcItem.DesignQuantity2;
  1963. bFounded := True;
  1964. Break;
  1965. end;
  1966. end;
  1967. if not bFounded then
  1968. begin
  1969. dqiDstItem := TDrawingQuantityItem.Create;
  1970. dqiDstItem.ID := FMaxDQID;
  1971. dqiDstItem.FBillsID := aDstNode.ID;
  1972. dqiDstItem.Assign(dqiSrcItem);
  1973. aDstNode.DQList.Add(dqiDstItem);
  1974. Inc(FMaxDQID);
  1975. end;
  1976. end;
  1977. end;
  1978. procedure TMergeGatherTree.UpdateGatherNode(aSrcNode,
  1979. aDstNode: TCacheGatherNode);
  1980. var
  1981. bAdd: Boolean;
  1982. iParentID: Integer;
  1983. iCompare: Integer;
  1984. cgnTemNode: TCacheGatherNode;
  1985. cgnParNode: TCacheGatherNode;
  1986. cgnNode: TCacheGatherNode;
  1987. begin
  1988. if aSrcNode = nil then Exit;
  1989. if aDstNode = nil then
  1990. begin
  1991. cgnNode := FirstNode;
  1992. iParentID := -1;
  1993. end
  1994. else
  1995. begin
  1996. cgnNode := aDstNode.FirstChild;
  1997. iParentID := aDstNode.ID;
  1998. end;
  1999. bAdd := True;
  2000. while Assigned(cgnNode) do
  2001. begin
  2002. if aSrcNode.FCode <> '' then
  2003. iCompare := CompareCodes(aSrcNode.FCode, '', aSrcNode.FName, cgnNode.FCode, '', cgnNode.FName)
  2004. else if aSrcNode.FBCode <> '' then
  2005. iCompare := CompareCodes('', aSrcNode.FBCode, aSrcNode.FName, '', cgnNode.FBCode, cgnNode.FName)
  2006. else
  2007. iCompare := CompareCodes('', '', aSrcNode.FName, '', '', cgnNode.FName);
  2008. if iCompare = 0 then
  2009. begin
  2010. UpdateGatherQuantity(aSrcNode, cgnNode);
  2011. UpdateGatherDrawItems(aSrcNode, cgnNode);
  2012. bAdd := False;
  2013. Break;
  2014. end
  2015. else if iCompare > 0 then
  2016. begin
  2017. if ((cgnNode.FCode <> '') and (Pos(cgnNode.FCode + '-', aSrcNode.FCode) = 1)) or
  2018. ((cgnNode.FBCode <> '') and (Pos(cgnNode.FBCode + '-', aSrcNode.FBCode) = 1))
  2019. then
  2020. begin
  2021. UpdateGatherNode(aSrcNode, cgnNode);
  2022. UpdateGatherNode(aSrcNode.NextSibling, aDstNode);
  2023. Exit;
  2024. end;
  2025. end
  2026. else
  2027. begin
  2028. if ((aSrcNode.FCode <> '') and (Pos(aSrcNode.FCode + '-', cgnNode.FCode) = 1)) or
  2029. ((aSrcNode.FBCode <> '') and (Pos(aSrcNode.FBCode + '-', cgnNode.FBCode) = 1)) then
  2030. begin
  2031. cgnTemNode := cgnNode.NextSibling;
  2032. cgnParNode := AddSingleGatherNode(aSrcNode, aDstNode);
  2033. AddGatherNode(aSrcNode.FirstChild, cgnParNode);
  2034. AdjustStructor(cgnParNode, cgnNode);
  2035. while Assigned(cgnTemNode) do
  2036. begin
  2037. cgnNode := cgnTemNode;
  2038. cgnTemNode := cgnTemNode.NextSibling;
  2039. if (cgnNode.FBCode <> '') and (Pos(cgnParNode.FBCode + '-', cgnNode.FBCode) = 1) then
  2040. AdjustStructor(cgnParNode, cgnNode);
  2041. end;
  2042. UpdateGatherNode(aSrcNode.NextSibling, aDstNode);
  2043. Exit;
  2044. end;
  2045. end;
  2046. cgnNode := cgnNode.NextSibling;
  2047. end;
  2048. if bAdd then
  2049. begin
  2050. if aSrcNode.ID < 100 then
  2051. cgnNode := AddCacheNode(aSrcNode.ID, iParentID, -1)
  2052. else
  2053. begin
  2054. cgnNode := AddCacheNode(FMaxID, iParentID, -1);
  2055. Inc(FMaxID);
  2056. end;
  2057. cgnNode.Assign(aSrcNode);
  2058. AddGatherNode(aSrcNode.FirstChild, cgnNode);
  2059. end
  2060. else
  2061. UpdateGatherNode(aSrcNode.FirstChild, cgnNode);
  2062. UpdateGatherNode(aSrcNode.NextSibling, aDstNode);
  2063. end;
  2064. procedure TMergeGatherTree.UpdateGatherQuantity(aSrcNode,
  2065. aDstNode: TCacheGatherNode);
  2066. begin
  2067. aDstNode.FQuantity := aDstNode.FQuantity + aSrcNode.Quantity;
  2068. aDstNode.FTotalPrice := aDstNode.FTotalPrice + aSrcNode.TotalPrice;
  2069. aDstNode.FDesignQuantity1 := aDstNode.FDesignQuantity1 + aSrcNode.DesignQuantity1;
  2070. aDstNode.FDesignQuantity2 := aDstNode.FDesignQuantity2 + aSrcNode.DesignQuantity2;
  2071. if aDstNode.FCode <> '' then
  2072. begin
  2073. if aDstNode.FDesignQuantity1 = 0 then
  2074. aDstNode.FDesignPrice := 0
  2075. else
  2076. aDstNode.FDesignPrice := RoundTo(aDstNode.FTotalPrice / aDstNode.FDesignQuantity1, -3);
  2077. end
  2078. else
  2079. begin
  2080. if aDstNode.FQuantity = 0 then
  2081. aDstNode.FUnitPrice := 0
  2082. else
  2083. aDstNode.FUnitPrice := RoundTo(aDstNode.FTotalPrice / aDstNode.FQuantity, -3);
  2084. end;
  2085. end;
  2086. procedure TMergeGatherTree.UpdateNode(aNode: TZjIDTreeNode;
  2087. aGatherNode: TCacheGatherNode);
  2088. function CompareNode(SrcNode: TScBillsItem; DestNode: TCacheGatherNode): Integer;
  2089. var
  2090. strSrcName, strDestName: string;
  2091. begin
  2092. if (not FMergeByCode) or ((SrcNode.SBillCode = '') and
  2093. (SrcNode.SBillBCode = '') and (DestNode.FCode = '') and (DestNode.FBCode = '')) then
  2094. begin
  2095. strSrcName := SrcNode.SBillName;
  2096. strDestName := DestNode.FName;
  2097. end;
  2098. Result := CompareCodes(SrcNode.SBillCode, SrcNode.SBillBCode, strSrcName,
  2099. DestNode.FCode, DestNode.FBCode, strDestName);
  2100. end;
  2101. var
  2102. bAdd: Boolean;
  2103. iCompare: Integer;
  2104. cgnNode: TCacheGatherNode;
  2105. cgnTemNode: TCacheGatherNode;
  2106. cgnParNode: TCacheGatherNode;
  2107. begin
  2108. if aNode = nil then Exit;
  2109. if aGatherNode = nil then
  2110. cgnNode := FirstNode
  2111. else
  2112. cgnNode := aGatherNode.FirstChild;
  2113. bAdd := True;
  2114. while Assigned(cgnNode) do
  2115. begin
  2116. iCompare := CompareNode(TScBillsItem(aNode), cgnNode);
  2117. {if TScBillsItem(aNode).SBillCode <> '' then
  2118. iCompare := CompareCodes(TScBillsItem(aNode).SBillCode, '', TScBillsItem(aNode).SBillName, cgnNode.FCode, '', cgnNode.FName)
  2119. else if TScBillsItem(aNode).SBillBCode <> '' then
  2120. iCompare := CompareCodes('', TScBillsItem(aNode).SBillBCode, TScBillsItem(aNode).SBillName, '', cgnNode.FBCode, cgnNode.FName)
  2121. else
  2122. iCompare := CompareCodes('', '', TScBillsItem(aNode).SBillName, '', '', cgnNode.FName); }
  2123. if iCompare = 0 then
  2124. begin
  2125. if FIsOpen2 then
  2126. begin
  2127. UpdateQuantityByOpened(aNode, cgnNode);
  2128. TDMDataBase(TAdditinalTree(FBillsTree2).Bills).PlusDQDesignQuantitys(aNode.ID, cgnNode, FMaxDQID);
  2129. end
  2130. else
  2131. begin
  2132. UpdateQuantity(aNode, cgnNode);
  2133. UpdateDrawItems(aNode.ID, cgnNode);
  2134. end;
  2135. bAdd := False;
  2136. Break;
  2137. end
  2138. else if iCompare > 0 then
  2139. begin
  2140. if ((cgnNode.FCode <> '') and (Pos(cgnNode.FCode + '-', TScBillsItem(aNode).SBillCode) = 1)) or
  2141. ((cgnNode.FBCode <> '') and (Pos(cgnNode.FBCode + '-', TScBillsItem(aNode).SBillBCode) = 1)) then
  2142. begin
  2143. UpdateNode(aNode, cgnNode);
  2144. // 去掉,重复计算了. 2011.6.17
  2145. //UpdateNode(aNode.NextSibling, aGatherNode);
  2146. Exit;
  2147. end;
  2148. end
  2149. else
  2150. begin
  2151. if ((TScBillsItem(aNode).SBillCode <> '') and (Pos(TScBillsItem(aNode).SBillCode + '-', cgnNode.FCode) = 1)) or
  2152. ((TScBillsItem(aNode).SBillBCode <> '') and (Pos(TScBillsItem(aNode).SBillBCode + '-', cgnNode.FBCode) = 1)) then
  2153. begin
  2154. cgnTemNode := cgnNode.NextSibling;
  2155. cgnParNode := AddSingleNode(aNode, aGatherNode, FBillsTree2, FCdsDraw2, FIsOpen2);
  2156. AddNode(aNode.FirstChild, cgnParNode, FBillsTree2, FCdsDraw2, FIsOpen2);
  2157. AdjustStructor(cgnParNode, cgnNode);
  2158. while Assigned(cgnTemNode) do
  2159. begin
  2160. cgnNode := cgnTemNode;
  2161. cgnTemNode := cgnTemNode.NextSibling;
  2162. if (cgnNode.FBCode <> '') then
  2163. begin
  2164. if (Pos(cgnParNode.FBCode + '-', cgnNode.FBCode) = 1) then
  2165. AdjustStructor(cgnParNode, cgnNode);
  2166. end;
  2167. end;
  2168. UpdateNode(aNode.NextSibling, aGatherNode);
  2169. Exit;
  2170. end;
  2171. end;
  2172. cgnNode := cgnNode.NextSibling;
  2173. end;
  2174. if bAdd then
  2175. begin
  2176. cgnNode := AddSingleNode(aNode, aGatherNode, FBillsTree2, FCdsDraw2, FIsOpen2);
  2177. AddNode(aNode.FirstChild, cgnNode, FBillsTree2, FCdsDraw2, FIsOpen2);
  2178. end
  2179. else
  2180. UpdateNode(aNode.FirstChild, cgnNode);
  2181. UpdateNode(aNode.NextSibling, aGatherNode);
  2182. end;
  2183. procedure TMergeGatherTree.UpdateQuantity(aNode: TZjIDTreeNode;
  2184. aGatherNode: TCacheGatherNode);
  2185. begin
  2186. aGatherNode.FQuantity := aGatherNode.FQuantity + TAdditionalItem(aNode).Quantity;
  2187. aGatherNode.FTotalPrice := aGatherNode.FTotalPrice + TAdditionalItem(aNode).TotalPrice;
  2188. aGatherNode.FDesignQuantity1 := aGatherNode.FDesignQuantity1 + TAdditionalItem(aNode).DesignQuantity;
  2189. aGatherNode.FDesignQuantity2 := aGatherNode.FDesignQuantity2 + TAdditionalItem(aNode).DesignQuantity2;
  2190. if aGatherNode.FCode <> '' then
  2191. begin
  2192. if aGatherNode.FDesignQuantity1 = 0 then
  2193. aGatherNode.FDesignPrice := 0
  2194. else
  2195. aGatherNode.FDesignPrice := RoundTo(aGatherNode.FTotalPrice / aGatherNode.FDesignQuantity1, -3);
  2196. end
  2197. else
  2198. begin
  2199. if aGatherNode.FQuantity = 0 then
  2200. aGatherNode.FUnitPrice := 0
  2201. else
  2202. aGatherNode.FUnitPrice := RoundTo(aGatherNode.FTotalPrice / aGatherNode.FQuantity, -3);
  2203. end;
  2204. end;
  2205. procedure TMergeGatherTree.UpdateQuantityByOpened(aNode: TZjIDTreeNode;
  2206. aGatherNode: TCacheGatherNode);
  2207. begin
  2208. with TDMDataBase(TAdditinalTree(FBillsTree2).Bills) do
  2209. begin
  2210. if cdsBills.FindKey([aNode.ID]) then
  2211. begin
  2212. aGatherNode.FTotalPrice := aGatherNode.FTotalPrice + cdsBillsTotalPrice.AsFloat;
  2213. aGatherNode.FQuantity := aGatherNode.FQuantity + cdsBillsQuantity.AsFloat;
  2214. aGatherNode.FDesignQuantity1 := aGatherNode.FDesignQuantity1 + cdsBillsDesignQuantity.AsFloat;
  2215. aGatherNode.FDesignQuantity2 := aGatherNode.FDesignQuantity2 + cdsBillsDesignQuantity2.AsFloat;
  2216. if aGatherNode.FCode <> '' then
  2217. begin
  2218. if aGatherNode.FDesignQuantity1 = 0 then
  2219. aGatherNode.FDesignPrice := 0
  2220. else
  2221. aGatherNode.FDesignPrice := RoundTo(aGatherNode.FTotalPrice / aGatherNode.FDesignQuantity1, -3);
  2222. end
  2223. else
  2224. begin
  2225. if aGatherNode.FQuantity = 0 then
  2226. aGatherNode.FUnitPrice := 0
  2227. else
  2228. aGatherNode.FUnitPrice := RoundTo(aGatherNode.FTotalPrice / aGatherNode.FQuantity, -3);
  2229. end;
  2230. end;
  2231. end;
  2232. end;
  2233. procedure TMergeGatherTree.WriteBills(aNode: TCacheGatherNode;
  2234. aTable: TDataSet);
  2235. begin
  2236. with aTable do
  2237. begin
  2238. Append;
  2239. FieldByName(SID).AsInteger := aNode.ID;
  2240. FieldByName(sParentID).AsInteger := aNode.ParentID;
  2241. FieldByName(sNextSiblingID).AsInteger := aNode.NextSiblingID;
  2242. FieldByName(sCode).AsString := aNode.Code;
  2243. if SameText(aNode.Code, '') then
  2244. begin
  2245. if aNode.Quantity <> 0 then
  2246. FieldByName(sQuantity).AsFloat := aNode.Quantity;
  2247. end
  2248. else
  2249. begin
  2250. FieldByName(sDesignQuantity).AsFloat := aNode.DesignQuantity1;
  2251. FieldByName(sDesignQuantity2).AsFloat := aNode.DesignQuantity2;
  2252. end;
  2253. FieldByName(sB_Code).AsString := aNode.BCode;
  2254. FieldByName(sName).AsString := aNode.Name;
  2255. FieldByName(sUnits).AsString := aNode.Units;
  2256. FieldByName(sUnitPrice).AsFloat := aNode.UnitPrice;
  2257. FieldByName(STotalPrice).AsFloat := aNode.TotalPrice;
  2258. FieldByName(sMemoStr).AsString := aNode.MemoString;
  2259. FieldByName(sIsPreDefine).AsBoolean := aNode.ParentID = -1;
  2260. Post;
  2261. end;
  2262. end;
  2263. procedure TMergeGatherTree.WriteDraw(aNode: TCacheGatherNode;
  2264. aTable: TDataSet);
  2265. var
  2266. I: Integer;
  2267. DQItem: TDrawingQuantityItem;
  2268. begin
  2269. for I := 0 to aNode.FDQList.Count - 1 do
  2270. begin
  2271. DQItem := TDrawingQuantityItem(ANode.FDQList.List^[I]);
  2272. with aTable do
  2273. begin
  2274. Append;
  2275. FieldByName(SID).AsInteger := DQItem.ID;
  2276. FieldByName(sSerinalNo).AsInteger := I + 1;
  2277. FieldByName(sBillsID).AsInteger := DQItem.BillsID;
  2278. FieldByName(sName).AsString := DQItem.Name;
  2279. FieldByName(sUnits).AsString := DQItem.Units;
  2280. if DQItem.DesignQuantity1 <> 0 then
  2281. FieldByName(sDQuantity1).AsFloat := DQItem.DesignQuantity1;
  2282. if DQItem.DesignQuantity2 <> 0 then
  2283. FieldByName(sDQuantity2).AsFloat := DQItem.DesignQuantity2;
  2284. FieldByName(sMemoContext).AsString := DQItem.MemoContext;
  2285. Post;
  2286. end;
  2287. end;
  2288. end;
  2289. procedure TMergeGatherTree.WriteExprs(aNode: TCacheGatherNode;
  2290. ADataset: TDataSet);
  2291. var
  2292. I: Integer;
  2293. expNode: TExprsNode;
  2294. begin
  2295. for I := 0 to aNode.FExprsList.Count - 1 do
  2296. begin
  2297. expNode := TExprsNode(aNode.FExprsList[I]);
  2298. ADataset.Append;
  2299. ADataset.FieldByName('MajorID').Value := expNode.FMajorID;
  2300. ADataset.FieldByName('MinorID').Value := expNode.FMinorID;
  2301. ADataset.FieldByName('RecdID').Value := expNode.FRecdID;
  2302. ADataset.FieldByName('Exprs').Value := expNode.FExprs;
  2303. ADataset.FieldByName('Exprs1').Value := expNode.FExprs1;
  2304. ADataset.Post;
  2305. end;
  2306. end;
  2307. procedure TMergeGatherTree.WriteTo(aBillsTable, aDrawTable, aExprsTable: TDataSet);
  2308. var
  2309. I: Integer;
  2310. cgnNode: TCacheGatherNode;
  2311. begin
  2312. MergeCacheList;
  2313. // Access 最后一次 Post 不能提交到数据库,以前也碰到过!
  2314. // 所以不能用Table, Query
  2315. // 改成 ClientDataSet 试试,结果是可以的。
  2316. // 第二次碰到这个问题了。如果不用加密的Access,结果是正确的
  2317. // 所以是加密的问题
  2318. CreateProgressForm(FCacheList.Count, '正在写入数据!');
  2319. for I := 0 to FCacheList.Count - 1 do
  2320. begin
  2321. // AddProgressForm(I, '正在写入数据…');
  2322. cgnNode := TCacheGatherNode(FCacheList[I]);
  2323. WriteBills(cgnNode, aBillsTable);
  2324. WriteDraw(cgnNode, aDrawTable);
  2325. WriteExprs(cgnNode, aExprsTable);
  2326. RefreshProgressForm(I, cgnNode.FName);
  2327. end;
  2328. CloseProgressForm;
  2329. end;
  2330. { TDrawingQuantityItem }
  2331. procedure TDrawingQuantityItem.Assign(aSrcItem: TDrawingQuantityItem);
  2332. begin
  2333. FName := aSrcItem.FName;
  2334. FUnits := aSrcItem.FUnits;
  2335. FDesignQuantity1 := aSrcItem.FDesignQuantity1;
  2336. FDesignQuantity2 := aSrcItem.FDesignQuantity2;
  2337. FMemoContext := aSrcItem.FMemoContext;
  2338. end;
  2339. { TSplitGatherTree }
  2340. function TSplitGatherTree.AddParent(
  2341. aNode: TZjIDTreeNode): TCacheGatherNode;
  2342. var
  2343. I: Integer;
  2344. ztnNode: TZjIDTreeNode;
  2345. ParList: TList;
  2346. cgnNode: TCacheGatherNode;
  2347. begin
  2348. ParList := TList.Create;
  2349. try
  2350. SearchParents(aNode, ParList);
  2351. Result := nil;
  2352. for I := ParList.Count - 1 downto 0 do
  2353. begin
  2354. ztnNode := TZjIDTreeNode(ParList.List^[I]);
  2355. cgnNode := FindChildNode(ztnNode, Result);
  2356. if cgnNode = nil then
  2357. Result := AddSingleNode(ztnNode, Result)
  2358. else
  2359. Result := cgnNode;
  2360. end;
  2361. finally
  2362. ParList.Free;
  2363. end;
  2364. end;
  2365. function TSplitGatherTree.AddSingleNode(aNode: TZjIDTreeNode;
  2366. aCgnNode: TCacheGatherNode): TCacheGatherNode;
  2367. var
  2368. iID: Integer;
  2369. iParentID: Integer;
  2370. begin
  2371. if aNode = nil then Exit;
  2372. { parentID }
  2373. if aCgnNode = nil then
  2374. iParentID := -1
  2375. else
  2376. iParentID := aCgnNode.ID;
  2377. { ID }
  2378. if aNode.ID < 100 then
  2379. iID := aNode.ID
  2380. else
  2381. begin
  2382. iID := FMaxID;
  2383. Inc(FMaxID);
  2384. end;
  2385. Result := AddCacheNode(iID, iParentID, -1);
  2386. { Assign }
  2387. AssignTo(aNode, Result);
  2388. AddDrawItems(FCdsDraw1, aNode.ID, Result);
  2389. end;
  2390. function TSplitGatherTree.FindChildNode(aNode: TZjIDTreeNode;
  2391. aCgnNode: TCacheGatherNode): TCacheGatherNode;
  2392. var
  2393. iCompare: Integer;
  2394. begin
  2395. if aCgnNode = nil then
  2396. Result := FirstNode
  2397. else
  2398. Result := aCgnNode.FirstChild;
  2399. while Assigned(Result) do
  2400. begin
  2401. if TAdditionalItem(aNode).Code <> '' then
  2402. iCompare := CompareCodes(TAdditionalItem(aNode).Code, '', TAdditionalItem(aNode).Name, Result.FCode, '', Result.FName)
  2403. else if TAdditionalItem(aNode).B_Code <> '' then
  2404. iCompare := CompareCodes('', TAdditionalItem(aNode).B_Code, TAdditionalItem(aNode).Name, '', Result.FBCode, Result.FName)
  2405. else
  2406. iCompare := CompareCodes('', '', TAdditionalItem(aNode).Name, '', '', Result.FName);
  2407. if iCompare = 0 then
  2408. begin
  2409. Break;
  2410. end;
  2411. Result := Result.NextSibling;
  2412. end;
  2413. end;
  2414. procedure TSplitGatherTree.GenerateGatherTree(aNode: TZjIDTreeNode);
  2415. var
  2416. cgnParent: TCacheGatherNode;
  2417. begin
  2418. if aNode = nil then Exit;
  2419. if not aNode.HasChildren and
  2420. (SameText(TAdditionalItem(aNode).OwnerName, FOwnerName) or
  2421. (TAdditionalItem(aNode).OwnerName = ''))
  2422. then
  2423. begin
  2424. cgnParent := AddParent(aNode);
  2425. AddSingleNode(aNode, cgnParent);
  2426. end;
  2427. GenerateGatherTree(aNode.FirstChild);
  2428. GenerateGatherTree(aNode.NextSibling);
  2429. end;
  2430. procedure TSplitGatherTree.SearchParents(aNode: TZjIDTreeNode;
  2431. aParList: TList);
  2432. begin
  2433. while Assigned(aNode.Parent) do
  2434. begin
  2435. aParList.Add(aNode.Parent);
  2436. aNode := aNode.Parent;
  2437. end;
  2438. end;
  2439. procedure TSplitGatherTree.SplitBillsTree(aBillsTree: TZjIDTree;
  2440. aCdsDraw: TClientDataSet; const aOwnerName: string);
  2441. begin
  2442. FBillsTree1 := aBillsTree;
  2443. FCdsDraw1 := aCdsDraw;
  2444. FOwnerName := aOwnerName;
  2445. InitMaxID;
  2446. GenerateGatherTree(FBillsTree1.FirstNode);
  2447. end;
  2448. end.