ScXMLPort.pas 248 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818
  1. {*******************************************************************************
  2. 单元名称: ScXMLPort.pas
  3. 单元说明: 导入、导出 XML文件接口。
  4. 作者时间: Chenshilong, 2013-06-18
  5. *******************************************************************************}
  6. unit ScXMLPort;
  7. interface
  8. uses
  9. SysUtils, Classes, DB, ADODB, Forms, ScConsts, NativeXml,
  10. ScProjectUnitPriceLibsUnit, ScProjectFeeRateLibsUnit, ScProjBaseDM,
  11. ScBillsDM, DBClient, ScRations, ScGroundCompensateDM, ScBaseTreeDM, sdDB;
  12. const OpenWHPort = {True;//}False; // 是否开放芫湖接口
  13. const OpenCZPort = {True;//}False; // 是否开放安徽接口 (池州)
  14. type
  15. TProcedure = procedure(AValue: Double) of object;
  16. TFunction = function(): Double of object;
  17. TArea = (areaZheJiang, areaChiZhou);
  18. PXMLNode = ^TXMLNodeRec;
  19. TXMLNodeRec = record
  20. Data: TXmlNode;
  21. FullCode: string;
  22. end;
  23. TXMLPort = class(TObject) // XML通用导出接口
  24. private
  25. FXMLDoc: TNativeXml;
  26. FRoot: TXmlNode;
  27. FFileType: TxmlFileType; // 招标,投标, 控制价。
  28. FRootName: string; // 编办地区。(一些地区导出的内容大部分相同,仅少量不同,代码上公用使用这个属性来区分)
  29. FArea: TArea;
  30. FXMLFile: string; // 输出的最终XML文件
  31. FBuildProjRec: TsdDataRecord; // 建设项目。
  32. FProject: TObject;
  33. FTenderRecList: TList; // 多项目。从此属性获取。但为兼容,旧接口可以直接从FProject取。
  34. FBillsTree: TScBillsTree;
  35. FQuery1: TADOQuery;
  36. FQuery2: TADOQuery; // 用于第二层嵌套,如定额
  37. FQuery3: TADOQuery; // 用于第三层嵌套,如工料机
  38. FQuery4: TADOQuery; // 用于第四层嵌套,如材料计算之原价计算
  39. FQuery5: TADOQuery; // 用于第五层嵌套,如原价计算下的定额
  40. FSearch1: TADOQuery; // 用于临时查询1
  41. FSearch2: TADOQuery; // 用于临时查询2
  42. FSearch3: TADOQuery; // 用于临时查询3
  43. FSearch4: TADOQuery; // 用于临时查询4
  44. FUnitPriceFile: TScProjectUnitPriceLib;
  45. FFeeRateFile: TScProjectFeeRateLib;
  46. FSerialNoOfID2: Integer; // ID为2的清单的 SerialNo
  47. FXMLNodesList: TList;
  48. FB_CodeFieldName: string;
  49. FProgressive: Boolean;
  50. FProgressiveFile: string;
  51. {---------------------------------------------------------------------------
  52. 存储内容:'Key=Code',如:'535-4-1-25.6=1511010-1'
  53. 分号前:4项合成的Key:GLJID-Type-CalculateType-RationPrice
  54. 分号后:新编号:Code-后缀。因同一工料机重复,修改成新编号,递增后缀。
  55. 由于 Delphi 找不到字符串到字符串的映射结构(二维数组不能动态定义),
  56. 这里用TStringList曲线救国。
  57. ----------------------------------------------------------------------------}
  58. FGLJKeyCodeMap: TStringList;
  59. FFirtProjIsNewOpen: Boolean;
  60. FProgressive2: Boolean;
  61. FProjectInfoCacheList: TStringList;
  62. FAllProjectsTotalPriceSum: Double;
  63. FOnOpenProject: TNotifyEvent; // 所有标段的总造价之和
  64. procedure AddRoot; virtual; // 兼容旧代码
  65. procedure AddDetail; virtual; // 兼容旧代码
  66. procedure AddNodes; virtual; // 新代码使用,替代AddRoot、AddDetail:开始添加内容(通常是建设项目级的内容,多标段循环外部)
  67. procedure SetProject(const Value: TObject);
  68. // 从数据表挑选指定字段的数据,挂载到XML文件的结点AXMLNode之下。AFlag: 标记,有的需要特殊处理一下。
  69. procedure AddTabToXML(AQuery: TADOQuery; ASQL: string; AXMLNode: TXmlNode; ATableName, AItemName: string; AFlag: string = '');
  70. function IDtoSerialNo(AID: Integer): Integer; // 根据清单ID查询SerialNo
  71. function ChangeUnit_m3(AUnit: string): string; // 单位立方米符号要转换成m3
  72. function GetZJByName(AName: string): string; // 获取章节号:100~1300.
  73. function GetZJ(AFullCode, AName: string): string; // 209-5 是 200
  74. function GetSeparatorCount(ACode: string): Integer; // 获取"-"的个数
  75. function GetProjectTotalPrice: string; // 获取总造价
  76. function DoSearch(ASQL, AResultFieldName: string; ADefaultValue: string = ''): string;
  77. function PV(AName: string; ADefault: string = ''): string; // 取属性值,代码简写
  78. function PD: TScProjBaseData; // 取TScProjBaseData值,代码简写
  79. function BV(AName: string): string; // 取建设项目属性
  80. function HasTable(ATabName: string): Boolean;
  81. function Rec(ANode: TScBillsItem; AName: string): string;
  82. function BillNode(AID: Integer): TScBillsItem;
  83. function CheckNull(Value: string): string; overload;
  84. function CheckNull(Value: string; defaultValue: string): string; overload;
  85. function CheckNull(Value: Double): string; overload;
  86. function CheckBool(Value: string): string;
  87. function GetCompareFullCode(AItem: TScBillsItem): string; overload;
  88. function GetCompareFullCode(AXMLNode: TXmlNode): string; overload;
  89. procedure AnalyzeQZZH(AZH: string; var AQ, AZ: string); // 解析起止桩号
  90. function ExtractNumbers(AStr: String):Double;
  91. procedure CalcBillsFees(AItem: TScBillsItem);
  92. // 从不同的软件导出的XML中,B_Code有被写成b_Code的,需要处理
  93. procedure CheckB_CodeFieldName;
  94. procedure SetProgressive(const Value: Boolean);
  95. procedure SetProgressiveFile(const Value: string);
  96. procedure CheckProj;
  97. procedure SetProgressive2(const Value: Boolean);
  98. procedure AddMultiProjects; virtual; // 添加多个标段。每个子类使用的位置不固定(一个建设项目下有多个标段)
  99. // 继续为每个标段追加内容。需要子类覆盖(多标段循环内部使用,即在AddMultiProjects内使用)n: 第几个标段,序号,有时内部方法会用到。
  100. procedure AddNodesForEveryProject(n: Integer); virtual;
  101. procedure CreateProjGLJNewCodeMap; // 创建工料机新编号映射
  102. procedure Create_Port_Prj; // 创建新的ProjectGLJ表(原因见定义处的详细说明)。
  103. function GetProjectGUID(AIsBuildProj: Boolean = False): string;
  104. function IDtoGUID(ID: Integer): string; // 接口需要GUID,我们的整数ID太短过不了评测。
  105. procedure RcsvAddBillItems(AProject: TObject; AParentItem: TScBillsItem; ANode: TXmlNode); // 导入:(根据Xml数据)生成Project的BillItem。
  106. procedure RcsvAddDayWorks(AProject: TObject; AParentItem: TScBillsItem; ANode: TXmlNode); // 导入:(根据Xml数据)生成Project的计日工部分。
  107. procedure SetBuildProjRec(const Value: TsdDataRecord);
  108. procedure SetOnOpenProject(const Value: TNotifyEvent);
  109. public
  110. constructor Create;
  111. destructor Destroy; override;
  112. procedure SaveToXML(NeedZip: Boolean = True);
  113. procedure LoadFromXML; virtual; // 加载xml文件到FXMLDoc对象中。需要在子类中覆盖:将FXMLDoc的数据写入Project中。
  114. { 功能: 将 ABDRootNode下挂的数据填充到AProject中。导入电子标接口使用。
  115. 参数: AProject:在后台新建的空标段。ABDRootNode:标段的根结点(Xml),如:<公路标段工程>
  116. 旧模式:导入前先手工打开一个标段,然后导入Xml文件进行数据覆盖,只能单个标段操作。
  117. 新模式:在项目管理导入xml文件,文件中的每个标段会自动生成一个Project,并将xml数据填入,支持多个标段。 }
  118. procedure FillData(AProject: TObject; ABDRootNode: TXmlNode);
  119. procedure DisposeXMLNodesList;
  120. procedure ZipFiles(AFileList: TStringList; AResultFileName: string);
  121. property BuildProjRec: TsdDataRecord read FBuildProjRec write SetBuildProjRec;
  122. property Project: TObject read FProject write SetProject;
  123. // 其它接口单项目,直接传参数FProject;全国接口(单项目或多项目),要传参数 TenderRecList。
  124. property TenderRecList: TList read FTenderRecList;
  125. property ProjectInfoCacheList: TStringList read FProjectInfoCacheList; // 打开项目后缓存一些项目的信息,避免再次使用时又要打开
  126. property BillsTree: TScBillsTree read FBillsTree write FBillsTree;
  127. property FileType: TxmlFileType read FFileType write FFileType;
  128. property XMLFile: string read FXMLFile write FXMLFile;
  129. property Progressive: Boolean read FProgressive write SetProgressive;
  130. property Progressive2: Boolean read FProgressive2 write SetProgressive2;
  131. property ProgressiveFile: string read FProgressiveFile write SetProgressiveFile;
  132. property FirtProjIsNewOpen: Boolean read FFirtProjIsNewOpen write FFirtProjIsNewOpen;
  133. property RootName: string read FRootName write FRootName;
  134. property Area: TArea read FArea write FArea; // 地区:不同地区在导出内容上有细微差别,用这个区分
  135. property OnOpenProject: TNotifyEvent read FOnOpenProject write SetOnOpenProject;
  136. end;
  137. // 全国接口,单机版→云版(原来的云南接口) 。
  138. TqgXMLPort = class(TXMLPort)
  139. private
  140. FSystemInfoNode: TXmlNode;
  141. FCostBasisNode: TXmlNode;
  142. FNormLibNode: TXmlNode;
  143. FRateNode: TXmlNode;
  144. FRateRaramsNode: TXmlNode;
  145. FRateRaramNode: TXmlNode;
  146. FRateValuesNode: TXmlNode;
  147. FRateValueNode: TXmlNode;
  148. FPract: TXmlNode;
  149. FPract_Param: TXmlNode;
  150. FPract_Mps: TXmlNode;
  151. FPract_Materials: TXmlNode;
  152. FPract_Mechs: TXmlNode;
  153. FEprjInfoNode: TXmlNode;
  154. FMakeInfoNode: TXmlNode;
  155. FParamsNode: TXmlNode;
  156. FItemsNode: TXmlNode;
  157. FIndexsNode: TXmlNode;
  158. // [(Value: 3; Name: '部颁公路工程预算定额(2018)'), ]
  159. FLibArr: array of TIdentMapEntry;
  160. FAllLibNames: array of string; // 每个标段的定额库ID 都是从0开始,多个标段时会出现问题,这里分开
  161. FGDSZDEKID: Integer; // 广东市政定额库ID,来自这个定额库的定额要特殊处理:导出接口时,定额编号前要加"D"
  162. procedure AddNodes; Override;
  163. procedure AddNodesForEveryProject(n: Integer); Override;
  164. procedure AddCprjInfo;
  165. // <CprjInfo>的7个子结点
  166. procedure AddDecimalOption; // <DecimalOption>
  167. procedure AddSystemInfo; // <SystemInfo>
  168. procedure AddCostBasis; // <CostBasis><NormLib> 定额库列表。
  169. procedure AddRationLibs; // 添加定额库
  170. procedure AddRate(AFileNo: Integer); // <Rate>
  171. procedure AddPract(AFileNo: Integer); // <Pract>
  172. procedure AddEprjInfo(AFileNo: Integer); // <EprjInfo>
  173. procedure AddIndexs; // <Indexs>
  174. // <Pract>的3个子结点(从项目工料机导出)
  175. procedure AddMps; // [1]、导出【人工】
  176. procedure AddMaterials; // [2]、导出【材料】
  177. procedure AddMechs; // [3]、导出【机械】
  178. procedure AddOrgPrices(AMaterialNode: TXmlNode; AMaterialID: Integer); // [2.2]、导出材料原价
  179. procedure AddTranFees(AMaterialNode: TXmlNode; AMaterialID: Integer); // [2.3]、导出材料运费
  180. procedure AddMCRations(AParentNode: TXmlNode; AType, AMaterialID, ABillID: Integer); // [2.2.1 & 2.3.1]、导出材料计算用的定额。
  181. procedure AddElectric(AMaterialNode: TXmlNode); // 2.4]、导出综合电价
  182. procedure AddFormula(ANode: TScBillsItem; AParentXMLNode: TXmlNode); // 导出清单的公式
  183. procedure AddRations(ANode: TScBillsItem; AParentXMLNode: TXmlNode); // 导出定额
  184. procedure AddBuildLoan(AParentXMLNode: TXmlNode); // 导出贷款利息
  185. procedure AddGC(AParentXMLNode: TXMLNode; const ABillsID: Integer); // 导出土地
  186. procedure AddGC2(ALeafTree: TBaseTree; AIndex1, AIndex2: Integer; AXMLNode: TXmlNode);
  187. procedure AddDrawQ(ANode: TScBillsItem; AParentXMLNode: TXmlNode); // 导出图纸算量
  188. // <EprjInfo>的子结点
  189. procedure AddMakeInfo;
  190. procedure AddParams(AFileNo: Integer);
  191. procedure AddItems; // 导出所有清单
  192. function AddItem(ANode: TScBillsItem; AParentXMLNode: TXmlNode): TXmlNode; virtual; // 导出单条清单
  193. function IsSpecialFormulaBill(ANode: TScBillsItem): Boolean; overload; // 投标项目, 特殊的清单,公式写死在代码里,用户也可以自定义。
  194. function IsSpecialFormulaBill(ABillID: Integer): Boolean; overload;
  195. function CanGC(ANode: TScBillsItem): Boolean; // 能否导出土地
  196. function GetItemTypeByCode(AItem: TScBillsItem): string;
  197. function GetNormLibNoByID(ALibID: Integer): string;
  198. // Akey: 4项合成的Key:GLJID-Type-CalculateType-RationPrice。eg: 1736-4-0-0.78=4013003-17
  199. // AOrgCode 工料机原编号。映射找不到时,返回原始编号。
  200. function GetGJLCodeByKey(AKey: string; AOrgCode: string): string;
  201. function GetType(AType, ACalculateType: Integer; AName: string = ''): Integer;
  202. function AdjustStateToPort(ARation: TScRationRecord): string; // 导出的定额调整状态,要转换成接口要求的格式。
  203. function OneAdjustToPort(AOneState: string; ARation: TScRationRecord): string; // 处理调整状态中的一个小分段(被分号隔开后的)。
  204. public
  205. end;
  206. // 招投标派系【招标、投标、控制价】
  207. TZTBXMLPort = class(TXMLPort)
  208. private
  209. FGCXX: TXmlNode; // 工程信息
  210. FZTBXX: TXmlNode; // 招投标信息
  211. FGLGCSJ: TXmlNode; // 公路工程数据
  212. FGLBDGC: TXmlNode; // 公路标段工程 1..n
  213. FGCLQDB: TXmlNode; // 工程量清单表
  214. FJRGXXB: TXmlNode; // 计日工信息表
  215. FZJHZB: TXmlNode; // 造价汇总表
  216. FRCJHZ: TXmlNode; // 人材机汇总
  217. FGLGCHZ: TXmlNode; // 公路工程汇总(浙江多一层,该对象是指 公路工程汇总标题)
  218. procedure AddNodes; Override;
  219. procedure AddNodesForEveryProject(n: Integer); Override;
  220. procedure AddGCXX;
  221. procedure AddZTBXX;
  222. procedure AddGLGCSJ;
  223. procedure AddGLBDGC(n: Integer);
  224. procedure AddGLGCHZMX;
  225. procedure AddBillNodes; // 导出:生成清单的XMLNode
  226. procedure RcsvAddBillNode(AItem: TScBillsItem; AXMLParent: TXmlNode);
  227. procedure AddRationNodes(ABillItem: TScBillsItem; ABillNode: TXmlNode);
  228. // 叶子清单下的材料汇总
  229. procedure AddBillMaterials(ABillItem: TScBillsItem; ABillMetNode: TXmlNode);
  230. procedure AddJRG;
  231. procedure AddZJHZMX;
  232. procedure AddProjGLJs;
  233. procedure GetZCLB(ABillName: string; var ACapter, AType: string);
  234. function GetDataCheckCode: string; // 计算数据校验码
  235. public
  236. end;
  237. // 昆明接口
  238. TkmXMLPort = class(TXMLPort)
  239. private
  240. FRationLibCode: string;
  241. FSPNode: TXmlNode; // SingleProject
  242. FUPNode: TXmlNode; // UnitProject
  243. FSN_EEBegin: Integer; // 机电备品备件部分的起始SerialNo
  244. FSN_ID2: Integer; // ID为2的清单的SerialNo
  245. FSN_BillsEnd: Integer; // 最后一条清单的SerialNo。如果没有900~1300章,则为 FSN_ID2 - 1; 如果有则为 FSN_EEBegin - 1;
  246. FEETotalPrice: Currency; // 机电备品备件部分金额
  247. FSubHint: string; // 提示信息缓存
  248. FSubHint2: string; // 提示信息缓存
  249. procedure AddBQTable; // 清单
  250. procedure AddNorms(ARoot: TXmlNode); // 定额
  251. procedure AddQuantityUnitPrice(ARoot: TXmlNode); // 数量单价
  252. procedure AddBQPriceAnalysisItem(ARoot: TXmlNode); // 单价分析(即我们的清单子目工料机汇总)
  253. procedure AddNormResUsageItem(ARoot: TXmlNode); // 项目文件-GLJList
  254. procedure AddDayWorkTable; // 计日工
  255. procedure AddMaterialTable; // 单价文件-GLJList
  256. procedure AddResource; // ProjectGLJ
  257. procedure AddMaterialProvisionalPriceTable; // 材料暂估价
  258. procedure AddProjEquipmentPriceTable; // 工程设备暂估价
  259. procedure AddProjProvisionalPriceTable; // 专业工程暂估价
  260. procedure AddSummary;
  261. procedure AddElectEquipmentTable; // 交通机电设施备品备件
  262. procedure EEValue(var ABeginSN: Integer; var ATotalPrice: Currency); // 云南从900章监控系统开始
  263. function GetEECostKind(AChapterID: Integer): string; // 1 监控系统 2 收费系统 3 通信系统 4 消防系统 5 供配电及照明系统
  264. procedure AddRoot; override;
  265. procedure AddDetail; override;
  266. public
  267. constructor Create;overload;
  268. procedure LoadFromXML; override;
  269. property RationLibCode: string read FRationLibCode write FRationLibCode;
  270. end;
  271. // 纵横接口,区别于外部公司的接口,如海德接口,昆明接口等。主要因为根结点内容、导出文件时机等有区别
  272. TzhXMLPort = class(TXMLPort)
  273. private
  274. procedure AddRoot; override;
  275. end;
  276. // 工料机价格信息收集上传(用户工料机、项目工料机)
  277. TgljXMLPort = class(TzhXMLPort)
  278. private
  279. procedure AddRoot; Override;
  280. procedure AddDetail; Override;
  281. end;
  282. // 为什么清单定额信息收集上传要另外写一个类,而不把方法写在工料机价格信息类
  283. // 里面一起操作呢?因为这部分数据庞大,分文件存放易于控制管理。
  284. // 清单定额信息收集上传 2014.12.1
  285. TbpXMLPort = class(TzhXMLPort)
  286. private
  287. procedure AddRoot; Override;
  288. procedure AddDetail; Override;
  289. end;
  290. // 芜湖接口
  291. TwhXMLPort = class(TXMLPort)
  292. private
  293. FDxgcxxNode: TXmlNode;
  294. FDwgcxxNode: TXmlNode;
  295. FQfxxNode: TXmlNode;
  296. FQdXmNode: TXmlNode;
  297. FZgClNode: TXmlNode;
  298. FJpClNode: TXmlNode;
  299. FRcjhzNode: TXmlNode;
  300. FJjFlbNode: TXmlNode;
  301. FJjFlxNode: TXmlNode;
  302. FJrgNode: TXmlNode;
  303. FBlackFontBillsNo: Integer;
  304. procedure AddRoot; Override;
  305. procedure AddDetail; Override;
  306. public
  307. end;
  308. // 图纸算量接口 2020.10.28
  309. TtzslXMLPort = class(TXMLPort)
  310. private
  311. FInfo: TXmlNode;
  312. FBillList: TXmlNode;
  313. FFirstBill: TXmlNode; // <Bills Code="1" Name="第一部分 建筑安装工程费">
  314. FSecondBill: TXmlNode; // <Bills Code="2" Name="第二部分 土地使用及拆迁补偿费">
  315. FThirdBill: TXmlNode;
  316. FFourthBill: TXmlNode;
  317. FCompareCDS: TClientDataSet; // 存放对比结构的内存表。
  318. FIsBills: Boolean; // 是否清单
  319. FXMLNodeList: TList;
  320. public
  321. function CheckXMLFile: Boolean; virtual;
  322. procedure AssignNode(ANode: TXmlNode; AItem: TScBillsItem);
  323. procedure AddRations(ANode: TXmlNode; AItem: TScBillsItem; var ASerialNo: Integer);
  324. procedure AddCountPrice(ANode: TXmlNode; AItem: TScBillsItem; ASerialNo: Integer);
  325. procedure AddEquipment(ANode: TXmlNode; AItem: TScBillsItem);
  326. procedure AddDQs(ANode: TXmlNode; AItem: TScBillsItem);
  327. procedure AddGroundCompensate(ANode: TXmlNode; AItem: TScBillsItem);
  328. procedure RcsvAddBills(ANode: TXmlNode; AParentItem: TScBillsItem);
  329. procedure LoadFromXML; override;
  330. procedure UpdateFromXML;
  331. procedure CompareFromXML(ACDS: TClientDataSet); // 根据XML文件对比造价书数量,显示变更结果
  332. procedure AnalyzeXMLNodesIntoList(ASelectItem: TScBillsItem);
  333. function SameFullCode(AXMLNodeFullCode: string; AItem: TScBillsItem): Boolean;
  334. procedure UpdateItem(AItem: TScBillsItem);
  335. procedure CompareItem(AItem: TScBillsItem);
  336. procedure RcsvUpdateItems(AItem: TScBillsItem);
  337. procedure RcsvCompareItems(AItem: TScBillsItem);
  338. procedure CompareDeleted; // 处理XML列表中的残余项:没匹配成功,因造价书中删除。
  339. function GetBillKindName(AItem: TScBillsItem): string; overload; // 分项 & 清单
  340. function GetBillKindName(ANode: TXmlNode): string; overload; // 分项 & 清单
  341. function GetRationKindName(ARec: TScRationRecord): string;
  342. end;
  343. // Excel块转成Xml文件格式
  344. TExcelBlockXMLPort = class(TtzslXMLPort)
  345. public
  346. function CheckXMLFile: Boolean; override;
  347. procedure LoadFromXML; override;
  348. end;
  349. const XftNames: array [TxmlFileType] of string = ('招标', '投标', '控制价');
  350. implementation
  351. uses ScProject, ProjectsDM,
  352. ScFeeRateLibsUnit, ScBills, ZjIDTree, ScProgressFrm, ScGLJLibs,
  353. ScBillsConsts, sdIDTree, Variants, ScConfig, ScUtils, ScPHPWeb,
  354. SysInfoUnit, ScProjectRationLibsUnit, ScXMLPortMap, ScTypes,
  355. VCLUnZip, VCLZip, EncdDecd, Controls, ShellAPI, Windows, ScExprs, PerlRegEx,
  356. Math, CslTimeDebug, ScRAdjusts, ScGLJ, ScXMLConsts, ScProjList, CLD_DogNoBySerialNo;
  357. {TXMLPort}
  358. procedure TXMLPort.SetProject(const Value: TObject);
  359. var vCon: TADOConnection;
  360. sSQL: string;
  361. begin
  362. FProject := Value;
  363. FBillsTree := TScProject(FProject).Bills.BillsTree;
  364. vCon := PD.acProject;
  365. FQuery1.Connection := vCon;
  366. FQuery2.Connection := vCon;
  367. FQuery3.Connection := vCon;
  368. FQuery4.Connection := vCon;
  369. FQuery5.Connection := vCon;
  370. FSearch1.Connection := vCon;
  371. FSearch2.Connection := vCon;
  372. FSearch3.Connection := vCon;
  373. FSearch4.Connection := vCon;
  374. FUnitPriceFile := TScProjectUnitPriceLib(TScProject(FProject).ProjectGLJ.ProjectUnitPriceLib);
  375. FFeeRateFile := TScProject(FProject).ProjectFeeRateLib;
  376. sSQL := Format('SELECT SerialNo FROM Bills WHERE ID = %d', [2]);
  377. FSerialNoOfID2 := StrToInt(DoSearch(sSQL, 'SerialNo', '0'));
  378. end;
  379. { 作用:从数据表挑选指定字段的数据,挂载到XML的某个结点之下。
  380. 参数:AQuery:干活的ADOQuery。ASQL:SQL语句。
  381. AXMLNode:在该XML结点下挂载数据。
  382. ATableName: 是否要在AXMLNode下加一层以表命名的子结点,默认空,即不加这一层。
  383. AItemName: AXMLNode子结点的名字
  384. 使用示例:
  385. procedure AddJjFlx;
  386. var sSQL: string;
  387. begin
  388. sSQL :=
  389. 'Select SerialNo as Bm, Name as Mc, Caption as ShuZhi ' +
  390. 'from FeeParams Order by SerialNo';
  391. AddTabToXML(FQuery2, sSQL, FJjFlxNode, '', 'JjFlxMx');
  392. end; }
  393. procedure TXMLPort.AddTabToXML(AQuery: TADOQuery; ASQL: string;
  394. AXMLNode: TXmlNode; ATableName, AItemName: string; AFlag: string);
  395. var vNode, vItemNode: TXmlNode;
  396. i: Integer;
  397. var sFN, sMN, sValue, sFullFN: string;
  398. begin
  399. AQuery.Close;
  400. AQuery.SQL.Clear;
  401. AQuery.SQL.Text := ASQL;
  402. AQuery.Open;
  403. if AQuery.RecordCount = 0 then Exit;
  404. if ATableName = '' then
  405. vNode := AXMLNode
  406. else
  407. vNode := AXMLNode.NodeNewUTF8(ATableName);
  408. AQuery.First;
  409. while not AQuery.Eof do
  410. begin
  411. vItemNode := vNode.NodeNewUTF8(AItemName);
  412. for i := 0 to AQuery.FieldCount - 1 do
  413. begin
  414. sFullFN := AQuery.Fields[i].FieldName;
  415. if IsMapFieldName(sFullFN) then
  416. begin
  417. sValue := StrMixMap(sFullFN, AQuery.Fields[i].AsString, sFN);
  418. vItemNode.AttributeAddUTF8(sFN, sValue);
  419. end
  420. else if SameText(sFullFN, 'Unit') then
  421. begin
  422. sValue := ChangeUnit_m3(AQuery.Fields[i].AsString);
  423. vItemNode.AttributeAddUTF8(sFullFN, sValue);
  424. end
  425. else if SameText(sFullFN, 'RateParamNo') then // <RateParam RateTypeNo="DJSGZJFFL" RateParamNo="9" Ratio="1"/>
  426. begin
  427. if AQuery.FieldByName('RateTypeNo').AsString = 'DJSGZJFFL' then // 冬季的下拉值要重新映射
  428. sValue := GetMapValue(GetMap('Map_WinterValues'), AQuery.Fields[i].AsString)
  429. else if AQuery.FieldByName('RateTypeNo').AsString = 'YUJSGZJFFL' then // 雨季的下拉值要重新映射
  430. sValue := GetMapValue(GetMap('Map_RainValues'), AQuery.Fields[i].AsString)
  431. else if AQuery.FieldByName('RateTypeNo').AsString = 'GYDQSGZJFFL' then // 高原的下拉值要重新映射
  432. sValue := GetMapValue(GetMap('Map_HighlandValues'), AQuery.Fields[i].AsString)
  433. else if AQuery.FieldByName('RateTypeNo').AsString = 'FSDQSGZJFFL' then // 风沙的下拉值要重新映射
  434. sValue := GetMapValue(GetMap('Map_SandValues'), AQuery.Fields[i].AsString)
  435. else if AQuery.FieldByName('RateTypeNo').AsString = 'XCGRGCSGZJFFL' then // 行车干扰的下拉值要重新映射
  436. sValue := GetMapValue(GetMap('Map_DriveCarValues'), AQuery.Fields[i].AsString)
  437. else
  438. begin
  439. if AQuery.FieldByName('RateParamNo').AsString = '计' then
  440. sValue := '1'
  441. else if AQuery.FieldByName('RateParamNo').AsString = '不计' then
  442. sValue := '0'
  443. else
  444. sValue := AQuery.Fields[i].AsString;
  445. end;
  446. vItemNode.AttributeAddUTF8(sFullFN, sValue);
  447. end
  448. else if SameText(sFullFN, 'RateValue') then // <RateValue CostTypeNo="TF" RateTypeNo="DJSGZJFFL" RateValue="0"/>
  449. begin
  450. if (AFlag = 'Flag_LrSj') then
  451. begin
  452. // <RateValue CostTypeNo="BJ" RateTypeNo="LRL" RateValue="0"/>
  453. // AQuery.Fields[0].FieldName →'CostTypeNo@Map_GetFeeKind_GS@0@2'
  454. // 14: ('14', '费率为0', 'BJ', '不计')
  455. if (AQuery.Fields[0].AsString = '14') and // 不计
  456. ((AQuery.FieldByName('RateTypeNo').AsString = 'LRL') or // 利润率、税率
  457. (AQuery.FieldByName('RateTypeNo').AsString = 'SL')) then
  458. sValue := '0'
  459. else
  460. sValue := AQuery.Fields[i].AsString;
  461. end
  462. else
  463. sValue := AQuery.Fields[i].AsString;
  464. vItemNode.AttributeAddUTF8(sFullFN, sValue);
  465. end
  466. else
  467. begin
  468. sValue := AQuery.Fields[i].AsString;
  469. vItemNode.AttributeAddUTF8(sFullFN, sValue);
  470. end;
  471. end;
  472. AQuery.Next;
  473. end;
  474. AQuery.Close;
  475. end;
  476. constructor TXMLPort.Create;
  477. begin
  478. inherited;
  479. FQuery1 := TADOQuery.Create(nil);
  480. FQuery2 := TADOQuery.Create(nil);
  481. FQuery3 := TADOQuery.Create(nil);
  482. FQuery4 := TADOQuery.Create(nil);
  483. FQuery5 := TADOQuery.Create(nil);
  484. FSearch1 := TADOQuery.Create(nil);
  485. FSearch2 := TADOQuery.Create(nil);
  486. FSearch3 := TADOQuery.Create(nil);
  487. FSearch4 := TADOQuery.Create(nil);
  488. FXMLDoc := TNativeXml.Create(nil);
  489. FXMLDoc.XmlFormat := xfReadable;
  490. FXMLDoc.VersionString := '1.0'; // 这里要加上,否则导出时 version 属性会在 encoding 属性后面,且不能控制。
  491. FXMLDoc.ExternalEncoding := seUTF8; // 这个控件最大的麻烦是,只能读取UTF-8格式的xml文件, 对GB2312识别乱码,这里设置成 seAnsi也没用,读的还是乱码。
  492. FRoot := FXMLDoc.Root;
  493. FXMLNodesList := TList.Create;
  494. FTenderRecList := TList.Create;
  495. FProjectInfoCacheList := TStringList.Create;
  496. FGLJKeyCodeMap := TStringList.Create;
  497. FFirtProjIsNewOpen := False;
  498. // FB_CodeFieldName := 'B_Code'; 从算量导进来的是 b_Code,这个属性要动态判断,不能写死。
  499. end;
  500. destructor TXMLPort.Destroy;
  501. var i: Integer;
  502. begin
  503. FQuery1.Free;
  504. FQuery2.Free;
  505. FQuery3.Free;
  506. FQuery4.Free;
  507. FQuery5.Free;
  508. FSearch1.Free;
  509. FSearch2.Free;
  510. FSearch3.Free;
  511. FSearch4.Free;
  512. FXMLDoc.Free;
  513. DisposeXMLNodesList;
  514. FXMLNodesList.Free;
  515. FTenderRecList.Free;
  516. FProjectInfoCacheList.Free;
  517. FGLJKeyCodeMap.Free;
  518. inherited;
  519. end;
  520. procedure TXMLPort.SaveToXML(NeedZip: Boolean);
  521. var
  522. vZip: TVCLZip;
  523. sOrgFullName, sNewFullName, sPath, sTitle: string;
  524. isTest: Boolean;
  525. begin
  526. if FFileType = null then
  527. sTitle := ''
  528. else
  529. sTitle := '-' + XftNames[FFileType];
  530. CreateProgressForm(100, '导出XML文件' + sTitle + ' >>>');
  531. CheckProj;
  532. // AddRoot、AddDetail 兼容旧代码。新代码使用 AddXMLNodes
  533. AddProgressForm(0, '生成根结点...');
  534. AddRoot;
  535. AddProgressForm(0, '生成明细数据...');
  536. AddDetail;
  537. // 新代码使用 AddNodes
  538. AddProgressForm(0, '生成XML结点数据...');
  539. AddNodes;
  540. AddProgressForm(10, '存储XML文件...');
  541. if FileExists(FXMLFile) then
  542. SysUtils.DeleteFile(FXMLFile);
  543. if not DirectoryExists(ExtractFileDir(FXMLFile)) then
  544. ForceDirectories(ExtractFileDir(FXMLFile));
  545. FXMLDoc.VersionString := '1.0';
  546. FXMLDoc.ExternalEncoding := seUTF8; // 这里设置成 seAnsi也没用,导出后的文件还是UTF-8格式。且根结点没有encoding="GB2312"属性。
  547. isTest := False; // 仅测试使用
  548. if isTest then
  549. begin
  550. FXMLDoc.SaveToFile(FXMLFile);
  551. CloseProgressForm;
  552. Exit;
  553. end;
  554. FXMLDoc.SaveToFile(FXMLFile);
  555. if NeedZip then
  556. begin
  557. AddProgressForm(10, '压缩加密...');
  558. vZip := TVCLZip.Create(nil);
  559. try
  560. sOrgFullName := FXMLFile;
  561. sPath := ExtractFilePath(FXMLFile);
  562. sNewFullName := sPath + 'main.xml';
  563. if FileExists(sNewFullName) then
  564. SysUtils.DeleteFile(PChar(sNewFullName));
  565. RenameFile(sOrgFullName, sNewFullName);
  566. vZip.FilesList.Add(sNewFullName);
  567. vZip.ZipName := sOrgFullName;
  568. vZip.Recurse := True;
  569. vZip.ZipComment := '纵横软件导出接口数据';
  570. vZip.OverwriteMode := Always;
  571. vZip.Zip;
  572. SysUtils.DeleteFile(PChar(sNewFullName));
  573. finally
  574. vZip.Free;
  575. end;
  576. end;
  577. CloseProgressForm;
  578. end;
  579. procedure TXMLPort.LoadFromXML;
  580. begin
  581. if not FileExists(FXMLFile) then Exit;
  582. CheckProj;
  583. FXMLDoc.LoadFromFile(FXMLFile);
  584. CheckB_CodeFieldName;
  585. end;
  586. function TXMLPort.IDtoSerialNo(AID: Integer): Integer;
  587. var sSQL: string;
  588. begin
  589. sSQL := Format('Select SerialNo from Bills where ID = %d', [AID]);
  590. Result := StrToInt(DoSearch(sSQL, 'SerialNo', '-1'));
  591. end;
  592. function TXMLPort.ChangeUnit_m3(AUnit: string): string;
  593. begin
  594. Result := StringReplace(AUnit, WideChar($00E0), 'm3', [rfReplaceAll,rfIgnoreCase]);
  595. end;
  596. function TXMLPort.GetZJByName(AName: string): string;
  597. var iPos1, iPos2: Integer;
  598. begin
  599. iPos1 := Pos('第', AName);
  600. iPos2 := Pos('章', AName);
  601. Result := Copy(AName, iPos1 + 2, iPos2 - iPos1 - 2);
  602. end;
  603. function TXMLPort.GetZJ(AFullCode, AName: string): string;
  604. begin
  605. if (AFullCode <> '') then
  606. Result := AFullCode[1] + '00'
  607. else
  608. Result := GetZJByName(AName);
  609. end;
  610. function TXMLPort.PV(AName: string; ADefault: string): string;
  611. begin
  612. Result := TScProject(FProject).Properties.PV[AName];
  613. if Result = '' then
  614. Result := ADefault;
  615. end;
  616. function TXMLPort.PD: TScProjBaseData;
  617. begin
  618. Result := TScProjBaseData(TScProject(FProject).ProjData);
  619. end;
  620. function TXMLPort.GetProjectTotalPrice: string;
  621. var iID: Integer;
  622. sSQL: string;
  623. begin
  624. if TScProject(FProject).ProjType = ptBills then
  625. iID := idProjectTotalPrice_Bills
  626. else
  627. iID := idProjectTotalPrice_Budget;
  628. sSQL := Format('SELECT TotalPrice FROM Bills WHERE ID = %d', [iID]);
  629. Result := DoSearch(sSQL, 'TotalPrice', '0');
  630. end;
  631. function TXMLPort.DoSearch(ASQL, AResultFieldName: string; ADefaultValue: string): string;
  632. begin
  633. Result := ADefaultValue;
  634. FSearch1.Close;
  635. FSearch1.SQL.Text := ASQL;
  636. FSearch1.Open;
  637. if FSearch1.RecordCount > 0 then
  638. Result := FSearch1.FieldByName(AResultFieldName).AsString;
  639. FSearch1.Close;
  640. end;
  641. function TXMLPort.HasTable(ATabName: string): Boolean;
  642. var
  643. I: Integer;
  644. vSL: TStringList;
  645. begin
  646. vSL := TStringList.Create;
  647. try
  648. PD.acProject.GetTableNames(vSL);
  649. Result := (vSL.IndexOf(ATabName) >= 0);
  650. finally
  651. vSL.Free;
  652. end;
  653. end;
  654. function TXMLPort.Rec(ANode: TScBillsItem; AName: string): string;
  655. begin
  656. Result := ANode.Rec.ValueByName(AName).AsString;
  657. end;
  658. function TXMLPort.BillNode(AID: Integer): TScBillsItem;
  659. begin
  660. Result := TScProject(FProject).Bills.BillsTree.BillsItem[AID];
  661. end;
  662. function TXMLPort.CheckNull(Value: string): string;
  663. var v: string;
  664. begin
  665. v := Trim(Value);
  666. if v = '' then
  667. Result := '0'
  668. else
  669. Result := v;
  670. end;
  671. function TXMLPort.CheckNull(Value: string; defaultValue: string): string;
  672. var v: string;
  673. begin
  674. v := Trim(Value);
  675. if v = '' then
  676. Result := defaultValue
  677. else
  678. Result := v;
  679. end;
  680. function TXMLPort.CheckBool(Value: string): string;
  681. var v: string;
  682. begin
  683. v := Value;
  684. if v = '' then
  685. v := '0'
  686. else
  687. begin
  688. if SameText(v, 'False') then
  689. v := '0'
  690. else //if SameText(v, 'True') then
  691. v := '1';
  692. end;
  693. Result := v;
  694. end;
  695. procedure TXMLPort.AnalyzeQZZH(AZH: string; var AQ, AZ: string);
  696. var i: Integer;
  697. begin
  698. i := Pos('~', AZH);
  699. if i > 0 then
  700. begin
  701. AQ := Copy(AZH, 1, i - 1);
  702. AZ := Copy(AZH, i + 1, Length(AZH) - i);
  703. end
  704. else
  705. begin
  706. AQ := AZH;
  707. AZ := '';
  708. end;
  709. end;
  710. function TXMLPort.ExtractNumbers(AStr: String): Double;
  711. var temp: String;
  712. i: integer;
  713. begin
  714. temp := '';
  715. for i := 1 to Length(AStr) do
  716. begin
  717. if (AStr[i] in ['0'..'9']) or (AStr[i] = '.') then
  718. temp := temp + AStr[i];
  719. end;
  720. if temp = '' then
  721. Result := 0
  722. else
  723. Result := StrToFloat(temp);
  724. end;
  725. procedure TXMLPort.CalcBillsFees(AItem: TScBillsItem);
  726. var i, j, k: Integer;
  727. vChild: TScBillsItem;
  728. vProc: TProcedure;
  729. vFunc1, vFunc2: TFunction;
  730. fTemp: Double;
  731. sSQL, sTemp: string;
  732. begin
  733. if AItem = nil then Exit;
  734. CalcBillsFees(TScBillsItem(AItem.FirstChild));
  735. if AItem.IsLeaf = True then
  736. begin
  737. sSQL := 'SELECT BillsItemID';
  738. for i := Low(G_Port_Fees) to High(G_Port_Fees) do
  739. begin
  740. sSQL := sSQL + ', Sum(' + G_Port_Fees[i] + ') as ' + G_Port_Fees[i];
  741. end;
  742. sSQL := sSQL + ' From RationCalclist where BillsItemID = ' + IntToStr(AItem.ID) + ' Group by BillsItemID';
  743. // 从定额来
  744. FSearch1.Close;
  745. FSearch1.SQL.Text := sSQL;
  746. FSearch1.Open;
  747. if FSearch1.RecordCount > 0 then
  748. begin
  749. // eg: AItem.LabourFee := FSearch1.FieldByName('LabourFee').AsFloat;
  750. // AItem.MaterialFee := FSearch1.FieldByName('MaterialFee').AsFloat; ...
  751. for i := Low(G_Port_Fees) to High(G_Port_Fees) do
  752. begin
  753. vProc := TProcedure(AItem.GetMethod('Set' + G_Port_Fees[i]));
  754. vProc(FSearch1.FieldByName(G_Port_Fees[i]).AsFloat);
  755. end;
  756. end;
  757. FSearch1.Close;
  758. end
  759. else
  760. begin
  761. //eg: AItem.LabourFee := 0; AItem.MaterialFee := 0;...
  762. for i := Low(G_Port_Fees) to High(G_Port_Fees) do
  763. begin
  764. vProc := TProcedure(AItem.GetMethod('Set' + G_Port_Fees[i]));
  765. vProc(0); // 全部清零
  766. end;
  767. // eg: AItem.LabourFee := AItem.LabourFee + vChild.LabourFee;
  768. // AItem.MaterialFee := AItem.MaterialFee + vChild.MaterialFee; ...
  769. for i := 0 to AItem.ChildCount - 1 do
  770. begin
  771. vChild := TScBillsItem(AItem.ChildNodes[i]);
  772. for j := Low(G_Port_Fees) to High(G_Port_Fees) do
  773. begin
  774. vFunc1 := TFunction(AItem.GetMethod('Get' + G_Port_Fees[j]));
  775. vFunc2 := TFunction(vChild.GetMethod('Get' + G_Port_Fees[j]));
  776. fTemp := vFunc1() + vFunc2();
  777. vProc := TProcedure(AItem.GetMethod('Set' + G_Port_Fees[j]));
  778. vProc(fTemp);
  779. end;
  780. end;
  781. end;
  782. CalcBillsFees(TScBillsItem(AItem.NextSibling));
  783. end;
  784. function TXMLPort.CheckNull(Value: Double): string;
  785. begin
  786. Result := CheckNull(FloatToStr(Value));
  787. end;
  788. procedure TXMLPort.DisposeXMLNodesList;
  789. var i: Integer;
  790. begin
  791. for i := 0 to FXMLNodesList.Count - 1 do
  792. begin
  793. if Assigned(PXMLNode(FXMLNodesList[i])) then
  794. Dispose(PXMLNode(FXMLNodesList[i])); // 释放指针
  795. end;
  796. end;
  797. // 工程量清单时,读取的 AItem.FullCode 只有自己编号,没有连接父项编号,不符合要求。
  798. function TXMLPort.GetCompareFullCode(AItem: TScBillsItem): string;
  799. var vCurItem: TScBillsItem;
  800. sCode: string;
  801. begin
  802. vCurItem := AItem;
  803. sCode := vCurItem.Code + vCurItem.B_Code;
  804. while (vCurItem.Parent <> nil) and ((TScBillsItem(vCurItem.Parent).Code + TScBillsItem(vCurItem.Parent).B_Code) <> '') do
  805. begin
  806. sCode := (TScBillsItem(vCurItem.Parent).Code + TScBillsItem(vCurItem.Parent).B_Code) + '-' + sCode;
  807. vCurItem := TScBillsItem(vCurItem.Parent);
  808. end;
  809. Result := sCode;
  810. end;
  811. function TXMLPort.GetCompareFullCode(AXMLNode: TXmlNode): string;
  812. var sCode: string;
  813. begin
  814. sCode := AXMLNode.AttributeValueByNameUTF8['Code'] + AXMLNode.AttributeValueByNameUTF8[FB_CodeFieldName];
  815. while (AXMLNode.Parent <> nil) and (AXMLNode.Parent.Name = 'Bills') and
  816. ((AXMLNode.Parent.AttributeValueByNameUTF8['Code'] + AXMLNode.Parent.AttributeValueByNameUTF8[FB_CodeFieldName]) <> '') do
  817. begin
  818. sCode := AXMLNode.Parent.AttributeValueByNameUTF8['Code'] + AXMLNode.Parent.AttributeValueByNameUTF8[FB_CodeFieldName] + '-' + sCode;
  819. AXMLNode := AXMLNode.Parent;
  820. end;
  821. Result := sCode;
  822. end;
  823. procedure TXMLPort.CheckB_CodeFieldName;
  824. //var
  825. // I: Integer;
  826. begin
  827. // AAAAA 换成了三方控件 NativeXml,下面这种写法玩不了
  828. // for I := 0 to FXMLDoc.XML.Count - 1 do
  829. // begin
  830. // if Pos('B_Code', FXMLDoc.XML[I]) > 0 then
  831. // begin
  832. // FB_CodeFieldName := 'B_Code';
  833. // Break;
  834. // end;
  835. // if Pos('b_Code', FXMLDoc.XML[I]) > 0 then
  836. // begin
  837. // FB_CodeFieldName := 'b_Code';
  838. // Break;
  839. // end;
  840. // end;
  841. FB_CodeFieldName := 'B_Code';
  842. if Pos('b_Code', FXMLDoc.WriteToString) > 0 then
  843. begin
  844. FB_CodeFieldName := 'b_Code';
  845. end;
  846. end;
  847. procedure TXMLPort.SetProgressive(const Value: Boolean);
  848. begin
  849. FProgressive := Value;
  850. end;
  851. procedure TXMLPort.SetProgressiveFile(const Value: string);
  852. begin
  853. FProgressiveFile := Value;
  854. end;
  855. procedure TXMLPort.CheckProj;
  856. var isNewOpen: Boolean;
  857. begin
  858. if (not Assigned(FProject)) and (FTenderRecList.Count > 0) then
  859. Project := GetProjectByTenderRec(TsdDataRecord(FTenderRecList[0]), isNewOpen); // 这里参数2打酱油,语法要求
  860. end;
  861. procedure TXMLPort.SetProgressive2(const Value: Boolean);
  862. begin
  863. FProgressive2 := Value;
  864. end;
  865. procedure TXMLPort.AddMultiProjects;
  866. var n: Integer;
  867. isNewOpen: Boolean;
  868. sValue, sTotalPrice: string;
  869. fTotalPrice: Double;
  870. begin
  871. for n := 0 to FTenderRecList.Count - 1 do
  872. begin
  873. AddProgressForm(10, Format('正在后台打开第 %d 个项目...', [n + 1]));
  874. Project := GetProjectByTenderRec(FTenderRecList[n], isNewOpen);
  875. sTotalPrice := GetProjectTotalPrice;
  876. fTotalPrice := StrToFloat(sTotalPrice);
  877. // 缓存当前打开项目的基本信息。序号;标段名称;金额;GUID
  878. sValue := Format('No=%d;Name=%s;TotalPrice=%s;GUID=%s',
  879. [n + 1, ProjectManager.TenderName(PD.ID), sTotalPrice, GetProjectGUID]);
  880. FProjectInfoCacheList.Add(sValue);
  881. FAllProjectsTotalPriceSum := FAllProjectsTotalPriceSum + fTotalPrice;
  882. CreateProjGLJNewCodeMap;
  883. AddNodesForEveryProject(n);
  884. // 打开项目事件
  885. if Assigned(FOnOpenProject) then
  886. FOnOpenProject(Project);
  887. { 第一个项目特殊,它在以下2种情况下可能是提前用后台打开过的:
  888. ①在导出前,要默认打开第一个项目取它的项目类型。
  889. ②要将FTenderRecList[0] 初始化给 FProject。
  890. 受第①条的影响,这里获取的isNewOpen值对第一个项目来说是不准的}
  891. if (n = 0) then
  892. begin
  893. if FFirtProjIsNewOpen then
  894. TScProjBaseData(TScProject(Project).ProjData).Close;
  895. end
  896. // 如果不是第一个项目,如果是新打开的,用完要关
  897. else
  898. begin
  899. if isNewOpen then
  900. TScProjBaseData(TScProject(Project).ProjData).Close;
  901. end;
  902. end;
  903. end;
  904. procedure TXMLPort.AddNodesForEveryProject(n: Integer);
  905. begin
  906. // nothing
  907. end;
  908. procedure TXMLPort.CreateProjGLJNewCodeMap;
  909. // 判断编号是否存在。两个位置判断:①项目工料机 ②新编号数组中。
  910. function IsExistCode(ACode: string): Boolean;
  911. var k: Integer;
  912. begin
  913. Result := False;
  914. FSearch3.Close;
  915. FSearch3.SQL.Text := Format('Select Code From Port_Prj WHERE Code=''%s''', [ACode]);
  916. FSearch3.Open;
  917. Result := (FSearch3.RecordCount > 0);
  918. FSearch3.Close;
  919. if (not Result) then
  920. begin
  921. for k := 0 to FGLJKeyCodeMap.Count - 1 do
  922. begin
  923. if FGLJKeyCodeMap.Values[FGLJKeyCodeMap.Names[k]] = ACode then
  924. begin
  925. Result := True;
  926. Break;
  927. end;
  928. end;
  929. end;
  930. end;
  931. procedure DealCodeWith_(var ACode: string; var ANum: Integer);
  932. var idx: Integer;
  933. sNewCode, sNum: string;
  934. begin
  935. idx := Pos('-', ACode);
  936. if idx = 0 then Exit;
  937. sNewCode := Copy(ACode, 1, idx - 1);
  938. sNum := Copy(ACode, idx + 1, Length(ACode) - idx);
  939. ACode := sNewCode;
  940. try
  941. ANum := StrToInt(sNum) + 1;
  942. except
  943. //
  944. end;
  945. end;
  946. procedure CutKey(AKey: string; var AID, AType, ACalcType, ARationPrice: string);
  947. var vSL: TStringList;
  948. begin
  949. vSL := TStringList.Create;
  950. try
  951. vSL.Delimiter := '-';
  952. vSL.DelimitedText := AKey;
  953. AID := vSL[0];
  954. AType := vSL[1];
  955. ACalcType := vSL[2];
  956. ARationPrice := vSL[3];
  957. finally
  958. vSL.Free;
  959. end;
  960. end;
  961. var
  962. i, iLen, n, c: Integer;
  963. sNewCode, sOldCode, sCode, sKey, sID, sType, sCalcType, sRPrice, sFileName, s1: string;
  964. bTest: Boolean;
  965. begin
  966. bTest := True; // 测试项目工料机的 Key-NewCode 映射表
  967. FGLJKeyCodeMap.Clear;
  968. AddProgressForm(10, '校验项目工料机类型,生成新的项目工料机表...');
  969. Create_Port_Prj;
  970. AddProgressForm(10, '检查项目工料机编号重复,生成KEY-新编号映射...');
  971. FSearch1.Close;
  972. FSearch1.SQL.Text := 'SELECT Code FROM Port_Prj GROUP BY Code HAVING COUNT(*) > 1';
  973. FSearch1.Open;
  974. if FSearch1.RecordCount = 0 then
  975. begin
  976. FSearch1.Close;
  977. Exit;
  978. end;
  979. try
  980. c := 0;
  981. FSearch1.First;
  982. while not FSearch1.Eof do
  983. begin
  984. Inc(c);
  985. sOldCode := FSearch1.FieldByName('Code').AsString;
  986. s1 := Format('为编号重复的工料机生成映射[%d/%d] %s', [c, FSearch1.RecordCount, sOldCode]);
  987. AddProgressForm(1, s1);
  988. FSearch2.Close;
  989. FSearch2.SQL.Text := Format('Select GLJID, Type, CalculateType, RationPrice from Port_Prj WHERE Code=''%s'' order by GLJID', [sOldCode]);
  990. FSearch2.Open;
  991. FSearch2.First;
  992. FSearch2.Next;
  993. n := 1;
  994. DealCodeWith_(sOldCode, n);
  995. while not FSearch2.Eof do
  996. begin
  997. sNewCode := sOldCode + '-' + IntToStr(n);
  998. while IsExistCode(sNewCode) do
  999. begin
  1000. Inc(n);
  1001. sNewCode := sOldCode + '-' + IntToStr(n);
  1002. end;
  1003. // '535-4-0=1511010-1' 2024.09.29 Key追加第4项:定额价。
  1004. sKey := Format('%d-%d-%d-%g', [FSearch2.FieldByName('GLJID').AsInteger, FSearch2.FieldByName('Type').AsInteger,
  1005. FSearch2.FieldByName('CalculateType').AsInteger, FSearch2.FieldByName('RationPrice').AsFloat]);
  1006. FGLJKeyCodeMap.Add(Format('%s=%s', [sKey, sNewCode]));
  1007. FSearch2.Next;
  1008. end;
  1009. FSearch1.Next;
  1010. end;
  1011. // 新编号写回 Port_Prj 表。
  1012. if (FGLJKeyCodeMap.Count > 0) then
  1013. begin
  1014. FGLJKeyCodeMap.Sort;
  1015. for i := 0 to FGLJKeyCodeMap.Count - 1 do
  1016. begin
  1017. sKey := FGLJKeyCodeMap.Names[i];
  1018. sCode := FGLJKeyCodeMap.Values[sKey];
  1019. CutKey(sKey, sID, sType, sCalcType, sRPrice);
  1020. FSearch1.Close;
  1021. FSearch1.SQL.Text := Format('update Port_Prj set Code=''%s'' where GLJID=%s and Type=%s and CalculateType=%s and RationPrice=%s',
  1022. [sCode, sID, sType, sCalcType, sRPrice]);
  1023. FSearch1.ExecSQL;
  1024. end;
  1025. if bTest then
  1026. begin
  1027. sFileName := ExtractFilePath(Application.ExeName) + 'UserData\' + 'GljKeyCodeMap.txt';
  1028. FGLJKeyCodeMap.SaveToFile(sFileName);
  1029. end;
  1030. end;
  1031. finally
  1032. FSearch1.Close;
  1033. FSearch2.Close;
  1034. end;
  1035. end;
  1036. procedure TXMLPort.Create_Port_Prj;
  1037. function CheckTable(ATableName: string): Boolean;
  1038. var
  1039. I: Integer;
  1040. Names: TStringList;
  1041. begin
  1042. Names := TStringList.Create;
  1043. try
  1044. FSearch1.Connection.GetTableNames(Names);
  1045. if Names.IndexOf(ATableName) < 0 then
  1046. Result := False
  1047. else
  1048. Result := True;
  1049. finally
  1050. Names.Free;
  1051. end;
  1052. end;
  1053. begin
  1054. if CheckTable('Port_GR') then
  1055. begin
  1056. FSearch1.SQL.Clear;
  1057. FSearch1.SQL.Add('Drop Table Port_GR');
  1058. FSearch1.ExecSQL;
  1059. end;
  1060. if CheckTable('Port_Prj') then
  1061. begin
  1062. FSearch1.SQL.Clear;
  1063. FSearch1.SQL.Add('Drop Table Port_Prj');
  1064. FSearch1.ExecSQL;
  1065. end;
  1066. // 先修复旧数据,在正确数据的基础上才展开各种业务设计,否则后续各种困难。
  1067. // 将 CalculateType 的 -1 全部改成 0,否则影响 Key 解析,如 1247-4--1。
  1068. FSearch1.Close;
  1069. FSearch1.SQL.Text := 'Update GLJList set CalculateType=0 where CalculateType=-1';
  1070. FSearch1.ExecSQL;
  1071. FSearch1.Close;
  1072. FSearch1.SQL.Text := 'Update ProjectGLJ set CalculateType=0 where CalculateType=-1';
  1073. FSearch1.ExecSQL;
  1074. // 1、定额工料机 Gljlist 表去重。2、量价、设备 RationCalcList 表去重(创建新工料机时,固定类型:材料4,0。设备6,0)。3、二者联合。
  1075. FSearch1.Close;
  1076. FSearch1.SQL.Text :=
  1077. 'Select * into Port_GR from ' +
  1078. '(Select GLJID, Type, CalculateType, RationPrice From GLJList Group By GLJID, Type, CalculateType, RationPrice ' +
  1079. 'union ' +
  1080. 'select distinct GLJID, IIF(IsMECalc=true, 6, 4) as Type, CalculateType, ' +
  1081. 'IIF(IsMECalc=true, IIF(isnull(UnitPrice), 0, UnitPrice), IIF(isnull(RationUnitDirectFee), 0, RationUnitDirectFee)) as RationPrice ' +
  1082. 'From RationCalcList as R, projectGLJ as P where GLJID is not NULL and R.GLJID=P.ID)';
  1083. FSearch1.ExecSQL;
  1084. // 查找项目工料机有,而定额工料机、量价、设备都没有的,合在Port_GR中,成为全Key表,然后联合ProjectGLJ,生成最终的项目工料机表2。
  1085. // 左多右少联合(在右创建新的项目工料机。多:指同一材料多种类型,少:项目工料机只有1条)。
  1086. FSearch1.Close;
  1087. FSearch1.SQL.Text :=
  1088. 'Select * into Port_Prj from ( ' +
  1089. 'select F.GLJID, F.Type, F.CalculateType, F.RationPrice, ' +
  1090. 'P.Code, P.Name, P.Type as PType, P.CalculateType as PCType, P.Unit, P.Specs, P.Amount, P.BasePrice, P.BudgetPrice, ' +
  1091. 'P.Main, P.New, P.FZAmount, P.SHRate, P.SHAmount, P.TaxFeeRate, P.DutiablePrice, ' +
  1092. 'F.Type-P.Type as DiffT, F.CalculateType-P.CalculateType as DiffCT, F.RationPrice-P.BasePrice as DiffP from ' +
  1093. '(Select GLJID, Type, CalculateType, RationPrice From Port_GR ' +
  1094. 'union all ' +
  1095. 'select ID as GLJID, Type, CalculateType, BasePrice as RationPrice from ProjectGLJ where ID not in (Select GLJID from Port_GR)) as F ' +
  1096. 'left join ProjectGLJ as P on F.GLJID=P.ID)';
  1097. FSearch1.ExecSQL;
  1098. // 创建主键
  1099. FSearch1.Close;
  1100. FSearch1.SQL.Text := 'alter table Port_Prj add constraint PrimaryKey Primary Key (GLJID, type, CalculateType, RationPrice)';
  1101. FSearch1.ExecSQL;
  1102. // 创建索引
  1103. FSearch1.Close;
  1104. FSearch1.SQL.Text := 'Create Unique Index idxID_Type_CalcType on Port_Prj (GLJID, type, CalculateType, RationPrice)';
  1105. FSearch1.ExecSQL;
  1106. FSearch1.Close;
  1107. end;
  1108. function TXMLPort.GetProjectGUID(AIsBuildProj: Boolean): string;
  1109. var sName: string;
  1110. begin
  1111. if Self.FileType = xftTB then // 投标直接读属性
  1112. begin
  1113. Result := PD.Properties.GUID;
  1114. end
  1115. else // 招标要自己造
  1116. begin
  1117. sName := ExtractFileName(PD.FileName);
  1118. sName := Copy(sName, 2, Length(sName) - 2);
  1119. Result := sName;
  1120. if AIsBuildProj and (Length(sName) > 0) then
  1121. begin
  1122. Result := 'SC99' + Copy(sName, 5, 28) + '99CS';
  1123. end;
  1124. end;
  1125. end;
  1126. {-------------------------------------------------------------------------------
  1127. GUID码 xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
  1128. 36个字符,第1段8个字符,第2~4段4个字符,第5段12字符。
  1129. x:表示 16 进制数字(0-9、a-f/A-F),大小写不敏感
  1130. M:版本号(1-5),标识 GUID 的生成算法(最常用的是版本 4,随机生成)
  1131. N:变体位(固定为 8、9、a、b 中的一个)
  1132. -------------------------------------------------------------------------------}
  1133. function TXMLPort.IDtoGUID(ID: Integer): string;
  1134. var i: Integer;
  1135. s1, s2: string;
  1136. begin
  1137. s1 := IntToStr(ID);
  1138. while Length(s1) < 8 do
  1139. begin
  1140. s1 := '0'+ s1;
  1141. end;
  1142. // 多个标段时,生成的GUID不能重复:尾部留8位随机数字。
  1143. s2 := '';
  1144. while Length(s2) < 8 do
  1145. begin
  1146. s2 := s2 + IntToStr(random(10));
  1147. end;
  1148. Result := s1 + '-FFFF-4FFF-aFFF-FFFF' + s2;
  1149. end;
  1150. function TXMLPort.GetSeparatorCount(ACode: string): Integer;
  1151. var i, L: Integer;
  1152. begin
  1153. Result := 0;
  1154. L := Length(ACode);
  1155. for i := 1 to L do
  1156. begin
  1157. if ACode[i] = '-' then
  1158. Inc(Result);
  1159. end;
  1160. end;
  1161. procedure TXMLPort.AddRoot;
  1162. begin
  1163. // nothing
  1164. end;
  1165. procedure TXMLPort.AddDetail;
  1166. begin
  1167. // nothing
  1168. end;
  1169. procedure TXMLPort.AddNodes;
  1170. begin
  1171. FRoot := FXMLDoc.Root;
  1172. if (FRootName <> '') then
  1173. FRoot.Name := AnsiToUtf8(FRootName);
  1174. end;
  1175. procedure TXMLPort.FillData(AProject: TObject; ABDRootNode: TXmlNode); // ABDRootNode: <公路标段工程>
  1176. var vNode: TXmlNode;
  1177. vItem: TScBillsItem;
  1178. OldRealTimeCalc: Boolean;
  1179. begin
  1180. OldRealTimeCalc := TScProject(AProject).RealTimeCalc;
  1181. try
  1182. TScProject(AProject).RealTimeCalc := False;
  1183. with TScProject(AProject).Bills do
  1184. begin
  1185. // 删除第一部分的子结点
  1186. vItem := BillsTree[idNormalBillsRoot];
  1187. BillsTree.DeleteChildren(vItem);
  1188. vNode := ABDRootNode.FindNodeUTF8('工程量清单表').Elements[0];
  1189. RcsvAddBillItems(AProject, vItem, vNode);
  1190. // 导入计日工
  1191. vItem := BillsTree[idDayWork];
  1192. BillsTree.DeleteChildren(vItem);
  1193. vNode := ABDRootNode.FindNodeUTF8('计日工信息表').Elements[0];
  1194. RcsvAddDayWorks(AProject, vItem, vNode);
  1195. TScProject(AProject).Bills.CalculateAll;
  1196. // 最后存储
  1197. TScProjBaseData(TScProject(AProject).ProjData).Save;
  1198. end;
  1199. finally
  1200. TScProject(AProject).RealTimeCalc := OldRealTimeCalc;
  1201. end;
  1202. end;
  1203. procedure TXMLPort.RcsvAddBillItems(AProject: TObject; AParentItem: TScBillsItem; ANode: TXmlNode);
  1204. function AddItemMX(AProject: TObject; AParentItem: TScBillsItem; ANode: TXmlNode): TScBillsItem;
  1205. var dt: string;
  1206. begin
  1207. dt := ANode.AttributeValueByNameUTF8['数据类型'];
  1208. Result := TScProject(AProject).Bills.BillsTree.AddBillsItem(AParentItem.ID, -1);
  1209. with Result.Rec do
  1210. begin
  1211. BeginUpdate;
  1212. GUIDstr.AsString := ANode.AttributeValueByNameUTF8['GUID'];
  1213. DataType.AsString := dt;
  1214. Code.AsString := ANode.AttributeValueByNameUTF8['子目号'];
  1215. Name.AsString := ANode.AttributeValueByNameUTF8['子目名称'];
  1216. MemoStr.AsString := ANode.AttributeValueByNameUTF8['备注'];
  1217. Units.AsString := ANode.AttributeValueByNameUTF8['单位'];
  1218. Quantity.AsString := ANode.AttributeValueByNameUTF8['数量'];
  1219. UnitPrice.AsString := ANode.AttributeValueByNameUTF8['单价'];
  1220. TotalPrice.AsString := ANode.AttributeValueByNameUTF8['合价'];
  1221. IsLeaf.AsBoolean := True;
  1222. if dt = '21' then
  1223. begin
  1224. IsSpecialInterim.AsBoolean := True;
  1225. InterimType.AsInteger := 3; // 显示专业工程
  1226. end;
  1227. CalcFlag.AsInteger := Flag_CustomTotalPrice;
  1228. EndUpdate;
  1229. end;
  1230. end;
  1231. var i: Integer;
  1232. vItem: TScBillsItem;
  1233. begin
  1234. if not Assigned(ANode) then Exit;
  1235. if (Utf8ToAnsi(ANode.Name) <> '工程量清单明细') then Exit;
  1236. vItem := AddItemMX(AProject, AParentItem, ANode);
  1237. if Assigned(ANode.Elements[0]) then
  1238. RcsvAddBillItems(AProject, vItem, ANode.Elements[0]);
  1239. if Assigned(ANode.NextSib) then
  1240. RcsvAddBillItems(AProject, AParentItem, ANode.NextSib);
  1241. end;
  1242. procedure TXMLPort.RcsvAddDayWorks(AProject: TObject;
  1243. AParentItem: TScBillsItem; ANode: TXmlNode);
  1244. function AddDayWrokMX(AProject: TObject; AParentItem: TScBillsItem; ANode: TXmlNode): TScBillsItem;
  1245. begin
  1246. Result := TScProject(AProject).Bills.BillsTree.AddBillsItem(AParentItem.ID, -1);
  1247. with Result.Rec do
  1248. begin
  1249. BeginUpdate;
  1250. Code.AsString := ANode.AttributeValueByNameUTF8['序号'];
  1251. Name.AsString := ANode.AttributeValueByNameUTF8['名称'];
  1252. TotalPrice.AsString := ANode.AttributeValueByNameUTF8['合价'];
  1253. CalcFlag.AsInteger := Flag_CustomTotalPrice;
  1254. EndUpdate;
  1255. end;
  1256. end;
  1257. var i: Integer;
  1258. vItem: TScBillsItem;
  1259. begin
  1260. if not Assigned(ANode) then Exit;
  1261. if (Utf8ToAnsi(ANode.Name) <> '计日工信息标题') and (Utf8ToAnsi(ANode.Name) <> '计日工信息明细') then Exit;
  1262. if (ANode.AttributeValueByNameUTF8['数据类型'] <> '0') then // 计日工这条重复。且招标文件这里的计日工第一层是平级,无树结构。
  1263. begin
  1264. vItem := AddDayWrokMX(AProject, AParentItem, ANode);
  1265. end;
  1266. if Assigned(ANode.Elements[0]) then
  1267. RcsvAddDayWorks(AProject, vItem, ANode.Elements[0]);
  1268. if Assigned(ANode.NextSib) then
  1269. RcsvAddDayWorks(AProject, AParentItem, ANode.NextSib);
  1270. end;
  1271. function TXMLPort.BV(AName: string): string;
  1272. begin
  1273. Result := ProjectManager.GetBuildProjectProperty(FBuildProjRec, AName);
  1274. end;
  1275. procedure TXMLPort.SetBuildProjRec(const Value: TsdDataRecord);
  1276. begin
  1277. FBuildProjRec := Value;
  1278. end;
  1279. procedure TXMLPort.SetOnOpenProject(const Value: TNotifyEvent);
  1280. begin
  1281. FOnOpenProject := Value;
  1282. end;
  1283. procedure TXMLPort.ZipFiles(AFileList: TStringList; AResultFileName: string);
  1284. var vZip: TVCLZip;
  1285. i: Integer;
  1286. begin
  1287. vZip := TVCLZip.Create(nil);
  1288. try
  1289. for i := 0 to AFileList.Count - 1 do
  1290. begin
  1291. vZip.FilesList.Add(AFileList[i]);
  1292. end;
  1293. vZip.ZipName := AResultFileName;
  1294. vZip.Recurse := True;
  1295. vZip.OverwriteMode := Always;
  1296. vZip.Zip;
  1297. for i := 0 to AFileList.Count - 1 do
  1298. begin
  1299. SysUtils.DeleteFile(PChar(AFileList[i]));
  1300. end;
  1301. finally
  1302. vZip.Free;
  1303. end;
  1304. end;
  1305. { TqgXMLPort }
  1306. procedure TqgXMLPort.AddCprjInfo;
  1307. var sProg1, sProg2, sT: string;
  1308. begin
  1309. FRoot.Name := 'CprjInfo';
  1310. FRoot.AttributeAddUTF8('CprjName', PD.BuildProjectName);
  1311. FRoot.AttributeAddUTF8('CalculateMode', IntToStr(PD.Properties.UnitPriceMode + 1));
  1312. sT := '';
  1313. case TScProject(FProject).ProjType of
  1314. ptBills: sT := 'QDYS';
  1315. ptBudget: sT := 'SGYS';
  1316. ptBillsBudget: sT := 'SJYS';
  1317. ptBudgetEstimate: sT := 'SJGS';
  1318. ptFeasibilityEstimate: sT := 'GKGS';
  1319. ptProposalEstimate: sT := 'JYGS';
  1320. end;
  1321. FRoot.AttributeAddUTF8('CprjType', sT);
  1322. FRoot.AttributeAddUTF8('SmartcostDigit', 'True');
  1323. if Progressive then
  1324. sProg1 := 'True'
  1325. else
  1326. sProg1 := 'False';
  1327. if Progressive2 then
  1328. sProg2 := 'True'
  1329. else
  1330. sProg2 := 'False';
  1331. FRoot.AttributeAddUTF8('CSDFeeProgressive', sProg1);
  1332. FRoot.AttributeAddUTF8('OECFeesProgressive', sProg2);
  1333. FRoot.AttributeAddUTF8('ProgressiveFile', ProgressiveFile);
  1334. end;
  1335. procedure TqgXMLPort.AddDecimalOption;
  1336. var vDO: TXmlNode;
  1337. begin
  1338. vDO := FRoot.NodeNewUTF8('DecimalOption');
  1339. vDO.AttributeAddUTF8('ItemPricePrecision', IntToStr(PD.Project.DigitManager.UnitPriceDigit));
  1340. vDO.AttributeAddUTF8('ItemSumPrecision', IntToStr(PD.Project.DigitManager.TotalPriceDigit));
  1341. vDO.AttributeAddUTF8('NormNumPrecision', IntToStr(PD.Project.DigitManager.RationQuantityDigit));
  1342. vDO.AttributeAddUTF8('NormPricePrecision', IntToStr(PD.Project.DigitManager.RationBuildPriceDigit));
  1343. vDO.AttributeAddUTF8('NormSumPrecision', IntToStr(PD.Project.DigitManager.RationFeesDigit));
  1344. vDO.AttributeAddUTF8('Consumption', IntToStr(PD.Project.DigitManager.GLJQuantityDigit));
  1345. vDO.AttributeAddUTF8('ConsumePrice', IntToStr(PD.Project.DigitManager.BudgetPriceDigit));
  1346. vDO.AttributeAddUTF8('RatePrecision', IntToStr(PD.Project.DigitManager.RateDigit));
  1347. end;
  1348. procedure TqgXMLPort.AddSystemInfo;
  1349. begin
  1350. AddProgressForm(10, '正在生成系统信息...');
  1351. FSystemInfoNode := FRoot.NodeNewUTF8('SystemInfo');
  1352. FSystemInfoNode.AttributeAddUTF8('Name', '公路工程造价数据标准');//PD.BuildProjectName;
  1353. FSystemInfoNode.AttributeAddUTF8('Version', '1.0');
  1354. FSystemInfoNode.AttributeAddUTF8('SoftwareName', Application.Title);
  1355. FSystemInfoNode.AttributeAddUTF8('SoftwareVer', ScGetVersion);
  1356. FSystemInfoNode.AttributeAddUTF8('SoftwareCompany', '珠海纵横创新软件有限公司');
  1357. // FSystemInfoNode.AttributeAdd('MakeDate', FormatDateTime('yyyy-mm-ddThh:nn:ss', Now)); // Copy(DateToStr(PD.EditDate), 1, 10)
  1358. FSystemInfoNode.AttributeAddUTF8('MakeDate', FormatDateTime('yyyy-mm-dd', Now) + 'T' + FormatDateTime('hh:nn:ss', Now));
  1359. end;
  1360. procedure TqgXMLPort.AddRationLibs;
  1361. var vLibs: TScProjectRationLibs;
  1362. vLib: TScProjectRationLib;
  1363. I, l: Integer;
  1364. function IsExist(ALibName: string): Boolean;
  1365. var
  1366. K: Integer;
  1367. begin
  1368. Result := False;
  1369. for K := 0 to Length(FAllLibNames) - 1 do
  1370. begin
  1371. if FAllLibNames[K] = ALibName then
  1372. begin
  1373. Result := True;
  1374. Break;
  1375. end;
  1376. end;
  1377. end;
  1378. begin
  1379. FGDSZDEKID := -1; // 每个项目都要初始化一次,重新赋值库ID。(因为总是从 0、1、2、3...开始,没有真正的唯一性ID)
  1380. vLibs := TScProject(FProject).RationLibs;
  1381. SetLength(FLibArr, 0);
  1382. SetLength(FLibArr, vLibs.Count);
  1383. for I := 0 to vLibs.Count - 1 do
  1384. begin
  1385. vLib := vLibs.FindLib(I);
  1386. FLibArr[I].Value := vLib.ID;
  1387. FLibArr[I].Name := vLib.LibName;
  1388. // FGDSZDEKID 正常情况下值为-1。当该属性值不为-1时,表示本项目存在该定额库,此时进一步判断,ID一致时,即为条件符合
  1389. if (vLib.LibName = '广东省市政工程综合定额(2018)') then FGDSZDEKID := vLib.ID;
  1390. if not IsExist(vLib.LibName) then
  1391. begin
  1392. FNormLibNode := FCostBasisNode.NodeNewUTF8('NormLib');
  1393. FNormLibNode.AttributeAddUTF8('NormLibNo', GetMapValue(GetMap('Map_RationLib'), vLib.LibName));
  1394. FNormLibNode.AttributeAddUTF8('NormLibName', vLib.LibName);
  1395. if (Length(FAllLibNames) = 0) then // 如果是主定额库,则显示“ZDEK”;如果是借用定额库,则显示“JYDEK”。
  1396. FNormLibNode.AttributeAddUTF8('Type', 'ZDEK')
  1397. else
  1398. FNormLibNode.AttributeAddUTF8('Type', 'JYDEK');
  1399. l := Length(FAllLibNames) + 1;
  1400. SetLength(FAllLibNames, l);
  1401. FAllLibNames[l-1]:= vLib.LibName;
  1402. end;
  1403. end;
  1404. end;
  1405. procedure TqgXMLPort.AddCostBasis;
  1406. begin
  1407. AddProgressForm(10, '正在生成造价依据信息...');
  1408. FCostBasisNode := FRoot.NodeNewUTF8('CostBasis');
  1409. case TScProject(FProject).ProjType of
  1410. ptBills, ptBudget, ptBudgetEstimate:
  1411. begin
  1412. FCostBasisNode.AttributeAddUTF8('MakeRuleNo', 'GYSBB-000000-2018-86');
  1413. FCostBasisNode.AttributeAddUTF8('MakeRuleName', '公路工程建设项目概算预算编制办法');
  1414. FCostBasisNode.AttributeAddUTF8('ItemStandardNo', 'GYSFX-000000-2018-86');
  1415. end;
  1416. ptFeasibilityEstimate, ptProposalEstimate:
  1417. begin
  1418. FCostBasisNode.AttributeAddUTF8('MakeRuleNo', 'GSBB-000000-2018-86');
  1419. FCostBasisNode.AttributeAddUTF8('MakeRuleName', '公路工程建设项目投资估算编制办法');
  1420. FCostBasisNode.AttributeAddUTF8('ItemStandardNo', 'GSFX-000000-2018-86');
  1421. end;
  1422. end;
  1423. end;
  1424. procedure TqgXMLPort.AddRate(AFileNo: Integer);
  1425. var sSQL, sSQLTemp, sTemp: string;
  1426. function GetRateLibNo: string;
  1427. var sName: string;
  1428. begin
  1429. FSearch1.Close;
  1430. FSearch1.SQL.Text := 'select Caption From FeeParams where ID=2';
  1431. FSearch1.Open;
  1432. sName := FSearch1.FieldByName('Caption').asString;
  1433. FSearch1.Close;
  1434. Result := GetMapValue(GetMap('Map_FeeRateLib'), sName);
  1435. end;
  1436. begin
  1437. AddProgressForm(10, '正在生成费率文件信息...');
  1438. FRateNode := FRoot.NodeNewUTF8('Rate');
  1439. FRateNode.AttributeAddUTF8('RateNo', IntToStr(AFileNo));
  1440. FRateNode.AttributeAddUTF8('Name', ExtractFileName(FFeeRateFile.LibName));
  1441. FRateNode.AttributeAddUTF8('RateLibNo', GetRateLibNo);
  1442. if FFileType = xftTB then
  1443. // sSQLTemp := 'round(Param * 1, 3) as RateParamNo, '
  1444. sSQLTemp := 'Caption as RateParamNo, ' // 改成映射Caption列
  1445. else
  1446. sSQLTemp := '''0'' as RateParamNo, ';
  1447. sSQL :=
  1448. 'Select Switch(ID=101, ''DJSGZJFFL'', ID=102, ''YUJSGZJFFL'', ID=103, ''YEJSGZJFFL'', ID=104, ''GYDQSGZJFFL'', ' +
  1449. 'ID=105, ''FSDQSGZJFFL'', ID=106, ''YHDQSGZJFFL'', ID=107, ''XCGRGCSGZJFFL'', ID=110, ''SGFZFFL'', ID=111, ''GDZYFFL'', ' +
  1450. 'true, ID) as RateTypeNo, ' + sSQLTemp +
  1451. '''1'' as Ratio from FeeParams where ID<200 and ID>2 ' +
  1452. 'union all ' +
  1453. 'Select Switch(ID=201, ''YANGLBXFFL'', ID=202, ''SYBXFFL'', ID=203, ''YILBXFFL'', ID=204, ''ZFGJJFL'', ID=205, ''GSBXFL'', ' +
  1454. 'ID=301, ''JBFYFL'', ID=302, ''ZFSYFBTFL'', ID=303, ''ZGTQLFFL'', ID=304, ''ZGQNBTFL'', ID=305, ''CWFYFL'', ' +
  1455. 'true, ID) as RateTypeNo, ' +
  1456. 'round(Param * 1, 3) as RateParamNo, ''1'' as Ratio from FeeParams where ID>200 and MinorID=0 ' +
  1457. 'union all ' +
  1458. 'Select ''LRL'' as RateTypeNo, round(Profit * 1, 3) as RateParamNo, ''1'' as Ratio from FeeOthers ' +
  1459. 'union all ' +
  1460. 'Select ''SL'' as RateTypeNo, round(Tax * 1, 3) as RateParamNo, ''1'' as Ratio from FeeOthers ';
  1461. // FSearch1.SQL.Text := sSQL;
  1462. // FSearch1.SQL.SaveToFile('C:\Users\Administrator\Desktop\T2.sql');
  1463. AddTabToXML(FQuery2, sSQL, FRateNode, 'RateParams', 'RateParam');
  1464. if FFileType = xftTB then
  1465. sSQL :=
  1466. ' Select CostTypeNo as [CostTypeNo@Map_GetFeeKind_GS@0@2], RateTypeNo, RateValue from( ' +
  1467. ' Select Code as CostTypeNo, Name, ''DJSGZJFFL'' as RateTypeNo, round(Value101 * 1, 3) as RateValue, ''01'' as orderNo from Fees ' + // 冬季施工
  1468. ' union all ' +
  1469. ' Select Code as CostTypeNo, Name, ''YUJSGZJFFL'' as RateTypeNo, round(Value102 * 1, 3) as RateValue, ''02'' as orderNo from Fees ' + // 雨季施工
  1470. ' union all ' +
  1471. ' Select Code as CostTypeNo, Name, ''YEJSGZJFFL'' as RateTypeNo, round(Value103 * 1, 3) as RateValue, ''03'' as orderNo from Fees ' + // 夜间施工
  1472. ' union all ' +
  1473. ' Select Code as CostTypeNo, Name, ''GYDQSGZJFFL'' as RateTypeNo, round(Value104 * 1, 3) as RateValue, ''04'' as orderNo from Fees ' + // 高原施工
  1474. ' union all ' +
  1475. ' Select Code as CostTypeNo, Name, ''FSDQSGZJFFL'' as RateTypeNo, round(Value105 * 1, 3) as RateValue, ''05'' as orderNo from Fees ' + // 风沙施工
  1476. ' union all ' +
  1477. ' Select Code as CostTypeNo, Name, ''YHDQSGZJFFL'' as RateTypeNo, round(Value106 * 1, 3) as RateValue, ''06'' as orderNo from Fees ' + // 沿海地区
  1478. ' union all ' +
  1479. ' Select Code as CostTypeNo, Name, ''XCGRGCSGZJFFL'' as RateTypeNo, round(Value107 * 1, 3) as RateValue, ''07'' as orderNo from Fees ' + // 行车干扰
  1480. ' union all ' +
  1481. ' Select Code as CostTypeNo, Name, ''SGFZFFL'' as RateTypeNo, round(Value110 * 1, 3) as RateValue, ''08'' as orderNo from Fees ' + // 施工辅助
  1482. ' union all ' +
  1483. ' Select Code as CostTypeNo, Name, ''GDZYFFL'' as RateTypeNo, round(Value111 * 1, 3) as RateValue, ''09'' as orderNo from Fees ' + // 工地转移(km)
  1484. ' union all ' +
  1485. ' Select Code as CostTypeNo, Name, ''YANGLBXFFL'' as RateTypeNo, round(Value201 * 1, 3) as RateValue, ''10'' as orderNo from Fees ' + // 养老保险(%)
  1486. ' union all ' +
  1487. ' Select Code as CostTypeNo, Name, ''SYBXFFL'' as RateTypeNo, round(Value202 * 1, 3) as RateValue, ''11'' as orderNo from Fees ' + // 失业保险(%)
  1488. ' union all ' +
  1489. ' Select Code as CostTypeNo, Name, ''YILBXFFL'' as RateTypeNo, round(Value203 * 1, 3) as RateValue, ''12'' as orderNo from Fees ' + // 医疗保险(%)
  1490. ' union all ' +
  1491. ' Select Code as CostTypeNo, Name, ''ZFGJJFL'' as RateTypeNo, round(Value204 * 1, 3) as RateValue, ''13'' as orderNo from Fees ' + // 住房公积金(%)
  1492. ' union all ' +
  1493. ' Select Code as CostTypeNo, Name, ''GSBXFL'' as RateTypeNo, round(Value205 * 1, 3) as RateValue, ''14'' as orderNo from Fees ' + // 工伤保险(%)
  1494. ' union all ' +
  1495. ' Select Code as CostTypeNo, Name, ''JBFYFL'' as RateTypeNo, round(Value301 * 1, 3) as RateValue, ''15'' as orderNo from Fees ' + // 基本费用
  1496. ' union all ' +
  1497. ' Select Code as CostTypeNo, Name, ''ZFSYFBTFL'' as RateTypeNo, round(Value302 * 1, 3) as RateValue, ''16'' as orderNo from Fees ' + // 综合里程(km)
  1498. ' union all ' +
  1499. ' Select Code as CostTypeNo, Name, ''ZGTQLFFL'' as RateTypeNo, round(Value303 * 1, 3) as RateValue, ''17'' as orderNo from Fees ' + // 职工探亲
  1500. ' union all ' +
  1501. ' Select Code as CostTypeNo, Name, ''ZGQNBTFL'' as RateTypeNo, round(Value304 * 1, 3) as RateValue, ''18'' as orderNo from Fees ' + // 职工取暖
  1502. ' union all ' +
  1503. ' Select Code as CostTypeNo, Name, ''CWFYFL'' as RateTypeNo, round(Value305 * 1, 3) as RateValue, ''19'' as orderNo from Fees ' + // 财务费用
  1504. ' union all ' +
  1505. ' Select Code as CostTypeNo, Name, ''LRL'' as RateTypeNo, round(Profit * 1, 3) as RateValue, ''20'' as orderNo from Fees, FeeOthers ' + // 利润
  1506. ' union all ' +
  1507. ' Select Code as CostTypeNo, Name, ''SL'' as RateTypeNo, round(Tax * 1, 3) as RateValue, ''21'' as orderNo from Fees, FeeOthers ' + // 税金
  1508. ' ) ' +
  1509. ' order by orderNo, CostTypeNo'
  1510. else
  1511. sSQL :=
  1512. ' Select CostTypeNo as [CostTypeNo@Map_GetFeeKind_GS@0@2], RateTypeNo, RateValue from( ' +
  1513. ' Select Code as CostTypeNo, Name, ''DJSGZJFFL'' as RateTypeNo, 0 as RateValue, ''01'' as orderNo from Fees ' + // 冬季施工
  1514. ' union all ' +
  1515. ' Select Code as CostTypeNo, Name, ''YUJSGZJFFL'' as RateTypeNo, 0 as RateValue, ''02'' as orderNo from Fees ' + // 雨季施工
  1516. ' union all ' +
  1517. ' Select Code as CostTypeNo, Name, ''YEJSGZJFFL'' as RateTypeNo, 0 as RateValue, ''03'' as orderNo from Fees ' + // 夜间施工
  1518. ' union all ' +
  1519. ' Select Code as CostTypeNo, Name, ''GYDQSGZJFFL'' as RateTypeNo, 0 as RateValue, ''04'' as orderNo from Fees ' + // 高原施工
  1520. ' union all ' +
  1521. ' Select Code as CostTypeNo, Name, ''FSDQSGZJFFL'' as RateTypeNo, 0 as RateValue, ''05'' as orderNo from Fees ' + // 风沙施工
  1522. ' union all ' +
  1523. ' Select Code as CostTypeNo, Name, ''YHDQSGZJFFL'' as RateTypeNo, 0 as RateValue, ''06'' as orderNo from Fees ' + // 沿海地区
  1524. ' union all ' +
  1525. ' Select Code as CostTypeNo, Name, ''XCGRGCSGZJFFL'' as RateTypeNo, 0 as RateValue, ''07'' as orderNo from Fees ' + // 行车干扰
  1526. ' union all ' +
  1527. ' Select Code as CostTypeNo, Name, ''SGFZFFL'' as RateTypeNo, 0 as RateValue, ''08'' as orderNo from Fees ' + // 施工辅助
  1528. ' union all ' +
  1529. ' Select Code as CostTypeNo, Name, ''GDZYFFL'' as RateTypeNo, 0 as RateValue, ''09'' as orderNo from Fees ' + // 工地转移(km)
  1530. ' union all ' +
  1531. ' Select Code as CostTypeNo, Name, ''YANGLBXFFL'' as RateTypeNo, 0 as RateValue, ''10'' as orderNo from Fees ' + // 养老保险(%)
  1532. ' union all ' +
  1533. ' Select Code as CostTypeNo, Name, ''SYBXFFL'' as RateTypeNo, 0 as RateValue, ''11'' as orderNo from Fees ' + // 失业保险(%)
  1534. ' union all ' +
  1535. ' Select Code as CostTypeNo, Name, ''YILBXFFL'' as RateTypeNo, 0 as RateValue, ''12'' as orderNo from Fees ' + // 医疗保险(%)
  1536. ' union all ' +
  1537. ' Select Code as CostTypeNo, Name, ''ZFGJJFL'' as RateTypeNo, 0 as RateValue, ''13'' as orderNo from Fees ' + // 住房公积金(%)
  1538. ' union all ' +
  1539. ' Select Code as CostTypeNo, Name, ''GSBXFL'' as RateTypeNo, 0 as RateValue, ''14'' as orderNo from Fees ' + // 工伤保险(%)
  1540. ' union all ' +
  1541. ' Select Code as CostTypeNo, Name, ''JBFYFL'' as RateTypeNo, 0 as RateValue, ''15'' as orderNo from Fees ' + // 基本费用
  1542. ' union all ' +
  1543. ' Select Code as CostTypeNo, Name, ''ZFSYFBTFL'' as RateTypeNo, 0 as RateValue, ''16'' as orderNo from Fees ' + // 综合里程(km)
  1544. ' union all ' +
  1545. ' Select Code as CostTypeNo, Name, ''ZGTQLFFL'' as RateTypeNo, 0 as RateValue, ''17'' as orderNo from Fees ' + // 职工探亲
  1546. ' union all ' +
  1547. ' Select Code as CostTypeNo, Name, ''ZGQNBTFL'' as RateTypeNo, 0 as RateValue, ''18'' as orderNo from Fees ' + // 职工取暖
  1548. ' union all ' +
  1549. ' Select Code as CostTypeNo, Name, ''CWFYFL'' as RateTypeNo, 0 as RateValue, ''19'' as orderNo from Fees ' + // 财务费用
  1550. ' union all ' +
  1551. ' Select Code as CostTypeNo, Name, ''LRL'' as RateTypeNo, 0 as RateValue, ''20'' as orderNo from Fees, FeeOthers ' + // 利润
  1552. ' union all ' +
  1553. ' Select Code as CostTypeNo, Name, ''SL'' as RateTypeNo, 0 as RateValue, ''21'' as orderNo from Fees, FeeOthers ' + // 税金
  1554. ' ) ' +
  1555. ' order by orderNo, CostTypeNo';
  1556. AddTabToXML(FQuery2, sSQL, FRateNode, 'RateValues', 'RateValue', 'Flag_LrSj');
  1557. end;
  1558. procedure TqgXMLPort.AddPract(AFileNo: Integer);
  1559. function GetCarTaxLibNo: string;
  1560. var sName: string;
  1561. begin
  1562. FSearch1.Close;
  1563. FSearch1.SQL.Text := Format('Select ItemValue From ProjProperty Where Name = ''%s''', ['SHORTFEETAXFILE']);
  1564. FSearch1.Open;
  1565. sName := FSearch1.FieldByName('ItemValue').asString;
  1566. FSearch1.Close;
  1567. Result := GetMapValue(GetMap('Map_CarTaxLib'), sName);
  1568. end;
  1569. var sAltitudeRatio: string;
  1570. begin
  1571. AddProgressForm(10, '正在生成工料机单价文件信息...');
  1572. FPract := FRoot.NodeNewUTF8('Pract');
  1573. FPract.AttributeAddUTF8('PractNo', IntToStr(AFileNo));
  1574. FPract.AttributeAddUTF8('Name', ExtractFileName(FUnitPriceFile.LibName));
  1575. // 费率界面的基价系数。PingCode #GLY-5678
  1576. sAltitudeRatio := FloatToStr(TScProject(FProject).FeeRate.RationPriceRatio);
  1577. FPract.AttributeAddUTF8('AltitudeRatio', sAltitudeRatio);
  1578. FPract.AttributeAddUTF8('TaxLibNo', GetCarTaxLibNo); // 车船税费库编号
  1579. FPract.AttributeAddUTF8('PriceFileNo', 'JGXX-440000-2019-05'); // 价格信息编号
  1580. AddMps; // 人
  1581. AddMaterials; // 材
  1582. AddMechs; // 机
  1583. end;
  1584. procedure TqgXMLPort.AddEprjInfo(AFileNo: Integer);
  1585. begin
  1586. AddProgressForm(10, '正在生成工程项目信息...');
  1587. FEprjInfoNode := FRoot.NodeNewUTF8('EprjInfo');
  1588. FEprjInfoNode.AttributeAddUTF8('Name', ProjectManager.TenderName(PD.ID));
  1589. FEprjInfoNode.AttributeAddUTF8('Sums', GetProjectTotalPrice);
  1590. AddMakeInfo;
  1591. AddParams(AFileNo);
  1592. AddItems;
  1593. end;
  1594. procedure TqgXMLPort.AddIndexs;
  1595. var sFile: string;
  1596. vNode: TXmlNode;
  1597. n: Integer;
  1598. isNewOpen: Boolean;
  1599. begin
  1600. AddProgressForm(10, '正在生成指标...');
  1601. // 打开最后一个项目
  1602. Project := GetProjectByTenderRec(FTenderRecList[FTenderRecList.Count - 1], isNewOpen);
  1603. FIndexsNode := FRoot.NodeNewUTF8('Indexs');
  1604. FQuery2.Close;
  1605. FQuery2.SQL.Clear;
  1606. FQuery2.SQL.Add(Format('SELECT Caption FROM FeeParams WHERE ID = %d', [1]));
  1607. FQuery2.Open;
  1608. if FQuery2.RecordCount > 0 then
  1609. begin
  1610. FQuery2.First;
  1611. vNode := FIndexsNode.NodeNewUTF8('IndexItem');
  1612. vNode.AttributeAddUTF8('Code', 'JBSX1');
  1613. vNode.AttributeAddUTF8('Name', '工程所在地');
  1614. vNode.AttributeAddUTF8('Unit', '');
  1615. vNode.AttributeAddUTF8('Value', FQuery2.FieldByName('Caption').asString);
  1616. vNode.AttributeAddUTF8('Remark', '');
  1617. end;
  1618. FQuery2.Close;
  1619. if isNewOpen then
  1620. TScProjBaseData(TScProject(Project).ProjData).Close;
  1621. end;
  1622. // [2.2.1 & 2.3.1]、导出材料计算用的定额。AType: 1原价,0运费(和数据库 MaterialRations 表 Type 字段保持一致) // 类型(0,运费;1,原价)
  1623. procedure TqgXMLPort.AddMCRations(AParentNode: TXmlNode; AType, AMaterialID, ABillID: Integer);
  1624. var sSQL, sFN, sKey, sCode: string;
  1625. vVirParent, vNorm, vCS, vCItem, vConsume, vConsumeItem: TXmlNode;
  1626. iRationID, i, iMaxFeeCode, iID, iType, iCalcType: Integer;
  1627. begin
  1628. sSQL := Format('Select * from MaterialRations where OwnerID=%d and BillsID=%d and Type=%d', [AMaterialID, ABillID, AType]);
  1629. FQuery4.Close;
  1630. FQuery4.SQL.Text := sSQL;
  1631. FQuery4.Open;
  1632. if FQuery4.RecordCount > 0 then
  1633. begin
  1634. // 添加虚拟父层,我们软件没有这层
  1635. if AType = 1 then
  1636. begin
  1637. vVirParent := AParentNode.NodeNewUTF8('SelfCollect');
  1638. vVirParent.AttributeAddUTF8('OtherCost', '0');
  1639. end
  1640. else
  1641. begin
  1642. vVirParent := AParentNode.NodeNewUTF8('SelfTrans');
  1643. end;
  1644. iMaxFeeCode := TScProject(FProject).FeeRate.MaxFeeCode;
  1645. FQuery4.First;
  1646. while not FQuery4.Eof do
  1647. begin
  1648. iRationID := FQuery4.FieldByName('ID').AsInteger;
  1649. vNorm := vVirParent.NodeNewUTF8('Norm');
  1650. vNorm.AttributeAddUTF8('NormLibNo', GetNormLibNoByID(FQuery4.FieldByName('LibID').AsInteger));
  1651. vNorm.AttributeAddUTF8('DisplayCode', FQuery4.FieldByName('Code').asString);
  1652. vNorm.AttributeAddUTF8('Name', FQuery4.FieldByName('Name').asString);
  1653. vNorm.AttributeAddUTF8('Unit', ChangeUnit_m3(FQuery4.FieldByName('Unit').asString));
  1654. vNorm.AttributeAddUTF8('Num', FQuery4.FieldByName('Quantity').asString);
  1655. if (FQuery4.FieldByName('GYFeeKind').AsInteger > iMaxFeeCode) then
  1656. vNorm.AttributeAddUTF8('CostTypeNo', 'BJ') // 兼容旧项目的旧取费类别。如果当前取费类别编号大于费率文件中的定义,则识别为不计。
  1657. else
  1658. vNorm.AttributeAddUTF8('CostTypeNo', GetMapValue(GetMap('Map_GetFeeKind_GS'), FQuery4.FieldByName('GYFeeKind').asString, 0, 2));
  1659. vNorm.AttributeAddUTF8('FabricationCost', FQuery4.FieldByName('BuildingFee').asString);
  1660. vNorm.AttributeAddUTF8('AdjustStatus', FQuery4.FieldByName('AdjustState').asString);
  1661. // 定额的费用组成:人工费、材料费...
  1662. vCS := vNorm.NodeNewUTF8('CostStructure');
  1663. for i := Low(Map_RationFees) to High(Map_RationFees) do
  1664. begin
  1665. if FQuery4.FindField(Map_RationFees[i][0]) <> nil then
  1666. begin
  1667. vCItem := vCS.NodeNewUTF8('CostItem');
  1668. vCItem.AttributeAddUTF8('ItemNo', Map_RationFees[i][1]);
  1669. if FFileType = xftTB then
  1670. vCItem.AttributeAddUTF8('Sum', CheckNull(FQuery4.FieldByName(Map_RationFees[i][0]).asString))
  1671. else
  1672. vCItem.AttributeAddUTF8('Sum', '0');
  1673. end;
  1674. end;
  1675. // 导出材料计算的定额的工料机
  1676. sSQL := Format(
  1677. 'SELECT P.Code, P.type, P.CalculateType, M.Quantity as Consumption, M.GLJID as ID ' +
  1678. 'FROM MaterialGLJList as M Left join Port_Prj as P on M.GLJID=P.GLJID ' +
  1679. 'WHERE M.OwnerID=%d and M.BillsID=%d and M.RationID=%d and M.Type <> 9',
  1680. [AMaterialID, ABillID, iRationID]);
  1681. FQuery5.Close;
  1682. FQuery5.SQL.Text := sSQL;
  1683. FQuery5.Open;
  1684. vConsume := vNorm.NodeNewUTF8('Consume');
  1685. FQuery5.First;
  1686. while not FQuery5.Eof do
  1687. begin
  1688. vConsumeItem := vConsume.NodeNewUTF8('ConsumeItem');
  1689. for i := 0 to FQuery5.FieldCount - 1 do
  1690. begin
  1691. sFN := FQuery5.Fields[i].FieldName;
  1692. if (sFN = 'ID') or (sFN = 'type') or (sFN = 'CalculateType') then Continue;
  1693. // 效果示例:vNode.AttributeAdd('Code'] := FQuery2.FieldByName('Code').AsString;
  1694. vConsumeItem.AttributeAddUTF8(sFN, FQuery5.Fields[i].AsString);
  1695. end;
  1696. FQuery5.Next;
  1697. end;
  1698. FQuery4.Next;
  1699. end;
  1700. end;
  1701. FQuery4.Close;
  1702. end;
  1703. procedure TqgXMLPort.AddElectric(AMaterialNode: TXmlNode);
  1704. var sSQL: string;
  1705. vElecNode: TXmlNode;
  1706. begin
  1707. sSQL := 'Select * From ElectricityCalc';
  1708. FQuery3.Close;
  1709. FQuery3.SQL.Text := sSQL;
  1710. FQuery3.Open;
  1711. if FQuery3.RecordCount > 0 then
  1712. begin
  1713. FQuery3.First;
  1714. while not FQuery3.Eof do
  1715. begin
  1716. vElecNode := AMaterialNode.NodeNewUTF8('Electro');
  1717. vElecNode.AttributeAddUTF8('Code', FQuery3.FieldByName('Code').AsString);
  1718. vElecNode.AttributeAddUTF8('Price', FQuery3.FieldByName('Price').AsString);
  1719. vElecNode.AttributeAddUTF8('Ratio', FQuery3.FieldByName('SumRate').AsString);
  1720. FQuery3.Next;
  1721. end;
  1722. end;
  1723. FQuery3.Close;
  1724. end;
  1725. // [2.2]、导出材料原价
  1726. procedure TqgXMLPort.AddOrgPrices(AMaterialNode: TXmlNode; AMaterialID: Integer);
  1727. var sSQL: string;
  1728. vOrgPrices: TXmlNode;
  1729. iBillID: Integer;
  1730. begin
  1731. // 原价清单
  1732. sSQL := 'Select Price, SumRate, Location, ID from MaterialOrgPrice where OwnerID = ' + IntToStr(AMaterialID);
  1733. FQuery3.Close;
  1734. FQuery3.SQL.Text := sSQL;
  1735. FQuery3.Open;
  1736. if FQuery3.RecordCount > 0 then
  1737. begin
  1738. FQuery3.First;
  1739. while not FQuery3.Eof do
  1740. begin
  1741. vOrgPrices := AMaterialNode.NodeNewUTF8('OrgPrices');
  1742. vOrgPrices.AttributeAddUTF8('OrgPricevalue', FQuery3.FieldByName('Price').AsString);
  1743. vOrgPrices.AttributeAddUTF8('Ratio', FQuery3.FieldByName('SumRate').AsString);
  1744. vOrgPrices.AttributeAddUTF8('SupplyLocation', FQuery3.FieldByName('Location').AsString);
  1745. iBillID := FQuery3.FieldByName('ID').AsInteger;
  1746. AddMCRations(vOrgPrices, 1, AMaterialID, iBillID);
  1747. FQuery3.Next;
  1748. end;
  1749. end;
  1750. FQuery3.Close;
  1751. end;
  1752. // [2.3]、导出材料运费
  1753. procedure TqgXMLPort.AddTranFees(AMaterialNode: TXmlNode; AMaterialID: Integer);
  1754. var sSQL: string;
  1755. vTransFees: TXmlNode;
  1756. iBillID: Integer;
  1757. begin
  1758. // 运杂清单(起讫地点)
  1759. sSQL :=
  1760. 'Select Locations,Length,UnitPrice,ZXCount,ZXPrice,OtherPrice,SumRate,Price,T.ID,C.Name ' +
  1761. 'from MaterialTransPrice as T left join MaterialConveyance as C on T.Conveyance = C.ID where OwnerID = ' + IntToStr(AMaterialID);
  1762. FQuery3.Close;
  1763. FQuery3.SQL.Text := sSQL;
  1764. FQuery3.Open;
  1765. if FQuery3.RecordCount > 0 then
  1766. begin
  1767. FQuery3.First;
  1768. while not FQuery3.Eof do
  1769. begin
  1770. vTransFees := AMaterialNode.NodeNewUTF8('TransFees');
  1771. vTransFees.AttributeAddUTF8('FromPlace', FQuery3.FieldByName('Locations').AsString);
  1772. vTransFees.AttributeAddUTF8('TransWay', FQuery3.FieldByName('Name').AsString);
  1773. vTransFees.AttributeAddUTF8('TransDistence', FQuery3.FieldByName('Length').AsString);
  1774. vTransFees.AttributeAddUTF8('TransFee', FQuery3.FieldByName('UnitPrice').AsString);
  1775. vTransFees.AttributeAddUTF8('LoadTimes', FQuery3.FieldByName('ZXCount').AsString);
  1776. vTransFees.AttributeAddUTF8('LoadCost', FQuery3.FieldByName('ZXPrice').AsString);
  1777. vTransFees.AttributeAddUTF8('OtherCost', FQuery3.FieldByName('OtherPrice').AsString);
  1778. vTransFees.AttributeAddUTF8('Ratio', FQuery3.FieldByName('SumRate').AsString);
  1779. vTransFees.AttributeAddUTF8('Freight', FQuery3.FieldByName('Price').AsString);
  1780. iBillID := FQuery3.FieldByName('ID').AsInteger;
  1781. AddMCRations(vTransFees, 0, AMaterialID, iBillID);
  1782. FQuery3.Next;
  1783. end;
  1784. end;
  1785. FQuery3.Close;
  1786. end;
  1787. // [1]、导出【人工】
  1788. procedure TqgXMLPort.AddMps;
  1789. var sSQL: string;
  1790. begin
  1791. FPract_Mps := FPract.NodeNewUTF8('Mps');
  1792. if FFileType = xftTB then
  1793. begin
  1794. sSQL := 'Select Code, Name as PractName, Specs as Spec, Unit, ' +
  1795. 'BudgetPrice, RationPrice as NormPrice, IIF(New=True,1,0) as IsAdd ' +
  1796. 'from Port_Prj ' +
  1797. 'where Type = 1';
  1798. AddTabToXML(FQuery1, sSQL, FPract_Mps, '', 'Mp');
  1799. end;
  1800. end;
  1801. // [2]、导出【材料】 2 混凝土 3 材料(兼容旧项目) 4 材料 6 设备。
  1802. // 联合MaterialPrice表是为了查询材料的原价、运价、运杂费率等基础数据。
  1803. // 注意:ID 要取两个,MaterialPrice 的 ID 用来判断当前材料是否有材料计算信息,ID为空表示没有。
  1804. procedure TqgXMLPort.AddMaterials;
  1805. var sSQL, sFN, sName: string;
  1806. vNode, vElecNode: TXmlNode;
  1807. i, iMtID, iType, iCalcType, n: Integer;
  1808. begin
  1809. FPract_Materials := FPract.NodeNewUTF8('Materials');
  1810. if FFileType <> xftTB then Exit;
  1811. AddProgressForm(0, '导出项目工料机(材料),校验材料类型...');
  1812. // SHValue 场外运输损耗费 HSValue (包装)回收价值 BGValue 采购保管费
  1813. sSQL :=
  1814. 'Select P.GLJID as P_GLJID, P.Type as Type, P.CalculateType as CalculateType, P.Code, P.Name as PractName, P.Specs as Spec, P.Unit,' +
  1815. 'BudgetPrice, RationPrice as NormPrice, Amount as Num, DutiablePrice as TaxInPrice, TaxFeeRate as TaxRate, ' +
  1816. 'IIF(New=True,1,0) as IsAdd, ' +
  1817. 'IIF(M.OrgPrice is null, 0, M.OrgPrice) as OrgPrice, IIF(TransPrice is null, 0, TransPrice) as TransFee, ' +
  1818. 'IIF(MZRate is null, 0, MZRate) as GwRate, IIF(M.SHRate is null, 0, M.SHRate) as OffSiteLf, 0 as OnSiteLf, ' +
  1819. 'IIF(ZXRate is null, 0, ZXRate) as LoadLf, IIF(BGRate is null, 0, BGRate) as StoreRate, ' +
  1820. 'IIF(HSValue is null, 0, HSValue) as PackageRecycleFee, ' +
  1821. 'ProvidePlace as SupplyLocation, ZXCount as HandlingTimes, ' +
  1822. 'M.ID as MID ' +
  1823. 'From Port_Prj as P Left join MaterialPrice as M on P.GLJID = M.ID where P.Type in (2,3,4,6) ' +
  1824. 'Order by P.Code, P.GLJID';
  1825. FQuery2.Close;
  1826. FQuery2.SQL.Text := sSQL;
  1827. FQuery2.Open;
  1828. if FQuery2.RecordCount = 0 then Exit;
  1829. n := 0;
  1830. FQuery2.First;
  1831. while not FQuery2.Eof do
  1832. begin
  1833. Inc(n);
  1834. AddProgressForm(1, Format('导出项目工料机,校验材料类型 [%d/%d]...', [n, FQuery2.RecordCount]));
  1835. vNode := FPract_Materials.NodeNewUTF8('Material');
  1836. for i := 0 to FQuery2.FieldCount - 1 do
  1837. begin
  1838. sFN := FQuery2.Fields[i].FieldName;
  1839. if (sFN = 'MID') or (sFN = 'P_GLJID') or (sFN = 'CalculateType') then Continue;
  1840. if (sFN = 'Code') then
  1841. begin
  1842. vNode.AttributeAddUTF8('Code', FQuery2.FieldByName('Code').AsString);
  1843. // 电。综合电价计算
  1844. if (FQuery2.FieldByName('Code').AsString = '3005002') then
  1845. begin
  1846. AddElectric(vNode);
  1847. end;
  1848. end
  1849. else if (sFN = 'Type') then
  1850. begin
  1851. iType := FQuery2.FieldByName('Type').AsInteger;
  1852. iCalcType := FQuery2.FieldByName('CalculateType').AsInteger;
  1853. sName := FQuery2.FieldByName('PractName').AsString;
  1854. vNode.AttributeAddUTF8('Type', IntToStr(GetType(iType, iCalcType, sName)));
  1855. end
  1856. else
  1857. // 效果示例:vNode.AttributeAddUtf8('Code', FQuery2.FieldByName('Code').AsString);
  1858. vNode.AttributeAddUTF8(sFN, FQuery2.Fields[i].AsString);
  1859. end;
  1860. iMtID := FQuery2.FieldByName('MID').AsInteger;
  1861. if iMtID > 0 then // 证明存在材料计算:原价计算或运杂费计算
  1862. begin
  1863. if FQuery2.FieldByName('OrgPrice').AsCurrency > 0 then // 原价
  1864. AddOrgPrices(vNode, iMtID);
  1865. if FQuery2.FieldByName('TransFee').AsCurrency > 0 then // 运杂
  1866. AddTranFees(vNode, iMtID);
  1867. end;
  1868. FQuery2.Next;
  1869. end;
  1870. FQuery2.Close;
  1871. end;
  1872. // [3]、导出【机械】
  1873. procedure TqgXMLPort.AddMechs;
  1874. var sSQL, sCode, sValue: string;
  1875. vNode, vFixedCost, vVariableCost, vFixedCostItem, vVariableCostItem: TXmlNode;
  1876. i: Integer;
  1877. begin
  1878. FPract_Mechs := FPract.NodeNewUTF8('Mechs');
  1879. if FFileType <> xftTB then Exit;
  1880. AddProgressForm(0, '导出项目工料机(机械)...');
  1881. sSQL :=
  1882. 'Select P.GLJID as P_GLJID, P.Code as PCode, P.Name as PName, P.Specs as PSpecs, P.Unit as PUnit, P.Amount as PAmount, P.type as P_Type, ' +
  1883. 'P.CalculateType as P_CalculateType, P.RationPrice as PRPrice, P.BudgetPrice as PBudgetPrice, P.RationPrice as PRationPrice, P.New as PNew, M.* ' +
  1884. 'from Port_Prj as P Left join MachinePrice as M on P.GLJID = M.ID where P.Type = 8 ';
  1885. FQuery2.Close;
  1886. FQuery2.SQL.Text := sSQL;
  1887. FQuery2.Open;
  1888. if FQuery2.RecordCount = 0 then Exit;
  1889. FQuery2.First;
  1890. while not FQuery2.Eof do
  1891. begin
  1892. vNode := FPract_Mechs.NodeNewUTF8('Mech');
  1893. sCode := FQuery2.FieldByName('PCode').AsString;
  1894. vNode.AttributeAddUTF8('Code', sCode);
  1895. vNode.AttributeAddUTF8('PractName', FQuery2.FieldByName('PName').AsString);
  1896. vNode.AttributeAddUTF8('Spec', FQuery2.FieldByName('PSpecs').AsString);
  1897. vNode.AttributeAddUTF8('Unit', ChangeUnit_m3(FQuery2.FieldByName('PUnit').AsString));
  1898. vNode.AttributeAddUTF8('BudgetPrice', FQuery2.FieldByName('PBudgetPrice').AsString);
  1899. vNode.AttributeAddUTF8('NormPrice', FQuery2.FieldByName('PRationPrice').AsString);
  1900. vNode.AttributeAddUTF8('Num', FQuery2.FieldByName('PAmount').AsString);
  1901. vNode.AttributeAddUTF8('IsAdd', CheckBool(FQuery2.FieldByName('PNew').AsString));
  1902. if (sCode <> SSmallMachineFeeCode) then // 小型机具使用费不要导出组成物
  1903. begin
  1904. vFixedCost := vNode.NodeNewUTF8('FixedCost');
  1905. sValue := CheckNull(FQuery2.FieldByName('BBFee').AsString);
  1906. vFixedCost.AttributeAddUTF8('FixedCostSum', sValue);
  1907. vFixedCost.AttributeAddUTF8('FixedRate', FloatToStr(PD.MachineBBFeeRate));
  1908. if (StrToFloat(sValue) > 0) then
  1909. begin
  1910. for i := Low(Map_Machine_BBFee) to High(Map_Machine_BBFee) do
  1911. begin
  1912. vFixedCostItem := vFixedCost.NodeNewUTF8('FixedCostItem');
  1913. vFixedCostItem.AttributeAddUTF8('FixedCostNo', Map_Machine_BBFee[i][1]);
  1914. vFixedCostItem.AttributeAddUTF8('Sum', FQuery2.FieldByName(Map_Machine_BBFee[i][0]).AsString);
  1915. end;
  1916. end;
  1917. vVariableCost := vNode.NodeNewUTF8('VariableCost');
  1918. sValue := CheckNull(FQuery2.FieldByName('KBFee').AsString);
  1919. vVariableCost.AttributeAddUTF8('VariableCostSum', sValue);
  1920. if (StrToFloat(sValue) > 0) then
  1921. begin
  1922. for i := Low(Map_Machine_KBFee) to High(Map_Machine_KBFee) do
  1923. begin
  1924. vVariableCostItem := vVariableCost.NodeNewUTF8('VariableCostItem');
  1925. vVariableCostItem.AttributeAddUTF8('VariableCostNo', Map_Machine_KBFee[i][1]);
  1926. vVariableCostItem.AttributeAddUTF8('Consumption', FQuery2.FieldByName(Map_Machine_KBFee[i][0]).AsString);
  1927. end;
  1928. end;
  1929. end;
  1930. FQuery2.Next;
  1931. end;
  1932. FQuery2.Close;
  1933. end;
  1934. // 清单-公式
  1935. procedure TqgXMLPort.AddFormula(ANode: TScBillsItem; AParentXMLNode: TXmlNode);
  1936. // 判断清单是否存在
  1937. function IsBillExist(AID: Integer): Boolean;
  1938. begin
  1939. Result := False;
  1940. if (AID >= 500) and (AID <= 999) then // 虚拟清单
  1941. begin
  1942. Result := True;
  1943. Exit;
  1944. end;
  1945. FSearch1.Close;
  1946. FSearch1.SQL.Text := 'select ID from Bills where ID=' + IntToStr(AID);
  1947. FSearch1.Open;
  1948. if FSearch1.RecordCount > 0 then
  1949. Result := True;
  1950. FSearch1.Close;
  1951. end;
  1952. // =100+200+@1+@502+@1102+@504*9%
  1953. // 最终只能使用三方正则库。目前以下算法不能解决:①部分匹配。如 @1,@1101 ②行引用表达式。如 @1102*9%。
  1954. // 云版要求:"{DEJAFⅡ}+{ZXZDHJ}+{GZQDHJ}+{@1101}+{@4}"
  1955. function getFormulas(ABillID: Integer): string;
  1956. var
  1957. sExpr, sOld, sNew, sMapName: string;
  1958. reg: TPerlRegEx;
  1959. iID: Integer;
  1960. vItem: TScBillsItem;
  1961. begin
  1962. sExpr := '';
  1963. sExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_Bills, ExprsID_Bills_TotalPrice, ABillID, 0);
  1964. if (sExpr = '') and IsSpecialFormulaBill(ABillID) then
  1965. begin
  1966. case ABillID of
  1967. idSpecialInterimSum: Result := '{ZXZDHJ}'; // 专项暂定合计
  1968. idBillSumExcludeSpecialInterim: Result := '{GZQDHJ}-{ZXZDHJ}'; // 各章清单合计 - 专项暂定合计
  1969. idProjectTotalPrice_Bills:
  1970. begin
  1971. vItem := BillNode(39); // 清单类型的项目,其它新增费用
  1972. if vItem <> nil then
  1973. Result := '{D100Z700}+{JRG}+{ZLJE}+{QTXZFY}' // 第一部分合计 + 计日工 + 不可预见费(暂列金额)+ 其它新增费用
  1974. else
  1975. Result := '{D100Z700}+{JRG}+{ZLJE}';
  1976. end;
  1977. end;
  1978. Exit;
  1979. end;
  1980. if Pos('=', sExpr) = 0 then // 没有"=",是纯四则运算表达式,如:1924*48+20.73*20400
  1981. begin
  1982. Result := sExpr;
  1983. Exit;
  1984. end;
  1985. sExpr := StringReplace(sExpr, '=', '', []);
  1986. reg := TPerlRegEx.Create;
  1987. try
  1988. reg.Subject := sExpr;
  1989. reg.RegEx := '@\d+';
  1990. while reg.MatchAgain do
  1991. begin
  1992. sOld := reg.MatchedText;
  1993. // 检验@xx 是否存在
  1994. iID := StrToInt(Copy(sOld, 2, Length(sOld) - 1));
  1995. if IsBillExist(iID) then
  1996. begin
  1997. if TScProject(FProject).IsBills then
  1998. sMapName := 'Map_Formula_Bill'
  1999. else
  2000. sMapName := 'Map_Formula_Budget';
  2001. sNew := GetMapValue(GetMap(sMapName), sOld, 0, 2);
  2002. end
  2003. else
  2004. sNew := '0';
  2005. if sNew <> '' then
  2006. begin
  2007. reg.Replacement := sNew;
  2008. reg.Replace; // 不能使用 reg.ReplaceAll; 只能使用 reg.Replace; 逐个匹配。
  2009. end
  2010. else // 为空表示标准映射列表中没有,是行引用
  2011. begin
  2012. reg.Replacement := '{' + sOld + '}';
  2013. reg.Replace;
  2014. end;
  2015. end;
  2016. Result := reg.Subject;
  2017. finally
  2018. reg.Free;
  2019. end;
  2020. end;
  2021. var vFormulaNode: TXmlNode;
  2022. begin
  2023. vFormulaNode := AParentXMLNode.NodeNewUTF8('Formula');
  2024. vFormulaNode.AttributeAddUTF8('Name', Rec(ANode, 'Name'));
  2025. vFormulaNode.AttributeAddUTF8('Formulas', getFormulas(ANode.ID));
  2026. vFormulaNode.AttributeAddUTF8('Ratio', '1');
  2027. vFormulaNode.AttributeAddUTF8('Sum', Rec(ANode, 'TotalPrice'));
  2028. vFormulaNode.AttributeAddUTF8('Remarks', Rec(ANode, 'MemoStr'));
  2029. end;
  2030. // 清单-定额、量价、设备
  2031. procedure TqgXMLPort.AddRations(ANode: TScBillsItem; AParentXMLNode: TXmlNode);
  2032. var vNorm, vCS, vCItem, vCost, vConsume, vConsumeItem: TXmlNode;
  2033. i, iMaxFeeCode, iID, iType, iCalcType: Integer;
  2034. sTemp, sSQL, sFN, sME, sStatus, sExpr, sKey, sCode, sUnit, sSpec, sGLJID: string;
  2035. vRation: TScRationRecord;
  2036. begin
  2037. iMaxFeeCode := TScProject(FProject).FeeRate.MaxFeeCode;
  2038. FQuery2.Close;
  2039. FQuery2.SQL.Clear;
  2040. FQuery2.SQL.Add(Format('SELECT * FROM RationCalcList WHERE BillsItemID = %d Order by SerialNo', [ANode.ID]));
  2041. FQuery2.Open;
  2042. if FQuery2.RecordCount = 0 then
  2043. begin
  2044. FQuery2.Close;
  2045. Exit;
  2046. end;
  2047. FQuery2.First;
  2048. while not FQuery2.Eof do
  2049. begin
  2050. // (1) 量价、设备
  2051. if FQuery2.FieldByName('Type').AsInteger = 1 then
  2052. begin
  2053. vCost := AParentXMLNode.NodeNewUTF8('Cost');
  2054. // 编号不能直接取。因为有可能被重新编号过的。要从Port_Prj中取最新的。
  2055. // vCost.AttributeAddUtf8('Code', FQuery2.FieldByName('Code').AsString);
  2056. FQuery3.Close;
  2057. FQuery3.SQL.Text := Format('SELECT Code FROM Port_Prj WHERE GLJID = %d', [
  2058. FQuery2.FieldByName('GLJID').AsInteger]);
  2059. FQuery3.Open;
  2060. vCost.AttributeAddUTF8('Code', FQuery3.FieldByName('Code').AsString);
  2061. FQuery3.Close;
  2062. vCost.AttributeAddUTF8('Name', FQuery2.FieldByName('Name').AsString);
  2063. // 直接插入工料机当定额用,旧版本有Bug,规格没有跟过来,导致这里取不到规格。此时应再去项目工料机里查。
  2064. sSpec := FQuery2.FieldByName('Specs').AsString;
  2065. sGLJID := FQuery2.FieldByName('GLJID').AsString;
  2066. if (sSpec = '') and (sGLJID <> '') then // 直接插入的工料机,GLJID字段有值(其它没有)
  2067. begin
  2068. sSQL := Format('select Specs from Port_Prj where GLJID = %s', [sGLJID]);
  2069. sSpec := DoSearch(sSQL, 'Specs', '');
  2070. end;
  2071. vCost.AttributeAddUTF8('Spec', sSpec);
  2072. sUnit := FQuery2.FieldByName('Unit').asString;
  2073. sUnit := ChangeUnit_m3(sUnit);
  2074. vCost.AttributeAddUTF8('Unit', sUnit);
  2075. vCost.AttributeAddUTF8('Num', FQuery2.FieldByName('Quantity').asString);
  2076. sExpr := '';
  2077. sExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_CountPrice, ExprsID_CountPrice_Quantity, FQuery2.FieldByName('ID').AsInteger, 0);
  2078. vCost.AttributeAddUTF8('NumExpression', sExpr);
  2079. sME := CheckBool(FQuery2.FieldByName('IsMECalc').asString);
  2080. if (sME = '1') then
  2081. vCost.AttributeAddUTF8('BasePrice', FQuery2.FieldByName('UnitPrice').asString) // 设备的基价取 UnitPrice
  2082. else
  2083. vCost.AttributeAddUTF8('BasePrice', FQuery2.FieldByName('RationUnitDirectFee').asString); // 量价的基价取 RationUnitDirectFee
  2084. vCost.AttributeAddUTF8('Price', FQuery2.FieldByName('UnitDirectFee').asString);
  2085. vCost.AttributeAddUTF8('IsEquipment', sME);
  2086. if (sME = '1') then
  2087. begin
  2088. vCost.AttributeAddUTF8('TransMiscRate', FQuery2.FieldByName('YZFeeRate').asString);
  2089. vCost.AttributeAddUTF8('TransInsuRate', FQuery2.FieldByName('YBFeeRate').asString);
  2090. vCost.AttributeAddUTF8('ProcuStorRate', FQuery2.FieldByName('CBFeeRate').asString);
  2091. end;
  2092. if (FQuery2.FieldByName('GetFeeKind').AsInteger > iMaxFeeCode) then
  2093. vCost.AttributeAddUTF8('CostTypeNo', 'BJ') // 兼容旧项目的旧取费类别。如果当前取费类别编号大于费率文件中的定义,则识别为不计。
  2094. else
  2095. vCost.AttributeAddUTF8('CostTypeNo', GetMapValue(GetMap('Map_GetFeeKind_GS'), FQuery2.FieldByName('GetFeeKind').asString, 0, 2));
  2096. vCost.AttributeAddUTF8('ProfitRate', FloatToStr(ScRoundTo(PD.Project.FeeRate.Rate(frProfit) * 100, -2)));
  2097. vCost.AttributeAddUTF8('TaxRate', FloatToStr(ScRoundTo(PD.Project.FeeRate.Rate(frTax) * 100, -3)));
  2098. vCost.AttributeAddUTF8('MpRatio', '0');
  2099. vCost.AttributeAddUTF8('MaterialRatio', '0');
  2100. vCost.AttributeAddUTF8('MechRatio', '0');
  2101. if FQuery2.FieldByName('IsCalcProfit').AsBoolean then
  2102. vCost.AttributeAddUTF8('LR', '1')
  2103. else
  2104. vCost.AttributeAddUTF8('LR', '0');
  2105. if FQuery2.FieldByName('IsCalcTax').AsBoolean then
  2106. vCost.AttributeAddUTF8('SJ', '1')
  2107. else
  2108. vCost.AttributeAddUTF8('SJ', '0');
  2109. case FQuery2.FieldByName('CountPriceType').AsInteger of
  2110. 1: vCost.AttributeValueByNameUTF8['MpRatio'] := '100';
  2111. 2: vCost.AttributeValueByNameUTF8['MaterialRatio'] := '100';
  2112. 3: vCost.AttributeValueByNameUTF8['MechRatio'] := '100';
  2113. end;
  2114. // 量价的各费(人工费、材料费...)
  2115. vCS := vCost.NodeNewUTF8('CostStructure');
  2116. for i := Low(Map_RationFees) to High(Map_RationFees) do
  2117. begin
  2118. vCItem := vCS.NodeNewUTF8('CostItem');
  2119. vCItem.AttributeAddUTF8('ItemNo', Map_RationFees[i][1]);
  2120. if FFileType = xftTB then
  2121. vCItem.AttributeAddUTF8('Sum', CheckNull(FQuery2.FieldByName(Map_RationFees[i][0]).asString))
  2122. else
  2123. vCItem.AttributeAddUTF8('Sum', '0');
  2124. end;
  2125. end
  2126. // (2) 定额
  2127. else
  2128. begin
  2129. vNorm := AParentXMLNode.NodeNewUTF8('Norm');
  2130. vNorm.AttributeAddUTF8('NormLibNo', GetNormLibNoByID(FQuery2.FieldByName('LibID').AsInteger));
  2131. sCode := FQuery2.FieldByName('Code').asString;
  2132. if (FGDSZDEKID <> -1) and (FQuery2.FieldByName('LibID').AsInteger = FGDSZDEKID) then
  2133. sCode := 'D' + sCode;
  2134. vNorm.AttributeAddUTF8('DisplayCode', sCode);
  2135. vNorm.AttributeAddUTF8('Name', FQuery2.FieldByName('Name').asString);
  2136. vNorm.AttributeAddUTF8('Unit', ChangeUnit_m3(FQuery2.FieldByName('Unit').asString));
  2137. vNorm.AttributeAddUTF8('Num', FQuery2.FieldByName('Quantity').asString);
  2138. sExpr := '';
  2139. sExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_Rations, ExprsID_Rations_Quantity, FQuery2.FieldByName('ID').AsInteger, 0);
  2140. vNorm.AttributeAddUTF8('NumExpression', sExpr);
  2141. if (FQuery2.FieldByName('GetFeeKind').AsInteger > iMaxFeeCode) then
  2142. vNorm.AttributeAddUTF8('CostTypeNo', 'BJ') // 兼容旧项目的旧取费类别。如果当前取费类别编号大于费率文件中的定义,则识别为不计。
  2143. else
  2144. vNorm.AttributeAddUTF8('CostTypeNo', GetMapValue(GetMap('Map_GetFeeKind_GS'), FQuery2.FieldByName('GetFeeKind').asString, 0, 2));
  2145. vNorm.AttributeAddUTF8('ProfitRate', FloatToStr(ScRoundTo(PD.Project.FeeRate.Rate(frProfit) * 100, -2)));
  2146. vNorm.AttributeAddUTF8('TaxRate', FloatToStr(ScRoundTo(PD.Project.FeeRate.Rate(frTax) * 100, -3)));
  2147. vNorm.AttributeAddUTF8('FabricationCost', FQuery2.FieldByName('BuildingFee').asString);
  2148. // vNorm.AttributeAddUtf8('AdjustStatus', FQuery2.FieldByName('AdjustState').asString);
  2149. vRation := TScProject(FProject).Rations.FindRation(FQuery2.FieldByName('ID').AsInteger);
  2150. sStatus := AdjustStateToPort(vRation);
  2151. vNorm.AttributeAddUTF8('AdjustStatus', sStatus);
  2152. // 定额是强制的,一定得算利润和税金,取消不了。量价和设备可以控制
  2153. vNorm.AttributeAddUTF8('LR', '1');
  2154. vNorm.AttributeAddUTF8('SJ', '1');
  2155. // (2).1 定额的各费(人工费、材料费...)
  2156. vCS := vNorm.NodeNewUTF8('CostStructure');
  2157. for i := Low(Map_RationFees) to High(Map_RationFees) do
  2158. begin
  2159. vCItem := vCS.NodeNewUTF8('CostItem');
  2160. vCItem.AttributeAddUTF8('ItemNo', Map_RationFees[i][1]);
  2161. if FFileType = xftTB then
  2162. vCItem.AttributeAddUTF8('Sum', CheckNull(FQuery2.FieldByName(Map_RationFees[i][0]).asString))
  2163. else
  2164. vCItem.AttributeAddUTF8('Sum', '0');
  2165. end;
  2166. // (2).2 定额的工料机 (注意:临时项目工料机表 CalculateType -1被改成0,这会导致定额工料机定位不上)
  2167. sSQL := Format('Select G2.*,P.Code as Code from ( ' +
  2168. 'SELECT G.RationID, G.GLJID as GLJID, G.Quantity as Consumption, G.Type, IIF(G.CalculateType=-1, 0, G.CalculateType) as GCType, G.RationPrice ' +
  2169. 'FROM GLJList as G ' +
  2170. 'WHERE G.RationID=%d and G.Type <> 9) as G2 Left join Port_Prj as P ' +
  2171. 'on G2.GLJID=P.GLJID and G2.Type=P.Type and G2.GCType=P.CalculateType and G2.RationPrice=P.RationPrice ' +
  2172. 'WHERE G2.RationID=%d', [FQuery2.FieldByName('ID').AsInteger, FQuery2.FieldByName('ID').AsInteger]);
  2173. FQuery3.Close;
  2174. FQuery3.SQL.Text := sSQL;
  2175. FQuery3.Open;
  2176. vConsume := vNorm.NodeNewUTF8('Consume');
  2177. FQuery3.First;
  2178. while not FQuery3.Eof do
  2179. begin
  2180. vConsumeItem := vConsume.NodeNewUTF8('ConsumeItem');
  2181. vConsumeItem.AttributeAddUTF8('Code', FQuery3.FieldByName('Code').AsString);
  2182. vConsumeItem.AttributeAddUTF8('Consumption', FQuery3.FieldByName('Consumption').AsString);
  2183. FQuery3.Next;
  2184. end;
  2185. end;
  2186. FQuery2.Next;
  2187. end;
  2188. FQuery2.Close;
  2189. end;
  2190. procedure TqgXMLPort.AddMakeInfo;
  2191. begin
  2192. AddProgressForm(5, '正在生成工程项目信息1...');
  2193. FMakeInfoNode := FEprjInfoNode.NodeNewUTF8('MakeInfo');
  2194. FMakeInfoNode.AttributeAddUTF8('ValuationModel', '1'); // 中山接口追加
  2195. FMakeInfoNode.AttributeAddUTF8('Manage', PD.BuildUnit);
  2196. FMakeInfoNode.AttributeAddUTF8('Designer', '');
  2197. FMakeInfoNode.AttributeAddUTF8('Compile', PD.Bidder); // 内容数:编4复2审3
  2198. FMakeInfoNode.AttributeAddUTF8('CompileApprover', PD.Author);
  2199. FMakeInfoNode.AttributeAddUTF8('CompileCertNo', PD.AuthorCertificate);
  2200. FMakeInfoNode.AttributeAddUTF8('CompileDate', FormatDateTime('yyyy-mm-dd', PD.EditDate) + 'T' + FormatDateTime('hh:nn:ss', PD.EditDate));
  2201. // if FFileType = xftTB then // 单机但凡有的都导出给云版用,不用管 Altova XMLSpy 检测。
  2202. FMakeInfoNode.AttributeAddUTF8('Review', '');
  2203. FMakeInfoNode.AttributeAddUTF8('ReviewApprover', PD.Auditor);
  2204. FMakeInfoNode.AttributeAddUTF8('ReviewCertNo', PD.AuditorCertificate);
  2205. FMakeInfoNode.AttributeAddUTF8('ReviewDate', FormatDateTime('yyyy-mm-dd', PD.EditDate) + 'T' + FormatDateTime('hh:nn:ss', PD.EditDate));
  2206. // if FFileType = xftTB then
  2207. begin
  2208. FMakeInfoNode.AttributeAddUTF8('Examine', PD.CheckUnit);
  2209. FMakeInfoNode.AttributeAddUTF8('ExamineApprover', PD.Checker);
  2210. FMakeInfoNode.AttributeAddUTF8('ExamineCertNo', '');
  2211. // 有这个属性后,Altova XMLSpy值类型检测不过。
  2212. FMakeInfoNode.AttributeAdd('ExamineDate', FormatDateTime('yyyy-mm-dd', PD.CheckDate) + 'T' + FormatDateTime('hh:nn:ss', PD.CheckDate));
  2213. FMakeInfoNode.AttributeAddUTF8('CompileExplain', '');
  2214. FMakeInfoNode.AttributeAddUTF8('ExamineExplain', '');
  2215. FMakeInfoNode.AttributeAddUTF8('ProjectExplain', '');
  2216. end;
  2217. end;
  2218. procedure TqgXMLPort.AddParams(AFileNo: Integer);
  2219. var s, sTemp: string;
  2220. begin
  2221. AddProgressForm(5, '正在生成工程项目信息2...');
  2222. FParamsNode := FEprjInfoNode.NodeNewUTF8('Params');
  2223. FParamsNode.AttributeAddUTF8('PrjArea', PD.ProjectLocation);
  2224. FParamsNode.AttributeAddUTF8('StartPileNo', PV('StartCode'));
  2225. FParamsNode.AttributeAddUTF8('EndPileNo', PV('StartCode'));
  2226. if PV('Newly') = '新建' then
  2227. FParamsNode.AttributeAddUTF8('BuildType', '0')
  2228. else
  2229. FParamsNode.AttributeAddUTF8('BuildType', '1');
  2230. if PV('Topography') = '平原' then
  2231. FParamsNode.AttributeAddUTF8('Terrain', '0')
  2232. else
  2233. FParamsNode.AttributeAddUTF8('Terrain', '1');
  2234. s := PV('RoadLevel');
  2235. if s = '一级公路' then
  2236. FParamsNode.AttributeAddUTF8('RoadGrade', '1')
  2237. else if s = '二级公路' then
  2238. FParamsNode.AttributeAddUTF8('RoadGrade', '2')
  2239. else if s = '三级公路' then
  2240. FParamsNode.AttributeAddUTF8('RoadGrade', '3')
  2241. else if s = '四级公路' then
  2242. FParamsNode.AttributeAddUTF8('RoadGrade', '4')
  2243. else
  2244. FParamsNode.AttributeAddUTF8('RoadGrade', '0'); // '高速公路'
  2245. FParamsNode.AttributeAddUTF8('DesignSpeed', PV('Speed'));
  2246. FParamsNode.AttributeAddUTF8('Structure', '0');//PV('RoadSurface'); // 取路面结构。沥青路面取0;水泥混凝土路面取1;其他类型路面取2。(现在软件中不是下拉)
  2247. FParamsNode.AttributeAddUTF8('SubgradeWidth', PV('RoadWidth', '0'));
  2248. FParamsNode.AttributeAddUTF8('RoadLength', PV('RoadLength', '0'));
  2249. FParamsNode.AttributeAddUTF8('BridgeLength', PV('BridgeLength', '0'));
  2250. FParamsNode.AttributeAddUTF8('TunnelLength', PV('TunnelLength', '0'));
  2251. FParamsNode.AttributeAddUTF8('BriTunRate', PV('BridgeRatio', '0'));
  2252. FParamsNode.AttributeAddUTF8('InterchangeNum', PV('CrossNum', '0'));
  2253. FParamsNode.AttributeAddUTF8('StubLengths', PV('BranchLength', '0'));
  2254. FParamsNode.AttributeAddUTF8('LaneLength', PV('SideRoadLength', '0'));
  2255. FParamsNode.AttributeAddUTF8('RisingRate', FloatToStr(ScRoundTo(PD.RaiseRateByYear * 100, -2)));
  2256. FParamsNode.AttributeAddUTF8('RisingYears', FloatToStr(PD.RaiseYear));
  2257. FParamsNode.AttributeAddUTF8('RateNo', IntToStr(AFileNo)); //sTemp;
  2258. FParamsNode.AttributeAddUTF8('PractNo', IntToStr(AFileNo)); //'JGXX-440000-2019-05';
  2259. end;
  2260. // 导出清单
  2261. procedure TqgXMLPort.AddItems;
  2262. var iBillCount, iTotalCount: Integer;
  2263. // 递归1:遍历读取清单
  2264. procedure ReadTreeNodes(ANode: TScBillsItem; AParentXMLNode: TXmlNode);
  2265. var vItemNode, vCC, vCS, vCItem, vDD, vGC: TXmlNode;
  2266. bHasExpr, bHasRation: Boolean;
  2267. i: Integer;
  2268. vFunc: TFunction;
  2269. begin
  2270. if ANode <> nil then
  2271. begin
  2272. Inc(iBillCount);
  2273. AddProgressForm(1, Format('导出清单[%d/%d] %s %s', [iBillCount, iTotalCount, ANode.Code + ANode.B_Code, ANode.Name]));
  2274. vItemNode := AddItem(ANode, AParentXMLNode);
  2275. if (ANode.IsLeaf and (FFileType = xftTB)) then
  2276. begin
  2277. // ANode.IsCalcExprs 会漏掉纯四则运算表达式。如 1924*48+20.73*20400。
  2278. // bHasExpr := ANode.IsCalcExprs;
  2279. bHasExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_Bills, ExprsID_Bills_TotalPrice, ANode.ID, 0) <> '';
  2280. // 投标项目的最后一行清单"投标价"(id=9)的公式固定在代码中。如果被用户手工修改过,才会存储在公式表里。
  2281. if (not bHasExpr) and IsSpecialFormulaBill(ANode) then bHasExpr := True;
  2282. bHasRation := ANode.HasRations;
  2283. if bHasExpr or bHasRation then
  2284. begin
  2285. vCC := vItemNode.NodeNewUTF8('CostComposition');
  2286. if bHasExpr then
  2287. begin
  2288. AddFormula(ANode, vCC);
  2289. if ANode.ID = idBuildLoanItem then
  2290. AddBuildLoan(vCC);
  2291. end
  2292. else if bHasRation then
  2293. AddRations(ANode, vCC);
  2294. end;
  2295. if CanGC(ANode) then
  2296. begin
  2297. vGC := vItemNode.NodeNewUTF8('GCTree');
  2298. AddGC(vGC, ANode.ID);
  2299. end;
  2300. end;
  2301. vCS := vItemNode.NodeNewUTF8('CostStructure');
  2302. // 清单的费用组成
  2303. for i := Low(Map_RationFees) to High(Map_RationFees) do
  2304. begin
  2305. vCItem := vCS.NodeNewUTF8('CostItem');
  2306. vCItem.AttributeAddUTF8('ItemNo', Map_RationFees[i][1]);
  2307. if FFileType = xftTB then
  2308. begin
  2309. vFunc := TFunction(ANode.GetMethod('Get' + Map_RationFees[i][0]));
  2310. vCItem.AttributeAddUTF8('Sum', CheckNull(FloatToStr(vFunc())));
  2311. end
  2312. else
  2313. vCItem.AttributeAddUTF8('Sum', '0');
  2314. end;
  2315. vDD := vItemNode.NodeNewUTF8('DesignDetails');
  2316. AddDrawQ(ANode, vDD);
  2317. if not ANode.IsLeaf then
  2318. begin
  2319. ReadTreeNodes(TScBillsItem(ANode.FirstChild), vItemNode);
  2320. end;
  2321. ReadTreeNodes(TScBillsItem(ANode.NextSibling), AParentXMLNode);
  2322. end;
  2323. end;
  2324. // 递归2:遍历汇总清单的各费
  2325. procedure CalcBillsFees(AItem: TScBillsItem);
  2326. var i, j: Integer;
  2327. vChild: TScBillsItem;
  2328. vProc: TProcedure;
  2329. vFunc1, vFunc2: TFunction;
  2330. fTemp,fF1, fF2: Double;
  2331. begin
  2332. if AItem = nil then Exit;
  2333. CalcBillsFees(TScBillsItem(AItem.FirstChild));
  2334. Inc(iBillCount);
  2335. AddProgressForm(1, Format('汇总清单各项费用[%d/%d] %s %s', [iBillCount, iTotalCount, AItem.Code + AItem.B_Code, AItem.Name]));
  2336. if AItem.IsLeaf = True then
  2337. begin
  2338. FSearch1.Close;
  2339. FSearch1.SQL.Clear;
  2340. // 有定额的清单
  2341. if AItem.HasRations then
  2342. begin
  2343. FSearch1.SQL.Text :=
  2344. 'SELECT BillsItemID, Sum(LabourFee) as RGF,' +
  2345. 'Sum(MaterialFee) as CLF, Sum(MachineFee) as JXSYF, ' +
  2346. 'Sum(DirectFee) as ZJF , Sum(RationDirectFee) as DEZJF , ' +
  2347. 'Sum(OtherDirectFee) as CSF,' +
  2348. 'IIF(Sum(OtherFee1) is null, 0, Sum(OtherFee1)) as CSF1, ' +
  2349. 'IIF(Sum(OtherFee2) is null, 0, Sum(OtherFee2)) as CSF2, ' +
  2350. 'IIF(Sum(ManageFee) is null, 0, Sum(ManageFee)) as QYGLF, ' +
  2351. 'Sum(LocaleFee) as GF,' +
  2352. 'Sum(Profit) as LR, Sum(Tax) as SJ, ' +
  2353. 'Sum(RationBuildingFee) as DEJAF, Sum(BuildingFee) as JAF ' +
  2354. 'From RationCalclist where BillsItemID=' + IntToStr(AItem.ID) +
  2355. ' Group by BillsItemID';
  2356. FSearch1.Open;
  2357. if FSearch1.RecordCount > 0 then
  2358. begin
  2359. // eg: AItem.LabourFee := FSearch1.FieldByName('RGF').AsFloat; ...
  2360. for j := Low(Map_RationFees) to High(Map_RationFees) do
  2361. begin
  2362. vProc := TProcedure(AItem.GetMethod('Set' + Map_RationFees[j][0]));
  2363. vProc(FSearch1.FieldByName(Map_RationFees[j][1]).AsFloat);
  2364. end;
  2365. end
  2366. end
  2367. // 公式清单、量价式清单
  2368. else
  2369. begin
  2370. FSearch1.SQL.Text :=
  2371. 'SELECT RationTotalPrice as DEJAF, TotalPrice as JAF ' +
  2372. 'From Bills where ID=' + IntToStr(AItem.ID);
  2373. FSearch1.Open;
  2374. if FSearch1.RecordCount > 0 then
  2375. begin
  2376. vProc := TProcedure(AItem.GetMethod('SetRationBuildingFee'));
  2377. vProc(FSearch1.FieldByName('DEJAF').AsFloat);
  2378. vProc := TProcedure(AItem.GetMethod('SetBuildingFee'));
  2379. vProc(FSearch1.FieldByName('JAF').AsFloat);
  2380. end
  2381. end;
  2382. FSearch1.Close;
  2383. end
  2384. else
  2385. begin
  2386. // AItem.LabourFee := 0; AItem.MaterialFee := 0;...
  2387. for j := Low(Map_RationFees) to High(Map_RationFees) do
  2388. begin
  2389. vProc := TProcedure(AItem.GetMethod('Set' + Map_RationFees[j][0]));
  2390. vProc(0);
  2391. end;
  2392. // AItem.LabourFee := AItem.LabourFee + vChild.LabourFee; AItem.MaterialFee := AItem.MaterialFee + vChild.MaterialFee; ...
  2393. for i := 0 to AItem.ChildCount - 1 do
  2394. begin
  2395. vChild := TScBillsItem(AItem.ChildNodes[i]);
  2396. for j := Low(Map_RationFees) to High(Map_RationFees) do
  2397. begin
  2398. vFunc1 := TFunction(AItem.GetMethod('Get' + Map_RationFees[j][0]));
  2399. vFunc2 := TFunction(vChild.GetMethod('Get' + Map_RationFees[j][0]));
  2400. fF1 := vFunc1();
  2401. fF2 := vFunc2();
  2402. fTemp := fF1 + fF2;
  2403. vProc := TProcedure(AItem.GetMethod('Set' + Map_RationFees[j][0]));
  2404. vProc(fTemp);
  2405. end;
  2406. end;
  2407. end;
  2408. CalcBillsFees(TScBillsItem(AItem.NextSibling));
  2409. end;
  2410. var vTree: TScBillsTree;
  2411. begin
  2412. FItemsNode := FEprjInfoNode.NodeNewUTF8('Items');
  2413. vTree := TScProject(FProject).Bills.BillsTree;
  2414. iTotalCount := vTree.Count;
  2415. AddProgressForm(10, '汇总清单各项费用...');
  2416. iBillCount := 0;
  2417. if (FFileType <> xftZB) then
  2418. CalcBillsFees(vTree.Items[0]);
  2419. AddProgressForm(10, '导出清单...');
  2420. iBillCount := 0;
  2421. ReadTreeNodes(vTree.Items[0], FItemsNode);
  2422. end;
  2423. procedure TqgXMLPort.AddNodes;
  2424. var
  2425. n: Integer;
  2426. isNewOpen: Boolean;
  2427. begin
  2428. inherited;
  2429. AddCprjInfo;
  2430. AddDecimalOption;
  2431. AddSystemInfo;
  2432. AddCostBasis;
  2433. AddMultiProjects;
  2434. AddIndexs;
  2435. end;
  2436. // 目的是容错处理。有的清单该输入的编号没输入,导致ItemType识别不准,导入云版后树结构会出现错误。
  2437. // 该方法去掉递归:总会有各种情况导致递归死循环。
  2438. function TqgXMLPort.GetItemTypeByCode(AItem: TScBillsItem): string;
  2439. // 是否两个编号都为空
  2440. function IsNoCode(Item: TScBillsItem): Boolean;
  2441. begin
  2442. Result := ((Rec(Item, 'B_Code') = '') and (Rec(Item, 'Code') = ''));
  2443. end;
  2444. // 只通过自己判断,不依赖父、前后兄弟。
  2445. function GetItemTypeBySelf(Item: TScBillsItem): string;
  2446. begin
  2447. if (Rec(Item, 'B_Code') <> '') then
  2448. Result := '1'
  2449. else
  2450. Result := '0';
  2451. end;
  2452. var vItem: TScBillsItem;
  2453. begin
  2454. // 两个编号都为空时,要依赖父、前后兄弟判断。
  2455. if IsNoCode(AItem) then
  2456. begin
  2457. if Assigned(AItem.PrevSibling) then // 如果有前兄弟,就按前兄弟
  2458. begin
  2459. vItem := TScBillsItem(AItem.PrevSibling);
  2460. if IsNoCode(vItem) then // 如果前兄弟不靠谱,就按父结点
  2461. vItem := TScBillsItem(AItem.Parent);
  2462. end
  2463. else if Assigned(AItem.NextSibling) then // 如果有后兄弟,就按后兄弟
  2464. begin
  2465. vItem := TScBillsItem(AItem.NextSibling);
  2466. if IsNoCode(vItem) then // 如果后兄弟不靠谱,就按父结点
  2467. vItem := TScBillsItem(AItem.Parent);
  2468. end
  2469. else if Assigned(AItem.Parent) then // 如果没有兄弟结点,就按父结点
  2470. begin
  2471. vItem := TScBillsItem(AItem.Parent);
  2472. end;
  2473. if Assigned(vItem) then // 到了这一层就结束,只按自己判断
  2474. begin
  2475. Result := GetItemTypeBySelf(vItem);
  2476. end
  2477. else
  2478. Result := '0';
  2479. end
  2480. else
  2481. Result := GetItemTypeBySelf(AItem);
  2482. end;
  2483. function TqgXMLPort.AddItem(ANode: TScBillsItem;
  2484. AParentXMLNode: TXmlNode): TXmlNode;
  2485. var sExpr, sCode, sMapValue, sMapName, sIT, sQty: string;
  2486. begin
  2487. Result := AParentXMLNode.NodeNewUTF8('Item');
  2488. Result.AttributeAddUTF8('ListCode', ANode.SmartCode);
  2489. Result.AttributeAddUTF8('ListName', Rec(ANode, 'Name'));
  2490. Result.AttributeAddUTF8('Unit', ChangeUnit_m3(Rec(ANode, 'Units')));
  2491. sExpr := '';
  2492. if (TScProject(FProject).ProjType in [ptBudget, ptBudgetEstimate, ptFeasibilityEstimate, ptProposalEstimate]) then
  2493. begin
  2494. Result.AttributeAddUTF8('Num', CheckNull(ANode.Rec.DesignQuantity.AsString));
  2495. Result.AttributeAddUTF8('Num1', CheckNull(ANode.Rec.DesignQuantity.AsString));
  2496. Result.AttributeAddUTF8('Num2', CheckNull(ANode.Rec.DesignQuantity2.AsString));
  2497. sExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_Bills, ExprsID_Bills_DesignQuantity, ANode.ID, 0);
  2498. Result.AttributeAddUTF8('NumExpression', sExpr);
  2499. end
  2500. else if (TScProject(FProject).ProjType = ptBillsBudget) then // 三级清单项目
  2501. begin
  2502. if (ANode.B_Code <> '') then // 清单
  2503. begin
  2504. sQty := CheckNull(ANode.Rec.Quantity.AsString);
  2505. sExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_Bills, ExprsID_Bills_Quantity, ANode.ID, 0);
  2506. {三级清单项目,清单工程量为0或空的情况: 用的是反算时,导出时,判断叶子清单,如果金额≠0,
  2507. 且没有基数计算,且工程量为0或空,则导出时工程量给定1。
  2508. 其他类型项目不处理,因验证了单机版和云版,工程量为0时,金额也是0。只有三级清单特殊 }
  2509. if (sQty = '0') and (sExpr = '') and (Rec(ANode, 'TotalPrice') <> '0')
  2510. and (TScProjBaseData(TScProject(FProject).ProjData).Properties.UnitPriceMode = 1)
  2511. and (ANode.IsLeaf = True)
  2512. then sQty := '1';
  2513. Result.AttributeAddUTF8('Num', sQty);
  2514. Result.AttributeAddUTF8('Num1', sQty);
  2515. Result.AttributeAddUTF8('NumExpression', sExpr);
  2516. end
  2517. else // 项目节
  2518. begin
  2519. Result.AttributeAddUTF8('Num', CheckNull(ANode.Rec.DesignQuantity.AsString));
  2520. Result.AttributeAddUTF8('Num1', CheckNull(ANode.Rec.DesignQuantity.AsString));
  2521. Result.AttributeAddUTF8('Num2', CheckNull(ANode.Rec.DesignQuantity2.AsString));
  2522. sExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_Bills, ExprsID_Bills_DesignQuantity, ANode.ID, 0);
  2523. Result.AttributeAddUTF8('NumExpression', sExpr);
  2524. end;
  2525. Result.AttributeAddUTF8('BillBudgetFlag', CheckBool(Rec(ANode, 'IsQDYS')));
  2526. end
  2527. else if (TScProject(FProject).ProjType = ptBills) then
  2528. begin
  2529. Result.AttributeAddUTF8('Num', CheckNull(ANode.Rec.Quantity.AsString));
  2530. Result.AttributeAddUTF8('Num1', CheckNull(ANode.Rec.Quantity.AsString));
  2531. sExpr := TScProject(FProject).Exprs.GetExprs(ExprsID_Bills, ExprsID_Bills_Quantity, ANode.ID, 0);
  2532. Result.AttributeAddUTF8('NumExpression', sExpr);
  2533. end;
  2534. if FFileType = xftTB then
  2535. Result.AttributeAddUTF8('Price', CheckNull(FloatToStr(ANode.SmartPrice)))
  2536. else
  2537. Result.AttributeAddUTF8('Price', '0');
  2538. if FFileType = xftTB then
  2539. Result.AttributeAddUTF8('Sum', Rec(ANode, 'TotalPrice'))
  2540. else
  2541. Result.AttributeAddUTF8('Sum', '0');
  2542. if ANode.Rec.ValueByName('InterimType').AsInteger > 0 then
  2543. Result.AttributeAddUTF8('ProvisionalType', IntToStr(ANode.Rec.ValueByName('InterimType').AsInteger - 1));
  2544. Result.AttributeAddUTF8('Remarks', Rec(ANode, 'MemoStr'));
  2545. Result.AttributeAddUTF8('MpRatio', CheckNull(Rec(ANode, 'XS_Labour')));
  2546. Result.AttributeAddUTF8('MaterialRatio', CheckNull(Rec(ANode, 'XS_Material')));
  2547. Result.AttributeAddUTF8('MechRatio', CheckNull(Rec(ANode, 'XS_Machine')));
  2548. Result.AttributeAddUTF8('AdjustedPrice', CheckNull(Rec(ANode, 'TenderUnitPrice')));
  2549. Result.AttributeAddUTF8('AdjustedSums', CheckNull(Rec(ANode, 'TenderTotalPrice')));
  2550. // ItemType,清单1,预算项目节0。
  2551. if TScProject(FProject).IsBills then
  2552. sIT := '1'
  2553. else if TScProject(FProject).IsBudget then
  2554. sIT := '0'
  2555. else // 三级清单
  2556. sIT := GetItemTypeByCode(ANode);
  2557. Result.AttributeAddUTF8('ItemType', sIT);
  2558. // 清单行的FormulaCode属性,用作行引用:有@ID和字母(不需要{})两种形式。
  2559. if ANode.ID = 1 then // ID为1的清单(@1)不能给成 GZQDHJ,否则云版计算会死循环
  2560. begin
  2561. if TScProject(FProject).IsBills then
  2562. sCode := 'D100Z700'
  2563. else
  2564. sCode := 'DYBF';
  2565. end
  2566. else
  2567. begin
  2568. sCode := '@' + IntToStr(ANode.ID);
  2569. if TScProject(FProject).IsBills then
  2570. sMapName := 'Map_Formula_Bill'
  2571. else
  2572. sMapName := 'Map_Formula_Budget';
  2573. sMapValue := GetMapValue(GetMap(sMapName), sCode, 0, 2); // 返回 {ZXZDHJ}
  2574. if sMapValue <> '' then
  2575. sCode := Copy(sMapValue, 2, Length(sMapValue) - 2); // 去掉{}
  2576. end;
  2577. Result.AttributeAddUTF8('FormulaCode', sCode);
  2578. end;
  2579. function TqgXMLPort.GetNormLibNoByID(ALibID: Integer): string;
  2580. var sLibName: string;
  2581. begin
  2582. IntToIdent(ALibID, sLibName, FLibArr);
  2583. Result := GetMapValue(GetMap('Map_RationLib'), sLibName);
  2584. end;
  2585. function TqgXMLPort.GetGJLCodeByKey(AKey: string; AOrgCode: string): string;
  2586. var sNewCode: string;
  2587. begin
  2588. sNewCode := FGLJKeyCodeMap.Values[AKey];
  2589. if sNewCode = '' then sNewCode := AOrgCode;
  2590. Result := sNewCode;
  2591. end;
  2592. function TqgXMLPort.GetType(AType, ACalculateType: Integer; AName: string): Integer;
  2593. begin
  2594. case AType of
  2595. 1:
  2596. begin
  2597. if AName = '机械工' then Result := 303
  2598. else Result := AType;
  2599. end;
  2600. 2:
  2601. begin
  2602. if ACalculateType = 0 then Result := 202 // 混凝土
  2603. else Result := AType;
  2604. end;
  2605. 3, 4: // 3 兼容旧项目材料
  2606. begin
  2607. if (ACalculateType = 0) or (ACalculateType = -1) then Result := 201 // 普通材料
  2608. else if ACalculateType = 1 then Result := 205 // 商品砼
  2609. else if ACalculateType = 2 then Result := 208 // 预制构件
  2610. else if ACalculateType = 3 then Result := 209 // 绿化苗木
  2611. else if ACalculateType = 4 then Result := 206 // 路基填料
  2612. else if ACalculateType = 5 then Result := 206 // 商品沥青混合料
  2613. else if ACalculateType = 6 then Result := 206 // 各类稳定土混合料
  2614. else Result := AType;
  2615. end;
  2616. 6:
  2617. begin
  2618. if ACalculateType = 0 then Result := 5 // 设备
  2619. else Result := AType;
  2620. end;
  2621. else
  2622. Result := AType;
  2623. end;
  2624. end;
  2625. // 投标项目, 特殊的清单,公式写死在代码里,用户也可以自定义。如:最后一行清单"投标价"(id=9)等。
  2626. function TqgXMLPort.IsSpecialFormulaBill(ANode: TScBillsItem): Boolean;
  2627. begin
  2628. Result := IsSpecialFormulaBill(ANode.ID);
  2629. end;
  2630. function TqgXMLPort.IsSpecialFormulaBill(ABillID: Integer): Boolean;
  2631. begin
  2632. Result := (TScProject(FProject).ProjType = ptBills) and
  2633. (ABillID in [idSpecialInterimSum, idBillSumExcludeSpecialInterim, idProjectTotalPrice_Bills]);
  2634. end;
  2635. procedure TqgXMLPort.AddDrawQ(ANode: TScBillsItem; AParentXMLNode: TXmlNode);
  2636. var vChild: TXmlNode;
  2637. begin
  2638. FQuery2.Close;
  2639. FQuery2.SQL.Clear;
  2640. FQuery2.SQL.Add(Format('SELECT * FROM DrawingQuantity WHERE BillsID = %d', [ANode.ID]));
  2641. FQuery2.Open;
  2642. if FQuery2.RecordCount > 0 then
  2643. begin
  2644. FQuery2.First;
  2645. while not FQuery2.Eof do
  2646. begin
  2647. vChild := AParentXMLNode.NodeNewUTF8('DesignDetail');
  2648. vChild.AttributeAddUTF8('OrderNumber', IntToStr(FQuery2.RecNo));
  2649. vChild.AttributeAddUTF8('Name', FQuery2.FieldByName('Name').asString);
  2650. vChild.AttributeAddUTF8('Unit', ChangeUnit_m3(FQuery2.FieldByName('Units').asString));
  2651. vChild.AttributeAddUTF8('Express', FQuery2.FieldByName('ExprsMemo').asString);
  2652. vChild.AttributeAddUTF8('DesignQuantity', FQuery2.FieldByName('DQuantity1').asString);
  2653. // vChild.AttributeAddUtf8('Kind', '2');
  2654. vChild.AttributeAddUTF8('Remark', FQuery2.FieldByName('MemoContext').asString);
  2655. FQuery2.Next;
  2656. end;
  2657. end;
  2658. FQuery2.Close;
  2659. end;
  2660. function TqgXMLPort.AdjustStateToPort(ARation: TScRationRecord): string;
  2661. var vSL: TStringList;
  2662. i: Integer;
  2663. sAdjustState, sOneState, sTemp: string;
  2664. begin
  2665. sAdjustState := ARation.AdjustState.AsString;
  2666. if Trim(sAdjustState) = '' then
  2667. begin
  2668. Result := '';
  2669. Exit;
  2670. end;
  2671. vSL := TStringList.Create;
  2672. try
  2673. vSL.Delimiter := ';';
  2674. vSL.DelimitedText := sAdjustState;
  2675. for i := 0 to vSL.Count - 1 do
  2676. begin
  2677. sOneState := vSL[i];
  2678. vSL[i] := OneAdjustToPort(sOneState, ARation); // 每项可读可改
  2679. end;
  2680. vSL.Delimiter := ';'; // 重新指定新的分隔符
  2681. Result := vSL.DelimitedText; // 改后的每项重新合成新串
  2682. finally
  2683. vSL.Free;
  2684. end;
  2685. // 辅助定额特殊处理:追加定额编号。这个逻辑不能在分段 OneAdjustToPort()中处理,因为会重复。在这里只加一次搞定。
  2686. if Pos('+', Result) > 0 then
  2687. begin
  2688. sTemp := ARation.Code.AsString + ' ' + '+';
  2689. Result := StringReplace(Result, '+', sTemp, []);
  2690. end;
  2691. end;
  2692. (*------------------------------------------------------------------------------
  2693. 单机导出部颁接口,定额调整文本,按以下规则输出:
  2694. (1)按“;”将调整状态拆分为多个。
  2695. (2)辅助定额,单条,显示格式为“2-2-13-1 +2×8”(定额的编号,不是辅助定额的编号)。多条,显示格式为“2-2-13-1 +5×9; +4×3; +6×27”
  2696. (3)自定义消耗量,显示格式为“[2005001]10.5量10.2”。
  2697. (4)添加材料,显示格式为“[2005001]0量10.2”。
  2698. (5)替换材料,工程量不变,显示格式为“[2009028]换[2009029]”。工程量变化,显示格式为“[2009028]0.89换[2009029]1.025”。
  2699. (6)稳定土配合比,显示格式为“配比[5501002:5503004:5509001]=[10:79:11]”。
  2700. (7)附注条件,显示格式为“人、机械、小型机具使用费×1.26”、“定额×0.73”,即附注条件的内容列。
  2701. (8)自定义系数,显示格式为“定额×2”、“工×2”、“料×1.1”、“机×1.5”。
  2702. (9)油石比,显示格式为“配比[3001001]=5.45”。
  2703. (10)处理材料编号。比如原文本是“[2009028]换[2009029]”,但导出接口时,2009029重编为2009029-1了;文本应更为“[2009028]换[2009029-1]”。
  2704. ------------------------------------------------------------------------------*)
  2705. function TqgXMLPort.OneAdjustToPort(AOneState: string; ARation: TScRationRecord): string;
  2706. var sRCode, sGLJCode, sQty, sTemp, sHint: string;
  2707. iPos1, iPos2, RID: Integer;
  2708. RAdjData: TScRAdjustData;
  2709. GLJRec: TScGLJRecord;
  2710. f: Double;
  2711. begin
  2712. Result := AOneState;
  2713. if AOneState = '' then Exit;
  2714. // 思路:典型的、确定可靠的先挑出来,避免干扰。
  2715. RAdjData := TScProject(FProject).Rations.RAdjusts;
  2716. RID := ARation.ID.AsInteger;
  2717. // 辅助定额:加定额编号。注意!这里先不加,因为多条辅助定额时会加重复。解决:在完整的调整状态位置,在第一个加号前加一次即可。
  2718. if AOneState[1] = '+' then
  2719. begin
  2720. Result := AOneState;
  2721. end
  2722. // 附注条件:原样输出
  2723. else if (Pos(',', AOneState) > 0) or (Pos(',', AOneState) > 0) then
  2724. begin
  2725. Result := AOneState;
  2726. end
  2727. // 配比:80:20 →配比[5501002:5503004:5509001]=[10:79:11]
  2728. else if Pos(':', AOneState) > 0 then
  2729. begin
  2730. Result := RAdjData.getPortAdjustState_PB(RID);
  2731. end
  2732. // 添加材料:添2003064量24 →[2003064]0量24
  2733. else if (Pos('添', AOneState) = 1) then
  2734. begin
  2735. Result := StringReplace(AOneState, '添', '[', []);
  2736. Result := StringReplace(Result, '量', ']0量', []);
  2737. end
  2738. // 油石比/自定义消耗量 两个货长一样:
  2739. // 油石比: 3001001量23 →配比[3001001]=5.45
  2740. // 自定义消耗量: 2009028量23 →[2009028]18量23
  2741. else if (Pos('量', AOneState) > 0) and (Pos(',', AOneState) = 0) then
  2742. begin
  2743. sGLJCode := Copy(AOneState, 1, Pos('量', AOneState) - 1);
  2744. f := RAdjData.getPortAdjustState_YS(RID);
  2745. if (f <> 0) then // 有油石比数据
  2746. begin
  2747. Result := Format('配比[%s]=%s', [sGLJCode, FloatToStr(f)]); // %f 有无法指定小数位数问题,直接搞成%s省心。
  2748. end
  2749. else
  2750. begin
  2751. GLJRec := TScProject(FProject).GLJ.FindGLJByRationIDAndGLJCode(RID, sGLJCode);
  2752. if not Assigned(GLJRec) then // 遇到过新工料机找不到的情况。
  2753. begin
  2754. sHint := Format('找不到工料机 %s :[标段]%s [定额]%s [工程量]%s',
  2755. [sGLJCode, FEprjInfoNode.AttributeValueByNameUTF8['Name'], ARation.Code.AsString, ARation.Quantity.AsString]);
  2756. MessageWarning(sHint);
  2757. sQty := '??';
  2758. end
  2759. else
  2760. begin
  2761. sQty := GLJRec.OrgRQuantity.AsString;
  2762. end;
  2763. sTemp := ']' + sQty + '量';
  2764. Result := StringReplace(AOneState, '量', sTemp, []);
  2765. Result := '[' + Result;
  2766. end;
  2767. end
  2768. // 替换材料: 2003008换2003009 →[2003008]换[2003009]
  2769. // 替换材料2: 2003008换2003009; 2003009量6 →[2003008]0.89换[2003009]6
  2770. else if Pos('换', AOneState) > 0 then
  2771. begin
  2772. Result := StringReplace(AOneState, '换', ']换[', []);
  2773. sTemp := Copy(Result, 1, Pos(']', Result) - 1); // "换"字前的 编号/简称/名称
  2774. if not IsNumberStr(sTemp) then
  2775. begin
  2776. // 替换简称、名称,如:'M10]换[M20'、'水C25-32.5-4]换[水C30-32.5-4'
  2777. Result := StringReplace(Result, sTemp, SearchDic_Concrete(sTemp, 2, 0), []);
  2778. iPos2 := Pos('[', Result);
  2779. sTemp := Copy(Result, iPos2 + 1, Length(Result) - iPos2);
  2780. Result := StringReplace(Result, sTemp, SearchDic_Concrete(sTemp, 2, 0), []);
  2781. end;
  2782. Result := Format('[%s]', [Result]);
  2783. end
  2784. // 自定义系数:这种也是直接出。(附注条件含的,已经在前面过滤掉了)
  2785. else if (Pos('定额×', AOneState) = 1) then
  2786. begin
  2787. Result := AOneState;
  2788. end
  2789. // 自定义系数
  2790. else if (Pos('人工×', AOneState) = 1) or (Pos('材料×', AOneState) = 1)
  2791. or (Pos('机械×', AOneState) = 1) then
  2792. begin
  2793. Result := StringReplace(AOneState, '人工×', '工×', []);
  2794. Result := StringReplace(Result, '材料×', '料×', []);
  2795. Result := StringReplace(Result, '机械×', '机×', []);
  2796. end
  2797. // 搞不定的都在这儿
  2798. else
  2799. begin
  2800. Result := AOneState;
  2801. end;
  2802. end;
  2803. procedure TqgXMLPort.AddBuildLoan(AParentXMLNode: TXmlNode);
  2804. var vBuildLoan, vBanks, vYear: TXmlNode;
  2805. sMethod, sName, sYun, sValue: string;
  2806. begin
  2807. vBuildLoan := AParentXMLNode.NodeNewUTF8('LoanDetails');
  2808. FSearch1.Close;
  2809. FSearch1.SQL.Text := 'Select ItemValue From ProjProperty Where Name=''BUILDLOANCALCMODE''';
  2810. FSearch1.Open;
  2811. sValue := FSearch1.FieldByName('ItemValue').AsString;
  2812. if sValue = '1' then // 固定金额
  2813. sMethod := '3'
  2814. else
  2815. begin
  2816. FSearch1.Close;
  2817. FSearch1.SQL.Text := 'Select ItemValue From ProjProperty Where Name=''BUILDLOANEXPMODE''';
  2818. FSearch1.Open;
  2819. sValue := FSearch1.FieldByName('ItemValue').AsString;
  2820. if sValue = '0' then
  2821. sMethod := '1' // 基数比例-总造价比例
  2822. else
  2823. sMethod := '2'; // 基数比例-一二三部分合计比例
  2824. end;
  2825. vBuildLoan.AttributeAddUTF8('LoanMethod', sMethod);
  2826. FSearch1.Close;
  2827. FSearch1.SQL.Text := 'Select ItemValue From ProjProperty Where Name=''BUILDLOANTOTALPROPORTION''';
  2828. FSearch1.Open;
  2829. sValue := FSearch1.FieldByName('ItemValue').AsString;
  2830. vBuildLoan.AttributeAddUTF8('LoanRatio', sValue);
  2831. FSearch1.Close;
  2832. FSearch1.SQL.Text := 'Select ItemValue From ProjProperty Where Name=''DEDUCTEXPR''';
  2833. FSearch1.Open;
  2834. vBuildLoan.AttributeAddUTF8('SubsidyDeduction', FSearch1.FieldByName('ItemValue').AsString);
  2835. FSearch1.Close;
  2836. FSearch1.SQL.Text := 'Select Sum(BankMoney) as total From ProjInfo';
  2837. FSearch1.Open;
  2838. vBuildLoan.AttributeAddUTF8('TotalLoans', FSearch1.FieldByName('total').AsString);
  2839. FSearch1.Close;
  2840. FSearch1.SQL.Text := 'Select * From ProjInfo';
  2841. FSearch1.Open;
  2842. FSearch1.First;
  2843. while not FSearch1.Eof do
  2844. begin
  2845. vBanks := vBuildLoan.NodeNewUTF8('Banks');
  2846. vBanks.AttributeAddUTF8('BankName', FSearch1.FieldByName('ProjName').AsString);
  2847. vBanks.AttributeAddUTF8('BankRatio', FSearch1.FieldByName('BankProportion').AsString);
  2848. vBanks.AttributeAddUTF8('BankLoanAmount', FSearch1.FieldByName('BankMoney').AsString);
  2849. vBanks.AttributeAddUTF8('InterestBearingYear', FSearch1.FieldByName('Years').AsString);
  2850. FSearch2.Close;
  2851. FSearch2.SQL.Text := 'Select * From YearLoan where ProjID=' + FSearch1.FieldByName('ProjID').AsString + ' order by YearNo';
  2852. FSearch2.Open;
  2853. FSearch2.First;
  2854. while not FSearch2.Eof do
  2855. begin
  2856. vYear := vBanks.NodeNewUTF8('InterestDetails');
  2857. vYear.AttributeAddUTF8('Annual', FSearch2.FieldByName('YearNo').AsString);
  2858. vYear.AttributeAddUTF8('AnnualName', FSearch2.FieldByName('YearName').AsString);
  2859. vYear.AttributeAddUTF8('AnnualRatio', FSearch2.FieldByName('YearProportion').AsString);
  2860. vYear.AttributeAddUTF8('AnnualLoanAmount', FSearch2.FieldByName('Principal').AsString);
  2861. vYear.AttributeAddUTF8('InterestRate', FSearch2.FieldByName('InterestRate').AsString);
  2862. // vYear.AttributeAddUtf8('LastYearsPI', FSearch2.FieldByName('LastYearsPI').AsString);
  2863. vYear.AttributeAddUTF8('Interest', FSearch2.FieldByName('Interest').AsString);
  2864. FSearch2.Next;
  2865. end;
  2866. FSearch1.Next;
  2867. end;
  2868. FSearch1.Close;
  2869. FSearch2.Close;
  2870. end;
  2871. function TqgXMLPort.CanGC(ANode: TScBillsItem): Boolean;
  2872. var b: Boolean;
  2873. begin
  2874. Result := False;
  2875. if TScProject(FProject).IsBills then Exit;
  2876. if not TScProject(FProject).IsGuangDong then Exit;
  2877. // idSurveyDesign、 idSupervisionService 这两个不管。只导出3种树
  2878. if ANode.IsInheritFrom(idGroundCompensate) or
  2879. ANode.IsInheritFrom(idGroundRemove) or
  2880. ANode.IsInheritFrom(idGroundTemporary) then
  2881. Result := True;
  2882. end;
  2883. procedure TqgXMLPort.AddGC(AParentXMLNode: TXMLNode; const ABillsID: Integer);
  2884. var vItem: TScBillsItem;
  2885. vTree: TBaseTree;
  2886. vFirst, vLast: TBaseNode;
  2887. begin
  2888. vItem := TScProject(FProject).Bills.BillsTree[ABillsID];
  2889. if not vItem.HasLeafTree then Exit;
  2890. vTree := TScProject(FProject).LeafTreesDM.TreeManager.IDItem[ABillsID];
  2891. if vTree.Count < 1 then Exit;
  2892. AParentXMLNode.AttributeAddUTF8(c_TreeType, IntToStr(vTree.TreeType));
  2893. vFirst := TBaseNode(vTree[0]);
  2894. vLast := vFirst;
  2895. while Assigned(vLast.NextSibling) do
  2896. vLast := TBaseNode(vLast.NextSibling);
  2897. AddGC2(vTree, vFirst.MajorIndex, vLast.MajorIndex, AParentXMLNode);
  2898. end;
  2899. // AGCNode比AXMLNode高一级别
  2900. procedure TqgXMLPort.AddGC2(ALeafTree: TBaseTree; AIndex1, AIndex2: Integer; AXMLNode: TXmlNode);
  2901. var
  2902. vXMLCurNode: TXmlNode;
  2903. vGCNode: TBaseNode;
  2904. iIndex: Integer;
  2905. function AddGC3(ANode: TBaseNode; AXMLNode: TXmlNode): TXMLNode;
  2906. var
  2907. vXMLNode: TXmlNode;
  2908. procedure AssignBaseProperty(AXMLNode: TXmlNode; ANode: TBaseNode);
  2909. begin
  2910. AXMLNode.AttributeAddUTF8('Code', ANode.Code);
  2911. AXMLNode.AttributeAddUTF8('Name', ANode.Name);
  2912. AXMLNode.AttributeAddUTF8('Units', ANode.Units);
  2913. AXMLNode.AttributeAddUTF8('Quantity', FloatToStr(ANode.Quantity));
  2914. AXMLNode.AttributeAddUTF8('UnitPrice', FloatToStr(ANode.UnitPrice));
  2915. AXMLNode.AttributeAddUTF8('TotalPrice', FloatToStr(ANode.TotalPrice));
  2916. AXMLNode.AttributeAddUTF8('MemoStr', ANode.MemoStr);
  2917. AXMLNode.AttributeAddUTF8('IsLeaf', BoolToStr(ANode.IsLeaf));
  2918. end;
  2919. function GetGroundKindName(ANode: TGCNode): string;
  2920. begin
  2921. Result := ANode.GroundKindName;
  2922. if Result = '' then
  2923. Result := '耕地';
  2924. end;
  2925. procedure AssignGCProperty(AXMLNode: TXmlNode; ANode: TGCNode);
  2926. begin
  2927. AXMLNode.AttributeAddUTF8(c_GroundCompSubtotal, CurrToStr(ANode.GroundCompSubtotal));
  2928. AXMLNode.AttributeAddUTF8(c_SeedlingCompSubtotal, CurrToStr(ANode.SeedlingCompSubtotal));
  2929. AXMLNode.AttributeAddUTF8(c_InsurePeopleCount, CurrToStr(ANode.InsurePeopleCount));
  2930. AXMLNode.AttributeAddUTF8(c_OtherFeeSubtotal, CurrToStr(ANode.OtherFeeSubtotal));
  2931. // AXMLNode.AttributeAddUtf8(c_InsureSubtotal, CurrToStr(ANode.InsureSubtotal)); 2011年的算法,现在不用了,不导出。
  2932. AXMLNode.AttributeAddUTF8(c_GroundTaxFeeSubtotal, CurrToStr(ANode.GroundTaxFeeSubtotal));
  2933. AXMLNode.AttributeAddUTF8(c_SeedlingCompFee, CurrToStr(ANode.SeedlingCompFee));
  2934. AXMLNode.AttributeAddUTF8(c_GroundCompFee, CurrToStr(ANode.GroundCompFee));
  2935. AXMLNode.AttributeAddUTF8(c_TilthAmountPerPeople, CurrToStr(ANode.TilthAmountPerPeople));
  2936. AXMLNode.AttributeAddUTF8(c_ExtractBase, CurrToStr(ANode.ExtractBase));
  2937. AXMLNode.AttributeAddUTF8(c_ExtractRatio, CurrToStr(ANode.ExtractRatio));
  2938. AXMLNode.AttributeAddUTF8(c_Resettle, CurrToStr(ANode.Resettle));
  2939. AXMLNode.AttributeAddUTF8(c_ExtractSubtotal, CurrToStr(ANode.ExtractSubtotal));
  2940. AXMLNode.AttributeAddUTF8(c_AreaStandard, CurrToStr(ANode.AreaStandard));
  2941. AXMLNode.AttributeAddUTF8(c_AgricultureTax, CurrToStr(ANode.AgricultureTax));
  2942. AXMLNode.AttributeAddUTF8(c_TilthImprTax, CurrToStr(ANode.TilthImprTax));
  2943. AXMLNode.AttributeAddUTF8(c_TilthAssartFee, CurrToStr(ANode.TilthAssartFee));
  2944. AXMLNode.AttributeAddUTF8(c_ForestRecoverFee, CurrToStr(ANode.ForestRecoverFee));
  2945. AXMLNode.AttributeAddUTF8(c_GroundRepayUseFee, CurrToStr(ANode.GroundRepayUseFee));
  2946. AXMLNode.AttributeAddUTF8(c_GroundManageFee, CurrToStr(ANode.GroundManageFee));
  2947. AXMLNode.AttributeAddUTF8(c_LeftGroundFee, CurrToStr(ANode.LeftGroundFee));
  2948. AXMLNode.AttributeAddUTF8(c_GroundSurveyFee, CurrToStr(ANode.GroundSurveyFee));
  2949. AXMLNode.AttributeAddUTF8(c_GroundKindID, IntToStr(ANode.GroundKindID));
  2950. AXMLNode.AttributeAddUTF8(c_AreaCategoryID, IntToStr(ANode.AreaCategoryID));
  2951. AXMLNode.AttributeAddUTF8(c_IsProtectedArea, BoolToStr(ANode.IsProtectedArea));
  2952. AXMLNode.AttributeAddUTF8(c_IsPaddyField, BoolToStr(ANode.IsPaddyField));
  2953. AXMLNode.AttributeAddUTF8(c_AreaID, IntToStr(ANode.AreaID));
  2954. AXMLNode.AttributeAddUTF8(c_AreaName, ANode.AreaName);
  2955. AXMLNode.AttributeAddUTF8(c_ForestRecoverID, IntToStr(ANode.ForestRecoverID));
  2956. AXMLNode.AttributeAddUTF8(c_IsCityForest, BoolToStr(ANode.IsCityForest));
  2957. AXMLNode.AttributeAddUTF8(c_AreaCategoryName, ANode.AreaCategoryName);
  2958. AXMLNode.AttributeAddUTF8(c_GroundKindName, GetGroundKindName(ANode));
  2959. AXMLNode.AttributeAddUTF8(c_NewAddFee_GC_1, CurrToStr(ANode.NewAddFee_GC_1));
  2960. AXMLNode.AttributeAddUTF8(c_NewAddFee_GC_2, CurrToStr(ANode.NewAddFee_GC_2));
  2961. AXMLNode.AttributeAddUTF8(c_NewAddFee_GC_3, CurrToStr(ANode.NewAddFee_GC_3));
  2962. AXMLNode.AttributeAddUTF8(c_NewAddFee_SC_1, CurrToStr(ANode.NewAddFee_SC_1));
  2963. AXMLNode.AttributeAddUTF8(c_NewAddFee_SC_2, CurrToStr(ANode.NewAddFee_SC_2));
  2964. AXMLNode.AttributeAddUTF8(c_NewAddFee_SC_3, CurrToStr(ANode.NewAddFee_SC_3));
  2965. AXMLNode.AttributeAddUTF8(c_NewAddFee_Other_1, CurrToStr(ANode.NewAddFee_Other_1));
  2966. AXMLNode.AttributeAddUTF8(c_NewAddFee_Other_2, CurrToStr(ANode.NewAddFee_Other_2));
  2967. AXMLNode.AttributeAddUTF8(c_NewAddFee_Other_3, CurrToStr(ANode.NewAddFee_Other_3));
  2968. AXMLNode.AttributeAddUTF8(c_NewAddFee_GT_1, CurrToStr(ANode.NewAddFee_GT_1));
  2969. AXMLNode.AttributeAddUTF8(c_NewAddFee_GT_2, CurrToStr(ANode.NewAddFee_GT_2));
  2970. AXMLNode.AttributeAddUTF8(c_NewAddFee_GT_3, CurrToStr(ANode.NewAddFee_GT_3));
  2971. AXMLNode.AttributeAddUTF8(c_IsCountPriceMode, BoolToStr(ANode.IsCountPriceMode));
  2972. AXMLNode.AttributeAddUTF8(c_PensionCount, CurrToStr(ANode.PensionCount));
  2973. AXMLNode.AttributeAddUTF8(c_Age16Rate, CurrToStr(ANode.Age16Rate));
  2974. AXMLNode.AttributeAddUTF8(c_Year15Insur, CurrToStr(ANode.Year15Insur));
  2975. AXMLNode.AttributeAddUTF8(c_LeftGroundRate, CurrToStr(ANode.LeftGroundRate));
  2976. AXMLNode.AttributeAddUTF8(c_IndustryLandPrice, CurrToStr(ANode.IndustryLandPrice));
  2977. AXMLNode.AttributeAddUTF8(c_LeftGroundFee2019, CurrToStr(ANode.LeftGroundFee2019));
  2978. AXMLNode.AttributeAddUTF8(c_PackageFee, CurrToStr(ANode.PackageFee));
  2979. AXMLNode.AttributeAddUTF8(c_RewardFee, CurrToStr(ANode.RewardFee));
  2980. end;
  2981. begin
  2982. vXMLNode := AXMLNode.NodeNewUTF8('GCNode');
  2983. Result := vXMLNode;
  2984. AssignBaseProperty(vXMLNode, ANode);
  2985. if TBaseTree(ANode.Owner).TreeType = tt_GroundCompensate then
  2986. if ANode.IsLeaf then
  2987. AssignGCProperty(vXMLNode, TGCNode(ANode));
  2988. end;
  2989. begin
  2990. if AIndex1 > AIndex2 then Exit;
  2991. vGCNode := TBaseNode(ALeafTree.Items[AIndex1]);
  2992. while (vGCNode <> nil) and (vGCNode.MajorIndex <= AIndex2) do
  2993. begin
  2994. vXMLCurNode := AddGC3(vGCNode, AXMLNode);
  2995. if vGCNode.HasChildren then
  2996. begin
  2997. iIndex := vGCNode.FirstChild.MajorIndex;
  2998. AddGC2(ALeafTree, iIndex, MaxInt, vXMLCurNode); // vXMLCurNode比当前vGCNode高一级别
  2999. end;
  3000. vGCNode := TBaseNode(vGCNode.NextSibling);
  3001. end;
  3002. end;
  3003. procedure TqgXMLPort.AddNodesForEveryProject(n: Integer);
  3004. begin
  3005. inherited;
  3006. AddRationLibs;
  3007. AddRate(n);
  3008. AddPract(n);
  3009. AddEprjInfo(n);
  3010. end;
  3011. {TZTBXMLPort}
  3012. procedure TZTBXMLPort.AddNodes;
  3013. begin
  3014. inherited;
  3015. AddGCXX;
  3016. AddZTBXX;
  3017. AddGLGCSJ;
  3018. // 修改投标总价
  3019. if (FFileType = xftTB) then
  3020. FZTBXX.Elements[0].AttributeValueByNameUTF8['投标总价'] := FloatToStr(FAllProjectsTotalPriceSum);
  3021. // 修改数据校验码
  3022. FGCXX.AttributeValueByNameUTF8['数据校验码'] := GetDataCheckCode;
  3023. end;
  3024. procedure TZTBXMLPort.AddNodesForEveryProject(n: Integer);
  3025. begin
  3026. inherited;
  3027. AddGLBDGC(n);
  3028. end;
  3029. procedure TZTBXMLPort.AddGCXX;
  3030. var s: string;
  3031. sTemp: string;
  3032. begin
  3033. AddProgressForm(10, '正在生成工程信息...');
  3034. FGCXX := FRoot.NodeNewUTF8('工程信息');
  3035. FGCXX.AttributeAddUTF8('项目编号', BV(SProjectNo));
  3036. FGCXX.AttributeAddUTF8('项目名称', PD.BuildProjectName);
  3037. FGCXX.AttributeAddUTF8('建设单位', BV(SBuildUnit));
  3038. FGCXX.AttributeAddUTF8('起始桩号', BV(SStartCode));
  3039. FGCXX.AttributeAddUTF8('终点桩号', BV(SEndCode));
  3040. FGCXX.AttributeAddUTF8('建设地址', BV(SProjectLocation));
  3041. FGCXX.AttributeAddUTF8('项目概况', BV(SProjectSummary));
  3042. // if (self.Area = areaZheJiang) then
  3043. // sTemp := '项目类型'
  3044. // else
  3045. // sTemp := '建设性质';
  3046. //
  3047. // if PV('Newly') = '新建' then
  3048. // FGCXX.AttributeAddUTF8(sTemp, '1')
  3049. // else
  3050. // FGCXX.AttributeAddUTF8(sTemp, '2');
  3051. FGCXX.AttributeAddUTF8('项目类型', '1'); // 1 施工,2 养护。 我们是施工,不是养护,单机版这个软件做不了养护的。
  3052. s := BV(SRoadLevel);
  3053. if s = '一级公路' then
  3054. FGCXX.AttributeAddUTF8('专业划分', '2')
  3055. else if s = '二级公路' then
  3056. FGCXX.AttributeAddUTF8('专业划分', '3')
  3057. else if s = '三级公路' then
  3058. FGCXX.AttributeAddUTF8('专业划分', '4')
  3059. else if s = '四级公路' then
  3060. FGCXX.AttributeAddUTF8('专业划分', '5')
  3061. else
  3062. FGCXX.AttributeAddUTF8('专业划分', '1'); // '高速公路'
  3063. if (self.Area = areaZheJiang) then
  3064. sTemp := '道路里程-公里'
  3065. else
  3066. sTemp := '道路里程';
  3067. FGCXX.AttributeAddUTF8(sTemp, BV(SRoadLength));
  3068. FGCXX.AttributeAddUTF8('设计单位', BV(SDesignUnit));
  3069. FGCXX.AttributeAddUTF8('计税方式', '1');
  3070. if FFileType = xftZB then
  3071. FGCXX.AttributeAddUTF8('文件类型', '1')
  3072. else if FFileType = xftKZJ then
  3073. FGCXX.AttributeAddUTF8('文件类型', '2')
  3074. else if FFileType = xftTB then
  3075. FGCXX.AttributeAddUTF8('文件类型', '3');
  3076. if (self.Area = areaZheJiang) then
  3077. begin
  3078. // 数据校验码:通过【投标信息】和【公路工程汇总】下的所有字段内容计算哈希值。这里超前取值,先占坑,后续覆盖。
  3079. FGCXX.AttributeAddUTF8('数据校验码', 'AAAAA');
  3080. // 软件校验码:后续通过工具获取,这里先占坑,后续覆盖。
  3081. FGCXX.AttributeAddUTF8('软件校验码', 'AAAAA');
  3082. end;
  3083. FGCXX.AttributeAddUTF8('标准版本号', '1.0');
  3084. FGCXX.AttributeAddUTF8('GUID', GetProjectGUID(True)); // 这是建设项目的GUID码
  3085. end;
  3086. procedure TZTBXMLPort.AddZTBXX;
  3087. var vChild: TXmlNode;
  3088. DogNo: string;
  3089. begin
  3090. AddProgressForm(10, '正在生成招投标信息...');
  3091. FZTBXX := FRoot.NodeNewUTF8('招投标信息');
  3092. if FFileType = xftZB then
  3093. vChild := FZTBXX.NodeNewUTF8('招标信息')
  3094. else if FFileType = xftKZJ then
  3095. vChild := FZTBXX.NodeNewUTF8('招标控制价')
  3096. else if FFileType = xftTB then
  3097. vChild := FZTBXX.NodeNewUTF8('投标信息');
  3098. if (self.Area = areaZheJiang) then
  3099. begin
  3100. if (FFileType = xftZB) then
  3101. begin
  3102. vChild.AttributeAddUTF8('招标人', BV(SZhaoBiaoRen));
  3103. vChild.AttributeAddUTF8('招标法定代表人或其授权人', BV(SZhaoBiaoRenRepresentative));
  3104. vChild.AttributeAddUTF8('编制人', BV(SAuthor));
  3105. vChild.AttributeAddUTF8('编制人资格证号', BV(SAuthorCertificate));
  3106. vChild.AttributeAddUTF8('编制日期', Copy(BV(SEditDate), 1, 10));
  3107. vChild.AttributeAddUTF8('招标代理机构', BV(SZhaoBiaoAgent));
  3108. vChild.AttributeAddUTF8('招标范围', BV(SZhaoBiaoRange));
  3109. vChild.AttributeAddUTF8('总工期日历天', BV(SZhaoBiaoCalendarDay));
  3110. end
  3111. else if (FFileType = xftTB) then
  3112. begin
  3113. DogNo := CLD_DogsBySerialNo;
  3114. vChild.AttributeAddUTF8('投标人', BV(STouBiaoRen));
  3115. vChild.AttributeAddUTF8('投标人法人或其授权人', BV(STouBiaoRenRepresentative));
  3116. vChild.AttributeAddUTF8('投标人资质证号', BV(STouBiaoRenCertificate));
  3117. vChild.AttributeAddUTF8('总工期日历天', BV(STouBiaoCalendarDay));
  3118. vChild.AttributeAddUTF8('投标总价', FloatToStr(FAllProjectsTotalPriceSum)); // 此时还取不到,标段遍历完再修改此值
  3119. vChild.AttributeAddUTF8('投标下浮率', BV(STouBiaoDownRate));
  3120. vChild.AttributeAddUTF8('投标报价说明', BV(STouBiaoQuoteNote));
  3121. vChild.AttributeAddUTF8('质量承诺', BV(STouBiaoQualityCommitment));
  3122. vChild.AttributeAddUTF8('投标保证金', BV(STouBiaoDeposit));
  3123. vChild.AttributeAddUTF8('项目经理或项目负责人', BV(STouBiaoProjectManager));
  3124. vChild.AttributeAddUTF8('项目经理或项目负责人资格证号', BV(STouBiaoProjectManagerCertificate));
  3125. vChild.AttributeAddUTF8('造价软件品牌', Application.Title);
  3126. vChild.AttributeAddUTF8('造价软件版本', ScGetVersion);
  3127. vChild.AttributeAddUTF8('造价软件加密锁编号', DogNo);
  3128. vChild.AttributeAddUTF8('计算机硬件信息', Get_CPU_SN + Get_HDD_SN + Get_MAC_Address);
  3129. vChild.AttributeAddUTF8('备注', '');
  3130. end;
  3131. end
  3132. else
  3133. begin
  3134. if (FFileType = xftZB) or (FFileType = xftKZJ) then
  3135. begin
  3136. vChild.AttributeAddUTF8('招标人', BV('ZhaoBR'));
  3137. vChild.AttributeAddUTF8('招标人纳税识别号', BV('ZhaoBRNSSBH'));
  3138. vChild.AttributeAddUTF8('招标法定代表人或其授权人', BV('ZhaoBFR'));
  3139. vChild.AttributeAddUTF8('招标法人或其授权人身份证号', BV('ZhaoBFRSFZH'));
  3140. vChild.AttributeAddUTF8('造价咨询人', BV('ZaoJZXR'));
  3141. vChild.AttributeAddUTF8('造价咨询人纳税识别号', BV('ZaoJZXRNSSBH'));
  3142. vChild.AttributeAddUTF8('造价咨询人法定代表人或其授权人', BV('ZaoJZXFR'));
  3143. vChild.AttributeAddUTF8('造价咨询法人或其授权人身份证号', BV('ZaoJZXFRSFZH'));
  3144. end
  3145. else if FFileType = xftTB then
  3146. begin
  3147. vChild.AttributeAddUTF8('投标人', BV('TouBR'));
  3148. vChild.AttributeAddUTF8('投标人纳税识别号', BV('TouBRNSSBH'));
  3149. vChild.AttributeAddUTF8('投标人法定代表或其授权人', BV('TouBFR'));
  3150. vChild.AttributeAddUTF8('投标人法人或其授权人身份证号', BV('TouBFRSFZH'));
  3151. end;
  3152. vChild.AttributeAddUTF8('编制人', PD.Author);
  3153. vChild.AttributeAddUTF8('编制人资格证号', PD.AuthorCertificate);
  3154. vChild.AttributeAddUTF8('编制日期', Copy(DateToStr(PD.EditDate), 1, 10));
  3155. vChild.AttributeAddUTF8('复核人', PD.Auditor);
  3156. vChild.AttributeAddUTF8('复核人资格证号', PD.AuditorCertificate);
  3157. vChild.AttributeAddUTF8('复核日期', Copy(DateToStr(PD.EditDate), 1, 10));
  3158. if (FFileType = xftKZJ) or (FFileType = xftTB) then
  3159. begin
  3160. vChild.AttributeAddUTF8('审核人', BV('ShenHR'));
  3161. vChild.AttributeAddUTF8('审核人资格证号', BV('ShenHRZGZH'));
  3162. vChild.AttributeAddUTF8('审核日期', BV('ShenHRQ'));
  3163. end;
  3164. if FFileType = xftKZJ then
  3165. begin
  3166. vChild.AttributeAddUTF8('控制价总价', BV('KongZJZJ'));
  3167. vChild.AttributeAddUTF8('工期', BV('GongQ'));
  3168. vChild.AttributeAddUTF8('质量要求', BV('ZhiLYQ'));
  3169. end;
  3170. if FFileType = xftTB then
  3171. begin
  3172. vChild.AttributeAddUTF8('投标总价', FloatToStr(FAllProjectsTotalPriceSum));
  3173. vChild.AttributeAddUTF8('工期', BV('GongQ'));
  3174. vChild.AttributeAddUTF8('投标担保金额', BV('TouBDBJE'));
  3175. vChild.AttributeAddUTF8('质量承诺', BV('ZhiLCN'));
  3176. vChild.AttributeAddUTF8('投标担保方式', GetMapValue(GetMap('Map_TenderGuaranteeStyle'), BV('TouBDBFS')));
  3177. vChild.AttributeAddUTF8('造价软件品牌', Application.Title);
  3178. vChild.AttributeAddUTF8('造价软件版本', ScGetVersion);
  3179. vChild.AttributeAddUTF8('造价软件加密锁编号', 'SCDOG001002');
  3180. vChild.AttributeAddUTF8('计算机硬件信息', Get_CPU_SN + Get_HDD_SN + Get_MAC_Address);
  3181. end;
  3182. end;
  3183. end;
  3184. procedure TZTBXMLPort.AddGLGCHZMX;
  3185. var n: Integer;
  3186. vSL: TStringList;
  3187. vGLGCHZMX: TXmlNode;
  3188. begin
  3189. vSL := TStringList.Create;
  3190. try
  3191. for n := 0 to FProjectInfoCacheList.Count - 1 do
  3192. begin
  3193. vSL.Delimiter := ';';
  3194. vSL.DelimitedText := FProjectInfoCacheList[n];
  3195. vGLGCHZMX := FGLGCHZ.NodeNewUTF8('公路工程汇总明细');
  3196. vGLGCHZMX.AttributeAddUTF8('序号', vSL.Values['No']);
  3197. vGLGCHZMX.AttributeAddUTF8('标段名称', vSL.Values['Name']);
  3198. if (FFileType = xftZB) then
  3199. vGLGCHZMX.AttributeAddUTF8('金额', '0')
  3200. else
  3201. vGLGCHZMX.AttributeAddUTF8('金额', vSL.Values['TotalPrice']);
  3202. vGLGCHZMX.AttributeAddUTF8('唯一标识-Guid', vSL.Values['GUID']);
  3203. vGLGCHZMX.AttributeAddUTF8('备注', '');
  3204. end;
  3205. finally
  3206. vSL.Free;
  3207. end;
  3208. end;
  3209. procedure TZTBXMLPort.AddGLGCSJ;
  3210. begin
  3211. FGLGCSJ := FRoot.NodeNewUTF8('公路工程数据');
  3212. AddMultiProjects;
  3213. FGLGCHZ := FGLGCSJ.NodeNewUTF8('公路工程汇总');
  3214. if (self.Area = areaZheJiang) then
  3215. begin
  3216. FGLGCHZ := FGLGCHZ.NodeNewUTF8('公路工程汇总标题');
  3217. end;
  3218. AddGLGCHZMX;
  3219. end;
  3220. procedure TZTBXMLPort.AddGLBDGC(n: Integer);
  3221. begin
  3222. FGLBDGC := FGLGCSJ.NodeNewUTF8('公路标段工程');
  3223. FGLBDGC.AttributeAddUTF8('序号', IntToStr(n + 1));
  3224. FGLBDGC.AttributeAddUTF8('标段名称', ProjectManager.TenderName(PD.ID));
  3225. if (FFileType = xftZB) then
  3226. FGLBDGC.AttributeAddUTF8('金额', '0')
  3227. else
  3228. FGLBDGC.AttributeAddUTF8('金额', GetProjectTotalPrice);
  3229. FGLBDGC.AttributeAddUTF8('唯一标识-Guid', GetProjectGUID);
  3230. AddProgressForm(10, '正在导出工程量清单表...');
  3231. FGCLQDB := FGLBDGC.NodeNewUTF8('工程量清单表');
  3232. AddBillNodes;
  3233. AddProgressForm(10, '正在导出计日工信息表...');
  3234. FJRGXXB := FGLBDGC.NodeNewUTF8('计日工信息表');
  3235. AddJRG;
  3236. AddProgressForm(10, '正在导出造价汇总表...');
  3237. AddZJHZMX;
  3238. if (FFileType = xftZB) then
  3239. FGLBDGC.NodeNewUTF8('人材机汇总')
  3240. else
  3241. begin
  3242. AddProgressForm(10, '正在导出人材机汇总...');
  3243. AddProjGLJs;
  3244. end;
  3245. end;
  3246. procedure TZTBXMLPort.AddBillNodes;
  3247. var vTree: TScBillsTree;
  3248. begin
  3249. vTree := TScProject(FProject).Bills.BillsTree;
  3250. CalcBillsFees(vTree.Items[0]);
  3251. RcsvAddBillNode(TScBillsItem(vTree.Items[0].FirstChild), FGCLQDB);
  3252. end;
  3253. procedure TZTBXMLPort.RcsvAddBillNode(AItem: TScBillsItem; AXMLParent: TXmlNode);
  3254. var vBillNode, vBillMetNode: TXmlNode;
  3255. procedure AddNodeMX; // 导出
  3256. var qdzjCode, sCode, sGUID, sDataType: string;
  3257. begin
  3258. vBillNode := AXMLParent.NodeNewUTF8('工程量清单明细');
  3259. vBillNode.AttributeAddUTF8('序号', Rec(AItem, 'SerialNo'));
  3260. if Self.FileType = xftZB then
  3261. sGUID := IDtoGUID(AItem.ID) // 招标要自己造GUID
  3262. else
  3263. sGUID := Rec(AItem, 'GUIDstr'); // 投标要直接读
  3264. vBillNode.AttributeAddUTF8('GUID', sGUID);
  3265. qdzjCode := GetZJ(AItem.FullCode, AItem.Name);
  3266. sCode := AItem.Code;
  3267. if sCode = '' then
  3268. begin
  3269. sCode := qdzjCode;
  3270. end;
  3271. vBillNode.AttributeAddUTF8('清单章节', qdzjCode);
  3272. vBillNode.AttributeAddUTF8('子目长编号', sCode); // 子目长编号=子目号
  3273. vBillNode.AttributeAddUTF8('子目号', sCode);
  3274. vBillNode.AttributeAddUTF8('子目名称', AItem.Name);
  3275. vBillNode.AttributeAddUTF8('单位', Rec(AItem, 'Units'));
  3276. vBillNode.AttributeAddUTF8('数量', CheckNull(Rec(AItem, 'Quantity')));
  3277. if (FFileType = xftZB) then
  3278. begin
  3279. if AItem.Rec.IsSpecialInterim.AsBoolean = True then // 21特殊,招标也要导出单价、合价。
  3280. begin
  3281. vBillNode.AttributeAddUTF8('单价', CheckNull(Rec(AItem, 'UnitPrice')));
  3282. vBillNode.AttributeAddUTF8('合价', CheckNull(Rec(AItem, 'TotalPrice')));
  3283. end
  3284. else
  3285. begin
  3286. vBillNode.AttributeAddUTF8('单价', '0');
  3287. vBillNode.AttributeAddUTF8('合价', '0');
  3288. end;
  3289. vBillNode.AttributeAddUTF8('备注', '');
  3290. if AItem.Rec.IsSpecialInterim.AsBoolean = True then
  3291. sDataType := '21' // 专项暂定
  3292. else
  3293. begin
  3294. if AItem.IsLeaf then
  3295. begin
  3296. if SameText(AItem.Code, '102-3') then sDataType := '22' // 安全生产费
  3297. else if SameText(AItem.Code, '101-1-1') then sDataType := '23' // 工程一切险
  3298. else if SameText(AItem.Code, '101-1-2') then sDataType := '24' // 第三者责任险
  3299. else if Pos('意外伤害险', AItem.Name) > 0 then sDataType := '25'
  3300. else if Pos('工伤保险', AItem.Name) > 0 then sDataType := '26'
  3301. else if Pos('其它保险', AItem.Name) > 0 then sDataType := '27'
  3302. else sDataType := '20';
  3303. end
  3304. else
  3305. sDataType := '1'; // 父清单
  3306. end;
  3307. vBillNode.AttributeAddUTF8('数据类型', sDataType);
  3308. end
  3309. else // 投标
  3310. begin
  3311. vBillNode.AttributeAddUTF8('单价', CheckNull(Rec(AItem, 'UnitPrice')));
  3312. vBillNode.AttributeAddUTF8('合价', CheckNull(Rec(AItem, 'TotalPrice')));
  3313. vBillNode.AttributeAddUTF8('备注', Rec(AItem, 'MemoStr'));
  3314. vBillNode.AttributeAddUTF8('数据类型', Rec(AItem, 'DataType'));
  3315. end;
  3316. vBillNode.AttributeAddUTF8('人工费', FloatToStr(AItem.LabourFee));
  3317. if (self.Area = areaZheJiang) then
  3318. begin
  3319. vBillNode.AttributeAddUTF8('人工单价', '0');
  3320. vBillNode.AttributeAddUTF8('人工消耗量', '0');
  3321. end;
  3322. vBillNode.AttributeAddUTF8('主材费', FloatToStr(AItem.MaterialFee));
  3323. vBillNode.AttributeAddUTF8('辅材费', '0');
  3324. vBillNode.AttributeAddUTF8('设备费', '0');
  3325. vBillNode.AttributeAddUTF8('机械使用费', FloatToStr(AItem.MachineFee));
  3326. vBillNode.AttributeAddUTF8('措施费1', FloatToStr(AItem.OtherFee1));
  3327. vBillNode.AttributeAddUTF8('措施费2', FloatToStr(AItem.OtherFee2));
  3328. vBillNode.AttributeAddUTF8('企业管理费', FloatToStr(AItem.ManageFee));
  3329. vBillNode.AttributeAddUTF8('规费', FloatToStr(AItem.LocaleFee));
  3330. vBillNode.AttributeAddUTF8('利润', FloatToStr(AItem.Profit));
  3331. vBillNode.AttributeAddUTF8('税金', FloatToStr(AItem.Tax));
  3332. vBillNode.AttributeAddUTF8('评审清单', '0');
  3333. if (AItem.IsLeaf and AItem.HasRations and (FFileType <> xftZB)) then
  3334. begin
  3335. if (self.Area = areaZheJiang) then
  3336. begin
  3337. vBillMetNode := vBillNode.NodeNewUTF8('清单主材表');
  3338. AddBillMaterials(AItem, vBillMetNode);
  3339. end;
  3340. AddRationNodes(AItem, vBillNode);
  3341. end;
  3342. end;
  3343. begin
  3344. if AItem = nil then Exit;
  3345. AddNodeMX;
  3346. RcsvAddBillNode(TScBillsItem(AItem.FirstChild), vBillNode);
  3347. RcsvAddBillNode(TScBillsItem(AItem.NextSibling), AXMLParent);
  3348. end;
  3349. procedure TZTBXMLPort.AddRationNodes(ABillItem: TScBillsItem; ABillNode: TXmlNode);
  3350. var vRationNode: TXmlNode;
  3351. // 定额工料机
  3352. procedure AddRationGLJs(ARationID: Integer; ARationNode: TXmlNode);
  3353. var vGLJNode: TXmlNode;
  3354. sName: string;
  3355. begin
  3356. FQuery3.Close;
  3357. FQuery3.SQL.Clear;
  3358. FQuery3.SQL.Add(Format('SELECT * FROM GLJList WHERE RationID = %d', [ARationID]));
  3359. FQuery3.Open;
  3360. if FQuery3.RecordCount > 0 then
  3361. begin
  3362. if Self.Area = areaZheJiang then
  3363. sName := '人材机编号'
  3364. else
  3365. sName := '人材机标识';
  3366. FQuery3.First;
  3367. while not FQuery3.Eof do
  3368. begin
  3369. vGLJNode := ARationNode.NodeNewUTF8('定额人材机含量明细');
  3370. vGLJNode.AttributeAddUTF8(sName, FQuery3.FieldByName('GLJID').asString);
  3371. vGLJNode.AttributeAddUTF8('人材机含量', FQuery3.FieldByName('Quantity').asString);
  3372. FQuery3.Next;
  3373. end;
  3374. end;
  3375. FQuery3.Close;
  3376. end;
  3377. // 数据类型
  3378. function GetDataType: Integer;
  3379. begin
  3380. // (1=材料暂定;2=设备暂定;3=普通定额;4=不取费定额)
  3381. // 旧:若清单的专项暂定是材料,则该清单下的定额的数据类型的值全取1;若是工程设备,则取2;其他情况取3。
  3382. // 新:
  3383. Result := 3;
  3384. // if ABillItem.Rec.IsSpecialInterim.AsBoolean = True then
  3385. // iDataType := ABillItem.Rec.InterimType.AsInteger;
  3386. if FQuery2.FieldByName('CountPriceType').AsInteger = 2 then // 量价窗口添加的量价(直接手工录入添加、弹窗选择添加)
  3387. begin
  3388. if FQuery2.FieldByName('GLJMode').AsInteger <> 1 then // 量价窗口添加的量价(直接手工录入添加)
  3389. Result := 4
  3390. else // 量价窗口添加的量价(弹窗选择添加)
  3391. Result := 1
  3392. end
  3393. else if FQuery2.FieldByName('CountPriceType').AsInteger = 3 then // 设备窗口添加的设备(直接手工录入添加、弹窗选择添加)
  3394. Result := 2;
  3395. end;
  3396. var upFieldName: string;
  3397. function V(AFieldName: string): string;
  3398. begin
  3399. Result := CheckNull(FQuery2.FieldByName(AFieldName).asString);
  3400. end;
  3401. begin
  3402. FQuery2.Close;
  3403. FQuery2.SQL.Clear;
  3404. FQuery2.SQL.Add(Format('SELECT * FROM RationCalcList WHERE BillsItemID = %d Order by SerialNo', [ABillItem.ID]));
  3405. FQuery2.Open;
  3406. if FQuery2.RecordCount > 0 then
  3407. begin
  3408. FQuery2.First;
  3409. while not FQuery2.Eof do
  3410. begin
  3411. vRationNode := ABillNode.NodeNewUTF8('定额信息表');
  3412. vRationNode.AttributeAddUTF8('序号', V('SerialNo'));
  3413. if (self.Area = areaZheJiang) then
  3414. begin
  3415. vRationNode.AttributeAddUTF8('GUID', IDtoGUID(FQuery2.FieldByName('ID').asInteger));
  3416. end;
  3417. vRationNode.AttributeAddUTF8('定额编号', FQuery2.FieldByName('Code').asString);
  3418. vRationNode.AttributeAddUTF8('定额名称', FQuery2.FieldByName('Name').asString);
  3419. vRationNode.AttributeAddUTF8('单位', CheckNull(FQuery2.FieldByName('Unit').asString, '-'));
  3420. vRationNode.AttributeAddUTF8('数量', V('Quantity'));
  3421. if FQuery2.FieldByName('Type').AsInteger = 1 then
  3422. upFieldName := 'UnitDirectFee'
  3423. else
  3424. upFieldName := 'BuildingUnitPrice';
  3425. vRationNode.AttributeAddUTF8('单价',V(upFieldName));
  3426. vRationNode.AttributeAddUTF8('合价', V('BuildingFee'));
  3427. vRationNode.AttributeAddUTF8('备注', '');
  3428. vRationNode.AttributeAddUTF8('数据类型', IntToStr(GetDataType));
  3429. vRationNode.AttributeAddUTF8('人工费', V('LabourFee'));
  3430. vRationNode.AttributeAddUTF8('主材费', V('MaterialFee'));
  3431. vRationNode.AttributeAddUTF8('辅材费', '0');
  3432. vRationNode.AttributeAddUTF8('机械使用费', V('MachineFee'));
  3433. vRationNode.AttributeAddUTF8('设备费', '0');
  3434. vRationNode.AttributeAddUTF8('措施费1', V('OtherFee1'));
  3435. vRationNode.AttributeAddUTF8('措施费2', V('OtherFee2'));
  3436. vRationNode.AttributeAddUTF8('企业管理费', V('ManageFee'));
  3437. vRationNode.AttributeAddUTF8('规费', V('LocaleFee'));
  3438. vRationNode.AttributeAddUTF8('利润', V('Profit'));
  3439. vRationNode.AttributeAddUTF8('税金', V('Tax'));
  3440. AddRationGLJs(FQuery2.FieldByName('ID').AsInteger, vRationNode);
  3441. FQuery2.Next;
  3442. end;
  3443. end;
  3444. FQuery2.Close;
  3445. end;
  3446. procedure TZTBXMLPort.AddBillMaterials(ABillItem: TScBillsItem; ABillMetNode: TXmlNode);
  3447. var billMetMX: TXmlNode;
  3448. i: Integer;
  3449. sSQL: string;
  3450. begin
  3451. sSQL := 'select Code, Name, Unit, BudgetPrice, Sum(Q) as Quantity, Format(Quantity * BudgetPrice, ''0.00'') AS HJ From (' +
  3452. 'SELECT P.Code, P.name, P.Unit, G.Quantity as Q, P.BudgetPrice FROM ProjectGLJ AS P ' +
  3453. 'LEFT JOIN GLJList AS G ON G.GLJID=P.ID ' +
  3454. 'WHERE P.Type=4 AND G.BillsItemID=' + IntToStr(ABillItem.ID) +
  3455. ') Group by Code, Name, Unit, BudgetPrice';
  3456. // ') Group by Code, Name, Unit, BudgetPrice ORDER by Code';
  3457. FQuery2.Close;
  3458. FQuery2.SQL.Clear;
  3459. FQuery2.SQL.Add(sSQL);
  3460. FQuery2.Open;
  3461. if FQuery2.RecordCount > 0 then
  3462. begin
  3463. i := 0;
  3464. FQuery2.First;
  3465. while not FQuery2.Eof do
  3466. begin
  3467. Inc(i);
  3468. billMetMX := ABillMetNode.NodeNewUTF8('清单主材明细');
  3469. billMetMX.AttributeAddUTF8('序号', IntToStr(i));
  3470. billMetMX.AttributeAddUTF8('材料编码', FQuery2.FieldByName('Code').asString);
  3471. billMetMX.AttributeAddUTF8('主材名称', FQuery2.FieldByName('Name').asString);
  3472. billMetMX.AttributeAddUTF8('单位', FQuery2.FieldByName('Unit').asString);
  3473. billMetMX.AttributeAddUTF8('主材消耗量', FQuery2.FieldByName('Quantity').asString);
  3474. billMetMX.AttributeAddUTF8('单价', FQuery2.FieldByName('BudgetPrice').asString);
  3475. billMetMX.AttributeAddUTF8('合价', FQuery2.FieldByName('HJ').asString);
  3476. billMetMX.AttributeAddUTF8('备注', '');
  3477. FQuery2.Next;
  3478. end;
  3479. end;
  3480. FQuery2.Close;
  3481. end;
  3482. { // 添加计日工:接口是死的,这里写成活的,但难处理,留着备用,以防需求变更。
  3483. procedure TahXMLPort.AddJRG;
  3484. var vBill: TScBillsItem;
  3485. procedure RcsvJRG(ABill: TScBillsItem; AXMLParent: IXMLNode);
  3486. var vXMLNode: IXMLNode;
  3487. begin
  3488. if ABill = nil then Exit;
  3489. if ABill.IsLeaf then
  3490. begin
  3491. vXMLNode := AXMLParent.NodeNew('计日工信息明细');
  3492. vXMLNode.AttributeAdd('编号', ABill.Code;
  3493. vXMLNode.AttributeAdd('名称', ABill.Name;
  3494. vXMLNode.AttributeAdd('数据类型', StrToInt(AXMLParent.AttributeAdd('数据类型']) + 3;
  3495. vXMLNode.AttributeAdd('单位', Rec(ABill, 'Unit');
  3496. vXMLNode.AttributeAdd('暂定数量', '0';
  3497. vXMLNode.AttributeAdd('单价', Rec(ABill, 'Unit');
  3498. vXMLNode.AttributeAdd('合价', Rec(ABill, 'Unit');
  3499. end
  3500. else
  3501. begin
  3502. vXMLNode := AXMLParent.NodeNew('计日工信息标题');
  3503. vXMLNode.AttributeAdd('序号', Rec(ABill, 'SerialNo');
  3504. vXMLNode.AttributeAdd('名称', ABill.Name;
  3505. if Pos('劳务', ABill.Name) > 0 then
  3506. vXMLNode.AttributeAdd('数据类型', '1'
  3507. else if Pos('材料', ABill.Name) > 0 then
  3508. vXMLNode.AttributeAdd('数据类型', '2'
  3509. else if Pos('机械', ABill.Name) > 0 then
  3510. vXMLNode.AttributeAdd('数据类型', '3';
  3511. vXMLNode.AttributeAdd('合价', Rec(ABill, 'TotalPrice');
  3512. end;
  3513. RcsvJRG(TScBillsItem(ABill.FirstChild), vXMLNode);
  3514. RcsvJRG(TScBillsItem(ABill.NextSibling), AXMLParent);
  3515. end;
  3516. begin
  3517. vBill := BillNode(idDayWork);
  3518. RcsvJRG(TScBillsItem(vBill.FirstChild), FJRGXXB);
  3519. end; }
  3520. // 添加计日工:接口是死的,写成活的难处理,这里也跟着写死。
  3521. procedure TZTBXMLPort.AddJRG;
  3522. var vJRG, vKind, vChild: TScBillsItem;
  3523. i, j: Integer;
  3524. vJRGNode, vKindNode, vChildNode: TXmlNode;
  3525. begin
  3526. vJRG := BillNode(idDayWork);
  3527. vJRGNode := FJRGXXB.NodeNewUTF8('计日工信息标题');
  3528. vJRGNode.AttributeAddUTF8('序号', Rec(vJRG, 'SerialNo'));
  3529. vJRGNode.AttributeAddUTF8('名称', vJRG.Name);
  3530. vJRGNode.AttributeAddUTF8('数据类型', '0');
  3531. if (FFileType = xftZB) then
  3532. vJRGNode.AttributeAddUTF8('合价', '0')
  3533. else
  3534. vJRGNode.AttributeAddUTF8('合价', Rec(vJRG, 'TotalPrice'));
  3535. for i := 0 to vJRG.ChildCount - 1 do
  3536. begin
  3537. vKind := TScBillsItem(vJRG.ChildNodes[i]);
  3538. vKindNode := FJRGXXB.NodeNewUTF8('计日工信息标题');
  3539. vKindNode.AttributeAddUTF8('序号', Rec(vKind, 'SerialNo'));
  3540. vKindNode.AttributeAddUTF8('名称', vKind.Name);
  3541. if Pos('劳务', vKind.Name) > 0 then
  3542. vKindNode.AttributeAddUTF8('数据类型', '1')
  3543. else if Pos('材料', vKind.Name) > 0 then
  3544. vKindNode.AttributeAddUTF8('数据类型', '2')
  3545. else if Pos('机械', vKind.Name) > 0 then
  3546. vKindNode.AttributeAddUTF8('数据类型', '3');
  3547. if (FFileType = xftZB) then
  3548. vKindNode.AttributeAddUTF8('合价', '0')
  3549. else
  3550. vKindNode.AttributeAddUTF8('合价', Rec(vKind, 'TotalPrice'));
  3551. for j := 0 to vKind.ChildCount - 1 do
  3552. begin
  3553. vChild := TScBillsItem(vKind.ChildNodes[j]);
  3554. vChildNode := vKindNode.NodeNewUTF8('计日工信息明细');
  3555. vChildNode.AttributeAddUTF8('编号', vChild.Code);
  3556. vChildNode.AttributeAddUTF8('名称', vChild.Name);
  3557. vChildNode.AttributeAddUTF8('数据类型', IntToStr(StrToInt(vKindNode.AttributeValueByNameUTF8['数据类型']) + 3));
  3558. vChildNode.AttributeAddUTF8('单位', Rec(vChild, 'Units'));
  3559. vChildNode.AttributeAddUTF8('暂定数量', Rec(vChild, 'Quantity'));
  3560. if (FFileType = xftZB) then
  3561. begin
  3562. vChildNode.AttributeAddUTF8('单价', '0');
  3563. vChildNode.AttributeAddUTF8('合价', '0');
  3564. end
  3565. else
  3566. begin
  3567. vChildNode.AttributeAddUTF8('单价', Rec(vChild, 'UnitPrice'));
  3568. vChildNode.AttributeAddUTF8('合价', Rec(vChild, 'TotalPrice'));
  3569. end;
  3570. end;
  3571. end;
  3572. end;
  3573. procedure TZTBXMLPort.AddZJHZMX;
  3574. var sSQL, sZC, sLB: string;
  3575. vZJHZB, vZJHZMX: TXmlNode;
  3576. n: Integer;
  3577. begin
  3578. vZJHZB := FGLBDGC.NodeNewUTF8('造价汇总表');
  3579. sSQL :=
  3580. 'select ID, SerialNo, Name, TotalPrice, MemoStr ' +
  3581. 'from Bills where (ParentID = -1) or (ParentID = 1) order by ParentID, SerialNo';
  3582. FQuery1.Close;
  3583. FQuery1.SQL.Text := sSQL;
  3584. FQuery1.Open;
  3585. FQuery1.First;
  3586. n := 0;
  3587. while not FQuery1.Eof do
  3588. begin
  3589. vZJHZMX := vZJHZB.NodeNewUTF8('造价汇总明细');
  3590. GetZCLB(FQuery1.FieldByName('Name').AsString, sZC, sLB);
  3591. if (self.Area = areaZheJiang) then
  3592. begin
  3593. if (sZC <> '') then
  3594. sLB := sZC;
  3595. end;
  3596. Inc(n);
  3597. vZJHZMX.AttributeAddUTF8('序号', IntToStr(n));
  3598. vZJHZMX.AttributeAddUTF8('章次', sZC);
  3599. vZJHZMX.AttributeAddUTF8('名称', FQuery1.FieldByName('Name').AsString);
  3600. if (FFileType = xftZB) and (not (FQuery1.FieldByName('ID').AsInteger in [idSpecialInterimSum, idReserve])) then
  3601. vZJHZMX.AttributeAddUTF8('金额', '0')
  3602. else
  3603. vZJHZMX.AttributeAddUTF8('金额', FloatToStr(ScRoundTo(FQuery1.FieldByName('TotalPrice').AsFloat, -2)));
  3604. vZJHZMX.AttributeAddUTF8('类别', sLB);
  3605. vZJHZMX.AttributeAddUTF8('备注', FQuery1.FieldByName('MemoStr').AsString);
  3606. FQuery1.Next;
  3607. end;
  3608. FQuery1.Close;
  3609. end;
  3610. {-------------------------------------------------------------------------------
  3611. 项目工料机:
  3612. 纵横:1=人工 2=混凝土 4=材料 6=设备 8=机械 9=定额基价
  3613. 池州:1=人工 2=材料 3=机械 4=设备 5=配比 6=机械台班 7=主材
  3614. 规则不同,所以需要转换。【Provider】0=乙供;1=甲供
  3615. BudgetPrice有太长的小数尾巴,即使Round(BudgetPrice, 2)也去不掉。
  3616. 用Round(BudgetPrice * 1, 2)搞定。
  3617. -------------------------------------------------------------------------------}
  3618. procedure TZTBXMLPort.AddProjGLJs;
  3619. var sSQL: string;
  3620. begin
  3621. if (self.Area = areaZheJiang) then
  3622. begin
  3623. sSQL :=
  3624. 'Select Code as 人材机编号, Name as 人材机名称, Specs as 规格型号, Unit as 单位, ' +
  3625. 'Round(Amount, 2) as 数量, Round(BudgetPrice * 1, 2) as 单价, ' +
  3626. 'Switch(Type=2,''5'', Type=4, ''2'', Type=6, ''4'', Type=8, ''6'', True, Type) as 人材机类别, ' +
  3627. 'IIF(Main=True, 1, 0) as 是否主要材料, ''0'' as 是否甲供, Remark as 备注 ' +
  3628. 'from ProjectGLJ where Type<>9';
  3629. end
  3630. else
  3631. begin
  3632. sSQL :=
  3633. 'Select ID as 人材机标识, Code as 人材机编号, Name as 人材机名称, Specs as 规格型号, Unit as 单位, ' +
  3634. 'Round(Amount, 2) as 数量, Round(BudgetPrice * 1, 2) as 单价, ' +
  3635. 'Switch(Type=2,''5'', Type=4, ''2'', Type=6, ''4'', Type=8, ''6'', True, Type) as 人材机类别, ' +
  3636. 'IIF(Main=True, 1, 0) as 是否主要材料, ''0'' as 是否甲供, ''0'' as 是否暂估, Remark as 备注 ' +
  3637. 'from ProjectGLJ where Type<>9';
  3638. end;
  3639. AddTabToXML(FQuery1, sSQL, FGLBDGC, '人材机汇总', '人材机汇总明细表');
  3640. end;
  3641. procedure TZTBXMLPort.GetZCLB(ABillName: string; var ACapter, AType: string);
  3642. const
  3643. // 这里取最小关键字,用于匹配清单名称的变化。
  3644. G_Names: array [0..12, 0..2] of string = (
  3645. ('第100章至700章清单', '', '1'),
  3646. ('已包含在清单合计中的材料', '', '2'),
  3647. ('清单合计减去材料', '', '3'),
  3648. ('计日工合计', '', '4'),
  3649. ('暂列金额', '', '5'),
  3650. ('投标报价', '', '6'),
  3651. ('第100章 ', '100', '11'), // 我们软件"章"字后面有2个空格!
  3652. ('第200章 ', '200', '12'),
  3653. ('第300章 ', '300', '13'),
  3654. ('第400章 ', '400', '14'),
  3655. ('第500章 ', '500', '15'),
  3656. ('第600章 ', '600', '16'),
  3657. ('第700章 ', '700', '17'));
  3658. var i, j: Integer;
  3659. begin
  3660. {------------------灵异事件:------------------------------------------------
  3661. for i := Low(G_Names) to High(G_Names) do 这句的 i 永远从 13 开始,递减到 1 结束。
  3662. ①换成下面两句依然不行:
  3663. for I := 0 to Length(G_Names) - 1 do
  3664. for i := 0 to 12 do
  3665. ②将二维数组换成3个常量数组,问题依旧:
  3666. G_Names: array [0..12] of string = ('第100章至第700章','已包含在...', ...);
  3667. G_Capters: array [0..12] of string = ('1', '', ...);
  3668. G_Types: array [0..12] of string = ('1', '2', ...);
  3669. ③ 将以上常量数组移到方法外面问题依旧。
  3670. ④ 改变数组类型,问题依旧: G_Names: array [0..12] of ShortString、WideString。
  3671. ⑤将该方法从Procedure换成function,问题依旧。
  3672. 最后,在循环体内加上一句 MessageHint(IntToStr(i)); 问题消失! i 终于从 0 开始了!
  3673. 所以,下面加个变量 j 转接一下 i 以解决该问题,虽然看上去比较奇怪...
  3674. -----------------------------------------------------------------------------}
  3675. for i := Low(G_Names) to High(G_Names) do
  3676. begin
  3677. if Pos(G_Names[i, 0], ABillName) > 0 then
  3678. begin
  3679. // MessageHint(IntToStr(i));
  3680. j := i + 1;
  3681. ACapter := G_Names[j - 1, 1];
  3682. AType := G_Names[j - 1, 2];
  3683. Break;
  3684. end;
  3685. end;
  3686. end;
  3687. // 通过【投标信息】和【公路工程汇总】下的所有字段内容计算哈希值。
  3688. function TZTBXMLPort.GetDataCheckCode: string;
  3689. var s: string;
  3690. vNode: TXmlNode;
  3691. i, n: Integer;
  3692. begin
  3693. s := '';
  3694. vNode := FZTBXX.Elements[0]; // <投标信息>
  3695. for i := 0 to vNode.AttributeCount - 1 do
  3696. begin
  3697. s := s + Utf8ToAnsi(vNode.AttributeValue[i]);
  3698. end;
  3699. for n := 0 to FGLGCHZ.ElementCount - 1 do
  3700. begin
  3701. vNode := FGLGCHZ.Elements[n]; // <公路工程汇总明细>
  3702. for i := 0 to vNode.AttributeCount - 1 do
  3703. begin
  3704. s := s + Utf8ToAnsi(vNode.AttributeValue[i]);
  3705. end;
  3706. end;
  3707. s := EncryptStringByMD5(s);
  3708. Result := s;
  3709. end;
  3710. {TkmXMLPort}
  3711. procedure TkmXMLPort.AddBQTable;
  3712. var vBillTabNode, vBillItem, vBQPANode, vBQTitle: TXmlNode;
  3713. j: Integer;
  3714. sUnit, sZJ, sJ: string;
  3715. procedure AddBQTitle;
  3716. begin
  3717. vBQTitle := vBillTabNode.NodeNewUTF8('BQTitle');
  3718. vBQTitle.AttributeAddUTF8('BQTitleID', FQuery1.FieldByName('BQItemID').AsString);
  3719. vBQTitle.AttributeAddUTF8('Name', FQuery1.FieldByName('Name').AsString);
  3720. vBQTitle.AttributeAddUTF8('Remark', FQuery1.FieldByName('Remark').AsString);
  3721. vBQTitle.AttributeAddUTF8('Sequence', FQuery1.FieldByName('Sequence').AsString);
  3722. sZJ := GetZJByName(vBQTitle.AttributeValueByNameUTF8['Name']);
  3723. end;
  3724. procedure AddBQItem;
  3725. procedure AddExtendFields(ABillID: Integer);
  3726. var k: Integer;
  3727. begin
  3728. FQuery2.Close;
  3729. FQuery2.SQL.Clear;
  3730. FQuery2.SQL.Text :=
  3731. 'select Format(LaborRate1/b.Quantity,''0.00'') as LaborRate,' +
  3732. 'Format(MaterialRate1/b.Quantity,''0.00'') as MaterialRate,' +
  3733. 'Format(MachineRate1/b.Quantity,''0.00'') as MachineRate,' +
  3734. 'Format(OtherRate1/b.Quantity,''0.00'') as OtherRate,' +
  3735. 'Format(OverheadRate1/b.Quantity,''0.00'') as OverheadRate,' +
  3736. 'Format(RegulateRate1/b.Quantity,''0.00'') as RegulateRate,' +
  3737. 'Format(ProfitRate1/b.Quantity,''0.00'') as ProfitRate,' +
  3738. 'Format(TaxRate1/b.Quantity,''0.00'') as TaxRate from ' +
  3739. '(SELECT BillsItemID, Sum(TenderLabourFee) as LaborRate1,' +
  3740. 'Sum(TenderMaterialFee) as MaterialRate1,' +
  3741. 'Sum(TenderMachineFee) as MachineRate1, Sum(TenderOtherDirectFee) as OtherRate1,' +
  3742. 'Sum(TenderManageFee) as OverheadRate1, Sum(TenderLocaleFee) as RegulateRate1,' +
  3743. 'Sum(TenderProfit) as ProfitRate1, Sum(TenderTax) as TaxRate1 ' +
  3744. 'from RationCalclist where BillsItemID=' +
  3745. IntToStr(ABillID) + ' group by BillsItemID) as j,Bills as b ' +
  3746. 'where j.BillsItemID=b.ID';
  3747. FQuery2.Open;
  3748. if FQuery2.RecordCount > 0 then
  3749. begin
  3750. for k := 0 to FQuery2.FieldCount - 1 do
  3751. vBillItem.AttributeAddUTF8(FQuery2.Fields[k].FieldName, FQuery2.Fields[k].AsString);
  3752. end;
  3753. FQuery2.Close;
  3754. end;
  3755. var i: Integer;
  3756. begin
  3757. vBillItem := vBQTitle.NodeNewUTF8('BQItem');
  3758. for i := 0 to FQuery1.FieldCount - 2 do
  3759. begin
  3760. if SameText(FQuery1.Fields[i].FieldName, 'Unit') then
  3761. vBillItem.AttributeAddUTF8(FQuery1.Fields[i].FieldName, ChangeUnit_m3(FQuery1.Fields[i].AsString))
  3762. else if SameText(FQuery1.Fields[i].FieldName, 'ZJID') then
  3763. vBillItem.AttributeAddUTF8(FQuery1.Fields[i].FieldName, sZJ)
  3764. else
  3765. vBillItem.AttributeAddUTF8(FQuery1.Fields[i].FieldName, FQuery1.Fields[i].AsString);
  3766. end;
  3767. if (FQuery1.FieldByName('IsLeaf').AsBoolean = True) then
  3768. begin
  3769. AddProgressForm(0, FSubHint2 + ':规费利润税金等');
  3770. AddExtendFields(StrToInt(vBillItem.AttributeValueByNameUTF8['BQItemID']));
  3771. end;
  3772. if (FFileType = xftTB) and (FQuery1.FieldByName('IsLeaf').AsBoolean = True) then
  3773. begin
  3774. AddProgressForm(0, FSubHint2 + ':定额、工料机');
  3775. AddNorms(vBillItem);
  3776. AddProgressForm(0, FSubHint2 + ':汇总分析');
  3777. AddBQPriceAnalysisItem(vBillItem);
  3778. end;
  3779. end;
  3780. begin
  3781. vBillTabNode := FUPNode.NodeNewUTF8('BQTable');
  3782. FQuery1.Close;
  3783. FQuery1.SQL.Clear;
  3784. FQuery1.SQL.Text :=
  3785. 'Select ID as BQItemID, FullCode as Code, Name, ''100'' as ZJID, Units as Unit, Quantity, ' +
  3786. 'TenderUnitPrice as Rate, TenderTotalPrice as Total, MemoStr as Remark, ' +
  3787. 'SerialNo as Sequence, ''False'' as IsPriceCeiling, IsLeaf ' +
  3788. 'from Bills where ID > 1 and SerialNo <= ' + IntToStr(FSN_BillsEnd) + ' order by SerialNo';
  3789. FQuery1.Open;
  3790. j := 0;
  3791. FQuery1.First;
  3792. while not FQuery1.Eof do
  3793. begin
  3794. if FQuery1.FieldByName('Code').AsString = '' then
  3795. AddBQTitle
  3796. else
  3797. AddBQItem;
  3798. Inc(j);
  3799. sJ := '第 ' + IntToStr(j) + ' 条';
  3800. FSubHint2 := FSubHint + sJ;
  3801. AddProgressForm(0, FSubHint2);
  3802. FQuery1.Next;
  3803. end;
  3804. FQuery1.Close;
  3805. end;
  3806. procedure TkmXMLPort.AddNorms(ARoot: TXmlNode); // 定额
  3807. var sBillID: string;
  3808. vRNode, vRItemNode: TXmlNode;
  3809. i: Integer;
  3810. begin
  3811. sBillID := ARoot.AttributeValueByNameUTF8['BQItemID'];
  3812. FQuery2.Close;
  3813. FQuery2.SQL.Clear;
  3814. FQuery2.SQL.Text := Format(
  3815. 'Select ID as NormItemID, Code, Name, Unit, Quantity, ' +
  3816. 'Format(TenderLabourFee/Quantity,''0.00'') as LaborRate, ' +
  3817. 'Format(TenderMaterialFee/Quantity,''0.00'') as MaterialRate, ' +
  3818. 'Format(TenderMachineFee/Quantity,''0.00'') as MachineRate, ' +
  3819. 'Format(TenderManageFee/Quantity,''0.00'') as OverheadRate, ' +
  3820. 'Format(TenderLocaleFee/Quantity,''0.00'') as RegulateRate,' +
  3821. 'Format(TenderProfit/Quantity,''0.00'') as ProfitRate, ' +
  3822. 'Format(TenderTax/Quantity,''0.00'') as TaxRate, ' +
  3823. 'Format(TenderOtherDirectFee/Quantity,''0.00'') as OtherRate, ' +
  3824. 'Format(TenderBuildingFee/Quantity,''0.00'') as Rate, ' +
  3825. 'TenderBuildingFee as Total, '''' as Remark, ' +
  3826. 'Code as StandardCode,' +
  3827. '''%s'' as NormLibrary, %d as FeeFileID, ' +
  3828. 'SerialNo as Sequence, ''False'' as IsPriceCeiling ' +
  3829. 'from RationCalcList where BillsItemID = %s',
  3830. [FRationLibCode, FFeeRateFile.Lib.ID, sBillID]);
  3831. FQuery2.Open;
  3832. if FQuery2.RecordCount = 0 then Exit;
  3833. vRNode := ARoot.NodeNewUTF8('Norms');
  3834. FQuery2.First;
  3835. while not FQuery2.Eof do
  3836. begin
  3837. vRItemNode := vRNode.NodeNewUTF8('NormsItem');
  3838. for i := 0 to FQuery2.FieldCount - 1 do
  3839. begin
  3840. if SameText(FQuery2.Fields[i].FieldName, 'Unit') then
  3841. vRItemNode.AttributeAddUTF8(FQuery2.Fields[i].FieldName, ChangeUnit_m3(FQuery2.Fields[i].AsString))
  3842. else
  3843. vRItemNode.AttributeAddUTF8(FQuery2.Fields[i].FieldName, FQuery2.Fields[i].AsString);
  3844. end;
  3845. AddNormResUsageItem(vRItemNode);
  3846. FQuery2.Next;
  3847. end;
  3848. FQuery2.Close;
  3849. end;
  3850. // 数量单价 云南接口中没有提到这个,暂时不用。
  3851. procedure TkmXMLPort.AddQuantityUnitPrice(ARoot: TXmlNode);
  3852. var sBillID, sSQL: string;
  3853. begin
  3854. sBillID := ARoot.AttributeValueByNameUTF8['BQItemID'];
  3855. sSQL := Format(
  3856. 'Select Name, Code, Unit, Quantity, ' +
  3857. 'UnitDirectFee as Rate, BuildingFee as Total, ' +
  3858. 'SerialNo as Sequence ' +
  3859. 'from RationCalcList where BillsItemID = %s and Type=1', [sBillID]);
  3860. AddTabToXML(FQuery2, sSQL, ARoot, '', 'QuantityUnitPriceItem');
  3861. end;
  3862. {-------------------------------------------------------------------------------
  3863. 清单子目(所有定额)工料机汇总
  3864. 对每条清单子目下的所有定额的工料机进行汇总,除以清单工程量
  3865. -------------------------------------------------------------------------------}
  3866. procedure TkmXMLPort.AddBQPriceAnalysisItem(ARoot: TXmlNode);
  3867. var sBillID, sSQL: string;
  3868. begin
  3869. sBillID := ARoot.AttributeValueByNameUTF8['BQItemID'];
  3870. sSQL := Format(
  3871. 'select Code, Specs as XHGG, Name, Unit, Format(Qty2,''0.00'') as Quantity, ' +
  3872. 'Format(TenderPrice,''0.00'') as Rate, ' +
  3873. 'Format(Qty2*TenderPrice,''0.00'') as Total, Code as Sequence ' +
  3874. 'from (select g.GLJID, g.Qty / b.Quantity as Qty2 from ' +
  3875. '(select BillsItemID,GLJID, Sum(TenderQuantity*RationItemQuantity) as Qty ' +
  3876. 'from GLJList where BillsItemID=%s and Code <> 1999 and Quantity <> 0 ' +
  3877. 'Group by BillsItemID,GLJID) as g, Bills as b ' +
  3878. 'where g.BillsItemID=b.ID) as j,ProjectGLJ as p ' +
  3879. 'where j.GLJID=p.ID order by Code', [sBillID]);
  3880. AddTabToXML(FQuery2, sSQL, ARoot, '', 'BQPriceAnalysisItem');
  3881. end;
  3882. procedure TkmXMLPort.AddNormResUsageItem(ARoot: TXmlNode);
  3883. var sRID, sSQL: string;
  3884. begin
  3885. sRID := ARoot.AttributeValueByNameUTF8['NormItemID'];
  3886. sSQL := Format(
  3887. 'Select RGLJID as [ResourceID], Quantity as [Usage] ' +
  3888. 'from GLJList where RationID = %s', [sRID]);
  3889. AddTabToXML(FQuery3, sSQL, ARoot, '', 'NormResUsageItem');
  3890. end;
  3891. {-------------------------------------------------------------------------------
  3892. 计日工:有树结构
  3893. 201 水泥 0.000
  3894. 201-1 32.5级水泥 t 280.000 270.79
  3895. 201-2 42.5级水泥 t 125.000 625.77
  3896. 201-3 52.5级水泥 t 75.000 60.28
  3897. 筑龙:【CostKind】1 劳务 2 材料 3 施工机械
  3898. 纵横:5 劳务 6 材料 7 施工机械
  3899. --------------------------------------------------------------------------------}
  3900. procedure TkmXMLPort.AddDayWorkTable;
  3901. var sSQL, sCK: string;
  3902. iSNFrom, iSNTo, iSN6, iSN7: Integer;
  3903. vDWTab, vDWTitle, vDWItem: TXmlNode;
  3904. procedure AddDayWorkTitle;
  3905. begin
  3906. vDWTitle := vDWTab.NodeNewUTF8('DayWorkTitle');
  3907. vDWTitle.AttributeAddUTF8('DayWorkTitleID', FQuery1.FieldByName('DayWorkItemID').AsString);
  3908. vDWTitle.AttributeAddUTF8('Code', FQuery1.FieldByName('Code').AsString);
  3909. vDWTitle.AttributeAddUTF8('Name', FQuery1.FieldByName('Name').AsString);
  3910. vDWTitle.AttributeAddUTF8('Total', FQuery1.FieldByName('Total').AsString);
  3911. vDWTitle.AttributeAddUTF8('CostKind', FQuery1.FieldByName('CostKind').AsString);
  3912. vDWTitle.AttributeAddUTF8('Remark', FQuery1.FieldByName('Remark').AsString);
  3913. vDWTitle.AttributeAddUTF8('Sequence', FQuery1.FieldByName('Sequence').AsString);
  3914. end;
  3915. procedure AddDayWorkItem;
  3916. var i: Integer;
  3917. begin
  3918. if FQuery1.FieldByName('ParentID').AsInteger in [5, 6, 7] then
  3919. vDWItem := vDWTab.NodeNewUTF8('DayWorkItem')
  3920. else
  3921. vDWItem := vDWTitle.NodeNewUTF8('DayWorkItem');
  3922. for i := 0 to FQuery1.FieldCount - 3 do
  3923. begin
  3924. if SameText(FQuery1.Fields[i].FieldName, 'Unit') then
  3925. vDWItem.AttributeAddUTF8(FQuery1.Fields[i].FieldName, ChangeUnit_m3(FQuery1.Fields[i].AsString))
  3926. else
  3927. vDWItem.AttributeAddUTF8(FQuery1.Fields[i].FieldName, FQuery1.Fields[i].AsString);
  3928. end;
  3929. end;
  3930. begin
  3931. if TScProject(FProject).Bills.BillsTree[idDayWork].ChildCount = 0 then Exit;
  3932. iSNFrom := IDtoSerialNo(idDayWorkLabour) + 1;
  3933. if iSNFrom = 1 then Exit; // 缺少“劳务”
  3934. iSN6 := IDtoSerialNo(idDayWorkMaterial);
  3935. if iSN6 = 0 then Exit; // 缺少“材料”
  3936. iSN7 := IDtoSerialNo(idDayWorkMachine);
  3937. if iSN7 = 0 then Exit; // 缺少“机械”
  3938. iSNTo := IDtoSerialNo(8) - 1;
  3939. vDWTab := FUPNode.NodeNewUTF8('DayWorkTable');
  3940. sCK := Format('Switch(SerialNo Between %d And %d, ''1'',' +
  3941. 'SerialNo Between %d And %d, ''2'', SerialNo Between %d And %d, ''3''' +
  3942. ') AS CostKind', [iSNFrom, iSN6, iSN6, iSN7, iSN7, iSNTo]);
  3943. sSQL := Format(
  3944. 'Select ID as DayWorkItemID, Code, Name, Units as Unit, Quantity, ' +
  3945. 'TenderUnitPrice as Rate, TenderTotalPrice as Total, %s, ' +
  3946. 'MemoStr as Remark, SerialNo as Sequence, IsLeaf, ParentID ' +
  3947. 'from Bills where (SerialNo between %d and %d) and ' +
  3948. '(ID not between %d and %d) order by SerialNo', [sCK, iSNFrom, iSNTo, 5, 7]);
  3949. FQuery1.Close;
  3950. FQuery1.SQL.Clear;
  3951. FQuery1.SQL.Text := sSQL;
  3952. FQuery1.Open;
  3953. FQuery1.First;
  3954. while not FQuery1.Eof do
  3955. begin
  3956. if FQuery1.FieldByName('IsLeaf').AsBoolean = False then
  3957. AddDayWorkTitle
  3958. else
  3959. AddDayWorkItem;
  3960. FQuery1.Next;
  3961. end;
  3962. FQuery1.Close;
  3963. end;
  3964. {-------------------------------------------------------------------------------
  3965. 材料:单价文件GLJList表
  3966. 纵横:1 人工 2 混凝土 3 材料 4 机械 5 定额基价
  3967. 筑龙:1 人工 2 材料 3 机械台班
  3968. -------------------------------------------------------------------------------}
  3969. procedure TkmXMLPort.AddMaterialTable;
  3970. var sSQL: string;
  3971. vQry: TADOQuery;
  3972. begin
  3973. vQry := TADOQuery.Create(nil);
  3974. try
  3975. vQry.Connection := FUnitPriceFile.Lib.Connection;
  3976. sSQL := 'Select Code as ItemID, Code, Name, Specs as Spec, Unit, ' +
  3977. 'Price as Rate, Switch(Type=3,''2'',Type=4,''3'',true,Type) as CostKind, ' +
  3978. ''''' as Remark, Code as Sequence From GLJList Order by Code';
  3979. AddTabToXML(vQry, sSQL, FUPNode, 'MaterialTable', 'MaterialItem');
  3980. finally
  3981. vQry.Close;
  3982. vQry.Free;
  3983. end;
  3984. end;
  3985. {-------------------------------------------------------------------------------
  3986. 项目工料机:
  3987. 纵横:1=人工 2=混凝土 3=材料 4=机械
  3988. 筑龙:1=人工 2=材料 3=机械 4=设备 5=主材
  3989. 规则不同,所以需要转换。【Provider】0=乙供;1=甲供
  3990. BudgetPrice有太长的小数尾巴,即使Round(BudgetPrice, 2)也去不掉。
  3991. 用Round(BudgetPrice * 1, 2)搞定。
  3992. -------------------------------------------------------------------------------}
  3993. procedure TkmXMLPort.AddResource;
  3994. var sSQL: string;
  3995. begin
  3996. sSQL :=
  3997. 'Select ID as ResourceID, Code, Name, Specs as Spec, Unit,' +
  3998. 'Round(TenderPrice * 1, 2) as Rate, Round(TenderAmount, 2) as Quantity, ' +
  3999. 'Round(TenderPrice * TenderAmount, 2) as Total, '+
  4000. 'Switch(Type=3 and Main=False,''9'', Type=3 and Main=True, ''2'', Type=4 and Main=True, ''3'', True, Type) as CostKind, ' +
  4001. 'Remark, '''' as ProducingArea, '''' as Supplier, '+
  4002. ''''' as Provider, Code as StandardCode, LibID as NormLibrary ' +
  4003. 'from ProjectGLJ';
  4004. AddTabToXML(FQuery1, sSQL, FUPNode, 'Resource', 'ResourceItem');
  4005. end;
  4006. procedure TkmXMLPort.AddMaterialProvisionalPriceTable;
  4007. var sSQL: string;
  4008. begin
  4009. sSQL :=
  4010. 'Select ID as ItemID, FullCode as Code, Name, Units as Unit, Quantity, TenderUnitPrice as Rate, ' +
  4011. 'TenderTotalPrice as Total, MemoStr as Remark, SerialNo as Sequence ' +
  4012. 'from Bills where InterimType=1';
  4013. AddTabToXML(FQuery1, sSQL, FUPNode, 'MaterialProvisionalPriceTable', 'MaterialProvisionalPriceItem');
  4014. end;
  4015. procedure TkmXMLPort.AddProjEquipmentPriceTable;
  4016. var sSQL: string;
  4017. begin
  4018. sSQL :=
  4019. 'Select ID as ItemID, FullCode as Code, Name, Units as Unit, Quantity, TenderUnitPrice as Rate, ' +
  4020. 'TenderTotalPrice as Total, MemoStr as Remark, SerialNo as Sequence ' +
  4021. 'from Bills where InterimType=2';
  4022. AddTabToXML(FQuery1, sSQL, FUPNode, 'ProjEquipmentPriceTable', 'ProjEquipmentPriceItem');
  4023. end;
  4024. procedure TkmXMLPort.AddProjProvisionalPriceTable;
  4025. var sSQL: string;
  4026. begin
  4027. sSQL :=
  4028. 'Select ID as ItemID, FullCode as Code, Name, '''' as Content, ' +
  4029. 'TenderTotalPrice as Price, MemoStr as Remark, SerialNo as Sequence ' +
  4030. 'from Bills where InterimType=3';
  4031. AddTabToXML(FQuery1, sSQL, FUPNode, 'ProjProvisionalPriceTable', 'ProjProvisionalPriceItem');
  4032. end;
  4033. {-------------------------------------------------------------------------------
  4034. 交通机电设施备品备件:
  4035. 公路工程工程量清单计量规范2010-05-18,P27有这张表,表里面的数据从清单第1300章读取。
  4036. 以上信息是王晶致电云南省交通运输厅工程造价管理局咨询的。
  4037. -------------------------------------------------------------------------------}
  4038. procedure TkmXMLPort.AddElectEquipmentTable;
  4039. var vEETable, vNode: TXmlNode;
  4040. i: Integer;
  4041. begin
  4042. vEETable := FUPNode.NodeNewUTF8('ElectEquipmentTable');
  4043. FQuery1.Close;
  4044. FQuery1.SQL.Clear;
  4045. FQuery1.SQL.Text := Format(
  4046. 'Select ID as ItemID, Name, '''' as Spec, Units as Unit, TenderUnitPrice as Rate, ' +
  4047. 'Quantity, TenderTotalPrice as Total, ChapterID as CostKind, ' +
  4048. 'MemoStr as Remark, SerialNo as Sequence ' +
  4049. 'from Bills where (SerialNo >= %d) and (SerialNo < %d) and (IsLeaf=True) order by SerialNo',
  4050. [FSN_EEBegin, FSN_ID2]);
  4051. FQuery1.Open;
  4052. FQuery1.First;
  4053. while not FQuery1.Eof do
  4054. begin
  4055. vNode := vEETable.NodeNewUTF8('ElectEquipmentItem');
  4056. for i := 0 to FQuery1.FieldCount - 1 do
  4057. begin
  4058. if SameText(FQuery1.Fields[i].FieldName, 'Unit') then
  4059. vNode.AttributeAddUTF8(FQuery1.Fields[i].FieldName, ChangeUnit_m3(FQuery1.Fields[i].AsString))
  4060. else if SameText(FQuery1.Fields[i].FieldName, 'CostKind') then
  4061. vNode.AttributeAddUTF8(FQuery1.Fields[i].FieldName, GetEECostKind(FQuery1.Fields[i].AsInteger))
  4062. else
  4063. vNode.AttributeAddUTF8(FQuery1.Fields[i].FieldName, FQuery1.Fields[i].AsString);
  4064. end;
  4065. FQuery1.Next;
  4066. end;
  4067. FQuery1.Close;
  4068. end;
  4069. procedure TkmXMLPort.AddDetail;
  4070. procedure AddTenderInfo;
  4071. var vNode: TXmlNode;
  4072. begin
  4073. vNode := FRoot.NodeNewUTF8('TenderInfo');
  4074. vNode.AttributeAddUTF8('Tenderer', '');
  4075. vNode.AttributeAddUTF8('Total', '');
  4076. vNode.AttributeAddUTF8('Duration', '');
  4077. vNode.AttributeAddUTF8('NoncompetitiveCost', '');
  4078. vNode.AttributeAddUTF8('Deposit', '');
  4079. vNode.AttributeAddUTF8('SuretyKind', '');
  4080. vNode.AttributeAddUTF8('QualityPromise', '');
  4081. end;
  4082. procedure AddProjectAddInfo;
  4083. var vNode, vItem: TXmlNode;
  4084. i: Integer;
  4085. begin
  4086. vNode := FRoot.NodeNewUTF8('ProjectAddInfo');
  4087. end;
  4088. procedure AddSingleProject;
  4089. begin
  4090. FSPNode := FRoot.NodeNewUTF8('SingleProject');
  4091. FSPNode.AttributeAddUTF8('ProjectID', '0');
  4092. FSPNode.AttributeAddUTF8('Code', '0');
  4093. FSPNode.AttributeAddUTF8('Name', PD.BuildProjectName);
  4094. FSPNode.AttributeAddUTF8('Total', '0');
  4095. FSPNode.AttributeAddUTF8('Sequence', '0');
  4096. end;
  4097. procedure AddUnitProject;
  4098. var
  4099. iProjectID: Integer;
  4100. strName: string;
  4101. PropRec: TsdDataRecord;
  4102. procedure GetProjInfo(AFileName: string);
  4103. var
  4104. Rec: TsdDataRecord;
  4105. begin
  4106. Rec := ProjectManager.TendersRec(AFileName);
  4107. iProjectID := Rec.ValueByName('ID').AsInteger;
  4108. strName := Rec.ValueByName('Name').AsString;
  4109. end;
  4110. function RecV(AField: string): string;
  4111. begin
  4112. Result := PropRec.ValueByName(AField).AsString;
  4113. end;
  4114. begin
  4115. GetProjInfo(PD.FileName);
  4116. PropRec := ProjectManager.PropertiesRec(iProjectID);
  4117. if PropRec <> nil then
  4118. begin
  4119. FUPNode := FSPNode.NodeNewUTF8('UnitProject');
  4120. FUPNode.AttributeAddUTF8('ProjectID', IntToStr(iProjectID));
  4121. FUPNode.AttributeAddUTF8('Code', RecV('Value14'));
  4122. FUPNode.AttributeAddUTF8('Name', strName);
  4123. FUPNode.AttributeAddUTF8('BuildingArea', RecV('Value5'));
  4124. FUPNode.AttributeAddUTF8('NoncompetitiveCost', '0');
  4125. FUPNode.AttributeAddUTF8('Total', RecV('Value2'));
  4126. FUPNode.AttributeAddUTF8('MarketPriceStandard', '');
  4127. FUPNode.AttributeAddUTF8('NormLibrary', '0');
  4128. FUPNode.AttributeAddUTF8('Sequence', '0');
  4129. end
  4130. else
  4131. begin
  4132. MessageWarning('操作失败:无法找到该标段的相关信息!');
  4133. Abort;
  4134. end;
  4135. end;
  4136. procedure AddFeeFileTable;
  4137. var vNode: TXmlNode;
  4138. begin
  4139. vNode := FUPNode.NodeNewUTF8('FeeFileTable');
  4140. vNode := vNode.NodeNewUTF8('FeeFileItem');
  4141. vNode.AttributeAddUTF8('FeeFileID', IntToStr(FFeeRateFile.Lib.ID));
  4142. vNode.AttributeAddUTF8('FeeFileName', ExtractFileName(FFeeRateFile.LibName));
  4143. vNode.AttributeAddUTF8('NormLibrary', FRationLibCode);
  4144. end;
  4145. var sHint: string;
  4146. iSN: Integer;
  4147. cTP: Currency;
  4148. begin
  4149. if not Assigned(FFeeRateFile.Lib) then
  4150. begin
  4151. MessageWarning('操作失败:请先选择费率文件然后再导出!');
  4152. Exit;
  4153. end;
  4154. if not Assigned(FUnitPriceFile.Lib) then
  4155. begin
  4156. MessageWarning('操作失败:请先选择单价文件然后再导出!');
  4157. Exit;
  4158. end;
  4159. if FFileType = xftTB then
  4160. sHint := '投标'
  4161. else
  4162. sHint := '招标';
  4163. RefreshProgressForm(0, Format('正在导出%s文件:%s...', [sHint, '建设项目']));
  4164. FSN_ID2 := IDtoSerialNo(2);
  4165. cTP := 0;
  4166. iSN := -1; // 这个必须!
  4167. EEValue(iSN, cTP);
  4168. FSN_EEBegin := iSN;
  4169. FEETotalPrice := cTP;
  4170. if FSN_EEBegin = -1 then
  4171. FSN_BillsEnd := FSN_ID2 - 1
  4172. else
  4173. FSN_BillsEnd := FSN_EEBegin - 1;
  4174. AddTenderInfo;
  4175. AddProjectAddInfo;
  4176. AddSingleProject;
  4177. AddUnitProject;
  4178. AddFeeFileTable;
  4179. if FFileType = xftTB then
  4180. AddSummary;
  4181. FSubHint := Format('正在导出%s文件:%s...', [sHint, '清单']);
  4182. AddProgressForm(10, FSubHint);
  4183. AddBQTable;
  4184. AddProgressForm(20, Format('正在导出%s文件:%s...', [sHint, '计日工']));
  4185. AddDayWorkTable;
  4186. AddProgressForm(10, Format('正在导出%s文件:%s...', [sHint, '材料暂估价']));
  4187. AddMaterialProvisionalPriceTable;
  4188. AddProgressForm(10, Format('正在导出%s文件:%s...', [sHint, '工程设备暂估价']));
  4189. AddProjEquipmentPriceTable;
  4190. AddProgressForm(10, Format('正在导出%s文件:%s...', [sHint, '专业工程暂估价']));
  4191. AddProjProvisionalPriceTable;
  4192. if FSN_EEBegin <> -1 then
  4193. begin
  4194. AddProgressForm(10, Format('正在导出%s文件:%s...', [sHint, '交通机电设施备品备件']));
  4195. AddElectEquipmentTable;
  4196. end;
  4197. if FFileType = xftTB then
  4198. begin
  4199. AddProgressForm(10, Format('正在导出%s文件:%s...', [sHint, '工料机单价']));
  4200. AddMaterialTable;
  4201. AddProgressForm(10, Format('正在导出%s文件:%s...', [sHint, '项目工料机']));
  4202. AddResource;
  4203. end;
  4204. end;
  4205. constructor TkmXMLPort.Create;
  4206. begin
  4207. inherited;
  4208. FRationLibCode := '0';
  4209. end;
  4210. procedure TkmXMLPort.AddSummary;
  4211. var sSQL: string;
  4212. vNode: TXmlNode;
  4213. i: Integer;
  4214. const SmyArr: array[1..7, 1..4] of string = (
  4215. ('1', '工程量清单人工费', 'VZ_RGF', 'TenderLabourFee'),
  4216. ('2', '工程量清单材料费', 'VZ_CLF', 'TenderMaterialFee'),
  4217. ('3', '工程量清单机械费', 'VZ_JXF', 'TenderMachineFee'),
  4218. ('4', '工程量清单管理费', 'VZ_GLF', 'TenderIndirectFee'),
  4219. ('5', '工程量清单利润费', 'VZ_LR', 'TenderProfit'),
  4220. ('6', '工程量清单税金', 'VZ_SJ', 'TenderTax'),
  4221. ('7', '工程量清单其他费', 'VZ_QTF', 'TenderOtherDirectFee')
  4222. );
  4223. const SmyArr2: array[1..6, 1..4] of string = (
  4224. ('8', '工程量清单合计', 'VZ_HJ', '1'),
  4225. ('9', '计日工合计', 'LXXM_HJ', '4'),
  4226. ('10', '暂估价合计', 'ZGJ_HJ', '2'),
  4227. ('11', '交通机电设施备品备件合计', 'JTJD_HJ', '1'), // 这里的ID=1只是为了返回一条记录,可以是其它任意一个存在的值。
  4228. ('12', '不可预见费合价', 'BKYJF_HJ', '8'),
  4229. ('13', '总造价', 'VZ_ZZJ', '9')
  4230. );
  4231. begin
  4232. vNode := FUPNode.NodeNewUTF8('Summary');
  4233. for i := Low(SmyArr) to High(SmyArr) do
  4234. begin
  4235. sSQL :=
  4236. Format(
  4237. 'Select %d as CostID, %d as CostKind, ''%s'' as CostCode, ''%s'' as Name, ' +
  4238. ''''' as CostBase, '''' as CostRate, Sum(%s) as Total, ' +
  4239. '''%s'' as Remark, ''false'' as IsNoncompetitiveCost, %d as Sequence ' +
  4240. 'from RationCalcList',[
  4241. StrToInt(SmyArr[i, 1]), StrToInt(SmyArr[i, 1]), SmyArr[i, 1], SmyArr[i, 2],
  4242. SmyArr[i, 4], SmyArr[i, 3], StrToInt(SmyArr[i, 1])
  4243. ]);
  4244. AddTabToXML(FQuery1, sSQL, vNode, '', 'SummaryItem');
  4245. end;
  4246. for i := Low(SmyArr2) to High(SmyArr2) do
  4247. begin
  4248. if i = 4 then
  4249. begin
  4250. sSQL := Format(
  4251. 'Select %d as CostID, %d as CostKind, ''%s'' as CostCode, ''%s'' as Name, ' +
  4252. ''''' as CostBase, '''' as CostRate, %f as Total, ' +
  4253. '''%s'' as Remark, ''false'' as IsNoncompetitiveCost, %d as Sequence ' +
  4254. 'from Bills where ID=%s',[
  4255. StrToInt(SmyArr2[i, 1]), StrToInt(SmyArr2[i, 1]), SmyArr2[i, 1], SmyArr2[i, 2],
  4256. FEETotalPrice , SmyArr2[i, 3], StrToInt(SmyArr2[i, 1]), SmyArr2[i, 4]
  4257. ]);
  4258. end
  4259. else
  4260. begin
  4261. sSQL := Format(
  4262. 'Select %d as CostID, %d as CostKind, ''%s'' as CostCode, ''%s'' as Name, ' +
  4263. ''''' as CostBase, '''' as CostRate, Sum(TenderTotalPrice) as Total, ' +
  4264. '''%s'' as Remark, ''false'' as IsNoncompetitiveCost, %d as Sequence ' +
  4265. 'from Bills where ID=%s',[
  4266. StrToInt(SmyArr2[i, 1]), StrToInt(SmyArr2[i, 1]), SmyArr2[i, 1], SmyArr2[i, 2],
  4267. SmyArr2[i, 3], StrToInt(SmyArr2[i, 1]), SmyArr2[i, 4]
  4268. ]);
  4269. end;
  4270. AddTabToXML(FQuery1, sSQL, vNode, '', 'SummaryItem');
  4271. end;
  4272. end;
  4273. procedure TkmXMLPort.EEValue(var ABeginSN: Integer; var ATotalPrice: Currency);
  4274. var vRoot, vNode: TScBillsItem;
  4275. i: Integer;
  4276. begin
  4277. with TScProject(FProject).Bills do
  4278. begin
  4279. vRoot := BillsTree.BillsItem[1];
  4280. for i := 0 to vRoot.ChildCount - 1 do
  4281. begin
  4282. vNode := TScBillsItem(vRoot.ChildNodes[i]);
  4283. if (vNode.Code = '') and (Pos('清单 第', vNode.Name) > 0) then
  4284. begin
  4285. if (Pos('900', vNode.Name) > 0) or (Pos('1000', vNode.Name) > 0)
  4286. or (Pos('1100', vNode.Name) > 0) or (Pos('1200', vNode.Name) > 0)
  4287. or (Pos('1300', vNode.Name) > 0) then
  4288. begin
  4289. ABeginSN := IDtoSerialNo(vNode.ID);
  4290. Break;
  4291. end;
  4292. end;
  4293. end;
  4294. if ABeginSN <> -1 then // 找到了
  4295. begin
  4296. FQuery1.Close;
  4297. FQuery1.SQL.Text := Format('Select Sum(TenderTotalPrice) as TP from Bills ' +
  4298. 'where ParentID=%d and SerialNo >= %d', [1, ABeginSN]);
  4299. FQuery1.Open;
  4300. ATotalPrice := FQuery1.FieldByName('TP').AsCurrency;
  4301. FQuery1.Close;
  4302. end;
  4303. end;
  4304. end;
  4305. function TkmXMLPort.GetEECostKind(AChapterID: Integer): string;
  4306. var strName, sZJ, sSQL: string;
  4307. begin
  4308. sSQL := Format('Select Name from Bills where ID = %d', [AChapterID]);
  4309. strName := DoSearch(sSQL, 'Name');
  4310. sZJ := GetZJByName(strName);
  4311. if sZJ = '900' then
  4312. Result := '1'
  4313. else if sZJ = '1000' then
  4314. Result := '2'
  4315. else if sZJ = '1100' then
  4316. Result := '3'
  4317. else if sZJ = '1200' then
  4318. Result := '4'
  4319. else if sZJ = '1300' then
  4320. Result := '5';
  4321. end;
  4322. procedure TkmXMLPort.LoadFromXML;
  4323. var vNode, vSingleProject, vUnitProject, vBQTable, vBQTitle, vBQItem: TXmlNode;
  4324. i: Integer;
  4325. vItem: TScBillsItem;
  4326. { 筑龙XML格式
  4327. <BQTitle BQTitleID="216" Name="清单 第100章 总则" Remark="" Sequence="1">
  4328. <BQItem BQItemID="217" Code="101" Name="通则" ZJID="100" Unit="" Quantity="0" Rate="0" Total="1100" Remark="" Sequence="2" IsPriceCeiling="False"/>
  4329. <BQItem BQItemID="218" Code="101-1" Name="保险费" ZJID="100" Unit="" Quantity="0" Rate="0" Total="1100" Remark="" Sequence="3" IsPriceCeiling="False"/>
  4330. <BQItem BQItemID="219" Code="101-1-1" Name="按合同条款规定,提供建筑工程一切险" ZJID="100" Unit="总额" Quantity="1" Rate="500" Total="500" Remark="" Sequence="4" IsPriceCeiling="False"/>
  4331. <BQItem BQItemID="221" Code="101-1-2" Name="按合同条款规定,提供第三者责任险" ZJID="100" Unit="总额" Quantity="1" Rate="600" Total="600" Remark="" Sequence="5" IsPriceCeiling="False"/>
  4332. </BQTitle> }
  4333. // ABQTitle、ABillItem 对应于同级
  4334. procedure LoadBQItems(ABQTitle: TXmlNode; ABillItem: TScBillsItem);
  4335. var j: Integer;
  4336. vBQItem, vPBQItem: TXmlNode;
  4337. sCode: string;
  4338. vCurItem, vCurItemParent: TScBillsItem;
  4339. iPreSptr, iCurSptr, iParentID, iPSptr: Integer;
  4340. begin
  4341. iPreSptr := -1;
  4342. for j := 0 to ABQTitle.ElementCount - 1 do
  4343. begin
  4344. vBQItem := ABQTitle.Elements[j];
  4345. sCode := vBQItem.AttributeValueByNameUTF8['Code'];
  4346. iCurSptr := GetSeparatorCount(sCode);
  4347. if iPreSptr = -1 then // 第一个结点
  4348. iParentID := ABillItem.ID
  4349. else
  4350. begin
  4351. if iCurSptr = iPreSptr then // 当前清单的分隔符等于上一条,则是后兄弟
  4352. iParentID := vCurItem.ParentID
  4353. else if iCurSptr > iPreSptr then // 多于则是孩子
  4354. iParentID := vCurItem.ID
  4355. else // 小于则表示比上一条级别高,高多少级未知
  4356. begin
  4357. vCurItemParent := TScBillsItem(vCurItem.Parent);
  4358. while Assigned(vCurItemParent) do // 找同级别的结点
  4359. begin
  4360. iPSptr := GetSeparatorCount(vCurItemParent.Code);
  4361. if iPSptr = iCurSptr then
  4362. begin
  4363. iParentID := vCurItemParent.ParentID;
  4364. Break;
  4365. end;
  4366. if iPSptr = 0 then Break; // 截止到编号如"101",则不再往上找。
  4367. vCurItemParent := TScBillsItem(vCurItemParent.Parent);
  4368. end;
  4369. end;
  4370. end;
  4371. ABillItem.LocateInControl;
  4372. vCurItem := TScProject(FProject).Bills.BillsTree.AddBillsItem(iParentID, -1);
  4373. with vCurItem.Rec do
  4374. begin
  4375. BeginUpdate;
  4376. Code.AsString := sCode;
  4377. Name.AsString := vBQItem.AttributeValueByNameUTF8['Name'];
  4378. MemoStr.AsString := vBQItem.AttributeValueByNameUTF8['Remark'];
  4379. Units.AsString := vBQItem.AttributeValueByNameUTF8['Unit'];
  4380. Quantity.AsString := vBQItem.AttributeValueByNameUTF8['Quantity'];
  4381. UnitPrice.AsString := vBQItem.AttributeValueByNameUTF8['Rate'];
  4382. if StrToIntDef(vBQItem.AttributeValueByNameUTF8['Rate'], 0) <> 0 then
  4383. begin
  4384. TotalPrice.AsString := vBQItem.AttributeValueByNameUTF8['Total'];
  4385. // lsIsLeaf.AsBoolean := True; 新版lsIsLeaf读的是HasChildren方法,不是lsIsLeaf字段。不能识别,暂时注释,用到时再处理
  4386. end;
  4387. CalcFlag.AsInteger := Flag_CustomTotalPrice;
  4388. EndUpdate;
  4389. end;
  4390. iPreSptr := iCurSptr;
  4391. end;
  4392. end;
  4393. // 筑龙这里的结构是拼凑的,用不了递归。很山寨,只好跟着它拼,鄙视筑龙的技术!
  4394. procedure LoadDayWork(ANode: TXmlNode);
  4395. var i, j: Integer;
  4396. vNode1, vNode2: TXmlNode;
  4397. vItem1, vParentItem: TScBillsItem;
  4398. function AddItem(AParentItem: TScBillsItem; ANode: TXmlNode): TScBillsItem;
  4399. var vtem: TScBillsItem;
  4400. begin
  4401. vtem := TScProject(FProject).Bills.BillsTree.AddBillsItem(AParentItem.ID, -1);
  4402. with vtem.Rec do
  4403. begin
  4404. BeginUpdate;
  4405. Code.AsString := ANode.AttributeValueByNameUTF8['Code'];
  4406. Name.AsString := ANode.AttributeValueByNameUTF8['Name'];
  4407. MemoStr.AsString := ANode.AttributeValueByNameUTF8['Remark'];
  4408. Units.AsString := ANode.AttributeValueByNameUTF8['Unit'];
  4409. Quantity.AsString := ANode.AttributeValueByNameUTF8['Quantity'];
  4410. UnitPrice.AsString := ANode.AttributeValueByNameUTF8['Rate'];
  4411. if StrToIntDef(ANode.AttributeValueByNameUTF8['Rate'], 0) <> 0 then
  4412. begin
  4413. TotalPrice.AsString := ANode.AttributeValueByNameUTF8['Total'];
  4414. IsLeaf.AsBoolean := True;
  4415. end;
  4416. CalcFlag.AsInteger := Flag_CustomTotalPrice;
  4417. EndUpdate;
  4418. end;
  4419. Result := vtem;
  4420. end;
  4421. begin
  4422. with TScProject(FProject).Bills do
  4423. begin
  4424. for i := 0 to ANode.ElementCount - 1 do
  4425. begin
  4426. vNode1 := ANode.Elements[i];
  4427. if vNode1.AttributeValueByNameUTF8['CostKind'] = '1' then
  4428. vParentItem := BillsTree[idDayWorkLabour]
  4429. else if vNode1.AttributeValueByNameUTF8['CostKind'] = '2' then
  4430. vParentItem := BillsTree[idDayWorkMaterial]
  4431. else if vNode1.AttributeValueByNameUTF8['CostKind'] = '3' then
  4432. vParentItem := BillsTree[idDayWorkMachine];
  4433. vItem1 := AddItem(vParentItem, vNode1);
  4434. for j := 0 to vNode1.ElementCount - 1 do
  4435. begin
  4436. vNode2 := vNode1.Elements[j];
  4437. AddItem(vItem1, vNode2);
  4438. end;
  4439. end;
  4440. end;
  4441. end;
  4442. function FindItemByName(AName: string): TScBillsItem;
  4443. var i: Integer;
  4444. begin
  4445. Result := nil;
  4446. with TScProject(FProject).Bills do
  4447. begin
  4448. for i := 0 to BillsTree.Count - 1 do
  4449. begin
  4450. if BillsTree.Items[i].Name = AName then
  4451. begin
  4452. Result := BillsTree.Items[i];
  4453. Break;
  4454. end;
  4455. end;
  4456. end;
  4457. end;
  4458. procedure LoadZGJ(ANode: TXmlNode; AInterim: Integer);
  4459. var vNdoe: TXmlNode;
  4460. vItem: TScBillsItem;
  4461. i: Integer;
  4462. begin
  4463. for i := 0 to ANode.ElementCount - 1 do
  4464. begin
  4465. vNdoe := ANode.Elements[i];
  4466. vItem := FindItemByName(vNdoe.AttributeValueByNameUTF8['Name']);
  4467. if Assigned(vItem) then
  4468. begin
  4469. vItem.Rec.BeginUpdate;
  4470. vItem.Rec.IsSpecialInterim.AsBoolean := True;
  4471. vItem.Rec.InterimType.AsInteger := AInterim;
  4472. vItem.Rec.EndUpdate;
  4473. end;
  4474. end;
  4475. end;
  4476. procedure LoadPropertities(ANode: TXmlNode);
  4477. var i: Integer;
  4478. vNode1: TXmlNode;
  4479. strName, sValue, sBildUnit, sBidder, sAuthor: string;
  4480. begin
  4481. for i := 0 to ANode.ElementCount - 1 do
  4482. begin
  4483. vNode1 := ANode.Elements[i];
  4484. strName := vNode1.AttributeValueByNameUTF8['Name'];
  4485. sValue := vNode1.AttributeValueByNameUTF8['Value'];
  4486. if strName = '招标人(建设单位)' then
  4487. sBildUnit := sValue
  4488. else if strName = '编制单位' then
  4489. sBidder := sValue
  4490. else if strName = '编制单位法定代表人' then
  4491. sAuthor := sValue;
  4492. end;
  4493. TScProjBaseData(TScProject(FProject).ProjData).LoadValuesByXML(sBildUnit, sBidder, sAuthor);
  4494. end;
  4495. var
  4496. OldRealTimeCalc: Boolean;
  4497. begin
  4498. inherited;
  4499. OldRealTimeCalc := TScProject(FProject).RealTimeCalc;
  4500. try
  4501. TScProject(FProject).RealTimeCalc := False;
  4502. with TScProject(FProject).Bills do
  4503. begin
  4504. vSingleProject := FRoot.FindNode('SingleProject');
  4505. vUnitProject := vSingleProject.FindNode('UnitProject');
  4506. vBQTable := vUnitProject.FindNode('BQTable');
  4507. // 删除第一部分的子结点
  4508. BillsTree.DeleteChildren(BillsTree[idNormalBillsRoot]);
  4509. for i := 0 to vBQTable.ElementCount - 1 do // 章节结点
  4510. begin
  4511. vBQTitle := vBQTable.Elements[i];
  4512. vItem := BillsTree.AddBillsItem(idNormalBillsRoot, -1);
  4513. with vItem.Rec do
  4514. begin
  4515. BeginUpdate;
  4516. Name.AsString := vBQTitle.AttributeValueByNameUTF8['Name'];
  4517. MemoStr.AsString := vBQTitle.AttributeValueByNameUTF8['Remark'];
  4518. EndUpdate;
  4519. end;
  4520. LoadBQItems(vBQTitle, vItem);
  4521. end;
  4522. // 导入计日工
  4523. vNode := vUnitProject.FindNode('DayWorkTable');
  4524. // vItem := BillsTree[idDayWork];
  4525. // LoadDayWorkItems(vNode.Elements[0],vItem); // 后参数比前参数高一级
  4526. if Assigned(vNode) then
  4527. LoadDayWork(vNode);
  4528. // 暂估价
  4529. vNode := vUnitProject.FindNode('MaterialProvisionalPriceTable');
  4530. if Assigned(vNode) then
  4531. LoadZGJ(vNode, 1);
  4532. vNode := vUnitProject.FindNode('ProjEquipmentPriceTable');
  4533. if Assigned(vNode) then
  4534. LoadZGJ(vNode, 2);
  4535. vNode := vUnitProject.FindNode('ProjProvisionalPriceTable');
  4536. if Assigned(vNode) then
  4537. LoadZGJ(vNode, 3);
  4538. // 标段属性
  4539. vNode := FRoot.FindNode('ProjectAddInfo');
  4540. if Assigned(vNode) then
  4541. LoadPropertities(vNode);
  4542. TScProject(FProject).Bills.CalculateAll;
  4543. // 最后存储
  4544. TScProjBaseData(TScProject(FProject).ProjData).Save;
  4545. end;
  4546. finally
  4547. TScProject(FProject).RealTimeCalc := OldRealTimeCalc;
  4548. end;
  4549. end;
  4550. procedure TkmXMLPort.AddRoot;
  4551. begin
  4552. FRoot.Name := 'ConstructProject';
  4553. FRoot.AttributeAddUTF8('Code', '0');
  4554. FRoot.AttributeAddUTF8('Name', PD.BuildProjectName);
  4555. FRoot.AttributeAddUTF8('Tenderee', '');
  4556. FRoot.AttributeAddUTF8('TendereeProxy', '');
  4557. FRoot.AttributeAddUTF8('Standard', '昆明市工程造价数据交换标准');
  4558. FRoot.AttributeAddUTF8('StandardVer', '1.0');
  4559. FRoot.AttributeAddUTF8('FileType', IntToStr(Ord(FFileType)));
  4560. FRoot.AttributeAddUTF8('InterfaceCode', '');
  4561. end;
  4562. { TzhXMLPort }
  4563. procedure TzhXMLPort.AddRoot;
  4564. begin
  4565. inherited;
  4566. FRoot.Name := '文件信息';
  4567. // 日期和时间是客户机的,因而意义不大,无需精确。本时间仅作为文件收集时间的一个参考,入库用服务器的时间
  4568. FRoot.AttributeAddUTF8('日期', FormatDateTime('yyyy-mm-dd', Date));
  4569. FRoot.AttributeAddUTF8('建设项目', PD.BuildProjectName);
  4570. FRoot.AttributeAddUTF8('标段', PD.Alias);
  4571. FRoot.AttributeAddUTF8('地区', TScProject(FProject).FeeRate.cdsFeeParams2.Lookup('ID', 1, 'Caption'));
  4572. if TScProject(FProject).IsQuanGuo then
  4573. FRoot.AttributeAddUTF8('区域版本', '全国')
  4574. else
  4575. FRoot.AttributeAddUTF8('区域版本', '广东');
  4576. if TScProject(FProject).IsBills then
  4577. FRoot.AttributeAddUTF8('分段类型', '招投标')
  4578. else if TScProject(FProject).IsBudget then
  4579. FRoot.AttributeAddUTF8('分段类型', '估概预')
  4580. else if TScProject(FProject).IsGD3J then
  4581. FRoot.AttributeAddUTF8('分段类型', '三级清单');
  4582. end;
  4583. { TgljXMLPort }
  4584. procedure TgljXMLPort.AddRoot;
  4585. begin
  4586. inherited;
  4587. FRoot.AttributeAddUTF8('数据分类', 'GLJPrice');
  4588. end;
  4589. procedure TgljXMLPort.AddDetail;
  4590. procedure AddProjectGLJ;
  4591. var vPNode, vNode: TXmlNode;
  4592. begin
  4593. vPNode := FRoot.NodeNewUTF8('项目工料机');
  4594. FQuery1.Close;
  4595. FQuery1.SQL.Text :=
  4596. 'Select Code, Name, Specs, Unit, Type, BudgetPrice from ProjectGLJ where (New = False) and ((type = 3) or (type = 4)) and (BudgetPrice > 0) order by Code';
  4597. FQuery1.Open;
  4598. FQuery1.First;
  4599. while not FQuery1.Eof do
  4600. begin
  4601. vNode := vPNode.NodeNewUTF8('ProjectGLJ');
  4602. vNode.AttributeAddUTF8('Code', FQuery1.FieldByName('Code').AsString);
  4603. vNode.AttributeAddUTF8('Name', FQuery1.FieldByName('Name').AsString);
  4604. vNode.AttributeAddUTF8('Spec', FQuery1.FieldByName('Specs').AsString);
  4605. vNode.AttributeAddUTF8('Unit', ChangeUnit_m3(FQuery1.FieldByName('Unit').AsString));
  4606. vNode.AttributeAddUTF8('Type', FQuery1.FieldByName('Type').AsString);
  4607. vNode.AttributeAddUTF8('Price', Format('%.2f', [FQuery1.FieldByName('BudgetPrice').AsFloat]));
  4608. vNode.AttributeAddUTF8('Lib', '1'); // 部颁工料机
  4609. FQuery1.Next;
  4610. end;
  4611. FQuery1.Close;
  4612. end;
  4613. procedure AddUserGLJ;
  4614. var vUNode, vNode: TXmlNode;
  4615. aqUserGLJ: TADOQuery;
  4616. begin
  4617. vUNode := FRoot.NodeNewUTF8('用户工料机');
  4618. aqUserGLJ := TADOQuery.Create(nil);
  4619. try
  4620. aqUserGLJ.Connection := UserGLJLib.acGLJLib;
  4621. aqUserGLJ.Close;
  4622. aqUserGLJ.SQL.Text :=
  4623. 'Select Code, Name, Specs, Unit, Type, BasePrice from GLJList where ((type = 3) or (type = 4)) and (BasePrice > 0) order by Code';
  4624. aqUserGLJ.Open;
  4625. aqUserGLJ.First;
  4626. while not aqUserGLJ.Eof do
  4627. begin
  4628. vNode := vUNode.NodeNewUTF8('UserGLJ');
  4629. vNode.AttributeAddUTF8('Code', aqUserGLJ.FieldByName('Code').AsString);
  4630. vNode.AttributeAddUTF8('Name', aqUserGLJ.FieldByName('Name').AsString);
  4631. vNode.AttributeAddUTF8('Spec', aqUserGLJ.FieldByName('Specs').AsString);
  4632. vNode.AttributeAddUTF8('Unit', ChangeUnit_m3(aqUserGLJ.FieldByName('Unit').AsString));
  4633. vNode.AttributeAddUTF8('Type', aqUserGLJ.FieldByName('Type').AsString);
  4634. vNode.AttributeAddUTF8('Price', Format('%.2f', [aqUserGLJ.FieldByName('BasePrice').AsFloat]));
  4635. vNode.AttributeAddUTF8('Lib', '2'); // 自定义工料机
  4636. aqUserGLJ.Next;
  4637. end;
  4638. aqUserGLJ.Close;
  4639. finally
  4640. aqUserGLJ.Free;
  4641. end;
  4642. end;
  4643. begin
  4644. inherited;
  4645. // 简化逻辑,不再区分,统一由项目属性值控制。一天同时打印多个项目导致全局数据
  4646. // 重复上传的机率很小吧?即使有,也无所谓,这点数据对于硬件来说实属小菜。
  4647. AddProjectGLJ;
  4648. AddUserGLJ;
  4649. end;
  4650. { TbpXMLPort }
  4651. procedure TbpXMLPort.AddRoot;
  4652. begin
  4653. inherited;
  4654. FRoot.AttributeAddUTF8('数据分类', 'BillPrice');
  4655. end;
  4656. procedure TbpXMLPort.AddDetail;
  4657. var iBID: Integer;
  4658. procedure AddItems;
  4659. var vPNode, vNode: TXmlNode;
  4660. sCodeField: string;
  4661. begin
  4662. vPNode := FRoot.NodeNewUTF8('叶子清单');
  4663. if TScProject(FProject).IsQuanGuo then // 全国Code显示的是短编号如“1”“-a”等
  4664. sCodeField := 'Fullcode'
  4665. else
  4666. sCodeField := 'Code';
  4667. FQuery1.Close;
  4668. FQuery1.SQL.Text := Format('Select Distinct %0:s, B_Code, Name, Units, IIF(UnitPrice is null, 0, UnitPrice) as UnitPrice, IIF(DesignPrice is null, 0, DesignPrice) as DesignPrice ' +
  4669. 'from Bills where (IsLeaf = True) and ((UnitPrice<> 0) or (DesignPrice<> 0)) and ' +
  4670. '((%0:s <> '''') or (B_Code <> '''')) order by %0:s, B_Code', [sCodeField]);
  4671. FQuery1.Open;
  4672. FQuery1.First;
  4673. while not FQuery1.Eof do
  4674. begin
  4675. vNode := vPNode.NodeNewUTF8('BillItem');
  4676. vNode.AttributeAddUTF8('Code', FQuery1.FieldByName(sCodeField).AsString);
  4677. vNode.AttributeAddUTF8('B_Code', FQuery1.FieldByName('B_Code').AsString);
  4678. vNode.AttributeAddUTF8('Name', FQuery1.FieldByName('Name').AsString);
  4679. vNode.AttributeAddUTF8('Units', ChangeUnit_m3(FQuery1.FieldByName('Units').AsString));
  4680. vNode.AttributeAddUTF8('UnitPrice', FQuery1.FieldByName('UnitPrice').AsString);
  4681. vNode.AttributeAddUTF8('DesignPrice', FQuery1.FieldByName('DesignPrice').AsString);
  4682. FQuery1.Next;
  4683. end;
  4684. FQuery1.Close;
  4685. end;
  4686. begin
  4687. inherited;
  4688. AddItems;
  4689. end;
  4690. //*****************************************芜湖接口*************************************************************************
  4691. { TwhXMLPort }
  4692. procedure TwhXMLPort.AddRoot;
  4693. begin
  4694. inherited;
  4695. FRoot.Name := 'JingJiBiao';
  4696. FRoot.AttributeAddUTF8('Xmbh', IntToStr(PD.BuildProjectID));
  4697. FRoot.AttributeAddUTF8('Xmmc', PD.BuildProjectName);
  4698. FRoot.AttributeAddUTF8('Bzlx', '清单');
  4699. FRoot.AttributeAddUTF8('Jjyj', '【18清单】2018部颁清单计价依据'); // 【18清单】2018部颁清单计价依据
  4700. FRoot.AttributeAddUTF8('Xmqzzh', PV('StartCode'));
  4701. FRoot.AttributeAddUTF8('Jsdw', PD.BuildUnit);
  4702. case FFileType of
  4703. xftZB: FRoot.AttributeAddUTF8('Czzt', '招标');
  4704. xftTB: FRoot.AttributeAddUTF8('Czzt', '投标');
  4705. xftKZJ: FRoot.AttributeAddUTF8('Czzt', '招标控制');
  4706. end;
  4707. FRoot.AttributeAddUTF8('Jsfs', '1');
  4708. FRoot.AttributeAddUTF8('Version', '1.0');
  4709. end;
  4710. procedure TwhXMLPort.AddDetail;
  4711. procedure AddHeadXx;
  4712. var vNode: TXmlNode;
  4713. sKey: string;
  4714. begin
  4715. case FFileType of
  4716. xftZB: sKey := 'ZhaoBiaoXx';
  4717. xftTB: sKey := 'TouBiaoXx';
  4718. xftKZJ: sKey := 'ZhaoBiaoKzXx';
  4719. end;
  4720. vNode := FRoot.NodeNewUTF8(sKey);
  4721. case FFileType of
  4722. xftZB, xftKZJ:
  4723. begin
  4724. vNode.AttributeAddUTF8('Zbr', '招标人');
  4725. vNode.AttributeAddUTF8('Zxr', '咨询人');
  4726. vNode.AttributeAddUTF8('ZbrDb', '招标人代表');
  4727. vNode.AttributeAddUTF8('ZxrDb', '咨询人代表');
  4728. vNode.AttributeAddUTF8('Bzr', PD.Author);
  4729. vNode.AttributeAddUTF8('Fhr', PD.Auditor);
  4730. vNode.AttributeAddUTF8('BzTime', Copy(DateToStr(PD.EditDate), 1, 10));
  4731. vNode.AttributeAddUTF8('FhTime', Copy(DateToStr(PD.EditDate), 1, 10));
  4732. if FFileType = xftKZJ then
  4733. begin
  4734. vNode.AttributeAddUTF8('Zbkzj', '');
  4735. end;
  4736. end;
  4737. xftTB: // <TouBiaoXx Zbr="招标人" Tbr="投标人" TbrDb="" Bzr="" BzTime="2019-06-06" Tbzj="639621.47" />
  4738. begin
  4739. vNode.AttributeAddUTF8('Zbr', '招标人');
  4740. vNode.AttributeAddUTF8('Tbr', '投标人');
  4741. vNode.AttributeAddUTF8('TbrDb', '投标人代表');
  4742. vNode.AttributeAddUTF8('Bzr', PD.Author);
  4743. vNode.AttributeAddUTF8('BzTime', Copy(DateToStr(PD.EditDate), 1, 10));
  4744. vNode.AttributeAddUTF8('Tbzj', GetProjectTotalPrice);
  4745. end;
  4746. end;
  4747. end;
  4748. procedure AddJjFlb;
  4749. var sSQL: string;
  4750. begin
  4751. sSQL :=
  4752. 'Select Name as , Code, Unit, Quantity, ' +
  4753. 'UnitDirectFee as Rate, BuildingFee as Total, ' +
  4754. 'SerialNo as Sequence ' +
  4755. 'from Fees';
  4756. AddTabToXML(FQuery1, sSQL, FJjFlbNode, '', 'JjFlbMx');
  4757. end;
  4758. procedure AddJjFlx;
  4759. var sSQL: string;
  4760. begin
  4761. sSQL :=
  4762. 'Select SerialNo as Bm, Name as Mc, Caption as ShuZhi ' +
  4763. 'from FeeParams Order by SerialNo';
  4764. AddTabToXML(FQuery2, sSQL, FJjFlxNode, '', 'JjFlxMx');
  4765. end;
  4766. procedure AddQfxx;
  4767. begin
  4768. FQfxxNode := FDwgcxxNode.NodeNewUTF8('Qfxx');
  4769. FJjFlbNode := FQfxxNode.NodeNewUTF8('JjFlb');
  4770. FJjFlxNode := FQfxxNode.NodeNewUTF8('JjFlx');
  4771. // AddJjFlb;
  4772. AddJjFlx;
  4773. end;
  4774. function Rec(ANode: TScBillsItem; AName: string): string;
  4775. begin
  4776. Result := ANode.Rec.ValueByName(AName).AsString;
  4777. end;
  4778. procedure ReadTreeNodes(ANode: TScBillsItem; AXMLParent: TXmlNode);
  4779. var vXMLNode, vRationNode, vRationMxNode, vGLJNode, vGLJMxNode: TXmlNode;
  4780. begin
  4781. if ANode <> nil then
  4782. begin
  4783. if ANode.Parent = nil then
  4784. begin
  4785. Inc(FBlackFontBillsNo);
  4786. vXMLNode := AXMLParent.NodeNewUTF8('QdBt');
  4787. vXMLNode.AttributeAddUTF8('Xh', IntToStr(FBlackFontBillsNo));
  4788. vXMLNode.AttributeAddUTF8('Bm', ANode.Code);
  4789. vXMLNode.AttributeAddUTF8('Name', ANode.Name);
  4790. vXMLNode.AttributeAddUTF8('Je', Rec(ANode, 'TotalPrice'));
  4791. vXMLNode.AttributeAddUTF8('Code', '');
  4792. vXMLNode.AttributeAddUTF8('Jsgs', '');
  4793. vXMLNode.AttributeAddUTF8('Lb', IntToStr(FBlackFontBillsNo));
  4794. vXMLNode.AttributeAddUTF8('Bz', Rec(ANode, 'MemoStr'));
  4795. if FBlackFontBillsNo = 4 then // 计日工合计
  4796. begin
  4797. FJrgNode := vXMLNode.NodeNewUTF8('Jrg');
  4798. vXMLNode := FJrgNode;
  4799. end;
  4800. end
  4801. else
  4802. begin
  4803. if AXMLParent = FJrgNode then
  4804. begin
  4805. vXMLNode := AXMLParent.NodeNewUTF8('JrgBt');
  4806. vXMLNode.AttributeAddUTF8('Name', ANode.Name);
  4807. vXMLNode.AttributeAddUTF8('Je', Rec(ANode, 'TotalPrice'));
  4808. if Pos('劳务', ANode.Name) > 0 then
  4809. vXMLNode.AttributeAddUTF8('Lb', '1')
  4810. else if Pos('材料', ANode.Name) > 0 then
  4811. vXMLNode.AttributeAddUTF8('Lb', '2')
  4812. else if Pos('机械', ANode.Name) > 0 then
  4813. vXMLNode.AttributeAddUTF8('Lb', '3');
  4814. vXMLNode.AttributeAddUTF8('Bz', Rec(ANode, 'MemoStr'));
  4815. end
  4816. else
  4817. begin
  4818. vXMLNode := AXMLParent.NodeNewUTF8('QdMx');
  4819. vXMLNode.AttributeAddUTF8('Xh', Rec(ANode, 'SerialNo'));
  4820. vXMLNode.AttributeAddUTF8('Qdbm', ANode.Code);
  4821. vXMLNode.AttributeAddUTF8('Name', ANode.Name);
  4822. vXMLNode.AttributeAddUTF8('Xmtz', '');
  4823. vXMLNode.AttributeAddUTF8('Dw', Rec(ANode, 'Units'));
  4824. vXMLNode.AttributeAddUTF8('Sl', Rec(ANode, 'Quantity'));
  4825. vXMLNode.AttributeAddUTF8('Sl2', '0');//Rec(ANode, 'Quantity2');
  4826. vXMLNode.AttributeAddUTF8('Rgf', '0');
  4827. vXMLNode.AttributeAddUTF8('Clf', '0');
  4828. vXMLNode.AttributeAddUTF8('Jxf', '0');
  4829. vXMLNode.AttributeAddUTF8('Sbf', '0');
  4830. vXMLNode.AttributeAddUTF8('Csf', '0');
  4831. vXMLNode.AttributeAddUTF8('Glf', '0');
  4832. vXMLNode.AttributeAddUTF8('Gf', '0');
  4833. vXMLNode.AttributeAddUTF8('Lr', '0');
  4834. vXMLNode.AttributeAddUTF8('Sj', '0');
  4835. if FFileType in [xftTB, xftKZJ] then
  4836. begin
  4837. vXMLNode.AttributeAddUTF8('Zhdj', Rec(ANode, 'UnitPrice'));
  4838. vXMLNode.AttributeAddUTF8('Zhhj', Rec(ANode, 'TotalPrice'));
  4839. end
  4840. else
  4841. begin
  4842. vXMLNode.AttributeAddUTF8('Zhdj', '0');
  4843. vXMLNode.AttributeAddUTF8('Zhhj', '0');
  4844. end;
  4845. vXMLNode.AttributeAddUTF8('Zgj', '0');
  4846. vXMLNode.AttributeAddUTF8('Iszg', 'false');
  4847. vXMLNode.AttributeAddUTF8('Djfx', 'true');
  4848. vXMLNode.AttributeAddUTF8('Jsgs', '');
  4849. vXMLNode.AttributeAddUTF8('Bl', '');
  4850. vXMLNode.AttributeAddUTF8('Bz', Rec(ANode, 'MemoStr'));
  4851. if FFileType = xftTB then
  4852. begin
  4853. if ANode.IsLeaf then
  4854. begin
  4855. FQuery2.Close;
  4856. FQuery2.SQL.Clear;
  4857. FQuery2.SQL.Add(Format('SELECT * FROM RationCalcList WHERE BillsItemID = %d', [ANode.ID]));
  4858. FQuery2.Open;
  4859. if FQuery2.RecordCount > 0 then
  4860. begin
  4861. vRationNode := vXMLNode.NodeNewUTF8('Qdxdezj');
  4862. FQuery2.First;
  4863. while not FQuery2.Eof do
  4864. begin
  4865. vRationMxNode := vRationNode.NodeNewUTF8('QdxdezjMx');
  4866. vRationMxNode.AttributeAddUTF8('Debm', FQuery2.FieldByName('Code').asString);
  4867. vRationMxNode.AttributeAddUTF8('Mc', FQuery2.FieldByName('Name').asString);
  4868. vRationMxNode.AttributeAddUTF8('Dw', FQuery2.FieldByName('Unit').asString);
  4869. vRationMxNode.AttributeAddUTF8('Sl', FQuery2.FieldByName('Quantity').asString);
  4870. vRationMxNode.AttributeAddUTF8('Dj', FQuery2.FieldByName('UnitPrice').asString);
  4871. vRationMxNode.AttributeAddUTF8('Hj', FQuery2.FieldByName('BuildingFee').asString);
  4872. vRationMxNode.AttributeAddUTF8('Rgf', FQuery2.FieldByName('LabourFee').asString);
  4873. vRationMxNode.AttributeAddUTF8('Clf', FQuery2.FieldByName('MaterialFee').asString);
  4874. vRationMxNode.AttributeAddUTF8('Jxf', FQuery2.FieldByName('MachineFee').asString);
  4875. vRationMxNode.AttributeAddUTF8('Sbf', '0');
  4876. vRationMxNode.AttributeAddUTF8('Csf', FQuery2.FieldByName('OtherDirectFee').asString);
  4877. vRationMxNode.AttributeAddUTF8('Glf', FQuery2.FieldByName('ManageFee').asString);
  4878. vRationMxNode.AttributeAddUTF8('Gf', FQuery2.FieldByName('LocaleFee').asString);
  4879. vRationMxNode.AttributeAddUTF8('Lr', FQuery2.FieldByName('Profit').asString);
  4880. vRationMxNode.AttributeAddUTF8('Sj', FQuery2.FieldByName('Tax').asString);
  4881. case FQuery2.FieldByName('Type').AsInteger of
  4882. 0: vRationMxNode.AttributeAddUTF8('Delb', '1');
  4883. 1:
  4884. begin
  4885. if FQuery2.FieldByName('IsMECalc').AsBoolean then
  4886. vRationMxNode.AttributeAddUTF8('Delb', '5') // 设备
  4887. else
  4888. begin
  4889. case FQuery2.FieldByName('CountPriceType').AsInteger of
  4890. 1: vRationMxNode.AttributeAddUTF8('Delb', '2'); // 数量单价人工
  4891. 2: vRationMxNode.AttributeAddUTF8('Delb', '3'); // 数量单价材料
  4892. 3: vRationMxNode.AttributeAddUTF8('Delb', '4'); // 数量单价机械
  4893. end;
  4894. end;
  4895. end;
  4896. end;
  4897. vRationMxNode.AttributeAddUTF8('Iszd', 'false');
  4898. FQuery3.Close;
  4899. FQuery3.SQL.Clear;
  4900. FQuery3.SQL.Add(Format('SELECT * FROM GLJList WHERE RationID = %d', [FQuery2.FieldByName('ID').AsInteger]));
  4901. FQuery3.Open;
  4902. if FQuery3.RecordCount > 0 then
  4903. begin
  4904. vGLJNode := vRationMxNode.NodeNewUTF8('Qdxdercjhl');
  4905. FQuery3.First;
  4906. while not FQuery3.Eof do
  4907. begin
  4908. vGLJMxNode := vGLJNode.NodeNewUTF8('QdxdercjhlMx');
  4909. vGLJMxNode.AttributeAddUTF8('RcjId', FQuery3.FieldByName('GLJID').asString);
  4910. vGLJMxNode.AttributeAddUTF8('Sl', FQuery3.FieldByName('Quantity').asString);
  4911. FQuery3.Next;
  4912. end;
  4913. end;
  4914. FQuery3.Close;
  4915. FQuery2.Next;
  4916. end;
  4917. vXMLNode.NodeNewUTF8('Qdxrcjhl');
  4918. end;
  4919. FQuery2.Close;
  4920. end;
  4921. end;
  4922. end;
  4923. end;
  4924. // 第3层计日工不导出:导出要换内容,太复杂且毫无意义。
  4925. if (ANode.Parent <> nil) and (TScBillsItem(ANode.Parent).Name = '计日工合计') then
  4926. begin
  4927. end
  4928. else
  4929. ReadTreeNodes(TScBillsItem(ANode.FirstChild), vXMLNode);
  4930. ReadTreeNodes(TScBillsItem(ANode.NextSibling), AXMLParent);
  4931. end;
  4932. end;
  4933. procedure AddQdXm;
  4934. var vTree: TScBillsTree;
  4935. begin
  4936. FQdXmNode := FDwgcxxNode.NodeNewUTF8('QdXm');
  4937. vTree := TScProject(FProject).Bills.BillsTree;
  4938. FBlackFontBillsNo := 0;
  4939. ReadTreeNodes(vTree.Items[0], FQdXmNode);
  4940. end;
  4941. procedure AddZgCl;
  4942. var vNode: TXmlNode;
  4943. begin
  4944. FZgClNode := FDwgcxxNode.NodeNewUTF8('ZgCl');
  4945. end;
  4946. procedure AddJpCl;
  4947. var vNode: TXmlNode;
  4948. begin
  4949. FJpClNode := FDwgcxxNode.NodeNewUTF8('JpCl');
  4950. end;
  4951. procedure AddRcjhz;
  4952. var vNode: TXmlNode;
  4953. sSQL: string;
  4954. begin
  4955. FRcjhzNode := FDwgcxxNode.NodeNewUTF8('Rcjhz');
  4956. // sSQL :=
  4957. // 'Select ID as RcjId, Code as RcjBm, Name, Specs as Ggxh, Unit as Dw, ' +
  4958. // 'BudgetPrice as Dj, Amount as Sl, BudgetPrice*Amount as Hj, '''' as Cd, '''' as Gycs, Type as Rcjlb, ''false'' as Jgbz,' +
  4959. // 'Main as Zyclbz, ''false'' as Zgjbz, ''false'' as Zcbz ' +
  4960. // 'from ProjectGLJ';
  4961. sSQL :=
  4962. 'Select ID as RcjId, Code as RcjBm, Name, Specs as Ggxh, Unit as Dw, ' +
  4963. 'BudgetPrice as Dj, Amount as Sl, BudgetPrice*Amount as Hj, '''' as Cd, '''' as Gycs, IIF(Type=2 or Type=4,2,IIF(Type=6 or Type=8,3,Type)) as Rcjlb, ''false'' as Jgbz,' +
  4964. 'Main as Zyclbz, ''false'' as Zgjbz, ''false'' as Zcbz ' +
  4965. 'from ProjectGLJ ' +
  4966. 'where Type <> 9';
  4967. AddTabToXML(FQuery1, sSQL, FRcjhzNode, '', 'RcjhzMx');
  4968. end;
  4969. procedure AddDwgcxx;
  4970. var vNode: TXmlNode;
  4971. begin
  4972. vNode := FDxgcxxNode.NodeNewUTF8('Dwgcxx');
  4973. vNode.AttributeAddUTF8('Dwgcbh', '珠海纵横创新软件有限公司');
  4974. vNode.AttributeAddUTF8('Dwgcmc', PD.BuildProjectName);
  4975. FDwgcxxNode := vNode;
  4976. AddProgressForm(10, '正在导出取费信息...');
  4977. AddQfxx;
  4978. AddProgressForm(10, '正在导出清单项目...');
  4979. AddQdXm;
  4980. AddProgressForm(10, '正在导出暂估材料表...');
  4981. AddZgCl;
  4982. AddProgressForm(10, '正在导出甲评材料表...');
  4983. AddJpCl;
  4984. AddProgressForm(10, '正在导出人材机汇总...');
  4985. if FFileType in [xftTB, xftKZJ] then
  4986. begin
  4987. AddRcjhz;
  4988. end;
  4989. end;
  4990. procedure AddDxgcxx;
  4991. var vNode: TXmlNode;
  4992. begin
  4993. vNode := FRoot.NodeNewUTF8('Dxgcxx');
  4994. vNode.AttributeAddUTF8('Dxgcbh', '珠海纵横创新软件有限公司');
  4995. vNode.AttributeAddUTF8('Dxgcmc', PD.BuildProjectName);
  4996. FDxgcxxNode := vNode;
  4997. AddDwgcxx;
  4998. end;
  4999. procedure AddJyxx;
  5000. var vNode: TXmlNode;
  5001. begin
  5002. AddProgressForm(10, '正在生成校验信息...');
  5003. vNode := FRoot.NodeNewUTF8('Jyxx');
  5004. vNode.AttributeAddUTF8('SoftName', Application.Title);
  5005. vNode.AttributeAddUTF8('SoftNum', 'SamrtCost10.1');
  5006. vNode.AttributeAddUTF8('MacAdress', Get_MAC_Address);
  5007. vNode.AttributeAddUTF8('DogNum', 'SCDOG001002');
  5008. vNode.AttributeAddUTF8('ComputerName', Get_Computer_Name);
  5009. vNode.AttributeAddUTF8('HDDSerial', Get_HDD_SN);
  5010. vNode.AttributeAddUTF8('CPUSerial', Get_CPU_SN);
  5011. end;
  5012. begin
  5013. inherited;
  5014. AddHeadXx;
  5015. AddDxgcxx;
  5016. AddJyxx;
  5017. end;
  5018. { TtzslXMLPort }
  5019. function TtzslXMLPort.CheckXMLFile: Boolean;
  5020. var
  5021. sType: string;
  5022. iProjType: Integer;
  5023. begin
  5024. Result := True;
  5025. FInfo := FRoot.FindNode('Info');
  5026. if FInfo <> nil then
  5027. sType := VarToStr(FInfo.AttributeValueByNameUTF8['DataType'])
  5028. else
  5029. sType := '';
  5030. if (FInfo = nil) or (sType = '') then
  5031. begin
  5032. MessageHint(0, '文件错误,请使用从算量软件导出的XML文件!');
  5033. Result := False;
  5034. Exit;
  5035. end;
  5036. // 2023/11/13 zhangyin 开始支持平级清单
  5037. (*if FFirstBill.ElementCount = 0 then
  5038. begin
  5039. MessageHint(0, '不支持导入平级的清单结构,请使用有树结构层次的清单!');
  5040. Result := False;
  5041. Exit;
  5042. end; *)
  5043. iProjType := Ord(TScProject(FProject).ProjType);
  5044. Result := (SameText(sType, 'Fx') and (iProjType in [5])) or // 三级清单
  5045. (SameText(sType, 'Gcl') and (iProjType in [0])) or // 清单
  5046. (SameText(sType, 'Xmj') and (iProjType in [1,2,3,4,6,7,8,9])); // 项目节
  5047. FIsBills := SameText(sType, 'Gcl');
  5048. if not Result then
  5049. begin
  5050. MessageHint(0, '操作失败,XML文件与当前项目的项目类型不匹配!');
  5051. Exit;
  5052. end;
  5053. FBillList := FRoot.FindNode('BillList');
  5054. FFirstBill := FBillList.Elements[0];
  5055. // 清单只有一个父项
  5056. if not FIsBills then
  5057. begin
  5058. if FBillList.ElementCount > 1 then
  5059. FSecondBill := FBillList.Elements[1];
  5060. if FBillList.ElementCount > 2 then
  5061. FThirdBill := FBillList.Elements[2];
  5062. if FBillList.ElementCount > 3 then
  5063. FFourthBill := FBillList.Elements[3];
  5064. end;
  5065. end;
  5066. procedure TtzslXMLPort.AnalyzeXMLNodesIntoList(ASelectItem: TScBillsItem);
  5067. var vFile: TextFile;
  5068. isTest: Boolean;
  5069. procedure AddNodesToList(ANode: TXmlNode);
  5070. var P: PXMLNode;
  5071. begin
  5072. if ANode = nil then Exit;
  5073. if (ANode.Name <> 'Bills') then Exit;
  5074. // if (not ANode.HasChildNodes) or
  5075. // (ANode.HasChildNodes and (ANode.Elements[0];.Name <> 'Bills')) then
  5076. begin
  5077. New(P);
  5078. P^.Data := ANode;
  5079. P^.FullCode := GetCompareFullCode(ANode);
  5080. FXMLNodesList.Add(P);
  5081. if isTest then
  5082. Writeln(vFile, Format('%s %s %s %s', [P^.FullCode, ANode.AttributeValueByNameUTF8['Name'],
  5083. ANode.AttributeValueByNameUTF8['Code'], ANode.AttributeValueByNameUTF8[FB_CodeFieldName]]));
  5084. end;
  5085. if Assigned(ANode.Elements[0]) then
  5086. AddNodesToList(ANode.Elements[0]);
  5087. // 当前Node有后兄弟, 且当前Node不是“第二部分 ...”才进入后兄弟。即:从"第三部分..." 开始不进入线性对比列表(它这里断了,它的后兄弟跟着全部都断了)。
  5088. if Assigned(ANode.NextSibling(ANode)) and (Pos('第二部分', ANode.AttributeValueByNameUTF8['Name']) = 0) then
  5089. AddNodesToList(ANode.NextSibling(ANode));
  5090. end;
  5091. // function GetSyncNode(AItem: TScBillsItem; ANode: IXMLNode; var ARstNode: IXMLNode): IXMLNode;
  5092. // begin
  5093. // if ANode = nil then Exit;
  5094. // if (ANode.Name <> 'Bills') then Exit;
  5095. //
  5096. // if (ANode.AttributeAdd('Code'] = AItem.Code) and
  5097. // (ANode.AttributeAdd('b_Code'] = AItem.B_Code) and
  5098. // (ANode.AttributeAdd('Name'] = AItem.Name) and
  5099. // SameText(GetFullCode(ANode), AItem.FullCode) then
  5100. // begin
  5101. // ARstNode := ANode;
  5102. // Exit;
  5103. // end;
  5104. //
  5105. // if ARstNode = nil then
  5106. // begin
  5107. // if Assigned(ANode.NextSibling) then
  5108. // GetSyncNode(AItem, ANode.NextSibling, ARstNode);
  5109. //
  5110. // if Assigned(ANode.Elements[0]) then
  5111. // GetSyncNode(AItem, ANode.Elements[0], ARstNode);
  5112. // end;
  5113. // end;
  5114. var vFromNode: TXmlNode;
  5115. begin
  5116. isTest := True;
  5117. DisposeXMLNodesList;
  5118. // if ASelectItem.ID = 1 then
  5119. // vFromNode := FFirstBill.Elements[0]
  5120. // else
  5121. // GetSyncNode(ASelectItem, FFirstBill.Elements[0], vFromNode);
  5122. // vFromNode := FFirstBill.Elements[0];
  5123. vFromNode := FFirstBill;
  5124. if isTest then AssignFile(vFile, ExtractFilePath(Application.ExeName) + 'UserData\OrgXML.test');
  5125. try
  5126. if isTest then ReWrite(vFile);
  5127. AddNodesToList(vFromNode);
  5128. finally
  5129. if isTest then CloseFile(vFile);
  5130. end;
  5131. end;
  5132. procedure TtzslXMLPort.LoadFromXML;
  5133. var
  5134. OldRealTimeCalc: Boolean;
  5135. vNode: TXmlNode;
  5136. vItem, vItem2, vItem3, vItem4: TScBillsItem;
  5137. begin
  5138. inherited;
  5139. if not CheckXMLFile then Exit;
  5140. Screen.Cursor := crHourGlass;
  5141. CreateProgressForm(100, '导入算量XML文件');
  5142. OldRealTimeCalc := TScProject(FProject).RealTimeCalc;
  5143. try
  5144. TScProject(FProject).RealTimeCalc := False;
  5145. FXMLNodeList := TList.Create;
  5146. vItem := BillsTree[idNormalBillsRoot];
  5147. // 删除第100章到700/900章清单/第一部分的子结点
  5148. BillsTree.DeleteChildren(vItem);
  5149. if not FIsBills then
  5150. begin
  5151. if Assigned(FSecondBill) then
  5152. begin
  5153. vItem2 := BillsTree[idSecondSection];
  5154. // 删除第二部分的子结点
  5155. BillsTree.DeleteChildren(vItem2);
  5156. end;
  5157. if Assigned(FThirdBill) then
  5158. begin
  5159. vItem3 := BillsTree[idThreeSection];
  5160. // 删除第三部分的子结点
  5161. BillsTree.DeleteChildren(vItem3);
  5162. end;
  5163. if Assigned(FFourthBill) then
  5164. begin
  5165. vItem4 := BillsTree[idFourthSection];
  5166. // 删除第四部分的子结点
  5167. BillsTree.DeleteChildren(vItem4);
  5168. end;
  5169. end;
  5170. TScProject(FProject).Bills.CalculateAll; // 导入到有数据的项目时,因根结点有金额,不让导入,且内存崩溃
  5171. BillsTree.SelectedIndex := -1; // 这句不加成不了树结构。
  5172. // 清单为平面列表
  5173. if FIsBills then
  5174. begin
  5175. AddProgressForm(10, '正在导入清单、定额、图纸算量...');
  5176. AssignNode(FFirstBill, vItem);
  5177. vNode := FFirstBill.NextSibling(FFirstBill);
  5178. RcsvAddBills(vNode, vItem);
  5179. end
  5180. // 三算从第一部分开始递归
  5181. else
  5182. begin
  5183. AssignNode(FFirstBill, vItem);
  5184. vNode := FFirstBill.Elements[0];
  5185. AddProgressForm(10, '正在导入项目节、定额、图纸算量...');
  5186. RcsvAddBills(vNode, vItem);
  5187. // 开始搞第二部分
  5188. if Assigned(FSecondBill) then
  5189. begin
  5190. BillsTree.SelectedIndex := -1;
  5191. AssignNode(FSecondBill, vItem2);
  5192. vNode := FSecondBill.Elements[0];
  5193. AddProgressForm(10, '正在导入土地...');
  5194. RcsvAddBills(vNode, vItem2);
  5195. end;
  5196. if Assigned(FThirdBill) then
  5197. begin
  5198. BillsTree.SelectedIndex := -1;
  5199. AssignNode(FThirdBill, vItem3);
  5200. vNode := FThirdBill.Elements[0];
  5201. AddProgressForm(10, '正在导入第三部分...');
  5202. RcsvAddBills(vNode, vItem3);
  5203. end;
  5204. if Assigned(FFourthBill) then
  5205. begin
  5206. BillsTree.SelectedIndex := -1;
  5207. AssignNode(FFourthBill, vItem4);
  5208. vNode := FFourthBill.Elements[0];
  5209. AddProgressForm(10, '正在导入第四部分...');
  5210. RcsvAddBills(vNode, vItem4);
  5211. end;
  5212. end;
  5213. // 标段属性
  5214. // vNode := FRoot.FindNode('ProjectAddInfo');
  5215. // if Assigned(vNode) then
  5216. // LoadPropertities(vNode);
  5217. AddProgressForm(60, '正在全局造价计算...');
  5218. TScProject(FProject).Bills.CalculateAll;
  5219. // 先不保存吧,万一客户操作失误,想更新却误用了导入,一保存就不能反悔了。
  5220. // TScProjBaseData(TScProject(Project).ProjData).Save;
  5221. finally
  5222. FXMLNodeList.Free;
  5223. TScProject(FProject).RealTimeCalc := OldRealTimeCalc;
  5224. CloseProgressForm;
  5225. Screen.Cursor := crDefault;
  5226. end;
  5227. end;
  5228. procedure TtzslXMLPort.RcsvUpdateItems(AItem: TScBillsItem);
  5229. begin
  5230. if AItem = nil then Exit;
  5231. UpdateItem(AItem);
  5232. if Assigned(AItem.FirstChild) then
  5233. RcsvUpdateItems(TScBillsItem(AItem.FirstChild));
  5234. if Assigned(AItem.NextSibling) then
  5235. RcsvUpdateItems(TScBillsItem(AItem.NextSibling));
  5236. end;
  5237. procedure TtzslXMLPort.RcsvCompareItems(AItem: TScBillsItem);
  5238. begin
  5239. if AItem = nil then Exit;
  5240. CompareItem(AItem);
  5241. if Assigned(AItem.FirstChild) then
  5242. RcsvCompareItems(TScBillsItem(AItem.FirstChild));
  5243. if Assigned(AItem.NextSibling) and (AItem.NextSibling.ID <> 3) then // 第三部分及以后都忽略
  5244. RcsvCompareItems(TScBillsItem(AItem.NextSibling));
  5245. end;
  5246. procedure TtzslXMLPort.UpdateFromXML;
  5247. var
  5248. OldRealTimeCalc: Boolean;
  5249. vNode: TXmlNode;
  5250. vItem: TScBillsItem;
  5251. sName: string;
  5252. begin
  5253. if not FileExists(FXMLFile) then Exit;
  5254. FXMLDoc.LoadFromFile(FXMLFile);
  5255. CheckB_CodeFieldName;
  5256. if not CheckXMLFile then Exit;
  5257. vItem := TScBillsItem(FBillsTree.Selected);
  5258. sName := FFirstBill.AttributeValueByNameUTF8['Name'];
  5259. if not ((vItem.Code = FFirstBill.AttributeValueByNameUTF8['Code'])
  5260. and (vItem.B_Code = FFirstBill.AttributeValueByNameUTF8[FB_CodeFieldName])
  5261. and (vItem.Name = sName))
  5262. // and SameText(vItem.FullCode, PXMLNode(FXMLNodesList[i]).FullCode)
  5263. then
  5264. begin
  5265. MessageHint(0, '操作失败,当前选中要更新的树节点跟文件的起始节点不一致!');
  5266. Exit;
  5267. end;
  5268. Screen.Cursor := crHourGlass;
  5269. CreateProgressForm(100, '从算量XML文件更新');
  5270. OldRealTimeCalc := TScProject(FProject).RealTimeCalc;
  5271. try
  5272. TScProject(FProject).RealTimeCalc := False;
  5273. // 先取XML文件中的清单,线性列表存储
  5274. AddProgressForm(5, '正在生成映射列表...');
  5275. AnalyzeXMLNodesIntoList(vItem);
  5276. if FXMLNodesList.Count = 0 then Exit;
  5277. AddProgressForm(5, '开始更新...');
  5278. RcsvUpdateItems(vItem);
  5279. AddProgressForm(60, '正在全局造价计算...');
  5280. TScProject(FProject).Bills.CalculateAll;
  5281. finally
  5282. TScProject(FProject).RealTimeCalc := OldRealTimeCalc;
  5283. CloseProgressForm;
  5284. Screen.Cursor := crDefault;
  5285. end;
  5286. end;
  5287. procedure TtzslXMLPort.CompareFromXML(ACDS: TClientDataSet);
  5288. var
  5289. OldRealTimeCalc: Boolean;
  5290. vNode: TXmlNode;
  5291. vItem: TScBillsItem;
  5292. begin
  5293. FCompareCDS := ACDS;
  5294. FCompareCDS.First;
  5295. while not FCompareCDS.Eof do
  5296. FCompareCDS.Delete;
  5297. if not FileExists(FXMLFile) then Exit;
  5298. FXMLDoc.LoadFromFile(FXMLFile);
  5299. CheckB_CodeFieldName;
  5300. if not CheckXMLFile then Exit;
  5301. vItem := TScBillsItem(FBillsTree.Selected);
  5302. // vItem := TScBillsItem(BillsTree[idNormalBillsRoot]);
  5303. if not (
  5304. (vItem.Code = FFirstBill.AttributeValueByNameUTF8['Code'])
  5305. and (vItem.B_Code = FFirstBill.AttributeValueByNameUTF8[FB_CodeFieldName])
  5306. and (vItem.Name = FFirstBill.AttributeValueByNameUTF8['Name'])
  5307. )
  5308. // and SameText(vItem.FullCode, PXMLNode(FXMLNodesList[i]).FullCode)
  5309. then
  5310. begin
  5311. MessageHint(0, '操作失败,当前选中要对比的节点跟XML文件不匹配!');
  5312. Exit;
  5313. end;
  5314. Screen.Cursor := crHourGlass;
  5315. CreateProgressForm(100, '从算量XML文件对比');
  5316. try
  5317. // 先取XML文件中的清单,线性列表存储
  5318. AddProgressForm(5, '正在生成映射列表...');
  5319. AnalyzeXMLNodesIntoList(vItem);
  5320. if FXMLNodesList.Count = 0 then Exit;
  5321. AddProgressForm(5, '开始对比...');
  5322. // CompareItem(vItem);
  5323. // RcsvCompareItems(TScBillsItem(vItem.FirstChild));
  5324. RcsvCompareItems(vItem);
  5325. CompareDeleted;
  5326. finally
  5327. FCompareCDS.First;
  5328. CloseProgressForm;
  5329. Screen.Cursor := crDefault;
  5330. end;
  5331. end;
  5332. function IsCheckMatched(AXMLNode: TXmlNode; ARec: TScRationRecord): Boolean;
  5333. var isSameAdjustState: Boolean;
  5334. sN, sR: string;
  5335. begin
  5336. Result := False;
  5337. // 判断定额调整状态
  5338. isSameAdjustState := True;
  5339. // if AXMLNode.HasAttribute('AdjustStr') and (AXMLNode.AttributeAdd('AdjustStr'] <> '') then
  5340. // begin
  5341. // // xml 多了()、尾部分号和空格
  5342. // sN := Trim(AXMLNode.AttributeAdd('AdjustStr']);
  5343. // sN := StringReplace(sN, '(', '', [rfReplaceAll, rfIgnoreCase]);
  5344. // sN := StringReplace(sN, ')', '', [rfReplaceAll, rfIgnoreCase]);
  5345. // sR := ARec.AdjustState.AsString + ';';
  5346. // // AnsiToUtf8()
  5347. // isSameAdjustState := (sN = sR);
  5348. // end;
  5349. if (AXMLNode.AttributeValueByNameUTF8['Code'] = Null) or (AXMLNode.AttributeValueByNameUTF8['Code'] = '') then
  5350. begin
  5351. Result := isSameAdjustState and (AXMLNode.AttributeValueByNameUTF8['Name'] = ARec.Name.AsString);
  5352. end
  5353. else
  5354. begin
  5355. Result := isSameAdjustState and (AXMLNode.AttributeValueByNameUTF8['Code'] = ARec.Code.AsString);
  5356. end;
  5357. end;
  5358. function TtzslXMLPort.SameFullCode(AXMLNodeFullCode: string; AItem: TScBillsItem): Boolean;
  5359. var sIC: string;
  5360. begin
  5361. sIC := GetCompareFullCode(AItem);
  5362. // XML可以不导出父层,此时FullCode不完整,所以只能用部分匹配比较。
  5363. Result := Pos(AXMLNodeFullCode, sIC) > 0;
  5364. end;
  5365. procedure TtzslXMLPort.UpdateItem(AItem: TScBillsItem);
  5366. var i, j, k, x: Integer;
  5367. vBNode, vRNode, vRLNode, vDQLNode: TXmlNode;
  5368. vRationList: TList;
  5369. vRRec: TScRationRecord;
  5370. sBI: string;
  5371. fValue, fValue1, fValue2: Double;
  5372. sFCode,sName: string;
  5373. const vArr: array[0..2] of String = ('RationList', 'MultiList', 'DeviceList');
  5374. begin
  5375. // if AItem.HasChildren then Exit; // 暂时只更新叶子清单,及其下定额。
  5376. sBI := AItem.Code + ' ' + AItem.B_Code + ' ' + AItem.Name;
  5377. AddProgressForm(1, '正在更新清单“' + sBI + '”...');
  5378. vRationList := TList.Create;
  5379. try
  5380. for i := 0 to FXMLNodesList.Count - 1 do
  5381. begin
  5382. vBNode := PXMLNode(FXMLNodesList[i]).Data;
  5383. sFCode := PXMLNode(FXMLNodesList[i]).FullCode;
  5384. sName := vBNode.AttributeValueByNameUTF8['Name'];
  5385. // 先匹配正确的清单。
  5386. if (AItem.Code = vBNode.AttributeValueByNameUTF8['Code'])
  5387. and (AItem.B_Code = vBNode.AttributeValueByNameUTF8[FB_CodeFieldName])
  5388. and (AItem.Name = sName)
  5389. and SameFullCode(sFCode, AItem) then
  5390. begin
  5391. // 清单
  5392. fValue := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['Quantity']);
  5393. fValue1 := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['DgnQuantity1']);
  5394. fValue2 := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['DgnQuantity2']);
  5395. if (AItem.Rec.Quantity.AsFloat <> fValue)
  5396. or (AItem.Rec.DesignQuantity.AsFloat <> fValue1)
  5397. or (AItem.Rec.DesignQuantity2.AsFloat <> fValue2) then
  5398. begin
  5399. AItem.Rec.BeginUpdate;
  5400. AItem.Rec.Quantity.AsVariant := fValue;
  5401. AItem.Rec.DesignQuantity.AsVariant := fValue1;
  5402. AItem.Rec.DesignQuantity2.AsVariant := fValue2;
  5403. AItem.Rec.EndUpdate;
  5404. end;
  5405. // // 定额、量价、设备
  5406. for x := 0 to High(vArr) do
  5407. begin
  5408. vRLNode := vBNode.FindNode(vArr[x]);
  5409. if (vRLNode <> nil) and (vRLNode.ElementCount > 0) then
  5410. begin
  5411. TScProject(FProject).Rations.GetRations(AItem.ID, vRationList);
  5412. for j := 0 to vRationList.Count - 1 do
  5413. begin
  5414. vRRec := TScRationRecord(vRationList[j]);
  5415. AddProgressForm(1, Format('正在更新定额:%s %s(清单:%s)', [vRRec.Code.AsString, vRRec.Name.AsString, sBI]));
  5416. for k := 0 to vRLNode.ElementCount - 1 do
  5417. begin
  5418. vRNode := vRLNode.Elements[k];
  5419. if IsCheckMatched(vRNode, vRRec) then
  5420. begin
  5421. fValue := XMLSafeDouble(vRNode.AttributeValueByNameUTF8['Quantity']);
  5422. if fValue <> vRRec.Quantity.AsVariant then
  5423. begin
  5424. vRRec.BeginUpdate;
  5425. vRRec.Quantity.AsVariant := fValue;
  5426. vRRec.EndUpdate;
  5427. end;
  5428. Break;
  5429. end;
  5430. end;
  5431. end;
  5432. end;
  5433. end;
  5434. // 图纸工程量
  5435. vDQLNode := vBNode.FindNode('DrawingQuantityList');
  5436. if (vDQLNode <> nil) and (vDQLNode.ElementCount > 0) then
  5437. begin
  5438. TScProject(FProject).Bills.DrawingQuantityDM.UpdateDQsByXML(AItem, vDQLNode);
  5439. end;
  5440. // 匹配成功,移出列表,提高后续效率
  5441. FXMLNodesList.Delete(i);
  5442. Break;
  5443. end;
  5444. end;
  5445. finally
  5446. vRationList.Free;
  5447. end;
  5448. end;
  5449. { 算法原理: 2021.04.01 CSL
  5450. 将XML文件中的结点抽出来,存成线性结构A。递归造价书的树结点,跟A对比:
  5451. ① 匹配成功的,a.判断有没有修改数量。b.从A中删除,以减少后续匹配量,提高效率,
  5452. 且为重要的第③步提供基础数据。
  5453. ② 没匹配成功的(A中找不到),表示造价书新增了结点。
  5454. ③ A剩余的,表示造价书中删除了。CompareDeleted()方法中处理 }
  5455. procedure TtzslXMLPort.CompareItem(AItem: TScBillsItem);
  5456. var i, j, k: Integer;
  5457. vBNode, vRNode, vRLNode, vDQLNode: TXmlNode;
  5458. vRItemList, vRNodeList: TList;
  5459. vRRec: TScRationRecord;
  5460. sBI, sState, sFCode: string;
  5461. fValue, fValue1, fValue2: Double;
  5462. isMatched, isRationMatched: Boolean;
  5463. procedure GetXMLRations(ABNode: TXmlNode; AList: TList);
  5464. var n, x: Integer;
  5465. vRLNode, vCurNode: TXmlNode;
  5466. const vArr: array[0..2] of String = ('RationList', 'MultiList', 'DeviceList');
  5467. const vNames: array[0..2] of String = ('定额', '量价', '设备');
  5468. begin
  5469. while AList.Count > 0 do
  5470. AList.Delete(0);
  5471. for x := 0 to High(vArr) do
  5472. begin
  5473. vRLNode := ABNode.FindNode(vArr[x]);
  5474. if (vRLNode <> nil) and (vRLNode.ElementCount > 0) then
  5475. begin
  5476. for n := 0 to vRLNode.ElementCount - 1 do
  5477. begin
  5478. vCurNode := vRLNode.Elements[n];
  5479. vCurNode.AttributeAddUTF8('kind', vNames[x]);
  5480. AList.Add(Pointer(vCurNode));
  5481. end;
  5482. end;
  5483. end;
  5484. end;
  5485. begin
  5486. // if AItem.HasChildren then Exit; // 暂时只更新叶子清单,及其下定额。
  5487. sBI := AItem.Code + ' ' + AItem.B_Code + ' ' + AItem.Name;
  5488. AddProgressForm(1, '正在对比清单“' + sBI + '”...');
  5489. isMatched := False;
  5490. vRItemList := TList.Create;
  5491. vRNodeList := TList.Create;
  5492. try
  5493. for i := 0 to FXMLNodesList.Count - 1 do
  5494. begin
  5495. vBNode := PXMLNode(FXMLNodesList[i]).Data;
  5496. sFCode := PXMLNode(FXMLNodesList[i]).FullCode;
  5497. // 先匹配正确的清单。
  5498. if (AItem.Code = vBNode.AttributeValueByNameUTF8['Code'])
  5499. and (AItem.B_Code = vBNode.AttributeValueByNameUTF8[FB_CodeFieldName])
  5500. and (AItem.Name = vBNode.AttributeValueByNameUTF8['Name'])
  5501. and SameFullCode(sFCode, AItem) then
  5502. begin
  5503. // 清单
  5504. fValue := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['Quantity']);
  5505. fValue1 := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['DgnQuantity1']);
  5506. fValue2 := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['DgnQuantity2']);
  5507. if (AItem.Rec.Quantity.AsFloat <> fValue)
  5508. or (AItem.Rec.DesignQuantity.AsFloat <> fValue1)
  5509. or (AItem.Rec.DesignQuantity2.AsFloat <> fValue2) then
  5510. begin
  5511. FCompareCDS.Append;
  5512. FCompareCDS.FieldByName('BillID').AsInteger := AItem.ID;
  5513. FCompareCDS.FieldByName('Operate').AsString := '修改';
  5514. FCompareCDS.FieldByName('Kind').AsString := GetBillKindName(AItem);
  5515. FCompareCDS.FieldByName('Code').AsString := AItem.Code + AItem.B_Code; // 合并显示
  5516. // FCompareCDS.FieldByName('B_Code').AsString := AItem.B_Code;
  5517. FCompareCDS.FieldByName('Name').AsString := AItem.Name;
  5518. // 以下为三大数量变动描述
  5519. sState := '';
  5520. if AItem.Rec.Quantity.AsFloat <> fValue then
  5521. // FCompareCDS.FieldByName('Quantity').AsString := Format('%g[%g]', [AItem.Rec.Quantity.AsFloat, fValue]);
  5522. sState := Format('数量%g改%g', [fValue, AItem.Rec.Quantity.AsFloat]);
  5523. if AItem.Rec.DesignQuantity.AsFloat <> fValue1 then
  5524. // FCompareCDS.FieldByName('DgnQuantity1').AsString := Format('%g[%g]', [AItem.Rec.DesignQuantity.AsFloat, fValue1]);
  5525. sState := sState + Format(',设一%g改%g', [fValue1, AItem.Rec.DesignQuantity.AsFloat]);
  5526. if AItem.Rec.DesignQuantity2.AsFloat <> fValue2 then
  5527. // FCompareCDS.FieldByName('DgnQuantity2').AsString := Format('%g[%g]', [AItem.Rec.DesignQuantity2.AsFloat, fValue2]);
  5528. sState := sState + Format(',设二%g改%g', [fValue2, AItem.Rec.DesignQuantity2.AsFloat]);
  5529. if sState <> '' then
  5530. begin
  5531. if Pos(',', sState) = 1 then
  5532. Delete(sState, 1, 2);
  5533. FCompareCDS.FieldByName('Quantity').AsString := sState;
  5534. end;
  5535. FCompareCDS.Post;
  5536. end;
  5537. // 定额对比 ↓↓↓------------------------------------------------------
  5538. TScProject(FProject).Rations.GetRations(AItem.ID, vRItemList);
  5539. GetXMLRations(vBNode, vRNodeList);
  5540. for j := 0 to vRItemList.Count - 1 do
  5541. begin
  5542. isRationMatched := False;
  5543. vRRec := TScRationRecord(vRItemList[j]);
  5544. AddProgressForm(1, Format('正在更新定额:%s %s(清单:%s)', [vRRec.Code.AsString, vRRec.Name.AsString, sBI]));
  5545. for k := 0 to vRNodeList.Count - 1 do
  5546. begin
  5547. vRNode := TXmlNode(vRNodeList[k]);
  5548. // if vRNode.AttributeAdd('Code'] = vRRec.Code.AsVariant then
  5549. if IsCheckMatched(vRNode, vRRec) then
  5550. begin
  5551. isRationMatched := True;
  5552. fValue := XMLSafeDouble(vRNode.AttributeValueByNameUTF8['Quantity']);
  5553. if fValue <> vRRec.Quantity.AsFloat then
  5554. begin
  5555. FCompareCDS.Append;
  5556. FCompareCDS.FieldByName('BillID').AsInteger := AItem.ID;
  5557. FCompareCDS.FieldByName('RationID').AsInteger := vRRec.ID.AsInteger;
  5558. FCompareCDS.FieldByName('Operate').AsString := '修改';
  5559. FCompareCDS.FieldByName('Kind').AsString := vRNode.AttributeValueByNameUTF8['kind'];
  5560. FCompareCDS.FieldByName('Code').AsString := vRRec.Code.AsString;
  5561. FCompareCDS.FieldByName('Name').AsString := vRRec.Name.AsString;
  5562. FCompareCDS.FieldByName('Quantity').AsString := Format('工程量%g改%g', [fValue, vRRec.Quantity.AsFloat]);
  5563. FCompareCDS.Post;
  5564. end;
  5565. vRNodeList.Delete(k);
  5566. Break;
  5567. end;
  5568. end;
  5569. if not isRationMatched then
  5570. begin
  5571. FCompareCDS.Append;
  5572. FCompareCDS.FieldByName('BillID').AsInteger := AItem.ID;
  5573. FCompareCDS.FieldByName('RationID').AsInteger := vRRec.ID.AsInteger;
  5574. FCompareCDS.FieldByName('Operate').AsString := '增加';
  5575. FCompareCDS.FieldByName('Kind').AsString := GetRationKindName(vRRec);
  5576. FCompareCDS.FieldByName('Code').AsString := vRRec.Code.AsString;
  5577. FCompareCDS.FieldByName('Name').AsString := vRRec.Name.AsString;
  5578. FCompareCDS.FieldByName('Quantity').AsString := Format('工程量%g', [vRRec.Quantity.AsFloat]);
  5579. FCompareCDS.Post;
  5580. end;
  5581. end;
  5582. if vRNodeList.Count > 0 then
  5583. begin
  5584. for k := 0 to vRNodeList.Count - 1 do
  5585. begin
  5586. vRNode := TXmlNode(vRNodeList[k]);
  5587. FCompareCDS.Append;
  5588. FCompareCDS.FieldByName('BillID').AsInteger := AItem.ID;
  5589. FCompareCDS.FieldByName('Operate').AsString := '删除';
  5590. FCompareCDS.FieldByName('Kind').AsString := vRNode.AttributeValueByNameUTF8['kind'];
  5591. FCompareCDS.FieldByName('Code').AsString := vRNode.AttributeValueByNameUTF8['Code'];
  5592. FCompareCDS.FieldByName('Name').AsString := vRNode.AttributeValueByNameUTF8['Name'];
  5593. FCompareCDS.FieldByName('Quantity').AsString := Format('工程量%s', [vRNode.AttributeValueByNameUTF8['Quantity']]);
  5594. FCompareCDS.Post;
  5595. end;
  5596. end;
  5597. // 定额对比 ↑↑↑------------------------------------------------------
  5598. // 图纸工程量:暂不提供,先屏蔽。
  5599. // vDQLNode := vBNode.FindNode('DrawingQuantityList');
  5600. // if (vDQLNode <> nil) and (vDQLNode.ElementCount > 0) then
  5601. // begin
  5602. // TScProject(FProject).Bills.DrawingQuantityDM.CompareDQsByXML(AItem, vDQLNode, FCompareCDS);
  5603. // end;
  5604. // 匹配成功,移出列表,提高后续效率
  5605. FXMLNodesList.Delete(i);
  5606. isMatched := True;
  5607. Break;
  5608. end;
  5609. end;
  5610. if not isMatched then
  5611. begin
  5612. FCompareCDS.Append;
  5613. FCompareCDS.FieldByName('BillID').AsInteger := AItem.ID;
  5614. FCompareCDS.FieldByName('Operate').AsString := '增加';
  5615. FCompareCDS.FieldByName('Kind').AsString := GetBillKindName(AItem);
  5616. FCompareCDS.FieldByName('Code').AsString := AItem.Code + AItem.B_Code;
  5617. // FCompareCDS.FieldByName('B_Code').AsString := AItem.B_Code;
  5618. FCompareCDS.FieldByName('Name').AsString := AItem.Name;
  5619. sState := '';
  5620. if AItem.Rec.Quantity.AsFloat <> 0 then
  5621. sState := Format('数量%g', [AItem.Rec.Quantity.AsFloat]);
  5622. if AItem.Rec.DesignQuantity.AsFloat <> 0 then
  5623. sState := sState + Format(',设一%g', [AItem.Rec.DesignQuantity.AsFloat]);
  5624. if AItem.Rec.DesignQuantity2.AsFloat <> 0 then
  5625. sState := sState + Format(',设二%g', [AItem.Rec.DesignQuantity2.AsFloat]);
  5626. if Pos(',', sState) = 1 then
  5627. Delete(sState, 1, 2);
  5628. FCompareCDS.FieldByName('Quantity').AsString := sState;
  5629. FCompareCDS.Post;
  5630. end;
  5631. finally
  5632. vRItemList.Free;
  5633. vRNodeList.Free;
  5634. end;
  5635. end;
  5636. procedure TtzslXMLPort.CompareDeleted;
  5637. var i: Integer;
  5638. vBNode: TXmlNode;
  5639. fValue, fValue1, fValue2: Double;
  5640. sState: string;
  5641. begin
  5642. for i := 0 to FXMLNodesList.Count - 1 do
  5643. begin
  5644. vBNode := PXMLNode(FXMLNodesList[i]).Data;
  5645. FCompareCDS.Append;
  5646. FCompareCDS.FieldByName('Operate').AsString := '删除';
  5647. FCompareCDS.FieldByName('Kind').AsString := GetBillKindName(vBNode);
  5648. FCompareCDS.FieldByName('Code').AsString := vBNode.AttributeValueByNameUTF8['Code'] + vBNode.AttributeValueByNameUTF8[FB_CodeFieldName];
  5649. FCompareCDS.FieldByName('Name').AsString := vBNode.AttributeValueByNameUTF8['Name'];
  5650. fValue := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['Quantity']);
  5651. fValue1 := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['DgnQuantity1']);
  5652. fValue2 := XMLSafeDouble(vBNode.AttributeValueByNameUTF8['DgnQuantity2']);
  5653. sState := '';
  5654. if fValue <> 0 then
  5655. sState := Format('数量%g', [fValue]);
  5656. if fValue1 <> 0 then
  5657. sState := sState + Format(',设一%g', [fValue1]);
  5658. if fValue2 <> 0 then
  5659. sState := sState + Format(',设二%g', [fValue2]);
  5660. if Pos(',', sState) = 1 then
  5661. Delete(sState, 1, 2);
  5662. FCompareCDS.FieldByName('Quantity').AsString := sState;
  5663. FCompareCDS.Post;
  5664. end;
  5665. end;
  5666. function TtzslXMLPort.GetBillKindName(AItem: TScBillsItem): string;
  5667. begin
  5668. if AItem.B_Code <> '' then
  5669. Result := '清单'
  5670. else
  5671. Result := '分项';
  5672. end;
  5673. function TtzslXMLPort.GetBillKindName(ANode: TXmlNode): string;
  5674. begin
  5675. if ANode.HasAttribute(FB_CodeFieldName) and (ANode.AttributeValueByNameUTF8[FB_CodeFieldName] <> '') then
  5676. Result := '清单'
  5677. else
  5678. Result := '分项';
  5679. end;
  5680. procedure TtzslXMLPort.AssignNode(ANode: TXmlNode; AItem: TScBillsItem);
  5681. begin
  5682. with AItem.Rec do
  5683. begin
  5684. BeginUpdate;
  5685. if FIsBills then
  5686. Code.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8[FB_CodeFieldName])
  5687. else
  5688. begin
  5689. Code.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['Code']);
  5690. B_Code.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8[FB_CodeFieldName]);
  5691. end;
  5692. Name.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['Name']);
  5693. Units.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['Units']);
  5694. Quantity.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['Quantity']);
  5695. DesignQuantity.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['DgnQuantity1']);
  5696. DesignQuantity2.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['DgnQuantity2']);
  5697. // 下面这三项有值时,导不进来。
  5698. // UnitPrice.AsVariant := ANode.AttributeValueByName['UnitPrice'];
  5699. // DesignPrice.AsVariant := ANode.AttributeValueByName['DgnPrice'];
  5700. // TotalPrice.AsVariant := ANode.AttributeValueByName['TotalPrice'];
  5701. MemoStr.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['MemoStr']);
  5702. IsCreatePriceAnalysis.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['IsCreatePriceAnalysis']);
  5703. IsQDYS.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['IsQDYS']);
  5704. if ANode.HasAttribute('InterimType') and (ANode.AttributeValueByNameUTF8['InterimType'] <> '') then // Excel 即使导出无值,导入时也有属性,值为''
  5705. begin
  5706. IsSpecialInterim.AsBoolean := True;
  5707. InterimType.AsVariant := XMLSafeVariant(ANode.AttributeValueByNameUTF8['InterimType']);
  5708. end;
  5709. EndUpdate;
  5710. end;
  5711. end;
  5712. procedure TtzslXMLPort.AddRations(ANode: TXmlNode; AItem: TScBillsItem; var ASerialNo: Integer);
  5713. var vRL: TXmlNode;
  5714. begin
  5715. vRL := ANode.FindNode('RationList');
  5716. if vRL = nil then Exit;
  5717. TScProject(FProject).Rations.AddRationsFromXML(AItem, vRL, ASerialNo);
  5718. end;
  5719. procedure TtzslXMLPort.AddCountPrice(ANode: TXmlNode; AItem: TScBillsItem; ASerialNo: Integer);
  5720. var vRL: TXmlNode;
  5721. begin
  5722. vRL := ANode.FindNode('MultiList');
  5723. if vRL = nil then Exit;
  5724. TScProject(FProject).Rations.AddCountPriceFromXML(AItem, vRL, False, ASerialNo);
  5725. end;
  5726. procedure TtzslXMLPort.AddEquipment(ANode: TXmlNode; AItem: TScBillsItem);
  5727. var vRL: TXmlNode;
  5728. begin
  5729. vRL := ANode.FindNode('DeviceList');
  5730. if vRL = nil then Exit;
  5731. TScProject(FProject).Rations.AddEquipmentFromXML(AItem, vRL);
  5732. end;
  5733. procedure TtzslXMLPort.AddDQs(ANode: TXmlNode; AItem: TScBillsItem);
  5734. var vDQL: TXmlNode;
  5735. begin
  5736. vDQL := ANode.FindNode('DrawingQuantityList');
  5737. if vDQL = nil then Exit;
  5738. TScProject(FProject).Bills.DrawingQuantityDM.AddDrawingQuantityFromXML(AItem, vDQL);
  5739. end;
  5740. procedure TtzslXMLPort.AddGroundCompensate(ANode: TXmlNode; AItem: TScBillsItem);
  5741. var vGC: TXmlNode;
  5742. begin
  5743. vGC := ANode.FindNode('Ground');
  5744. if not Assigned(vGC) then Exit;
  5745. BillsTree.SelectedIndex := BillsTree.IndexOf(AItem);
  5746. TScProject(FProject).LeafTreesDM.TreeManager.AddLeafTreeFromXML(FProject, AItem, vGC);
  5747. end;
  5748. procedure TtzslXMLPort.RcsvAddBills(ANode: TXmlNode; AParentItem: TScBillsItem);
  5749. function CodeFieldName: string;
  5750. begin
  5751. if FIsBills then
  5752. Result := FB_CodeFieldName
  5753. else
  5754. Result := 'Code';
  5755. end;
  5756. function NodeLevel(ACode: string): Integer;
  5757. var
  5758. iPos: Integer;
  5759. strTemp: string;
  5760. begin
  5761. Result := 0;
  5762. strTemp := ACode;
  5763. repeat
  5764. iPos := Pos('-', strTemp);
  5765. if iPos > 0 then
  5766. begin
  5767. Inc(Result);
  5768. strTemp := Copy(strTemp, iPos + 1, Length(strTemp) - iPos);
  5769. end;
  5770. until iPos <= 0;
  5771. end;
  5772. function CutLastPart(ACode: string): string;
  5773. var
  5774. I: Integer;
  5775. begin
  5776. Result := '';
  5777. for I := Length(ACode) downto 1 do
  5778. if SameText(ACode[I], '-') then
  5779. begin
  5780. Result := Copy(ACode, 1, I - 1);
  5781. Break;
  5782. end;
  5783. end;
  5784. function InChapter(AChapterName, AChildCode: string): Boolean;
  5785. var
  5786. iPosDi, iChapterNum, iChildNum: Integer;
  5787. chChapter, chChild: Char;
  5788. begin
  5789. Result := False;
  5790. if (AChapterName = '') or (AChildCode = '') then Exit;
  5791. iPosDi := Pos('第', AChapterName);
  5792. if (iPosDi <= 0) and (Pos('00章', AChapterName) <= 0) then
  5793. Exit;
  5794. chChapter := AChapterName[iPosDi + 2];
  5795. chChild := AChildCode[1];
  5796. Result := (chChapter in ['1'..'9']) and (chChild in ['1'..'9']) and (chChapter = chChild);
  5797. end;
  5798. function IsChapter(AChapterName: string): Boolean;
  5799. begin
  5800. Result := (Pos('第', AChapterName) > 0) and (Pos('00章', AChapterName) > 0);
  5801. end;
  5802. function GetFirstChild: TXmlNode;
  5803. var
  5804. NextNode: TXmlNode;
  5805. strCode, strName, strNextCode: string;
  5806. begin
  5807. Result := nil;
  5808. NextNode := ANode.NextSibling(ANode);
  5809. if NextNode = nil then Exit;
  5810. strCode := ANode.AttributeValueByNameUTF8[CodeFieldName];
  5811. strName := ANode.AttributeValueByNameUTF8['Name'];
  5812. strNextCode := NextNode.AttributeValueByNameUTF8[CodeFieldName];
  5813. // 101 -> 101-1 或 第100章 -> 101
  5814. if ((strCode <> '') and SameText(strCode, CutLastPart(strNextCode))) or InChapter(strName, strNextCode) then
  5815. begin
  5816. Result := NextNode;
  5817. FXMLNodeList.Add(TXMLNode(Result));
  5818. end;
  5819. end;
  5820. function GetNextSibling: TXmlNode;
  5821. var
  5822. NextNode: TXmlNode;
  5823. strCode, strName, strNextCode, strNextName: string;
  5824. begin
  5825. Result := nil;
  5826. NextNode := ANode.NextSibling(ANode);
  5827. while NextNode <> nil do
  5828. begin
  5829. // 已加过的节点Continue
  5830. if FXMLNodeList.IndexOf(TXMLNode(NextNode)) >= 0 then
  5831. begin
  5832. NextNode := NextNode.NextSibling(NextNode);
  5833. Continue;
  5834. end;
  5835. strCode := ANode.AttributeValueByNameUTF8[CodeFieldName];
  5836. strName := ANode.AttributeValueByNameUTF8['Name'];
  5837. strNextCode := NextNode.AttributeValueByNameUTF8[CodeFieldName];
  5838. strNextName := NextNode.AttributeValueByNameUTF8['Name'];
  5839. //if (strCode='502') and (strNextCode='503') then
  5840. // MessageHint(Format('Code: %s, %s; level: %d, %d; p: %s, %s', [strCode, strNextCode, NodeLevel(strCode), NodeLevel(strNextCode), CutLastPart(strCode), CutLastPart(strNextCode)]));
  5841. // 101 -> 102 // 层次相同 // 编号前面部分相同
  5842. //if ((strCode <> '') and (strNextCode <> '') and (NodeLevel(strCode) = NodeLevel(strNextCode)) and SameText(CutLastPart(strCode), CutLastPart(strNextCode)))
  5843. // 遇到另一章中止
  5844. if (strCode <> '') and (strNextCode = '') and IsChapter(strNextName) then
  5845. Break;
  5846. // 101 -> 102
  5847. if ((strCode <> '') and (strNextCode <> '') and (SameText(AParentItem.Code, CutLastPart(strNextCode)) // 是否同父节点
  5848. or (IsChapter(AParentItem.Name) and InChapter(AParentItem.Name, strNextCode)))) // 全国清单缺中间层次节点,底层直接挂在章节点下
  5849. or (IsChapter(strName) and IsChapter(strNextName)) then //或 第100章 -> 第200章
  5850. begin
  5851. Result := NextNode;
  5852. FXMLNodeList.Add(TXMLNode(Result));
  5853. Break;
  5854. end;
  5855. NextNode := NextNode.NextSibling(NextNode);
  5856. end;
  5857. end;
  5858. var
  5859. vItem: TScBillsItem;
  5860. iID, iSN: Integer;
  5861. sCode, sName: string;
  5862. firstNode, ChildNode, NextSiblingNode: TXmlNode;
  5863. begin
  5864. if ANode = nil then Exit;
  5865. if ANode.Name <> 'Bills' then Exit;
  5866. iID := -1;
  5867. if (ANode.AttributeValueByNameUTF8[CodeFieldName] <> '') then
  5868. begin
  5869. sCode := ANode.AttributeValueByNameUTF8[CodeFieldName];
  5870. sName := ANode.AttributeValueByNameUTF8['Name'];
  5871. if (sCode = '110') then iID := idSpecifyFee
  5872. else if (sCode = '11001') then iID := idSiteConstructItem
  5873. else if (sCode = '11002') then iID := idSafeProduction
  5874. // 土地部分
  5875. else if ((sCode = '20101') and (sName = '永久征用土地')) then iID := idGroundCompensate
  5876. else if ((sCode = '20102') and (sName = '临时用地')) then iID := idGroundTemporary
  5877. else if ((sCode = '202') and (sName = '拆迁补偿费')) then iID := idGroundRemove;
  5878. end;
  5879. if (iID <> -1) then
  5880. vItem := BillsTree.AddBillsItem(iID, AParentItem.ID, -1)
  5881. else
  5882. vItem := BillsTree.AddBillsItem(AParentItem.ID, -1);
  5883. AssignNode(ANode, vItem);
  5884. AddProgressForm(1, Format('正在导入清单:%s %s %s', [vItem.Code, vItem.B_Code, vItem.Name]));
  5885. iSN := 1;
  5886. AddRations(ANode, vItem, iSN);
  5887. AddCountPrice(ANode, vItem, iSN); // 导入量价
  5888. AddEquipment(ANode, vItem); // 导入设备
  5889. AddDQs(ANode, vItem);
  5890. AddGroundCompensate(ANode, vItem); // 导入土地
  5891. // 算量导出的清单类型xml全部是平级,所以要特殊处理
  5892. if FIsBills then
  5893. begin
  5894. ChildNode := GetFirstChild;
  5895. if ChildNode <> nil then
  5896. RcsvAddBills(ChildNode, vItem);
  5897. NextSiblingNode := GetNextSibling;
  5898. if NextSiblingNode <> nil then
  5899. RcsvAddBills(NextSiblingNode, AParentItem);
  5900. end
  5901. else
  5902. begin
  5903. // 当父清单有子结点<DrawingQuantityList>、<Bills>时,第一孩子不符合条件退出,导致后兄弟<Bills>无法导入。此时第一孩子老大不行应换老二来。
  5904. firstNode := ANode.Elements[0];
  5905. if Assigned(firstNode) then
  5906. begin
  5907. if (firstNode.Name = 'DrawingQuantityList') then
  5908. RcsvAddBills(firstNode.NextSibling(firstNode), vItem)
  5909. else
  5910. RcsvAddBills(firstNode, vItem);
  5911. end;
  5912. if Assigned(ANode.NextSibling(ANode)) then
  5913. RcsvAddBills(ANode.NextSibling(ANode), AParentItem);
  5914. end;
  5915. end;
  5916. function TtzslXMLPort.GetRationKindName(ARec: TScRationRecord): string;
  5917. begin
  5918. if ARec.IsMECalc.AsBoolean then
  5919. Result := '设备'
  5920. else if ARec.RationType.AsInteger = 1 then
  5921. Result := '量价'
  5922. else
  5923. Result := '定额';
  5924. end;
  5925. { TExcelToXMLPort }
  5926. function TExcelBlockXMLPort.CheckXMLFile: Boolean;
  5927. var
  5928. sType: string;
  5929. iProjType: Integer;
  5930. begin
  5931. FInfo := FRoot.FindNode('Info');
  5932. FBillList := FRoot.FindNode('BillList');
  5933. FFirstBill := FBillList.Elements[0];
  5934. Result := True;
  5935. end;
  5936. procedure TExcelBlockXMLPort.LoadFromXML;
  5937. var
  5938. OldRealTimeCalc: Boolean;
  5939. vItem, vFirstChildItem, curItem: TScBillsItem;
  5940. sFile: string;
  5941. eaSL: TStringList;
  5942. curNode: TXmlNode;
  5943. i: Integer;
  5944. begin
  5945. if not FileExists(FXMLFile) then Exit;
  5946. FXMLDoc.LoadFromFile(FXMLFile);
  5947. CheckB_CodeFieldName;
  5948. CheckXMLFile;
  5949. Screen.Cursor := crHourGlass;
  5950. CreateProgressForm(100, '导入Excel块文件');
  5951. OldRealTimeCalc := TScProject(FProject).RealTimeCalc;
  5952. eaSL := TScProject(FProject).Rations.RAdjusts.ErrorAdjustList;
  5953. eaSL.Clear;
  5954. try
  5955. TScProject(FProject).RealTimeCalc := False;
  5956. vItem := TScBillsItem(BillsTree.Selected); // (选择位置后)新插入的空行
  5957. AddProgressForm(10, '正在导入清单、定额、图纸算量...');
  5958. RcsvAddBills(FFirstBill, vItem);
  5959. // 修正树结构:上述操作后,所有项变成空行的子项。这些子项全部要先升级(从最后一个子结点开始)。
  5960. for i := vItem.ChildCount - 1 downto 0 do
  5961. begin
  5962. curItem := TScBillsItem(vItem.ChildNodes[i]);
  5963. curItem.UpLevel;
  5964. end;
  5965. // 再删除空行
  5966. BillsTree.DeleteNode(vItem);
  5967. AddProgressForm(60, '正在全局造价计算...');
  5968. TScProject(FProject).Bills.CalculateAll;
  5969. if eaSL.Count > 0 then
  5970. begin
  5971. MessageWarning(0, Format('Excel块导入完成,但有%d条定额的调整状态来自旧版本,无法识别,请手工调整。',[eaSL.Count]));
  5972. sFile := ExtractFilePath(Application.ExeName) + '\UserData\导入Excel块调整失败定额.txt';
  5973. eaSL.SaveToFile(sFile);
  5974. ShellExecute(Application.Handle, 'open', PChar('NOTEPAD.EXE'), PChar(sFile), nil, SW_SHOW);
  5975. end;
  5976. finally
  5977. eaSL.Clear;
  5978. TScProject(FProject).RealTimeCalc := OldRealTimeCalc;
  5979. CloseProgressForm;
  5980. Screen.Cursor := crDefault;
  5981. end;
  5982. end;
  5983. end.