styles.go 112 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822
  1. // Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
  2. // this source code is governed by a BSD-style license that can be found in
  3. // the LICENSE file.
  4. //
  5. // Package excelize providing a set of functions that allow you to write to and
  6. // read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
  7. // writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
  8. // Supports complex components by high compatibility, and provided streaming
  9. // API for generating or reading data from a worksheet with huge amounts of
  10. // data. This library needs Go version 1.16 or later.
  11. package excelize
  12. import (
  13. "bytes"
  14. "encoding/xml"
  15. "fmt"
  16. "io"
  17. "math"
  18. "reflect"
  19. "sort"
  20. "strconv"
  21. "strings"
  22. )
  23. // Excel styles can reference number formats that are built-in, all of which
  24. // have an id less than 164. Note that this number format code list is under
  25. // English localization.
  26. var builtInNumFmt = map[int]string{
  27. 0: "general",
  28. 1: "0",
  29. 2: "0.00",
  30. 3: "#,##0",
  31. 4: "#,##0.00",
  32. 9: "0%",
  33. 10: "0.00%",
  34. 11: "0.00e+00",
  35. 12: "# ?/?",
  36. 13: "# ??/??",
  37. 14: "mm-dd-yy",
  38. 15: "d-mmm-yy",
  39. 16: "d-mmm",
  40. 17: "mmm-yy",
  41. 18: "h:mm am/pm",
  42. 19: "h:mm:ss am/pm",
  43. 20: "hh:mm",
  44. 21: "hh:mm:ss",
  45. 22: "m/d/yy hh:mm",
  46. 37: "#,##0 ;(#,##0)",
  47. 38: "#,##0 ;[red](#,##0)",
  48. 39: "#,##0.00;(#,##0.00)",
  49. 40: "#,##0.00;[red](#,##0.00)",
  50. 41: `_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)`,
  51. 42: `_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)`,
  52. 43: `_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)`,
  53. 44: `_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)`,
  54. 45: "mm:ss",
  55. 46: "[h]:mm:ss",
  56. 47: "mmss.0",
  57. 48: "##0.0e+0",
  58. 49: "@",
  59. }
  60. // langNumFmt defined number format code (with unicode values provided for
  61. // language glyphs where they occur) in different language.
  62. var langNumFmt = map[string]map[int]string{
  63. "zh-tw": {
  64. 27: "[$-404]e/m/d",
  65. 28: `[$-404]e"年"m"月"d"日"`,
  66. 29: `[$-404]e"年"m"月"d"日"`,
  67. 30: "m/d/yy",
  68. 31: `yyyy"年"m"月"d"日"`,
  69. 32: `hh"時"mm"分"`,
  70. 33: `hh"時"mm"分"ss"秒"`,
  71. 34: `上午/下午 hh"時"mm"分"`,
  72. 35: `上午/下午 hh"時"mm"分"ss"秒"`,
  73. 36: "[$-404]e/m/d",
  74. 50: "[$-404]e/m/d",
  75. 51: `[$-404]e"年"m"月"d"日"`,
  76. 52: `上午/下午 hh"時"mm"分"`,
  77. 53: `上午/下午 hh"時"mm"分"ss"秒"`,
  78. 54: `[$-404]e"年"m"月"d"日"`,
  79. 55: `上午/下午 hh"時"mm"分"`,
  80. 56: `上午/下午 hh"時"mm"分"ss"秒"`,
  81. 57: "[$-404]e/m/d",
  82. 58: `[$-404]e"年"m"月"d"日"`,
  83. },
  84. "zh-cn": {
  85. 27: `yyyy"年"m"月"`,
  86. 28: `m"月"d"日"`,
  87. 29: `m"月"d"日"`,
  88. 30: "m-d-yy",
  89. 31: `yyyy"年"m"月"d"日"`,
  90. 32: `h"时"mm"分"`,
  91. 33: `h"时"mm"分"ss"秒"`,
  92. 34: `上午/下午 h"时"mm"分"`,
  93. 35: `上午/下午 h"时"mm"分"ss"秒"`,
  94. 36: `yyyy"年"m"月"`,
  95. 50: `yyyy"年"m"月"`,
  96. 51: `m"月"d"日"`,
  97. 52: `yyyy"年"m"月"`,
  98. 53: `m"月"d"日"`,
  99. 54: `m"月"d"日"`,
  100. 55: `上午/下午 h"时"mm"分"`,
  101. 56: `上午/下午 h"时"mm"分"ss"秒"`,
  102. 57: `yyyy"年"m"月"`,
  103. 58: `m"月"d"日"`,
  104. },
  105. "zh-tw_unicode": {
  106. 27: "[$-404]e/m/d",
  107. 28: `[$-404]e"5E74"m"6708"d"65E5"`,
  108. 29: `[$-404]e"5E74"m"6708"d"65E5"`,
  109. 30: "m/d/yy",
  110. 31: `yyyy"5E74"m"6708"d"65E5"`,
  111. 32: `hh"6642"mm"5206"`,
  112. 33: `hh"6642"mm"5206"ss"79D2"`,
  113. 34: `4E0A5348/4E0B5348hh"6642"mm"5206"`,
  114. 35: `4E0A5348/4E0B5348hh"6642"mm"5206"ss"79D2"`,
  115. 36: "[$-404]e/m/d",
  116. 50: "[$-404]e/m/d",
  117. 51: `[$-404]e"5E74"m"6708"d"65E5"`,
  118. 52: `4E0A5348/4E0B5348hh"6642"mm"5206"`,
  119. 53: `4E0A5348/4E0B5348hh"6642"mm"5206"ss"79D2"`,
  120. 54: `[$-404]e"5E74"m"6708"d"65E5"`,
  121. 55: `4E0A5348/4E0B5348hh"6642"mm"5206"`,
  122. 56: `4E0A5348/4E0B5348hh"6642"mm"5206"ss"79D2"`,
  123. 57: "[$-404]e/m/d",
  124. 58: `[$-404]e"5E74"m"6708"d"65E5"`,
  125. },
  126. "zh-cn_unicode": {
  127. 27: `yyyy"5E74"m"6708"`,
  128. 28: `m"6708"d"65E5"`,
  129. 29: `m"6708"d"65E5"`,
  130. 30: "m-d-yy",
  131. 31: `yyyy"5E74"m"6708"d"65E5"`,
  132. 32: `h"65F6"mm"5206"`,
  133. 33: `h"65F6"mm"5206"ss"79D2"`,
  134. 34: `4E0A5348/4E0B5348h"65F6"mm"5206"`,
  135. 35: `4E0A5348/4E0B5348h"65F6"mm"5206"ss"79D2"`,
  136. 36: `yyyy"5E74"m"6708"`,
  137. 50: `yyyy"5E74"m"6708"`,
  138. 51: `m"6708"d"65E5"`,
  139. 52: `yyyy"5E74"m"6708"`,
  140. 53: `m"6708"d"65E5"`,
  141. 54: `m"6708"d"65E5"`,
  142. 55: `4E0A5348/4E0B5348h"65F6"mm"5206"`,
  143. 56: `4E0A5348/4E0B5348h"65F6"mm"5206"ss"79D2"`,
  144. 57: `yyyy"5E74"m"6708"`,
  145. 58: `m"6708"d"65E5"`,
  146. },
  147. "ja-jp": {
  148. 27: "[$-411]ge.m.d",
  149. 28: `[$-411]ggge"年"m"月"d"日"`,
  150. 29: `[$-411]ggge"年"m"月"d"日"`,
  151. 30: "m/d/yy",
  152. 31: `yyyy"年"m"月"d"日"`,
  153. 32: `h"時"mm"分"`,
  154. 33: `h"時"mm"分"ss"秒"`,
  155. 34: `yyyy"年"m"月"`,
  156. 35: `m"月"d"日"`,
  157. 36: "[$-411]ge.m.d",
  158. 50: "[$-411]ge.m.d",
  159. 51: `[$-411]ggge"年"m"月"d"日"`,
  160. 52: `yyyy"年"m"月"`,
  161. 53: `m"月"d"日"`,
  162. 54: `[$-411]ggge"年"m"月"d"日"`,
  163. 55: `yyyy"年"m"月"`,
  164. 56: `m"月"d"日"`,
  165. 57: "[$-411]ge.m.d",
  166. 58: `[$-411]ggge"年"m"月"d"日"`,
  167. },
  168. "ko-kr": {
  169. 27: `yyyy"年" mm"月" dd"日"`,
  170. 28: "mm-dd",
  171. 29: "mm-dd",
  172. 30: "mm-dd-yy",
  173. 31: `yyyy"년" mm"월" dd"일"`,
  174. 32: `h"시" mm"분"`,
  175. 33: `h"시" mm"분" ss"초"`,
  176. 34: `yyyy-mm-dd`,
  177. 35: `yyyy-mm-dd`,
  178. 36: `yyyy"年" mm"月" dd"日"`,
  179. 50: `yyyy"年" mm"月" dd"日"`,
  180. 51: "mm-dd",
  181. 52: "yyyy-mm-dd",
  182. 53: "yyyy-mm-dd",
  183. 54: "mm-dd",
  184. 55: "yyyy-mm-dd",
  185. 56: "yyyy-mm-dd",
  186. 57: `yyyy"年" mm"月" dd"日"`,
  187. 58: "mm-dd",
  188. },
  189. "ja-jp_unicode": {
  190. 27: "[$-411]ge.m.d",
  191. 28: `[$-411]ggge"5E74"m"6708"d"65E5"`,
  192. 29: `[$-411]ggge"5E74"m"6708"d"65E5"`,
  193. 30: "m/d/yy",
  194. 31: `yyyy"5E74"m"6708"d"65E5"`,
  195. 32: `h"6642"mm"5206"`,
  196. 33: `h"6642"mm"5206"ss"79D2"`,
  197. 34: `yyyy"5E74"m"6708"`,
  198. 35: `m"6708"d"65E5"`,
  199. 36: "[$-411]ge.m.d",
  200. 50: "[$-411]ge.m.d",
  201. 51: `[$-411]ggge"5E74"m"6708"d"65E5"`,
  202. 52: `yyyy"5E74"m"6708"`,
  203. 53: `m"6708"d"65E5"`,
  204. 54: `[$-411]ggge"5E74"m"6708"d"65E5"`,
  205. 55: `yyyy"5E74"m"6708"`,
  206. 56: `m"6708"d"65E5"`,
  207. 57: "[$-411]ge.m.d",
  208. 58: `[$-411]ggge"5E74"m"6708"d"65E5"`,
  209. },
  210. "ko-kr_unicode": {
  211. 27: `yyyy"5E74" mm"6708" dd"65E5"`,
  212. 28: "mm-dd",
  213. 29: "mm-dd",
  214. 30: "mm-dd-yy",
  215. 31: `yyyy"B144" mm"C6D4" dd"C77C"`,
  216. 32: `h"C2DC" mm"BD84"`,
  217. 33: `h"C2DC" mm"BD84" ss"CD08"`,
  218. 34: "yyyy-mm-dd",
  219. 35: "yyyy-mm-dd",
  220. 36: `yyyy"5E74" mm"6708" dd"65E5"`,
  221. 50: `yyyy"5E74" mm"6708" dd"65E5"`,
  222. 51: "mm-dd",
  223. 52: "yyyy-mm-dd",
  224. 53: "yyyy-mm-dd",
  225. 54: "mm-dd",
  226. 55: "yyyy-mm-dd",
  227. 56: "yyyy-mm-dd",
  228. 57: `yyyy"5E74" mm"6708" dd"65E5"`,
  229. 58: "mm-dd",
  230. },
  231. "th-th": {
  232. 59: "t0",
  233. 60: "t0.00",
  234. 61: "t#,##0",
  235. 62: "t#,##0.00",
  236. 67: "t0%",
  237. 68: "t0.00%",
  238. 69: "t# ?/?",
  239. 70: "t# ??/??",
  240. 71: "ว/ด/ปปปป",
  241. 72: "ว-ดดด-ปป",
  242. 73: "ว-ดดด",
  243. 74: "ดดด-ปป",
  244. 75: "ช:นน",
  245. 76: "ช:นน:ทท",
  246. 77: "ว/ด/ปปปป ช:นน",
  247. 78: "นน:ทท",
  248. 79: "[ช]:นน:ทท",
  249. 80: "นน:ทท.0",
  250. 81: "d/m/bb",
  251. },
  252. "th-th_unicode": {
  253. 59: "t0",
  254. 60: "t0.00",
  255. 61: "t#,##0",
  256. 62: "t#,##0.00",
  257. 67: "t0%",
  258. 68: "t0.00%",
  259. 69: "t# ?/?",
  260. 70: "t# ??/??",
  261. 71: "0E27/0E14/0E1B0E1B0E1B0E1B",
  262. 72: "0E27-0E140E140E14-0E1B0E1B",
  263. 73: "0E27-0E140E140E14",
  264. 74: "0E140E140E14-0E1B0E1B",
  265. 75: "0E0A:0E190E19",
  266. 76: "0E0A:0E190E19:0E170E17",
  267. 77: "0E27/0E14/0E1B0E1B0E1B0E1B 0E0A:0E190E19",
  268. 78: "0E190E19:0E170E17",
  269. 79: "[0E0A]:0E190E19:0E170E17",
  270. 80: "0E190E19:0E170E17.0",
  271. 81: "d/m/bb",
  272. },
  273. }
  274. // currencyNumFmt defined the currency number format map.
  275. var currencyNumFmt = map[int]string{
  276. 164: `"¥"#,##0.00`,
  277. 165: "[$$-409]#,##0.00",
  278. 166: "[$$-45C]#,##0.00",
  279. 167: "[$$-1004]#,##0.00",
  280. 168: "[$$-404]#,##0.00",
  281. 169: "[$$-C09]#,##0.00",
  282. 170: "[$$-2809]#,##0.00",
  283. 171: "[$$-1009]#,##0.00",
  284. 172: "[$$-2009]#,##0.00",
  285. 173: "[$$-1409]#,##0.00",
  286. 174: "[$$-4809]#,##0.00",
  287. 175: "[$$-2C09]#,##0.00",
  288. 176: "[$$-2409]#,##0.00",
  289. 177: "[$$-1000]#,##0.00",
  290. 178: `#,##0.00\ [$$-C0C]`,
  291. 179: "[$$-475]#,##0.00",
  292. 180: "[$$-83E]#,##0.00",
  293. 181: `[$$-86B]\ #,##0.00`,
  294. 182: `[$$-340A]\ #,##0.00`,
  295. 183: "[$$-240A]#,##0.00",
  296. 184: `[$$-300A]\ #,##0.00`,
  297. 185: "[$$-440A]#,##0.00",
  298. 186: "[$$-80A]#,##0.00",
  299. 187: "[$$-500A]#,##0.00",
  300. 188: "[$$-540A]#,##0.00",
  301. 189: `[$$-380A]\ #,##0.00`,
  302. 190: "[$£-809]#,##0.00",
  303. 191: "[$£-491]#,##0.00",
  304. 192: "[$£-452]#,##0.00",
  305. 193: "[$¥-804]#,##0.00",
  306. 194: "[$¥-411]#,##0.00",
  307. 195: "[$¥-478]#,##0.00",
  308. 196: "[$¥-451]#,##0.00",
  309. 197: "[$¥-480]#,##0.00",
  310. 198: "#,##0.00\\ [$\u058F-42B]",
  311. 199: "[$\u060B-463]#,##0.00",
  312. 200: "[$\u060B-48C]#,##0.00",
  313. 201: "[$\u09F3-845]\\ #,##0.00",
  314. 202: "#,##0.00[$\u17DB-453]",
  315. 203: "[$\u20A1-140A]#,##0.00",
  316. 204: "[$\u20A6-468]\\ #,##0.00",
  317. 205: "[$\u20A6-470]\\ #,##0.00",
  318. 206: "[$\u20A9-412]#,##0.00",
  319. 207: "[$\u20AA-40D]\\ #,##0.00",
  320. 208: "#,##0.00\\ [$\u20AB-42A]",
  321. 209: "#,##0.00\\ [$\u20AC-42D]",
  322. 210: "#,##0.00\\ [$\u20AC-47E]",
  323. 211: "#,##0.00\\ [$\u20AC-403]",
  324. 212: "#,##0.00\\ [$\u20AC-483]",
  325. 213: "[$\u20AC-813]\\ #,##0.00",
  326. 214: "[$\u20AC-413]\\ #,##0.00",
  327. 215: "[$\u20AC-1809]#,##0.00",
  328. 216: "#,##0.00\\ [$\u20AC-425]",
  329. 217: "[$\u20AC-2]\\ #,##0.00",
  330. 218: "#,##0.00\\ [$\u20AC-1]",
  331. 219: "#,##0.00\\ [$\u20AC-40B]",
  332. 220: "#,##0.00\\ [$\u20AC-80C]",
  333. 221: "#,##0.00\\ [$\u20AC-40C]",
  334. 222: "#,##0.00\\ [$\u20AC-140C]",
  335. 223: "#,##0.00\\ [$\u20AC-180C]",
  336. 224: "[$\u20AC-200C]#,##0.00",
  337. 225: "#,##0.00\\ [$\u20AC-456]",
  338. 226: "#,##0.00\\ [$\u20AC-C07]",
  339. 227: "#,##0.00\\ [$\u20AC-407]",
  340. 228: "#,##0.00\\ [$\u20AC-1007]",
  341. 229: "#,##0.00\\ [$\u20AC-408]",
  342. 230: "#,##0.00\\ [$\u20AC-243B]",
  343. 231: "[$\u20AC-83C]#,##0.00",
  344. 232: "[$\u20AC-410]\\ #,##0.00",
  345. 233: "[$\u20AC-476]#,##0.00",
  346. 234: "#,##0.00\\ [$\u20AC-2C1A]",
  347. 235: "[$\u20AC-426]\\ #,##0.00",
  348. 236: "#,##0.00\\ [$\u20AC-427]",
  349. 237: "#,##0.00\\ [$\u20AC-82E]",
  350. 238: "#,##0.00\\ [$\u20AC-46E]",
  351. 239: "[$\u20AC-43A]#,##0.00",
  352. 240: "#,##0.00\\ [$\u20AC-C3B]",
  353. 241: "#,##0.00\\ [$\u20AC-482]",
  354. 242: "#,##0.00\\ [$\u20AC-816]",
  355. 243: "#,##0.00\\ [$\u20AC-301A]",
  356. 244: "#,##0.00\\ [$\u20AC-203B]",
  357. 245: "#,##0.00\\ [$\u20AC-41B]",
  358. 246: "#,##0.00\\ [$\u20AC-424]",
  359. 247: "#,##0.00\\ [$\u20AC-C0A]",
  360. 248: "#,##0.00\\ [$\u20AC-81D]",
  361. 249: "#,##0.00\\ [$\u20AC-484]",
  362. 250: "#,##0.00\\ [$\u20AC-42E]",
  363. 251: "[$\u20AC-462]\\ #,##0.00",
  364. 252: "#,##0.00\\ [$₭-454]",
  365. 253: "#,##0.00\\ [$₮-450]",
  366. 254: "[$\u20AE-C50]#,##0.00",
  367. 255: "[$\u20B1-3409]#,##0.00",
  368. 256: "[$\u20B1-464]#,##0.00",
  369. 257: "#,##0.00[$\u20B4-422]",
  370. 258: "[$\u20B8-43F]#,##0.00",
  371. 259: "[$\u20B9-460]#,##0.00",
  372. 260: "[$\u20B9-4009]\\ #,##0.00",
  373. 261: "[$\u20B9-447]\\ #,##0.00",
  374. 262: "[$\u20B9-439]\\ #,##0.00",
  375. 263: "[$\u20B9-44B]\\ #,##0.00",
  376. 264: "[$\u20B9-860]#,##0.00",
  377. 265: "[$\u20B9-457]\\ #,##0.00",
  378. 266: "[$\u20B9-458]#,##0.00",
  379. 267: "[$\u20B9-44E]\\ #,##0.00",
  380. 268: "[$\u20B9-861]#,##0.00",
  381. 269: "[$\u20B9-448]\\ #,##0.00",
  382. 270: "[$\u20B9-446]\\ #,##0.00",
  383. 271: "[$\u20B9-44F]\\ #,##0.00",
  384. 272: "[$\u20B9-459]#,##0.00",
  385. 273: "[$\u20B9-449]\\ #,##0.00",
  386. 274: "[$\u20B9-820]#,##0.00",
  387. 275: "#,##0.00\\ [$\u20BA-41F]",
  388. 276: "#,##0.00\\ [$\u20BC-42C]",
  389. 277: "#,##0.00\\ [$\u20BC-82C]",
  390. 278: "#,##0.00\\ [$\u20BD-419]",
  391. 279: "#,##0.00[$\u20BD-485]",
  392. 280: "#,##0.00\\ [$\u20BE-437]",
  393. 281: "[$B/.-180A]\\ #,##0.00",
  394. 282: "[$Br-472]#,##0.00",
  395. 283: "[$Br-477]#,##0.00",
  396. 284: "#,##0.00[$Br-473]",
  397. 285: "[$Bs-46B]\\ #,##0.00",
  398. 286: "[$Bs-400A]\\ #,##0.00",
  399. 287: "[$Bs.-200A]\\ #,##0.00",
  400. 288: "[$BWP-832]\\ #,##0.00",
  401. 289: "[$C$-4C0A]#,##0.00",
  402. 290: "[$CA$-85D]#,##0.00",
  403. 291: "[$CA$-47C]#,##0.00",
  404. 292: "[$CA$-45D]#,##0.00",
  405. 293: "[$CFA-340C]#,##0.00",
  406. 294: "[$CFA-280C]#,##0.00",
  407. 295: "#,##0.00\\ [$CFA-867]",
  408. 296: "#,##0.00\\ [$CFA-488]",
  409. 297: "#,##0.00\\ [$CHF-100C]",
  410. 298: "[$CHF-1407]\\ #,##0.00",
  411. 299: "[$CHF-807]\\ #,##0.00",
  412. 300: "[$CHF-810]\\ #,##0.00",
  413. 301: "[$CHF-417]\\ #,##0.00",
  414. 302: "[$CLP-47A]\\ #,##0.00",
  415. 303: "[$CN¥-850]#,##0.00",
  416. 304: "#,##0.00\\ [$DZD-85F]",
  417. 305: "[$FCFA-2C0C]#,##0.00",
  418. 306: "#,##0.00\\ [$Ft-40E]",
  419. 307: "[$G-3C0C]#,##0.00",
  420. 308: "[$Gs.-3C0A]\\ #,##0.00",
  421. 309: "[$GTQ-486]#,##0.00",
  422. 310: "[$HK$-C04]#,##0.00",
  423. 311: "[$HK$-3C09]#,##0.00",
  424. 312: "#,##0.00\\ [$HRK-41A]",
  425. 313: "[$IDR-3809]#,##0.00",
  426. 314: "[$IQD-492]#,##0.00",
  427. 315: "#,##0.00\\ [$ISK-40F]",
  428. 316: "[$K-455]#,##0.00",
  429. 317: "#,##0.00\\ [$K\u010D-405]",
  430. 318: "#,##0.00\\ [$KM-141A]",
  431. 319: "#,##0.00\\ [$KM-101A]",
  432. 320: "#,##0.00\\ [$KM-181A]",
  433. 321: "[$kr-438]\\ #,##0.00",
  434. 322: "[$kr-43B]\\ #,##0.00",
  435. 323: "#,##0.00\\ [$kr-83B]",
  436. 324: "[$kr-414]\\ #,##0.00",
  437. 325: "[$kr-814]\\ #,##0.00",
  438. 326: "#,##0.00\\ [$kr-41D]",
  439. 327: "[$kr.-406]\\ #,##0.00",
  440. 328: "[$kr.-46F]\\ #,##0.00",
  441. 329: "[$Ksh-441]#,##0.00",
  442. 330: "[$L-818]#,##0.00",
  443. 331: "[$L-819]#,##0.00",
  444. 332: "[$L-480A]\\ #,##0.00",
  445. 333: "#,##0.00\\ [$Lek\u00EB-41C]",
  446. 334: "[$MAD-45F]#,##0.00",
  447. 335: "[$MAD-380C]#,##0.00",
  448. 336: "#,##0.00\\ [$MAD-105F]",
  449. 337: "[$MOP$-1404]#,##0.00",
  450. 338: "#,##0.00\\ [$MVR-465]_-",
  451. 339: "#,##0.00[$Nfk-873]",
  452. 340: "[$NGN-466]#,##0.00",
  453. 341: "[$NGN-467]#,##0.00",
  454. 342: "[$NGN-469]#,##0.00",
  455. 343: "[$NGN-471]#,##0.00",
  456. 344: "[$NOK-103B]\\ #,##0.00",
  457. 345: "[$NOK-183B]\\ #,##0.00",
  458. 346: "[$NZ$-481]#,##0.00",
  459. 347: "[$PKR-859]\\ #,##0.00",
  460. 348: "[$PYG-474]#,##0.00",
  461. 349: "[$Q-100A]#,##0.00",
  462. 350: "[$R-436]\\ #,##0.00",
  463. 351: "[$R-1C09]\\ #,##0.00",
  464. 352: "[$R-435]\\ #,##0.00",
  465. 353: "[$R$-416]\\ #,##0.00",
  466. 354: "[$RD$-1C0A]#,##0.00",
  467. 355: "#,##0.00\\ [$RF-487]",
  468. 356: "[$RM-4409]#,##0.00",
  469. 357: "[$RM-43E]#,##0.00",
  470. 358: "#,##0.00\\ [$RON-418]",
  471. 359: "[$Rp-421]#,##0.00",
  472. 360: "[$Rs-420]#,##0.00_-",
  473. 361: "[$Rs.-849]\\ #,##0.00",
  474. 362: "#,##0.00\\ [$RSD-81A]",
  475. 363: "#,##0.00\\ [$RSD-C1A]",
  476. 364: "#,##0.00\\ [$RUB-46D]",
  477. 365: "#,##0.00\\ [$RUB-444]",
  478. 366: "[$S/.-C6B]\\ #,##0.00",
  479. 367: "[$S/.-280A]\\ #,##0.00",
  480. 368: "#,##0.00\\ [$SEK-143B]",
  481. 369: "#,##0.00\\ [$SEK-1C3B]",
  482. 370: "#,##0.00\\ [$so\u02BBm-443]",
  483. 371: "#,##0.00\\ [$so\u02BBm-843]",
  484. 372: "#,##0.00\\ [$SYP-45A]",
  485. 373: "[$THB-41E]#,##0.00",
  486. 374: "#,##0.00[$TMT-442]",
  487. 375: "[$US$-3009]#,##0.00",
  488. 376: "[$ZAR-46C]\\ #,##0.00",
  489. 377: "[$ZAR-430]#,##0.00",
  490. 378: "[$ZAR-431]#,##0.00",
  491. 379: "[$ZAR-432]\\ #,##0.00",
  492. 380: "[$ZAR-433]#,##0.00",
  493. 381: "[$ZAR-434]\\ #,##0.00",
  494. 382: "#,##0.00\\ [$z\u0142-415]",
  495. 383: "#,##0.00\\ [$\u0434\u0435\u043D-42F]",
  496. 384: "#,##0.00\\ [$КМ-201A]",
  497. 385: "#,##0.00\\ [$КМ-1C1A]",
  498. 386: "#,##0.00\\ [$\u043B\u0432.-402]",
  499. 387: "#,##0.00\\ [$р.-423]",
  500. 388: "#,##0.00\\ [$\u0441\u043E\u043C-440]",
  501. 389: "#,##0.00\\ [$\u0441\u043E\u043C-428]",
  502. 390: "[$\u062C.\u0645.-C01]\\ #,##0.00_-",
  503. 391: "[$\u062F.\u0623.-2C01]\\ #,##0.00_-",
  504. 392: "[$\u062F.\u0625.-3801]\\ #,##0.00_-",
  505. 393: "[$\u062F.\u0628.-3C01]\\ #,##0.00_-",
  506. 394: "[$\u062F.\u062A.-1C01]\\ #,##0.00_-",
  507. 395: "[$\u062F.\u062C.-1401]\\ #,##0.00_-",
  508. 396: "[$\u062F.\u0639.-801]\\ #,##0.00_-",
  509. 397: "[$\u062F.\u0643.-3401]\\ #,##0.00_-",
  510. 398: "[$\u062F.\u0644.-1001]#,##0.00_-",
  511. 399: "[$\u062F.\u0645.-1801]\\ #,##0.00_-",
  512. 400: "[$\u0631-846]\\ #,##0.00",
  513. 401: "[$\u0631.\u0633.-401]\\ #,##0.00_-",
  514. 402: "[$\u0631.\u0639.-2001]\\ #,##0.00_-",
  515. 403: "[$\u0631.\u0642.-4001]\\ #,##0.00_-",
  516. 404: "[$\u0631.\u064A.-2401]\\ #,##0.00_-",
  517. 405: "[$\u0631\u06CC\u0627\u0644-429]#,##0.00_-",
  518. 406: "[$\u0644.\u0633.-2801]\\ #,##0.00_-",
  519. 407: "[$\u0644.\u0644.-3001]\\ #,##0.00_-",
  520. 408: "[$\u1265\u122D-45E]#,##0.00",
  521. 409: "[$\u0930\u0942-461]#,##0.00",
  522. 410: "[$\u0DBB\u0DD4.-45B]\\ #,##0.00",
  523. 411: "[$ADP]\\ #,##0.00",
  524. 412: "[$AED]\\ #,##0.00",
  525. 413: "[$AFA]\\ #,##0.00",
  526. 414: "[$AFN]\\ #,##0.00",
  527. 415: "[$ALL]\\ #,##0.00",
  528. 416: "[$AMD]\\ #,##0.00",
  529. 417: "[$ANG]\\ #,##0.00",
  530. 418: "[$AOA]\\ #,##0.00",
  531. 419: "[$ARS]\\ #,##0.00",
  532. 420: "[$ATS]\\ #,##0.00",
  533. 421: "[$AUD]\\ #,##0.00",
  534. 422: "[$AWG]\\ #,##0.00",
  535. 423: "[$AZM]\\ #,##0.00",
  536. 424: "[$AZN]\\ #,##0.00",
  537. 425: "[$BAM]\\ #,##0.00",
  538. 426: "[$BBD]\\ #,##0.00",
  539. 427: "[$BDT]\\ #,##0.00",
  540. 428: "[$BEF]\\ #,##0.00",
  541. 429: "[$BGL]\\ #,##0.00",
  542. 430: "[$BGN]\\ #,##0.00",
  543. 431: "[$BHD]\\ #,##0.00",
  544. 432: "[$BIF]\\ #,##0.00",
  545. 433: "[$BMD]\\ #,##0.00",
  546. 434: "[$BND]\\ #,##0.00",
  547. 435: "[$BOB]\\ #,##0.00",
  548. 436: "[$BOV]\\ #,##0.00",
  549. 437: "[$BRL]\\ #,##0.00",
  550. 438: "[$BSD]\\ #,##0.00",
  551. 439: "[$BTN]\\ #,##0.00",
  552. 440: "[$BWP]\\ #,##0.00",
  553. 441: "[$BYR]\\ #,##0.00",
  554. 442: "[$BZD]\\ #,##0.00",
  555. 443: "[$CAD]\\ #,##0.00",
  556. 444: "[$CDF]\\ #,##0.00",
  557. 445: "[$CHE]\\ #,##0.00",
  558. 446: "[$CHF]\\ #,##0.00",
  559. 447: "[$CHW]\\ #,##0.00",
  560. 448: "[$CLF]\\ #,##0.00",
  561. 449: "[$CLP]\\ #,##0.00",
  562. 450: "[$CNY]\\ #,##0.00",
  563. 451: "[$COP]\\ #,##0.00",
  564. 452: "[$COU]\\ #,##0.00",
  565. 453: "[$CRC]\\ #,##0.00",
  566. 454: "[$CSD]\\ #,##0.00",
  567. 455: "[$CUC]\\ #,##0.00",
  568. 456: "[$CVE]\\ #,##0.00",
  569. 457: "[$CYP]\\ #,##0.00",
  570. 458: "[$CZK]\\ #,##0.00",
  571. 459: "[$DEM]\\ #,##0.00",
  572. 460: "[$DJF]\\ #,##0.00",
  573. 461: "[$DKK]\\ #,##0.00",
  574. 462: "[$DOP]\\ #,##0.00",
  575. 463: "[$DZD]\\ #,##0.00",
  576. 464: "[$ECS]\\ #,##0.00",
  577. 465: "[$ECV]\\ #,##0.00",
  578. 466: "[$EEK]\\ #,##0.00",
  579. 467: "[$EGP]\\ #,##0.00",
  580. 468: "[$ERN]\\ #,##0.00",
  581. 469: "[$ESP]\\ #,##0.00",
  582. 470: "[$ETB]\\ #,##0.00",
  583. 471: "[$EUR]\\ #,##0.00",
  584. 472: "[$FIM]\\ #,##0.00",
  585. 473: "[$FJD]\\ #,##0.00",
  586. 474: "[$FKP]\\ #,##0.00",
  587. 475: "[$FRF]\\ #,##0.00",
  588. 476: "[$GBP]\\ #,##0.00",
  589. 477: "[$GEL]\\ #,##0.00",
  590. 478: "[$GHC]\\ #,##0.00",
  591. 479: "[$GHS]\\ #,##0.00",
  592. 480: "[$GIP]\\ #,##0.00",
  593. 481: "[$GMD]\\ #,##0.00",
  594. 482: "[$GNF]\\ #,##0.00",
  595. 483: "[$GRD]\\ #,##0.00",
  596. 484: "[$GTQ]\\ #,##0.00",
  597. 485: "[$GYD]\\ #,##0.00",
  598. 486: "[$HKD]\\ #,##0.00",
  599. 487: "[$HNL]\\ #,##0.00",
  600. 488: "[$HRK]\\ #,##0.00",
  601. 489: "[$HTG]\\ #,##0.00",
  602. 490: "[$HUF]\\ #,##0.00",
  603. 491: "[$IDR]\\ #,##0.00",
  604. 492: "[$IEP]\\ #,##0.00",
  605. 493: "[$ILS]\\ #,##0.00",
  606. 494: "[$INR]\\ #,##0.00",
  607. 495: "[$IQD]\\ #,##0.00",
  608. 496: "[$IRR]\\ #,##0.00",
  609. 497: "[$ISK]\\ #,##0.00",
  610. 498: "[$ITL]\\ #,##0.00",
  611. 499: "[$JMD]\\ #,##0.00",
  612. 500: "[$JOD]\\ #,##0.00",
  613. 501: "[$JPY]\\ #,##0.00",
  614. 502: "[$KAF]\\ #,##0.00",
  615. 503: "[$KES]\\ #,##0.00",
  616. 504: "[$KGS]\\ #,##0.00",
  617. 505: "[$KHR]\\ #,##0.00",
  618. 506: "[$KMF]\\ #,##0.00",
  619. 507: "[$KPW]\\ #,##0.00",
  620. 508: "[$KRW]\\ #,##0.00",
  621. 509: "[$KWD]\\ #,##0.00",
  622. 510: "[$KYD]\\ #,##0.00",
  623. 511: "[$KZT]\\ #,##0.00",
  624. 512: "[$LAK]\\ #,##0.00",
  625. 513: "[$LBP]\\ #,##0.00",
  626. 514: "[$LKR]\\ #,##0.00",
  627. 515: "[$LRD]\\ #,##0.00",
  628. 516: "[$LSL]\\ #,##0.00",
  629. 517: "[$LTL]\\ #,##0.00",
  630. 518: "[$LUF]\\ #,##0.00",
  631. 519: "[$LVL]\\ #,##0.00",
  632. 520: "[$LYD]\\ #,##0.00",
  633. 521: "[$MAD]\\ #,##0.00",
  634. 522: "[$MDL]\\ #,##0.00",
  635. 523: "[$MGA]\\ #,##0.00",
  636. 524: "[$MGF]\\ #,##0.00",
  637. 525: "[$MKD]\\ #,##0.00",
  638. 526: "[$MMK]\\ #,##0.00",
  639. 527: "[$MNT]\\ #,##0.00",
  640. 528: "[$MOP]\\ #,##0.00",
  641. 529: "[$MRO]\\ #,##0.00",
  642. 530: "[$MTL]\\ #,##0.00",
  643. 531: "[$MUR]\\ #,##0.00",
  644. 532: "[$MVR]\\ #,##0.00",
  645. 533: "[$MWK]\\ #,##0.00",
  646. 534: "[$MXN]\\ #,##0.00",
  647. 535: "[$MXV]\\ #,##0.00",
  648. 536: "[$MYR]\\ #,##0.00",
  649. 537: "[$MZM]\\ #,##0.00",
  650. 538: "[$MZN]\\ #,##0.00",
  651. 539: "[$NAD]\\ #,##0.00",
  652. 540: "[$NGN]\\ #,##0.00",
  653. 541: "[$NIO]\\ #,##0.00",
  654. 542: "[$NLG]\\ #,##0.00",
  655. 543: "[$NOK]\\ #,##0.00",
  656. 544: "[$NPR]\\ #,##0.00",
  657. 545: "[$NTD]\\ #,##0.00",
  658. 546: "[$NZD]\\ #,##0.00",
  659. 547: "[$OMR]\\ #,##0.00",
  660. 548: "[$PAB]\\ #,##0.00",
  661. 549: "[$PEN]\\ #,##0.00",
  662. 550: "[$PGK]\\ #,##0.00",
  663. 551: "[$PHP]\\ #,##0.00",
  664. 552: "[$PKR]\\ #,##0.00",
  665. 553: "[$PLN]\\ #,##0.00",
  666. 554: "[$PTE]\\ #,##0.00",
  667. 555: "[$PYG]\\ #,##0.00",
  668. 556: "[$QAR]\\ #,##0.00",
  669. 557: "[$ROL]\\ #,##0.00",
  670. 558: "[$RON]\\ #,##0.00",
  671. 559: "[$RSD]\\ #,##0.00",
  672. 560: "[$RUB]\\ #,##0.00",
  673. 561: "[$RUR]\\ #,##0.00",
  674. 562: "[$RWF]\\ #,##0.00",
  675. 563: "[$SAR]\\ #,##0.00",
  676. 564: "[$SBD]\\ #,##0.00",
  677. 565: "[$SCR]\\ #,##0.00",
  678. 566: "[$SDD]\\ #,##0.00",
  679. 567: "[$SDG]\\ #,##0.00",
  680. 568: "[$SDP]\\ #,##0.00",
  681. 569: "[$SEK]\\ #,##0.00",
  682. 570: "[$SGD]\\ #,##0.00",
  683. 571: "[$SHP]\\ #,##0.00",
  684. 572: "[$SIT]\\ #,##0.00",
  685. 573: "[$SKK]\\ #,##0.00",
  686. 574: "[$SLL]\\ #,##0.00",
  687. 575: "[$SOS]\\ #,##0.00",
  688. 576: "[$SPL]\\ #,##0.00",
  689. 577: "[$SRD]\\ #,##0.00",
  690. 578: "[$SRG]\\ #,##0.00",
  691. 579: "[$STD]\\ #,##0.00",
  692. 580: "[$SVC]\\ #,##0.00",
  693. 581: "[$SYP]\\ #,##0.00",
  694. 582: "[$SZL]\\ #,##0.00",
  695. 583: "[$THB]\\ #,##0.00",
  696. 584: "[$TJR]\\ #,##0.00",
  697. 585: "[$TJS]\\ #,##0.00",
  698. 586: "[$TMM]\\ #,##0.00",
  699. 587: "[$TMT]\\ #,##0.00",
  700. 588: "[$TND]\\ #,##0.00",
  701. 589: "[$TOP]\\ #,##0.00",
  702. 590: "[$TRL]\\ #,##0.00",
  703. 591: "[$TRY]\\ #,##0.00",
  704. 592: "[$TTD]\\ #,##0.00",
  705. 593: "[$TWD]\\ #,##0.00",
  706. 594: "[$TZS]\\ #,##0.00",
  707. 595: "[$UAH]\\ #,##0.00",
  708. 596: "[$UGX]\\ #,##0.00",
  709. 597: "[$USD]\\ #,##0.00",
  710. 598: "[$USN]\\ #,##0.00",
  711. 599: "[$USS]\\ #,##0.00",
  712. 600: "[$UYI]\\ #,##0.00",
  713. 601: "[$UYU]\\ #,##0.00",
  714. 602: "[$UZS]\\ #,##0.00",
  715. 603: "[$VEB]\\ #,##0.00",
  716. 604: "[$VEF]\\ #,##0.00",
  717. 605: "[$VND]\\ #,##0.00",
  718. 606: "[$VUV]\\ #,##0.00",
  719. 607: "[$WST]\\ #,##0.00",
  720. 608: "[$XAF]\\ #,##0.00",
  721. 609: "[$XAG]\\ #,##0.00",
  722. 610: "[$XAU]\\ #,##0.00",
  723. 611: "[$XB5]\\ #,##0.00",
  724. 612: "[$XBA]\\ #,##0.00",
  725. 613: "[$XBB]\\ #,##0.00",
  726. 614: "[$XBC]\\ #,##0.00",
  727. 615: "[$XBD]\\ #,##0.00",
  728. 616: "[$XCD]\\ #,##0.00",
  729. 617: "[$XDR]\\ #,##0.00",
  730. 618: "[$XFO]\\ #,##0.00",
  731. 619: "[$XFU]\\ #,##0.00",
  732. 620: "[$XOF]\\ #,##0.00",
  733. 621: "[$XPD]\\ #,##0.00",
  734. 622: "[$XPF]\\ #,##0.00",
  735. 623: "[$XPT]\\ #,##0.00",
  736. 624: "[$XTS]\\ #,##0.00",
  737. 625: "[$XXX]\\ #,##0.00",
  738. 626: "[$YER]\\ #,##0.00",
  739. 627: "[$YUM]\\ #,##0.00",
  740. 628: "[$ZAR]\\ #,##0.00",
  741. 629: "[$ZMK]\\ #,##0.00",
  742. 630: "[$ZMW]\\ #,##0.00",
  743. 631: "[$ZWD]\\ #,##0.00",
  744. 632: "[$ZWL]\\ #,##0.00",
  745. 633: "[$ZWN]\\ #,##0.00",
  746. 634: "[$ZWR]\\ #,##0.00",
  747. }
  748. // builtInNumFmtFunc defined the format conversion functions map. Partial format
  749. // code doesn't support currently and will return original string.
  750. var builtInNumFmtFunc = map[int]func(v, format string, date1904 bool) string{
  751. 0: format,
  752. 1: formatToInt,
  753. 2: formatToFloat,
  754. 3: formatToIntSeparator,
  755. 4: formatToFloat,
  756. 9: formatToC,
  757. 10: formatToD,
  758. 11: formatToE,
  759. 12: format, // Doesn't support currently
  760. 13: format, // Doesn't support currently
  761. 14: format,
  762. 15: format,
  763. 16: format,
  764. 17: format,
  765. 18: format,
  766. 19: format,
  767. 20: format,
  768. 21: format,
  769. 22: format,
  770. 37: formatToA,
  771. 38: formatToA,
  772. 39: formatToB,
  773. 40: formatToB,
  774. 41: format, // Doesn't support currently
  775. 42: format, // Doesn't support currently
  776. 43: format, // Doesn't support currently
  777. 44: format, // Doesn't support currently
  778. 45: format,
  779. 46: format,
  780. 47: format,
  781. 48: formatToE,
  782. 49: format,
  783. }
  784. // validType defined the list of valid validation types.
  785. var validType = map[string]string{
  786. "cell": "cellIs",
  787. "date": "date", // Doesn't support currently
  788. "time": "time", // Doesn't support currently
  789. "average": "aboveAverage",
  790. "duplicate": "duplicateValues",
  791. "unique": "uniqueValues",
  792. "top": "top10",
  793. "bottom": "top10",
  794. "text": "text", // Doesn't support currently
  795. "time_period": "timePeriod", // Doesn't support currently
  796. "blanks": "containsBlanks", // Doesn't support currently
  797. "no_blanks": "notContainsBlanks", // Doesn't support currently
  798. "errors": "containsErrors", // Doesn't support currently
  799. "no_errors": "notContainsErrors", // Doesn't support currently
  800. "2_color_scale": "2_color_scale",
  801. "3_color_scale": "3_color_scale",
  802. "data_bar": "dataBar",
  803. "formula": "expression",
  804. "icon_set": "iconSet",
  805. }
  806. // criteriaType defined the list of valid criteria types.
  807. var criteriaType = map[string]string{
  808. "between": "between",
  809. "not between": "notBetween",
  810. "equal to": "equal",
  811. "=": "equal",
  812. "==": "equal",
  813. "not equal to": "notEqual",
  814. "!=": "notEqual",
  815. "<>": "notEqual",
  816. "greater than": "greaterThan",
  817. ">": "greaterThan",
  818. "less than": "lessThan",
  819. "<": "lessThan",
  820. "greater than or equal to": "greaterThanOrEqual",
  821. ">=": "greaterThanOrEqual",
  822. "less than or equal to": "lessThanOrEqual",
  823. "<=": "lessThanOrEqual",
  824. "containing": "containsText",
  825. "not containing": "notContains",
  826. "begins with": "beginsWith",
  827. "ends with": "endsWith",
  828. "yesterday": "yesterday",
  829. "today": "today",
  830. "last 7 days": "last7Days",
  831. "last week": "lastWeek",
  832. "this week": "thisWeek",
  833. "continue week": "continueWeek",
  834. "last month": "lastMonth",
  835. "this month": "thisMonth",
  836. "continue month": "continueMonth",
  837. }
  838. // operatorType defined the list of valid operator types.
  839. var operatorType = map[string]string{
  840. "lastMonth": "last month",
  841. "between": "between",
  842. "notEqual": "not equal to",
  843. "greaterThan": "greater than",
  844. "lessThanOrEqual": "less than or equal to",
  845. "today": "today",
  846. "equal": "equal to",
  847. "notContains": "not containing",
  848. "thisWeek": "this week",
  849. "endsWith": "ends with",
  850. "yesterday": "yesterday",
  851. "lessThan": "less than",
  852. "beginsWith": "begins with",
  853. "last7Days": "last 7 days",
  854. "thisMonth": "this month",
  855. "containsText": "containing",
  856. "lastWeek": "last week",
  857. "continueWeek": "continue week",
  858. "continueMonth": "continue month",
  859. "notBetween": "not between",
  860. "greaterThanOrEqual": "greater than or equal to",
  861. }
  862. // printCommaSep format number with thousands separator.
  863. func printCommaSep(text string) string {
  864. var (
  865. target strings.Builder
  866. subStr = strings.Split(text, ".")
  867. length = len(subStr[0])
  868. )
  869. for i := 0; i < length; i++ {
  870. if i > 0 && (length-i)%3 == 0 {
  871. target.WriteString(",")
  872. }
  873. target.WriteString(string(text[i]))
  874. }
  875. if len(subStr) == 2 {
  876. target.WriteString(".")
  877. target.WriteString(subStr[1])
  878. }
  879. return target.String()
  880. }
  881. // formatToInt provides a function to convert original string to integer
  882. // format as string type by given built-in number formats code and cell
  883. // string.
  884. func formatToInt(v, format string, date1904 bool) string {
  885. if strings.Contains(v, "_") {
  886. return v
  887. }
  888. f, err := strconv.ParseFloat(v, 64)
  889. if err != nil {
  890. return v
  891. }
  892. return strconv.FormatFloat(math.Round(f), 'f', -1, 64)
  893. }
  894. // formatToFloat provides a function to convert original string to float
  895. // format as string type by given built-in number formats code and cell
  896. // string.
  897. func formatToFloat(v, format string, date1904 bool) string {
  898. if strings.Contains(v, "_") {
  899. return v
  900. }
  901. f, err := strconv.ParseFloat(v, 64)
  902. if err != nil {
  903. return v
  904. }
  905. source := strconv.FormatFloat(f, 'f', -1, 64)
  906. if !strings.Contains(source, ".") {
  907. return source + ".00"
  908. }
  909. return fmt.Sprintf("%.2f", f)
  910. }
  911. // formatToIntSeparator provides a function to convert original string to
  912. // integer format as string type by given built-in number formats code and cell
  913. // string.
  914. func formatToIntSeparator(v, format string, date1904 bool) string {
  915. if strings.Contains(v, "_") {
  916. return v
  917. }
  918. f, err := strconv.ParseFloat(v, 64)
  919. if err != nil {
  920. return v
  921. }
  922. return printCommaSep(strconv.FormatFloat(math.Round(f), 'f', -1, 64))
  923. }
  924. // formatToA provides a function to convert original string to special format
  925. // as string type by given built-in number formats code and cell string.
  926. func formatToA(v, format string, date1904 bool) string {
  927. if strings.Contains(v, "_") {
  928. return v
  929. }
  930. f, err := strconv.ParseFloat(v, 64)
  931. if err != nil {
  932. return v
  933. }
  934. var target strings.Builder
  935. if f < 0 {
  936. target.WriteString("(")
  937. }
  938. target.WriteString(printCommaSep(strconv.FormatFloat(math.Abs(math.Round(f)), 'f', -1, 64)))
  939. if f < 0 {
  940. target.WriteString(")")
  941. } else {
  942. target.WriteString(" ")
  943. }
  944. return target.String()
  945. }
  946. // formatToB provides a function to convert original string to special format
  947. // as string type by given built-in number formats code and cell string.
  948. func formatToB(v, format string, date1904 bool) string {
  949. if strings.Contains(v, "_") {
  950. return v
  951. }
  952. f, err := strconv.ParseFloat(v, 64)
  953. if err != nil {
  954. return v
  955. }
  956. var target strings.Builder
  957. if f < 0 {
  958. target.WriteString("(")
  959. }
  960. source := strconv.FormatFloat(math.Abs(f), 'f', -1, 64)
  961. var text string
  962. if !strings.Contains(source, ".") {
  963. text = printCommaSep(source + ".00")
  964. } else {
  965. text = printCommaSep(fmt.Sprintf("%.2f", math.Abs(f)))
  966. }
  967. target.WriteString(text)
  968. if f < 0 {
  969. target.WriteString(")")
  970. } else {
  971. target.WriteString(" ")
  972. }
  973. return target.String()
  974. }
  975. // formatToC provides a function to convert original string to special format
  976. // as string type by given built-in number formats code and cell string.
  977. func formatToC(v, format string, date1904 bool) string {
  978. if strings.Contains(v, "_") {
  979. return v
  980. }
  981. f, err := strconv.ParseFloat(v, 64)
  982. if err != nil {
  983. return v
  984. }
  985. source := strconv.FormatFloat(f, 'f', -1, 64)
  986. if !strings.Contains(source, ".") {
  987. return source + "00%"
  988. }
  989. return fmt.Sprintf("%.f%%", f*100)
  990. }
  991. // formatToD provides a function to convert original string to special format
  992. // as string type by given built-in number formats code and cell string.
  993. func formatToD(v, format string, date1904 bool) string {
  994. if strings.Contains(v, "_") {
  995. return v
  996. }
  997. f, err := strconv.ParseFloat(v, 64)
  998. if err != nil {
  999. return v
  1000. }
  1001. source := strconv.FormatFloat(f, 'f', -1, 64)
  1002. if !strings.Contains(source, ".") {
  1003. return source + "00.00%"
  1004. }
  1005. return fmt.Sprintf("%.2f%%", f*100)
  1006. }
  1007. // formatToE provides a function to convert original string to special format
  1008. // as string type by given built-in number formats code and cell string.
  1009. func formatToE(v, format string, date1904 bool) string {
  1010. if strings.Contains(v, "_") {
  1011. return v
  1012. }
  1013. f, err := strconv.ParseFloat(v, 64)
  1014. if err != nil {
  1015. return v
  1016. }
  1017. return fmt.Sprintf("%.2E", f)
  1018. }
  1019. // stylesReader provides a function to get the pointer to the structure after
  1020. // deserialization of xl/styles.xml.
  1021. func (f *File) stylesReader() (*xlsxStyleSheet, error) {
  1022. if f.Styles == nil {
  1023. f.Styles = new(xlsxStyleSheet)
  1024. if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathStyles)))).
  1025. Decode(f.Styles); err != nil && err != io.EOF {
  1026. return f.Styles, err
  1027. }
  1028. }
  1029. return f.Styles, nil
  1030. }
  1031. // styleSheetWriter provides a function to save xl/styles.xml after serialize
  1032. // structure.
  1033. func (f *File) styleSheetWriter() {
  1034. if f.Styles != nil {
  1035. output, _ := xml.Marshal(f.Styles)
  1036. f.saveFileList(defaultXMLPathStyles, f.replaceNameSpaceBytes(defaultXMLPathStyles, output))
  1037. }
  1038. }
  1039. // themeWriter provides a function to save xl/theme/theme1.xml after serialize
  1040. // structure.
  1041. func (f *File) themeWriter() {
  1042. if f.Theme != nil {
  1043. output, _ := xml.Marshal(f.Theme)
  1044. f.saveFileList(defaultXMLPathTheme, f.replaceNameSpaceBytes(defaultXMLPathTheme, output))
  1045. }
  1046. }
  1047. // sharedStringsWriter provides a function to save xl/sharedStrings.xml after
  1048. // serialize structure.
  1049. func (f *File) sharedStringsWriter() {
  1050. if f.SharedStrings != nil {
  1051. output, _ := xml.Marshal(f.SharedStrings)
  1052. f.saveFileList(defaultXMLPathSharedStrings, f.replaceNameSpaceBytes(defaultXMLPathSharedStrings, output))
  1053. }
  1054. }
  1055. // parseFormatStyleSet provides a function to parse the format settings of the
  1056. // cells and conditional formats.
  1057. func parseFormatStyleSet(style *Style) (*Style, error) {
  1058. var err error
  1059. if style.Font != nil {
  1060. if len(style.Font.Family) > MaxFontFamilyLength {
  1061. return style, ErrFontLength
  1062. }
  1063. if style.Font.Size > MaxFontSize {
  1064. return style, ErrFontSize
  1065. }
  1066. }
  1067. if style.CustomNumFmt != nil && len(*style.CustomNumFmt) == 0 {
  1068. err = ErrCustomNumFmt
  1069. }
  1070. return style, err
  1071. }
  1072. // NewStyle provides a function to create the style for cells by given style
  1073. // options. This function is concurrency safe. Note that the 'Font.Color' field
  1074. // uses an RGB color represented in 'RRGGBB' hexadecimal notation.
  1075. //
  1076. // The following table shows the border types used in 'Border.Type' supported by
  1077. // excelize:
  1078. //
  1079. // Type | Description
  1080. // --------------+------------------
  1081. // left | Left border
  1082. // top | Top border
  1083. // right | Right border
  1084. // bottom | Bottom border
  1085. // diagonalDown | Diagonal down border
  1086. // diagonalUp | Diagonal up border
  1087. //
  1088. // The following table shows the border styles used in 'Border.Style' supported
  1089. // by excelize index number:
  1090. //
  1091. // Index | Name | Weight | Style
  1092. // -------+---------------+--------+-------------
  1093. // 0 | None | 0 |
  1094. // 1 | Continuous | 1 | -----------
  1095. // 2 | Continuous | 2 | -----------
  1096. // 3 | Dash | 1 | - - - - - -
  1097. // 4 | Dot | 1 | . . . . . .
  1098. // 5 | Continuous | 3 | -----------
  1099. // 6 | Double | 3 | ===========
  1100. // 7 | Continuous | 0 | -----------
  1101. // 8 | Dash | 2 | - - - - - -
  1102. // 9 | Dash Dot | 1 | - . - . - .
  1103. // 10 | Dash Dot | 2 | - . - . - .
  1104. // 11 | Dash Dot Dot | 1 | - . . - . .
  1105. // 12 | Dash Dot Dot | 2 | - . . - . .
  1106. // 13 | SlantDash Dot | 2 | / - . / - .
  1107. //
  1108. // The following table shows the border styles used in 'Border.Style' in the
  1109. // order shown in the Excel dialog:
  1110. //
  1111. // Index | Style | Index | Style
  1112. // -------+-------------+-------+-------------
  1113. // 0 | None | 12 | - . . - . .
  1114. // 7 | ----------- | 13 | / - . / - .
  1115. // 4 | . . . . . . | 10 | - . - . - .
  1116. // 11 | - . . - . . | 8 | - - - - - -
  1117. // 9 | - . - . - . | 2 | -----------
  1118. // 3 | - - - - - - | 5 | -----------
  1119. // 1 | ----------- | 6 | ===========
  1120. //
  1121. // The following table shows the shading styles used in 'Fill.Shading' supported
  1122. // by excelize index number:
  1123. //
  1124. // Index | Style | Index | Style
  1125. // -------+-----------------+-------+-----------------
  1126. // 0-2 | Horizontal | 9-11 | Diagonal down
  1127. // 3-5 | Vertical | 12-15 | From corner
  1128. // 6-8 | Diagonal Up | 16 | From center
  1129. //
  1130. // The following table shows the pattern styles used in 'Fill.Pattern' supported
  1131. // by excelize index number:
  1132. //
  1133. // Index | Style | Index | Style
  1134. // -------+-----------------+-------+-----------------
  1135. // 0 | None | 10 | darkTrellis
  1136. // 1 | solid | 11 | lightHorizontal
  1137. // 2 | mediumGray | 12 | lightVertical
  1138. // 3 | darkGray | 13 | lightDown
  1139. // 4 | lightGray | 14 | lightUp
  1140. // 5 | darkHorizontal | 15 | lightGrid
  1141. // 6 | darkVertical | 16 | lightTrellis
  1142. // 7 | darkDown | 17 | gray125
  1143. // 8 | darkUp | 18 | gray0625
  1144. // 9 | darkGrid | |
  1145. //
  1146. // The following table shows the type of cells' horizontal alignment used
  1147. // in 'Alignment.Horizontal':
  1148. //
  1149. // Style
  1150. // ------------------
  1151. // left
  1152. // center
  1153. // right
  1154. // fill
  1155. // justify
  1156. // centerContinuous
  1157. // distributed
  1158. //
  1159. // The following table shows the type of cells' vertical alignment used in
  1160. // 'Alignment.Vertical':
  1161. //
  1162. // Style
  1163. // ------------------
  1164. // top
  1165. // center
  1166. // justify
  1167. // distributed
  1168. //
  1169. // The following table shows the type of font underline style used in
  1170. // 'Font.Underline':
  1171. //
  1172. // Style
  1173. // ------------------
  1174. // none
  1175. // single
  1176. // double
  1177. //
  1178. // Excel's built-in all languages formats are shown in the following table:
  1179. //
  1180. // Index | Format String
  1181. // -------+----------------------------------------------------
  1182. // 0 | General
  1183. // 1 | 0
  1184. // 2 | 0.00
  1185. // 3 | #,##0
  1186. // 4 | #,##0.00
  1187. // 5 | ($#,##0_);($#,##0)
  1188. // 6 | ($#,##0_);[Red]($#,##0)
  1189. // 7 | ($#,##0.00_);($#,##0.00)
  1190. // 8 | ($#,##0.00_);[Red]($#,##0.00)
  1191. // 9 | 0%
  1192. // 10 | 0.00%
  1193. // 11 | 0.00E+00
  1194. // 12 | # ?/?
  1195. // 13 | # ??/??
  1196. // 14 | m/d/yy
  1197. // 15 | d-mmm-yy
  1198. // 16 | d-mmm
  1199. // 17 | mmm-yy
  1200. // 18 | h:mm AM/PM
  1201. // 19 | h:mm:ss AM/PM
  1202. // 20 | h:mm
  1203. // 21 | h:mm:ss
  1204. // 22 | m/d/yy h:mm
  1205. // ... | ...
  1206. // 37 | (#,##0_);(#,##0)
  1207. // 38 | (#,##0_);[Red](#,##0)
  1208. // 39 | (#,##0.00_);(#,##0.00)
  1209. // 40 | (#,##0.00_);[Red](#,##0.00)
  1210. // 41 | _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)
  1211. // 42 | _($* #,##0_);_($* (#,##0);_($* "-"_);_(@_)
  1212. // 43 | _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)
  1213. // 44 | _($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)
  1214. // 45 | mm:ss
  1215. // 46 | [h]:mm:ss
  1216. // 47 | mm:ss.0
  1217. // 48 | ##0.0E+0
  1218. // 49 | @
  1219. //
  1220. // Number format code in zh-tw language:
  1221. //
  1222. // Index | Symbol
  1223. // -------+-------------------------------------------
  1224. // 27 | [$-404]e/m/d
  1225. // 28 | [$-404]e"年"m"月"d"日"
  1226. // 29 | [$-404]e"年"m"月"d"日"
  1227. // 30 | m/d/yy
  1228. // 31 | yyyy"年"m"月"d"日"
  1229. // 32 | hh"時"mm"分"
  1230. // 33 | hh"時"mm"分"ss"秒"
  1231. // 34 | 上午/下午 hh"時"mm"分"
  1232. // 35 | 上午/下午 hh"時"mm"分"ss"秒"
  1233. // 36 | [$-404]e/m/d
  1234. // 50 | [$-404]e/m/d
  1235. // 51 | [$-404]e"年"m"月"d"日"
  1236. // 52 | 上午/下午 hh"時"mm"分"
  1237. // 53 | 上午/下午 hh"時"mm"分"ss"秒"
  1238. // 54 | [$-404]e"年"m"月"d"日"
  1239. // 55 | 上午/下午 hh"時"mm"分"
  1240. // 56 | 上午/下午 hh"時"mm"分"ss"秒"
  1241. // 57 | [$-404]e/m/d
  1242. // 58 | [$-404]e"年"m"月"d"日"
  1243. //
  1244. // Number format code in zh-cn language:
  1245. //
  1246. // Index | Symbol
  1247. // -------+-------------------------------------------
  1248. // 27 | yyyy"年"m"月"
  1249. // 28 | m"月"d"日"
  1250. // 29 | m"月"d"日"
  1251. // 30 | m-d-yy
  1252. // 31 | yyyy"年"m"月"d"日"
  1253. // 32 | h"时"mm"分"
  1254. // 33 | h"时"mm"分"ss"秒"
  1255. // 34 | 上午/下午 h"时"mm"分"
  1256. // 35 | 上午/下午 h"时"mm"分"ss"秒
  1257. // 36 | yyyy"年"m"月
  1258. // 50 | yyyy"年"m"月
  1259. // 51 | m"月"d"日
  1260. // 52 | yyyy"年"m"月
  1261. // 53 | m"月"d"日
  1262. // 54 | m"月"d"日
  1263. // 55 | 上午/下午 h"时"mm"分
  1264. // 56 | 上午/下午 h"时"mm"分"ss"秒
  1265. // 57 | yyyy"年"m"月
  1266. // 58 | m"月"d"日"
  1267. //
  1268. // Number format code with unicode values provided for language glyphs where
  1269. // they occur in zh-tw language:
  1270. //
  1271. // Index | Symbol
  1272. // -------+-------------------------------------------
  1273. // 27 | [$-404]e/m/
  1274. // 28 | [$-404]e"5E74"m"6708"d"65E5
  1275. // 29 | [$-404]e"5E74"m"6708"d"65E5
  1276. // 30 | m/d/y
  1277. // 31 | yyyy"5E74"m"6708"d"65E5
  1278. // 32 | hh"6642"mm"5206
  1279. // 33 | hh"6642"mm"5206"ss"79D2
  1280. // 34 | 4E0A5348/4E0B5348hh"6642"mm"5206
  1281. // 35 | 4E0A5348/4E0B5348hh"6642"mm"5206"ss"79D2
  1282. // 36 | [$-404]e/m/
  1283. // 50 | [$-404]e/m/
  1284. // 51 | [$-404]e"5E74"m"6708"d"65E5
  1285. // 52 | 4E0A5348/4E0B5348hh"6642"mm"5206
  1286. // 53 | 4E0A5348/4E0B5348hh"6642"mm"5206"ss"79D2
  1287. // 54 | [$-404]e"5E74"m"6708"d"65E5
  1288. // 55 | 4E0A5348/4E0B5348hh"6642"mm"5206
  1289. // 56 | 4E0A5348/4E0B5348hh"6642"mm"5206"ss"79D2
  1290. // 57 | [$-404]e/m/
  1291. // 58 | [$-404]e"5E74"m"6708"d"65E5"
  1292. //
  1293. // Number format code with unicode values provided for language glyphs where
  1294. // they occur in zh-cn language:
  1295. //
  1296. // Index | Symbol
  1297. // -------+-------------------------------------------
  1298. // 27 | yyyy"5E74"m"6708
  1299. // 28 | m"6708"d"65E5
  1300. // 29 | m"6708"d"65E5
  1301. // 30 | m-d-y
  1302. // 31 | yyyy"5E74"m"6708"d"65E5
  1303. // 32 | h"65F6"mm"5206
  1304. // 33 | h"65F6"mm"5206"ss"79D2
  1305. // 34 | 4E0A5348/4E0B5348h"65F6"mm"5206
  1306. // 35 | 4E0A5348/4E0B5348h"65F6"mm"5206"ss"79D2
  1307. // 36 | yyyy"5E74"m"6708
  1308. // 50 | yyyy"5E74"m"6708
  1309. // 51 | m"6708"d"65E5
  1310. // 52 | yyyy"5E74"m"6708
  1311. // 53 | m"6708"d"65E5
  1312. // 54 | m"6708"d"65E5
  1313. // 55 | 4E0A5348/4E0B5348h"65F6"mm"5206
  1314. // 56 | 4E0A5348/4E0B5348h"65F6"mm"5206"ss"79D2
  1315. // 57 | yyyy"5E74"m"6708
  1316. // 58 | m"6708"d"65E5"
  1317. //
  1318. // Number format code in ja-jp language:
  1319. //
  1320. // Index | Symbol
  1321. // -------+-------------------------------------------
  1322. // 27 | [$-411]ge.m.d
  1323. // 28 | [$-411]ggge"年"m"月"d"日
  1324. // 29 | [$-411]ggge"年"m"月"d"日
  1325. // 30 | m/d/y
  1326. // 31 | yyyy"年"m"月"d"日
  1327. // 32 | h"時"mm"分
  1328. // 33 | h"時"mm"分"ss"秒
  1329. // 34 | yyyy"年"m"月
  1330. // 35 | m"月"d"日
  1331. // 36 | [$-411]ge.m.d
  1332. // 50 | [$-411]ge.m.d
  1333. // 51 | [$-411]ggge"年"m"月"d"日
  1334. // 52 | yyyy"年"m"月
  1335. // 53 | m"月"d"日
  1336. // 54 | [$-411]ggge"年"m"月"d"日
  1337. // 55 | yyyy"年"m"月
  1338. // 56 | m"月"d"日
  1339. // 57 | [$-411]ge.m.d
  1340. // 58 | [$-411]ggge"年"m"月"d"日"
  1341. //
  1342. // Number format code in ko-kr language:
  1343. //
  1344. // Index | Symbol
  1345. // -------+-------------------------------------------
  1346. // 27 | yyyy"年" mm"月" dd"日
  1347. // 28 | mm-d
  1348. // 29 | mm-d
  1349. // 30 | mm-dd-y
  1350. // 31 | yyyy"년" mm"월" dd"일
  1351. // 32 | h"시" mm"분
  1352. // 33 | h"시" mm"분" ss"초
  1353. // 34 | yyyy-mm-d
  1354. // 35 | yyyy-mm-d
  1355. // 36 | yyyy"年" mm"月" dd"日
  1356. // 50 | yyyy"年" mm"月" dd"日
  1357. // 51 | mm-d
  1358. // 52 | yyyy-mm-d
  1359. // 53 | yyyy-mm-d
  1360. // 54 | mm-d
  1361. // 55 | yyyy-mm-d
  1362. // 56 | yyyy-mm-d
  1363. // 57 | yyyy"年" mm"月" dd"日
  1364. // 58 | mm-dd
  1365. //
  1366. // Number format code with unicode values provided for language glyphs where
  1367. // they occur in ja-jp language:
  1368. //
  1369. // Index | Symbol
  1370. // -------+-------------------------------------------
  1371. // 27 | [$-411]ge.m.d
  1372. // 28 | [$-411]ggge"5E74"m"6708"d"65E5
  1373. // 29 | [$-411]ggge"5E74"m"6708"d"65E5
  1374. // 30 | m/d/y
  1375. // 31 | yyyy"5E74"m"6708"d"65E5
  1376. // 32 | h"6642"mm"5206
  1377. // 33 | h"6642"mm"5206"ss"79D2
  1378. // 34 | yyyy"5E74"m"6708
  1379. // 35 | m"6708"d"65E5
  1380. // 36 | [$-411]ge.m.d
  1381. // 50 | [$-411]ge.m.d
  1382. // 51 | [$-411]ggge"5E74"m"6708"d"65E5
  1383. // 52 | yyyy"5E74"m"6708
  1384. // 53 | m"6708"d"65E5
  1385. // 54 | [$-411]ggge"5E74"m"6708"d"65E5
  1386. // 55 | yyyy"5E74"m"6708
  1387. // 56 | m"6708"d"65E5
  1388. // 57 | [$-411]ge.m.d
  1389. // 58 | [$-411]ggge"5E74"m"6708"d"65E5"
  1390. //
  1391. // Number format code with unicode values provided for language glyphs where
  1392. // they occur in ko-kr language:
  1393. //
  1394. // Index | Symbol
  1395. // -------+-------------------------------------------
  1396. // 27 | yyyy"5E74" mm"6708" dd"65E5
  1397. // 28 | mm-d
  1398. // 29 | mm-d
  1399. // 30 | mm-dd-y
  1400. // 31 | yyyy"B144" mm"C6D4" dd"C77C
  1401. // 32 | h"C2DC" mm"BD84
  1402. // 33 | h"C2DC" mm"BD84" ss"CD08
  1403. // 34 | yyyy-mm-d
  1404. // 35 | yyyy-mm-d
  1405. // 36 | yyyy"5E74" mm"6708" dd"65E5
  1406. // 50 | yyyy"5E74" mm"6708" dd"65E5
  1407. // 51 | mm-d
  1408. // 52 | yyyy-mm-d
  1409. // 53 | yyyy-mm-d
  1410. // 54 | mm-d
  1411. // 55 | yyyy-mm-d
  1412. // 56 | yyyy-mm-d
  1413. // 57 | yyyy"5E74" mm"6708" dd"65E5
  1414. // 58 | mm-dd
  1415. //
  1416. // Number format code in th-th language:
  1417. //
  1418. // Index | Symbol
  1419. // -------+-------------------------------------------
  1420. // 59 | t
  1421. // 60 | t0.0
  1422. // 61 | t#,##
  1423. // 62 | t#,##0.0
  1424. // 67 | t0
  1425. // 68 | t0.00
  1426. // 69 | t# ?/
  1427. // 70 | t# ??/?
  1428. // 71 | ว/ด/ปปป
  1429. // 72 | ว-ดดด-ป
  1430. // 73 | ว-ดด
  1431. // 74 | ดดด-ป
  1432. // 75 | ช:น
  1433. // 76 | ช:นน:ท
  1434. // 77 | ว/ด/ปปปป ช:น
  1435. // 78 | นน:ท
  1436. // 79 | [ช]:นน:ท
  1437. // 80 | นน:ทท.
  1438. // 81 | d/m/bb
  1439. //
  1440. // Number format code with unicode values provided for language glyphs where
  1441. // they occur in th-th language:
  1442. //
  1443. // Index | Symbol
  1444. // -------+-------------------------------------------
  1445. // 59 | t
  1446. // 60 | t0.0
  1447. // 61 | t#,##
  1448. // 62 | t#,##0.0
  1449. // 67 | t0
  1450. // 68 | t0.00
  1451. // 69 | t# ?/
  1452. // 70 | t# ??/?
  1453. // 71 | 0E27/0E14/0E1B0E1B0E1B0E1
  1454. // 72 | 0E27-0E140E140E14-0E1B0E1
  1455. // 73 | 0E27-0E140E140E1
  1456. // 74 | 0E140E140E14-0E1B0E1
  1457. // 75 | 0E0A:0E190E1
  1458. // 76 | 0E0A:0E190E19:0E170E1
  1459. // 77 | 0E27/0E14/0E1B0E1B0E1B0E1B 0E0A:0E190E1
  1460. // 78 | 0E190E19:0E170E1
  1461. // 79 | [0E0A]:0E190E19:0E170E1
  1462. // 80 | 0E190E19:0E170E17.
  1463. // 81 | d/m/bb
  1464. //
  1465. // Excelize built-in currency formats are shown in the following table, only
  1466. // support these types in the following table (Index number is used only for
  1467. // markup and is not used inside an Excel file and you can't get formatted value
  1468. // by the function GetCellValue) currently:
  1469. //
  1470. // Index | Symbol
  1471. // -------+---------------------------------------------------------------
  1472. // 164 | ¥
  1473. // 165 | $ English (United States)
  1474. // 166 | $ Cherokee (United States)
  1475. // 167 | $ Chinese (Singapore)
  1476. // 168 | $ Chinese (Taiwan)
  1477. // 169 | $ English (Australia)
  1478. // 170 | $ English (Belize)
  1479. // 171 | $ English (Canada)
  1480. // 172 | $ English (Jamaica)
  1481. // 173 | $ English (New Zealand)
  1482. // 174 | $ English (Singapore)
  1483. // 175 | $ English (Trinidad & Tobago)
  1484. // 176 | $ English (U.S. Virgin Islands)
  1485. // 177 | $ English (United States)
  1486. // 178 | $ French (Canada)
  1487. // 179 | $ Hawaiian (United States)
  1488. // 180 | $ Malay (Brunei)
  1489. // 181 | $ Quechua (Ecuador)
  1490. // 182 | $ Spanish (Chile)
  1491. // 183 | $ Spanish (Colombia)
  1492. // 184 | $ Spanish (Ecuador)
  1493. // 185 | $ Spanish (El Salvador)
  1494. // 186 | $ Spanish (Mexico)
  1495. // 187 | $ Spanish (Puerto Rico)
  1496. // 188 | $ Spanish (United States)
  1497. // 189 | $ Spanish (Uruguay)
  1498. // 190 | £ English (United Kingdom)
  1499. // 191 | £ Scottish Gaelic (United Kingdom)
  1500. // 192 | £ Welsh (United Kindom)
  1501. // 193 | ¥ Chinese (China)
  1502. // 194 | ¥ Japanese (Japan)
  1503. // 195 | ¥ Sichuan Yi (China)
  1504. // 196 | ¥ Tibetan (China)
  1505. // 197 | ¥ Uyghur (China)
  1506. // 198 | ֏ Armenian (Armenia)
  1507. // 199 | ؋ Pashto (Afghanistan)
  1508. // 200 | ؋ Persian (Afghanistan)
  1509. // 201 | ৳ Bengali (Bangladesh)
  1510. // 202 | ៛ Khmer (Cambodia)
  1511. // 203 | ₡ Spanish (Costa Rica)
  1512. // 204 | ₦ Hausa (Nigeria)
  1513. // 205 | ₦ Igbo (Nigeria)
  1514. // 206 | ₩ Korean (South Korea)
  1515. // 207 | ₪ Hebrew (Israel)
  1516. // 208 | ₫ Vietnamese (Vietnam)
  1517. // 209 | € Basque (Spain)
  1518. // 210 | € Breton (France)
  1519. // 211 | € Catalan (Spain)
  1520. // 212 | € Corsican (France)
  1521. // 213 | € Dutch (Belgium)
  1522. // 214 | € Dutch (Netherlands)
  1523. // 215 | € English (Ireland)
  1524. // 216 | € Estonian (Estonia)
  1525. // 217 | € Euro (€ 123)
  1526. // 218 | € Euro (123 €)
  1527. // 219 | € Finnish (Finland)
  1528. // 220 | € French (Belgium)
  1529. // 221 | € French (France)
  1530. // 222 | € French (Luxembourg)
  1531. // 223 | € French (Monaco)
  1532. // 224 | € French (Réunion)
  1533. // 225 | € Galician (Spain)
  1534. // 226 | € German (Austria)
  1535. // 227 | € German (German)
  1536. // 228 | € German (Luxembourg)
  1537. // 229 | € Greek (Greece)
  1538. // 230 | € Inari Sami (Finland)
  1539. // 231 | € Irish (Ireland)
  1540. // 232 | € Italian (Italy)
  1541. // 233 | € Latin (Italy)
  1542. // 234 | € Latin, Serbian (Montenegro)
  1543. // 235 | € Larvian (Latvia)
  1544. // 236 | € Lithuanian (Lithuania)
  1545. // 237 | € Lower Sorbian (Germany)
  1546. // 238 | € Luxembourgish (Luxembourg)
  1547. // 239 | € Maltese (Malta)
  1548. // 240 | € Northern Sami (Finland)
  1549. // 241 | € Occitan (France)
  1550. // 242 | € Portuguese (Portugal)
  1551. // 243 | € Serbian (Montenegro)
  1552. // 244 | € Skolt Sami (Finland)
  1553. // 245 | € Slovak (Slovakia)
  1554. // 246 | € Slovenian (Slovenia)
  1555. // 247 | € Spanish (Spain)
  1556. // 248 | € Swedish (Finland)
  1557. // 249 | € Swiss German (France)
  1558. // 250 | € Upper Sorbian (Germany)
  1559. // 251 | € Western Frisian (Netherlands)
  1560. // 252 | ₭ Lao (Laos)
  1561. // 253 | ₮ Mongolian (Mongolia)
  1562. // 254 | ₮ Mongolian, Mongolian (Mongolia)
  1563. // 255 | ₱ English (Philippines)
  1564. // 256 | ₱ Filipino (Philippines)
  1565. // 257 | ₴ Ukrainian (Ukraine)
  1566. // 258 | ₸ Kazakh (Kazakhstan)
  1567. // 259 | ₹ Arabic, Kashmiri (India)
  1568. // 260 | ₹ English (India)
  1569. // 261 | ₹ Gujarati (India)
  1570. // 262 | ₹ Hindi (India)
  1571. // 263 | ₹ Kannada (India)
  1572. // 264 | ₹ Kashmiri (India)
  1573. // 265 | ₹ Konkani (India)
  1574. // 266 | ₹ Manipuri (India)
  1575. // 267 | ₹ Marathi (India)
  1576. // 268 | ₹ Nepali (India)
  1577. // 269 | ₹ Oriya (India)
  1578. // 270 | ₹ Punjabi (India)
  1579. // 271 | ₹ Sanskrit (India)
  1580. // 272 | ₹ Sindhi (India)
  1581. // 273 | ₹ Tamil (India)
  1582. // 274 | ₹ Urdu (India)
  1583. // 275 | ₺ Turkish (Turkey)
  1584. // 276 | ₼ Azerbaijani (Azerbaijan)
  1585. // 277 | ₼ Cyrillic, Azerbaijani (Azerbaijan)
  1586. // 278 | ₽ Russian (Russia)
  1587. // 279 | ₽ Sakha (Russia)
  1588. // 280 | ₾ Georgian (Georgia)
  1589. // 281 | B/. Spanish (Panama)
  1590. // 282 | Br Oromo (Ethiopia)
  1591. // 283 | Br Somali (Ethiopia)
  1592. // 284 | Br Tigrinya (Ethiopia)
  1593. // 285 | Bs Quechua (Bolivia)
  1594. // 286 | Bs Spanish (Bolivia)
  1595. // 287 | BS. Spanish (Venezuela)
  1596. // 288 | BWP Tswana (Botswana)
  1597. // 289 | C$ Spanish (Nicaragua)
  1598. // 290 | CA$ Latin, Inuktitut (Canada)
  1599. // 291 | CA$ Mohawk (Canada)
  1600. // 292 | CA$ Unified Canadian Aboriginal Syllabics, Inuktitut (Canada)
  1601. // 293 | CFA French (Mali)
  1602. // 294 | CFA French (Senegal)
  1603. // 295 | CFA Fulah (Senegal)
  1604. // 296 | CFA Wolof (Senegal)
  1605. // 297 | CHF French (Switzerland)
  1606. // 298 | CHF German (Liechtenstein)
  1607. // 299 | CHF German (Switzerland)
  1608. // 300 | CHF Italian (Switzerland)
  1609. // 301 | CHF Romansh (Switzerland)
  1610. // 302 | CLP Mapuche (Chile)
  1611. // 303 | CN¥ Mongolian, Mongolian (China)
  1612. // 304 | DZD Central Atlas Tamazight (Algeria)
  1613. // 305 | FCFA French (Cameroon)
  1614. // 306 | Ft Hungarian (Hungary)
  1615. // 307 | G French (Haiti)
  1616. // 308 | Gs. Spanish (Paraguay)
  1617. // 309 | GTQ K'iche' (Guatemala)
  1618. // 310 | HK$ Chinese (Hong Kong (China))
  1619. // 311 | HK$ English (Hong Kong (China))
  1620. // 312 | HRK Croatian (Croatia)
  1621. // 313 | IDR English (Indonesia)
  1622. // 314 | IQD Arbic, Central Kurdish (Iraq)
  1623. // 315 | ISK Icelandic (Iceland)
  1624. // 316 | K Burmese (Myanmar (Burma))
  1625. // 317 | Kč Czech (Czech Republic)
  1626. // 318 | KM Bosnian (Bosnia & Herzegovina)
  1627. // 319 | KM Croatian (Bosnia & Herzegovina)
  1628. // 320 | KM Latin, Serbian (Bosnia & Herzegovina)
  1629. // 321 | kr Faroese (Faroe Islands)
  1630. // 322 | kr Northern Sami (Norway)
  1631. // 323 | kr Northern Sami (Sweden)
  1632. // 324 | kr Norwegian Bokmål (Norway)
  1633. // 325 | kr Norwegian Nynorsk (Norway)
  1634. // 326 | kr Swedish (Sweden)
  1635. // 327 | kr. Danish (Denmark)
  1636. // 328 | kr. Kalaallisut (Greenland)
  1637. // 329 | Ksh Swahili (kenya)
  1638. // 330 | L Romanian (Moldova)
  1639. // 331 | L Russian (Moldova)
  1640. // 332 | L Spanish (Honduras)
  1641. // 333 | Lekë Albanian (Albania)
  1642. // 334 | MAD Arabic, Central Atlas Tamazight (Morocco)
  1643. // 335 | MAD French (Morocco)
  1644. // 336 | MAD Tifinagh, Central Atlas Tamazight (Morocco)
  1645. // 337 | MOP$ Chinese (Macau (China))
  1646. // 338 | MVR Divehi (Maldives)
  1647. // 339 | Nfk Tigrinya (Eritrea)
  1648. // 340 | NGN Bini (Nigeria)
  1649. // 341 | NGN Fulah (Nigeria)
  1650. // 342 | NGN Ibibio (Nigeria)
  1651. // 343 | NGN Kanuri (Nigeria)
  1652. // 344 | NOK Lule Sami (Norway)
  1653. // 345 | NOK Southern Sami (Norway)
  1654. // 346 | NZ$ Maori (New Zealand)
  1655. // 347 | PKR Sindhi (Pakistan)
  1656. // 348 | PYG Guarani (Paraguay)
  1657. // 349 | Q Spanish (Guatemala)
  1658. // 350 | R Afrikaans (South Africa)
  1659. // 351 | R English (South Africa)
  1660. // 352 | R Zulu (South Africa)
  1661. // 353 | R$ Portuguese (Brazil)
  1662. // 354 | RD$ Spanish (Dominican Republic)
  1663. // 355 | RF Kinyarwanda (Rwanda)
  1664. // 356 | RM English (Malaysia)
  1665. // 357 | RM Malay (Malaysia)
  1666. // 358 | RON Romanian (Romania)
  1667. // 359 | Rp Indonesoan (Indonesia)
  1668. // 360 | Rs Urdu (Pakistan)
  1669. // 361 | Rs. Tamil (Sri Lanka)
  1670. // 362 | RSD Latin, Serbian (Serbia)
  1671. // 363 | RSD Serbian (Serbia)
  1672. // 364 | RUB Bashkir (Russia)
  1673. // 365 | RUB Tatar (Russia)
  1674. // 366 | S/. Quechua (Peru)
  1675. // 367 | S/. Spanish (Peru)
  1676. // 368 | SEK Lule Sami (Sweden)
  1677. // 369 | SEK Southern Sami (Sweden)
  1678. // 370 | soʻm Latin, Uzbek (Uzbekistan)
  1679. // 371 | soʻm Uzbek (Uzbekistan)
  1680. // 372 | SYP Syriac (Syria)
  1681. // 373 | THB Thai (Thailand)
  1682. // 374 | TMT Turkmen (Turkmenistan)
  1683. // 375 | US$ English (Zimbabwe)
  1684. // 376 | ZAR Northern Sotho (South Africa)
  1685. // 377 | ZAR Southern Sotho (South Africa)
  1686. // 378 | ZAR Tsonga (South Africa)
  1687. // 379 | ZAR Tswana (south Africa)
  1688. // 380 | ZAR Venda (South Africa)
  1689. // 381 | ZAR Xhosa (South Africa)
  1690. // 382 | zł Polish (Poland)
  1691. // 383 | ден Macedonian (Macedonia)
  1692. // 384 | KM Cyrillic, Bosnian (Bosnia & Herzegovina)
  1693. // 385 | KM Serbian (Bosnia & Herzegovina)
  1694. // 386 | лв. Bulgarian (Bulgaria)
  1695. // 387 | p. Belarusian (Belarus)
  1696. // 388 | сом Kyrgyz (Kyrgyzstan)
  1697. // 389 | сом Tajik (Tajikistan)
  1698. // 390 | ج.م. Arabic (Egypt)
  1699. // 391 | د.أ. Arabic (Jordan)
  1700. // 392 | د.أ. Arabic (United Arab Emirates)
  1701. // 393 | د.ب. Arabic (Bahrain)
  1702. // 394 | د.ت. Arabic (Tunisia)
  1703. // 395 | د.ج. Arabic (Algeria)
  1704. // 396 | د.ع. Arabic (Iraq)
  1705. // 397 | د.ك. Arabic (Kuwait)
  1706. // 398 | د.ل. Arabic (Libya)
  1707. // 399 | د.م. Arabic (Morocco)
  1708. // 400 | ر Punjabi (Pakistan)
  1709. // 401 | ر.س. Arabic (Saudi Arabia)
  1710. // 402 | ر.ع. Arabic (Oman)
  1711. // 403 | ر.ق. Arabic (Qatar)
  1712. // 404 | ر.ي. Arabic (Yemen)
  1713. // 405 | ریال Persian (Iran)
  1714. // 406 | ل.س. Arabic (Syria)
  1715. // 407 | ل.ل. Arabic (Lebanon)
  1716. // 408 | ብር Amharic (Ethiopia)
  1717. // 409 | रू Nepaol (Nepal)
  1718. // 410 | රු. Sinhala (Sri Lanka)
  1719. // 411 | ADP
  1720. // 412 | AED
  1721. // 413 | AFA
  1722. // 414 | AFN
  1723. // 415 | ALL
  1724. // 416 | AMD
  1725. // 417 | ANG
  1726. // 418 | AOA
  1727. // 419 | ARS
  1728. // 420 | ATS
  1729. // 421 | AUD
  1730. // 422 | AWG
  1731. // 423 | AZM
  1732. // 424 | AZN
  1733. // 425 | BAM
  1734. // 426 | BBD
  1735. // 427 | BDT
  1736. // 428 | BEF
  1737. // 429 | BGL
  1738. // 430 | BGN
  1739. // 431 | BHD
  1740. // 432 | BIF
  1741. // 433 | BMD
  1742. // 434 | BND
  1743. // 435 | BOB
  1744. // 436 | BOV
  1745. // 437 | BRL
  1746. // 438 | BSD
  1747. // 439 | BTN
  1748. // 440 | BWP
  1749. // 441 | BYR
  1750. // 442 | BZD
  1751. // 443 | CAD
  1752. // 444 | CDF
  1753. // 445 | CHE
  1754. // 446 | CHF
  1755. // 447 | CHW
  1756. // 448 | CLF
  1757. // 449 | CLP
  1758. // 450 | CNY
  1759. // 451 | COP
  1760. // 452 | COU
  1761. // 453 | CRC
  1762. // 454 | CSD
  1763. // 455 | CUC
  1764. // 456 | CVE
  1765. // 457 | CYP
  1766. // 458 | CZK
  1767. // 459 | DEM
  1768. // 460 | DJF
  1769. // 461 | DKK
  1770. // 462 | DOP
  1771. // 463 | DZD
  1772. // 464 | ECS
  1773. // 465 | ECV
  1774. // 466 | EEK
  1775. // 467 | EGP
  1776. // 468 | ERN
  1777. // 469 | ESP
  1778. // 470 | ETB
  1779. // 471 | EUR
  1780. // 472 | FIM
  1781. // 473 | FJD
  1782. // 474 | FKP
  1783. // 475 | FRF
  1784. // 476 | GBP
  1785. // 477 | GEL
  1786. // 478 | GHC
  1787. // 479 | GHS
  1788. // 480 | GIP
  1789. // 481 | GMD
  1790. // 482 | GNF
  1791. // 483 | GRD
  1792. // 484 | GTQ
  1793. // 485 | GYD
  1794. // 486 | HKD
  1795. // 487 | HNL
  1796. // 488 | HRK
  1797. // 489 | HTG
  1798. // 490 | HUF
  1799. // 491 | IDR
  1800. // 492 | IEP
  1801. // 493 | ILS
  1802. // 494 | INR
  1803. // 495 | IQD
  1804. // 496 | IRR
  1805. // 497 | ISK
  1806. // 498 | ITL
  1807. // 499 | JMD
  1808. // 500 | JOD
  1809. // 501 | JPY
  1810. // 502 | KAF
  1811. // 503 | KES
  1812. // 504 | KGS
  1813. // 505 | KHR
  1814. // 506 | KMF
  1815. // 507 | KPW
  1816. // 508 | KRW
  1817. // 509 | KWD
  1818. // 510 | KYD
  1819. // 511 | KZT
  1820. // 512 | LAK
  1821. // 513 | LBP
  1822. // 514 | LKR
  1823. // 515 | LRD
  1824. // 516 | LSL
  1825. // 517 | LTL
  1826. // 518 | LUF
  1827. // 519 | LVL
  1828. // 520 | LYD
  1829. // 521 | MAD
  1830. // 522 | MDL
  1831. // 523 | MGA
  1832. // 524 | MGF
  1833. // 525 | MKD
  1834. // 526 | MMK
  1835. // 527 | MNT
  1836. // 528 | MOP
  1837. // 529 | MRO
  1838. // 530 | MTL
  1839. // 531 | MUR
  1840. // 532 | MVR
  1841. // 533 | MWK
  1842. // 534 | MXN
  1843. // 535 | MXV
  1844. // 536 | MYR
  1845. // 537 | MZM
  1846. // 538 | MZN
  1847. // 539 | NAD
  1848. // 540 | NGN
  1849. // 541 | NIO
  1850. // 542 | NLG
  1851. // 543 | NOK
  1852. // 544 | NPR
  1853. // 545 | NTD
  1854. // 546 | NZD
  1855. // 547 | OMR
  1856. // 548 | PAB
  1857. // 549 | PEN
  1858. // 550 | PGK
  1859. // 551 | PHP
  1860. // 552 | PKR
  1861. // 553 | PLN
  1862. // 554 | PTE
  1863. // 555 | PYG
  1864. // 556 | QAR
  1865. // 557 | ROL
  1866. // 558 | RON
  1867. // 559 | RSD
  1868. // 560 | RUB
  1869. // 561 | RUR
  1870. // 562 | RWF
  1871. // 563 | SAR
  1872. // 564 | SBD
  1873. // 565 | SCR
  1874. // 566 | SDD
  1875. // 567 | SDG
  1876. // 568 | SDP
  1877. // 569 | SEK
  1878. // 570 | SGD
  1879. // 571 | SHP
  1880. // 572 | SIT
  1881. // 573 | SKK
  1882. // 574 | SLL
  1883. // 575 | SOS
  1884. // 576 | SPL
  1885. // 577 | SRD
  1886. // 578 | SRG
  1887. // 579 | STD
  1888. // 580 | SVC
  1889. // 581 | SYP
  1890. // 582 | SZL
  1891. // 583 | THB
  1892. // 584 | TJR
  1893. // 585 | TJS
  1894. // 586 | TMM
  1895. // 587 | TMT
  1896. // 588 | TND
  1897. // 589 | TOP
  1898. // 590 | TRL
  1899. // 591 | TRY
  1900. // 592 | TTD
  1901. // 593 | TWD
  1902. // 594 | TZS
  1903. // 595 | UAH
  1904. // 596 | UGX
  1905. // 597 | USD
  1906. // 598 | USN
  1907. // 599 | USS
  1908. // 600 | UYI
  1909. // 601 | UYU
  1910. // 602 | UZS
  1911. // 603 | VEB
  1912. // 604 | VEF
  1913. // 605 | VND
  1914. // 606 | VUV
  1915. // 607 | WST
  1916. // 608 | XAF
  1917. // 609 | XAG
  1918. // 610 | XAU
  1919. // 611 | XB5
  1920. // 612 | XBA
  1921. // 613 | XBB
  1922. // 614 | XBC
  1923. // 615 | XBD
  1924. // 616 | XCD
  1925. // 617 | XDR
  1926. // 618 | XFO
  1927. // 619 | XFU
  1928. // 620 | XOF
  1929. // 621 | XPD
  1930. // 622 | XPF
  1931. // 623 | XPT
  1932. // 624 | XTS
  1933. // 625 | XXX
  1934. // 626 | YER
  1935. // 627 | YUM
  1936. // 628 | ZAR
  1937. // 629 | ZMK
  1938. // 630 | ZMW
  1939. // 631 | ZWD
  1940. // 632 | ZWL
  1941. // 633 | ZWN
  1942. // 634 | ZWR
  1943. //
  1944. // Excelize support set custom number format for cell. For example, set number
  1945. // as date type in Uruguay (Spanish) format for Sheet1!A6:
  1946. //
  1947. // f := excelize.NewFile()
  1948. // defer func() {
  1949. // if err := f.Close(); err != nil {
  1950. // fmt.Println(err)
  1951. // }
  1952. // }()
  1953. // if err := f.SetCellValue("Sheet1", "A6", 42920.5); err != nil {
  1954. // fmt.Println(err)
  1955. // return
  1956. // }
  1957. // exp := "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"
  1958. // style, err := f.NewStyle(&excelize.Style{CustomNumFmt: &exp})
  1959. // if err != nil {
  1960. // fmt.Println(err)
  1961. // return
  1962. // }
  1963. // err = f.SetCellStyle("Sheet1", "A6", "A6", style)
  1964. //
  1965. // Cell Sheet1!A6 in the Excel Application: martes, 04 de Julio de 2017
  1966. func (f *File) NewStyle(style *Style) (int, error) {
  1967. var (
  1968. fs *Style
  1969. font *xlsxFont
  1970. err error
  1971. cellXfsID, fontID, borderID, fillID int
  1972. )
  1973. if style == nil {
  1974. return cellXfsID, err
  1975. }
  1976. fs, err = parseFormatStyleSet(style)
  1977. if err != nil {
  1978. return cellXfsID, err
  1979. }
  1980. if fs.DecimalPlaces == 0 {
  1981. fs.DecimalPlaces = 2
  1982. }
  1983. s, err := f.stylesReader()
  1984. if err != nil {
  1985. return cellXfsID, err
  1986. }
  1987. s.Lock()
  1988. defer s.Unlock()
  1989. // check given style already exist.
  1990. if cellXfsID, err = f.getStyleID(s, fs); err != nil || cellXfsID != -1 {
  1991. return cellXfsID, err
  1992. }
  1993. numFmtID := newNumFmt(s, fs)
  1994. if fs.Font != nil {
  1995. fontID, _ = f.getFontID(s, fs)
  1996. if fontID == -1 {
  1997. s.Fonts.Count++
  1998. font, _ = f.newFont(fs)
  1999. s.Fonts.Font = append(s.Fonts.Font, font)
  2000. fontID = s.Fonts.Count - 1
  2001. }
  2002. }
  2003. borderID = getBorderID(s, fs)
  2004. if borderID == -1 {
  2005. if len(fs.Border) == 0 {
  2006. borderID = 0
  2007. } else {
  2008. s.Borders.Count++
  2009. s.Borders.Border = append(s.Borders.Border, newBorders(fs))
  2010. borderID = s.Borders.Count - 1
  2011. }
  2012. }
  2013. if fillID = getFillID(s, fs); fillID == -1 {
  2014. if fill := newFills(fs, true); fill != nil {
  2015. s.Fills.Count++
  2016. s.Fills.Fill = append(s.Fills.Fill, fill)
  2017. fillID = s.Fills.Count - 1
  2018. } else {
  2019. fillID = 0
  2020. }
  2021. }
  2022. applyAlignment, alignment := fs.Alignment != nil, newAlignment(fs)
  2023. applyProtection, protection := fs.Protection != nil, newProtection(fs)
  2024. return setCellXfs(s, fontID, numFmtID, fillID, borderID, applyAlignment, applyProtection, alignment, protection)
  2025. }
  2026. var getXfIDFuncs = map[string]func(int, xlsxXf, *Style) bool{
  2027. "numFmt": func(numFmtID int, xf xlsxXf, style *Style) bool {
  2028. if style.CustomNumFmt == nil && numFmtID == -1 {
  2029. return xf.NumFmtID != nil && *xf.NumFmtID == 0
  2030. }
  2031. if style.NegRed || style.Lang != "" || style.DecimalPlaces != 2 {
  2032. return false
  2033. }
  2034. return xf.NumFmtID != nil && *xf.NumFmtID == numFmtID
  2035. },
  2036. "font": func(fontID int, xf xlsxXf, style *Style) bool {
  2037. if style.Font == nil {
  2038. return (xf.FontID == nil || *xf.FontID == 0) && (xf.ApplyFont == nil || !*xf.ApplyFont)
  2039. }
  2040. return xf.FontID != nil && *xf.FontID == fontID && xf.ApplyFont != nil && *xf.ApplyFont
  2041. },
  2042. "fill": func(fillID int, xf xlsxXf, style *Style) bool {
  2043. if style.Fill.Type == "" {
  2044. return (xf.FillID == nil || *xf.FillID == 0) && (xf.ApplyFill == nil || !*xf.ApplyFill)
  2045. }
  2046. return xf.FillID != nil && *xf.FillID == fillID && xf.ApplyFill != nil && *xf.ApplyFill
  2047. },
  2048. "border": func(borderID int, xf xlsxXf, style *Style) bool {
  2049. if len(style.Border) == 0 {
  2050. return (xf.BorderID == nil || *xf.BorderID == 0) && (xf.ApplyBorder == nil || !*xf.ApplyBorder)
  2051. }
  2052. return xf.BorderID != nil && *xf.BorderID == borderID && xf.ApplyBorder != nil && *xf.ApplyBorder
  2053. },
  2054. "alignment": func(ID int, xf xlsxXf, style *Style) bool {
  2055. if style.Alignment == nil {
  2056. return xf.ApplyAlignment == nil || !*xf.ApplyAlignment
  2057. }
  2058. return reflect.DeepEqual(xf.Alignment, newAlignment(style))
  2059. },
  2060. "protection": func(ID int, xf xlsxXf, style *Style) bool {
  2061. if style.Protection == nil {
  2062. return xf.ApplyProtection == nil || !*xf.ApplyProtection
  2063. }
  2064. return reflect.DeepEqual(xf.Protection, newProtection(style)) && xf.ApplyProtection != nil && *xf.ApplyProtection
  2065. },
  2066. }
  2067. // getStyleID provides a function to get styleID by given style. If given
  2068. // style does not exist, will return -1.
  2069. func (f *File) getStyleID(ss *xlsxStyleSheet, style *Style) (int, error) {
  2070. var (
  2071. err error
  2072. fontID int
  2073. styleID = -1
  2074. )
  2075. if ss.CellXfs == nil {
  2076. return styleID, err
  2077. }
  2078. numFmtID, borderID, fillID := getNumFmtID(ss, style), getBorderID(ss, style), getFillID(ss, style)
  2079. if fontID, err = f.getFontID(ss, style); err != nil {
  2080. return styleID, err
  2081. }
  2082. if style.CustomNumFmt != nil {
  2083. numFmtID = getCustomNumFmtID(ss, style)
  2084. }
  2085. for xfID, xf := range ss.CellXfs.Xf {
  2086. if getXfIDFuncs["numFmt"](numFmtID, xf, style) &&
  2087. getXfIDFuncs["font"](fontID, xf, style) &&
  2088. getXfIDFuncs["fill"](fillID, xf, style) &&
  2089. getXfIDFuncs["border"](borderID, xf, style) &&
  2090. getXfIDFuncs["alignment"](0, xf, style) &&
  2091. getXfIDFuncs["protection"](0, xf, style) {
  2092. styleID = xfID
  2093. return styleID, err
  2094. }
  2095. }
  2096. return styleID, err
  2097. }
  2098. // NewConditionalStyle provides a function to create style for conditional
  2099. // format by given style format. The parameters are the same with the NewStyle
  2100. // function.
  2101. func (f *File) NewConditionalStyle(style *Style) (int, error) {
  2102. s, err := f.stylesReader()
  2103. if err != nil {
  2104. return 0, err
  2105. }
  2106. fs, err := parseFormatStyleSet(style)
  2107. if err != nil {
  2108. return 0, err
  2109. }
  2110. dxf := dxf{
  2111. Fill: newFills(fs, false),
  2112. }
  2113. if fs.Alignment != nil {
  2114. dxf.Alignment = newAlignment(fs)
  2115. }
  2116. if len(fs.Border) > 0 {
  2117. dxf.Border = newBorders(fs)
  2118. }
  2119. if fs.Font != nil {
  2120. dxf.Font, _ = f.newFont(fs)
  2121. }
  2122. dxfStr, _ := xml.Marshal(dxf)
  2123. if s.Dxfs == nil {
  2124. s.Dxfs = &xlsxDxfs{}
  2125. }
  2126. s.Dxfs.Count++
  2127. s.Dxfs.Dxfs = append(s.Dxfs.Dxfs, &xlsxDxf{
  2128. Dxf: string(dxfStr[5 : len(dxfStr)-6]),
  2129. })
  2130. return s.Dxfs.Count - 1, nil
  2131. }
  2132. // GetDefaultFont provides the default font name currently set in the
  2133. // workbook. The spreadsheet generated by excelize default font is Calibri.
  2134. func (f *File) GetDefaultFont() (string, error) {
  2135. font, err := f.readDefaultFont()
  2136. if err != nil {
  2137. return "", err
  2138. }
  2139. return *font.Name.Val, err
  2140. }
  2141. // SetDefaultFont changes the default font in the workbook.
  2142. func (f *File) SetDefaultFont(fontName string) error {
  2143. font, err := f.readDefaultFont()
  2144. if err != nil {
  2145. return err
  2146. }
  2147. font.Name.Val = stringPtr(fontName)
  2148. s, _ := f.stylesReader()
  2149. s.Fonts.Font[0] = font
  2150. custom := true
  2151. s.CellStyles.CellStyle[0].CustomBuiltIn = &custom
  2152. return err
  2153. }
  2154. // readDefaultFont provides an un-marshalled font value.
  2155. func (f *File) readDefaultFont() (*xlsxFont, error) {
  2156. s, err := f.stylesReader()
  2157. if err != nil {
  2158. return nil, err
  2159. }
  2160. return s.Fonts.Font[0], err
  2161. }
  2162. // getFontID provides a function to get font ID.
  2163. // If given font does not exist, will return -1.
  2164. func (f *File) getFontID(styleSheet *xlsxStyleSheet, style *Style) (int, error) {
  2165. var err error
  2166. fontID := -1
  2167. if styleSheet.Fonts == nil || style.Font == nil {
  2168. return fontID, err
  2169. }
  2170. for idx, fnt := range styleSheet.Fonts.Font {
  2171. font, err := f.newFont(style)
  2172. if err != nil {
  2173. return fontID, err
  2174. }
  2175. if reflect.DeepEqual(*fnt, *font) {
  2176. fontID = idx
  2177. return fontID, err
  2178. }
  2179. }
  2180. return fontID, err
  2181. }
  2182. // newFontColor set font color by given styles.
  2183. func newFontColor(font *Font) *xlsxColor {
  2184. var fontColor *xlsxColor
  2185. prepareFontColor := func() {
  2186. if fontColor != nil {
  2187. return
  2188. }
  2189. fontColor = &xlsxColor{}
  2190. }
  2191. if font.Color != "" {
  2192. prepareFontColor()
  2193. fontColor.RGB = getPaletteColor(font.Color)
  2194. }
  2195. if font.ColorIndexed >= 0 && font.ColorIndexed <= len(IndexedColorMapping)+1 {
  2196. prepareFontColor()
  2197. fontColor.Indexed = font.ColorIndexed
  2198. }
  2199. if font.ColorTheme != nil {
  2200. prepareFontColor()
  2201. fontColor.Theme = font.ColorTheme
  2202. }
  2203. if font.ColorTint != 0 {
  2204. prepareFontColor()
  2205. fontColor.Tint = font.ColorTint
  2206. }
  2207. return fontColor
  2208. }
  2209. // newFont provides a function to add font style by given cell format
  2210. // settings.
  2211. func (f *File) newFont(style *Style) (*xlsxFont, error) {
  2212. var err error
  2213. if style.Font.Size < MinFontSize {
  2214. style.Font.Size = 11
  2215. }
  2216. fnt := xlsxFont{
  2217. Sz: &attrValFloat{Val: float64Ptr(style.Font.Size)},
  2218. Name: &attrValString{Val: stringPtr(style.Font.Family)},
  2219. Family: &attrValInt{Val: intPtr(2)},
  2220. }
  2221. fnt.Color = newFontColor(style.Font)
  2222. if style.Font.Bold {
  2223. fnt.B = &attrValBool{Val: &style.Font.Bold}
  2224. }
  2225. if style.Font.Italic {
  2226. fnt.I = &attrValBool{Val: &style.Font.Italic}
  2227. }
  2228. if *fnt.Name.Val == "" {
  2229. if *fnt.Name.Val, err = f.GetDefaultFont(); err != nil {
  2230. return &fnt, err
  2231. }
  2232. }
  2233. if style.Font.Strike {
  2234. fnt.Strike = &attrValBool{Val: &style.Font.Strike}
  2235. }
  2236. if idx := inStrSlice(supportedUnderlineTypes, style.Font.Underline, true); idx != -1 {
  2237. fnt.U = &attrValString{Val: stringPtr(supportedUnderlineTypes[idx])}
  2238. }
  2239. return &fnt, err
  2240. }
  2241. // getNumFmtID provides a function to get number format code ID.
  2242. // If given number format code does not exist, will return -1.
  2243. func getNumFmtID(styleSheet *xlsxStyleSheet, style *Style) (numFmtID int) {
  2244. numFmtID = -1
  2245. if _, ok := builtInNumFmt[style.NumFmt]; ok {
  2246. return style.NumFmt
  2247. }
  2248. for lang, numFmt := range langNumFmt {
  2249. if _, ok := numFmt[style.NumFmt]; ok && lang == style.Lang {
  2250. numFmtID = style.NumFmt
  2251. return
  2252. }
  2253. }
  2254. if fmtCode, ok := currencyNumFmt[style.NumFmt]; ok {
  2255. numFmtID = style.NumFmt
  2256. if styleSheet.NumFmts != nil {
  2257. for _, numFmt := range styleSheet.NumFmts.NumFmt {
  2258. if numFmt.FormatCode == fmtCode {
  2259. numFmtID = numFmt.NumFmtID
  2260. return
  2261. }
  2262. }
  2263. }
  2264. }
  2265. return
  2266. }
  2267. // newNumFmt provides a function to check if number format code in the range
  2268. // of built-in values.
  2269. func newNumFmt(styleSheet *xlsxStyleSheet, style *Style) int {
  2270. dp := "0."
  2271. numFmtID := 164 // Default custom number format code from 164.
  2272. if style.DecimalPlaces < 0 || style.DecimalPlaces > 30 {
  2273. style.DecimalPlaces = 2
  2274. }
  2275. for i := 0; i < style.DecimalPlaces; i++ {
  2276. dp += "0"
  2277. }
  2278. if style.CustomNumFmt != nil {
  2279. if customNumFmtID := getCustomNumFmtID(styleSheet, style); customNumFmtID != -1 {
  2280. return customNumFmtID
  2281. }
  2282. return setCustomNumFmt(styleSheet, style)
  2283. }
  2284. _, ok := builtInNumFmt[style.NumFmt]
  2285. if !ok {
  2286. fc, currency := currencyNumFmt[style.NumFmt]
  2287. if !currency {
  2288. return setLangNumFmt(styleSheet, style)
  2289. }
  2290. fc = strings.ReplaceAll(fc, "0.00", dp)
  2291. if style.NegRed {
  2292. fc = fc + ";[Red]" + fc
  2293. }
  2294. if styleSheet.NumFmts != nil {
  2295. numFmtID = styleSheet.NumFmts.NumFmt[len(styleSheet.NumFmts.NumFmt)-1].NumFmtID + 1
  2296. nf := xlsxNumFmt{
  2297. FormatCode: fc,
  2298. NumFmtID: numFmtID,
  2299. }
  2300. styleSheet.NumFmts.NumFmt = append(styleSheet.NumFmts.NumFmt, &nf)
  2301. styleSheet.NumFmts.Count++
  2302. } else {
  2303. nf := xlsxNumFmt{
  2304. FormatCode: fc,
  2305. NumFmtID: numFmtID,
  2306. }
  2307. numFmts := xlsxNumFmts{
  2308. NumFmt: []*xlsxNumFmt{&nf},
  2309. Count: 1,
  2310. }
  2311. styleSheet.NumFmts = &numFmts
  2312. }
  2313. return numFmtID
  2314. }
  2315. return style.NumFmt
  2316. }
  2317. // setCustomNumFmt provides a function to set custom number format code.
  2318. func setCustomNumFmt(styleSheet *xlsxStyleSheet, style *Style) int {
  2319. nf := xlsxNumFmt{FormatCode: *style.CustomNumFmt}
  2320. if styleSheet.NumFmts != nil {
  2321. nf.NumFmtID = styleSheet.NumFmts.NumFmt[len(styleSheet.NumFmts.NumFmt)-1].NumFmtID + 1
  2322. styleSheet.NumFmts.NumFmt = append(styleSheet.NumFmts.NumFmt, &nf)
  2323. styleSheet.NumFmts.Count++
  2324. } else {
  2325. nf.NumFmtID = 164
  2326. numFmts := xlsxNumFmts{
  2327. NumFmt: []*xlsxNumFmt{&nf},
  2328. Count: 1,
  2329. }
  2330. styleSheet.NumFmts = &numFmts
  2331. }
  2332. return nf.NumFmtID
  2333. }
  2334. // getCustomNumFmtID provides a function to get custom number format code ID.
  2335. // If given custom number format code does not exist, will return -1.
  2336. func getCustomNumFmtID(styleSheet *xlsxStyleSheet, style *Style) (customNumFmtID int) {
  2337. customNumFmtID = -1
  2338. if styleSheet.NumFmts == nil {
  2339. return
  2340. }
  2341. for _, numFmt := range styleSheet.NumFmts.NumFmt {
  2342. if style.CustomNumFmt != nil && numFmt.FormatCode == *style.CustomNumFmt {
  2343. customNumFmtID = numFmt.NumFmtID
  2344. return
  2345. }
  2346. }
  2347. return
  2348. }
  2349. // setLangNumFmt provides a function to set number format code with language.
  2350. func setLangNumFmt(styleSheet *xlsxStyleSheet, style *Style) int {
  2351. numFmts, ok := langNumFmt[style.Lang]
  2352. if !ok {
  2353. return 0
  2354. }
  2355. var fc string
  2356. fc, ok = numFmts[style.NumFmt]
  2357. if !ok {
  2358. return 0
  2359. }
  2360. nf := xlsxNumFmt{FormatCode: fc}
  2361. if styleSheet.NumFmts != nil {
  2362. nf.NumFmtID = styleSheet.NumFmts.NumFmt[len(styleSheet.NumFmts.NumFmt)-1].NumFmtID + 1
  2363. styleSheet.NumFmts.NumFmt = append(styleSheet.NumFmts.NumFmt, &nf)
  2364. styleSheet.NumFmts.Count++
  2365. } else {
  2366. nf.NumFmtID = style.NumFmt
  2367. numFmts := xlsxNumFmts{
  2368. NumFmt: []*xlsxNumFmt{&nf},
  2369. Count: 1,
  2370. }
  2371. styleSheet.NumFmts = &numFmts
  2372. }
  2373. return nf.NumFmtID
  2374. }
  2375. // getFillID provides a function to get fill ID. If given fill is not
  2376. // exist, will return -1.
  2377. func getFillID(styleSheet *xlsxStyleSheet, style *Style) (fillID int) {
  2378. fillID = -1
  2379. if styleSheet.Fills == nil || style.Fill.Type == "" {
  2380. return
  2381. }
  2382. fills := newFills(style, true)
  2383. if fills == nil {
  2384. return
  2385. }
  2386. for idx, fill := range styleSheet.Fills.Fill {
  2387. if reflect.DeepEqual(fill, fills) {
  2388. fillID = idx
  2389. return
  2390. }
  2391. }
  2392. return
  2393. }
  2394. // newFills provides a function to add fill elements in the styles.xml by
  2395. // given cell format settings.
  2396. func newFills(style *Style, fg bool) *xlsxFill {
  2397. patterns := []string{
  2398. "none",
  2399. "solid",
  2400. "mediumGray",
  2401. "darkGray",
  2402. "lightGray",
  2403. "darkHorizontal",
  2404. "darkVertical",
  2405. "darkDown",
  2406. "darkUp",
  2407. "darkGrid",
  2408. "darkTrellis",
  2409. "lightHorizontal",
  2410. "lightVertical",
  2411. "lightDown",
  2412. "lightUp",
  2413. "lightGrid",
  2414. "lightTrellis",
  2415. "gray125",
  2416. "gray0625",
  2417. }
  2418. variants := []xlsxGradientFill{
  2419. {Degree: 90, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2420. {Degree: 270, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2421. {Degree: 90, Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
  2422. {Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2423. {Degree: 180, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2424. {Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
  2425. {Degree: 45, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2426. {Degree: 255, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2427. {Degree: 45, Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
  2428. {Degree: 135, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2429. {Degree: 315, Stop: []*xlsxGradientFillStop{{}, {Position: 1}}},
  2430. {Degree: 135, Stop: []*xlsxGradientFillStop{{}, {Position: 0.5}, {Position: 1}}},
  2431. {Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path"},
  2432. {Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Left: 1, Right: 1},
  2433. {Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Bottom: 1, Top: 1},
  2434. {Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Bottom: 1, Left: 1, Right: 1, Top: 1},
  2435. {Stop: []*xlsxGradientFillStop{{}, {Position: 1}}, Type: "path", Bottom: 0.5, Left: 0.5, Right: 0.5, Top: 0.5},
  2436. }
  2437. var fill xlsxFill
  2438. switch style.Fill.Type {
  2439. case "gradient":
  2440. if len(style.Fill.Color) != 2 || style.Fill.Shading < 0 || style.Fill.Shading > 16 {
  2441. break
  2442. }
  2443. gradient := variants[style.Fill.Shading]
  2444. gradient.Stop[0].Color.RGB = getPaletteColor(style.Fill.Color[0])
  2445. gradient.Stop[1].Color.RGB = getPaletteColor(style.Fill.Color[1])
  2446. if len(gradient.Stop) == 3 {
  2447. gradient.Stop[2].Color.RGB = getPaletteColor(style.Fill.Color[0])
  2448. }
  2449. fill.GradientFill = &gradient
  2450. case "pattern":
  2451. if style.Fill.Pattern > 18 || style.Fill.Pattern < 0 {
  2452. break
  2453. }
  2454. if len(style.Fill.Color) < 1 {
  2455. break
  2456. }
  2457. var pattern xlsxPatternFill
  2458. pattern.PatternType = patterns[style.Fill.Pattern]
  2459. if fg {
  2460. if pattern.FgColor == nil {
  2461. pattern.FgColor = new(xlsxColor)
  2462. }
  2463. pattern.FgColor.RGB = getPaletteColor(style.Fill.Color[0])
  2464. } else {
  2465. if pattern.BgColor == nil {
  2466. pattern.BgColor = new(xlsxColor)
  2467. }
  2468. pattern.BgColor.RGB = getPaletteColor(style.Fill.Color[0])
  2469. }
  2470. fill.PatternFill = &pattern
  2471. default:
  2472. return nil
  2473. }
  2474. return &fill
  2475. }
  2476. // newAlignment provides a function to formatting information pertaining to
  2477. // text alignment in cells. There are a variety of choices for how text is
  2478. // aligned both horizontally and vertically, as well as indentation settings,
  2479. // and so on.
  2480. func newAlignment(style *Style) *xlsxAlignment {
  2481. var alignment xlsxAlignment
  2482. if style.Alignment != nil {
  2483. alignment.Horizontal = style.Alignment.Horizontal
  2484. alignment.Indent = style.Alignment.Indent
  2485. alignment.JustifyLastLine = style.Alignment.JustifyLastLine
  2486. alignment.ReadingOrder = style.Alignment.ReadingOrder
  2487. alignment.RelativeIndent = style.Alignment.RelativeIndent
  2488. alignment.ShrinkToFit = style.Alignment.ShrinkToFit
  2489. alignment.TextRotation = style.Alignment.TextRotation
  2490. alignment.Vertical = style.Alignment.Vertical
  2491. alignment.WrapText = style.Alignment.WrapText
  2492. }
  2493. return &alignment
  2494. }
  2495. // newProtection provides a function to set protection properties associated
  2496. // with the cell.
  2497. func newProtection(style *Style) *xlsxProtection {
  2498. var protection xlsxProtection
  2499. if style.Protection != nil {
  2500. protection.Hidden = &style.Protection.Hidden
  2501. protection.Locked = &style.Protection.Locked
  2502. }
  2503. return &protection
  2504. }
  2505. // getBorderID provides a function to get border ID. If given border is not
  2506. // exist, will return -1.
  2507. func getBorderID(styleSheet *xlsxStyleSheet, style *Style) (borderID int) {
  2508. borderID = -1
  2509. if styleSheet.Borders == nil || len(style.Border) == 0 {
  2510. return
  2511. }
  2512. for idx, border := range styleSheet.Borders.Border {
  2513. if reflect.DeepEqual(*border, *newBorders(style)) {
  2514. borderID = idx
  2515. return
  2516. }
  2517. }
  2518. return
  2519. }
  2520. // newBorders provides a function to add border elements in the styles.xml by
  2521. // given borders format settings.
  2522. func newBorders(style *Style) *xlsxBorder {
  2523. styles := []string{
  2524. "none",
  2525. "thin",
  2526. "medium",
  2527. "dashed",
  2528. "dotted",
  2529. "thick",
  2530. "double",
  2531. "hair",
  2532. "mediumDashed",
  2533. "dashDot",
  2534. "mediumDashDot",
  2535. "dashDotDot",
  2536. "mediumDashDotDot",
  2537. "slantDashDot",
  2538. }
  2539. var border xlsxBorder
  2540. for _, v := range style.Border {
  2541. if 0 <= v.Style && v.Style < 14 {
  2542. var color xlsxColor
  2543. color.RGB = getPaletteColor(v.Color)
  2544. switch v.Type {
  2545. case "left":
  2546. border.Left.Style = styles[v.Style]
  2547. border.Left.Color = &color
  2548. case "right":
  2549. border.Right.Style = styles[v.Style]
  2550. border.Right.Color = &color
  2551. case "top":
  2552. border.Top.Style = styles[v.Style]
  2553. border.Top.Color = &color
  2554. case "bottom":
  2555. border.Bottom.Style = styles[v.Style]
  2556. border.Bottom.Color = &color
  2557. case "diagonalUp":
  2558. border.Diagonal.Style = styles[v.Style]
  2559. border.Diagonal.Color = &color
  2560. border.DiagonalUp = true
  2561. case "diagonalDown":
  2562. border.Diagonal.Style = styles[v.Style]
  2563. border.Diagonal.Color = &color
  2564. border.DiagonalDown = true
  2565. }
  2566. }
  2567. }
  2568. return &border
  2569. }
  2570. // setCellXfs provides a function to set describes all of the formatting for a
  2571. // cell.
  2572. func setCellXfs(style *xlsxStyleSheet, fontID, numFmtID, fillID, borderID int, applyAlignment, applyProtection bool, alignment *xlsxAlignment, protection *xlsxProtection) (int, error) {
  2573. var xf xlsxXf
  2574. xf.FontID = intPtr(fontID)
  2575. if fontID != 0 {
  2576. xf.ApplyFont = boolPtr(true)
  2577. }
  2578. xf.NumFmtID = intPtr(numFmtID)
  2579. if numFmtID != 0 {
  2580. xf.ApplyNumberFormat = boolPtr(true)
  2581. }
  2582. xf.FillID = intPtr(fillID)
  2583. if fillID != 0 {
  2584. xf.ApplyFill = boolPtr(true)
  2585. }
  2586. xf.BorderID = intPtr(borderID)
  2587. if borderID != 0 {
  2588. xf.ApplyBorder = boolPtr(true)
  2589. }
  2590. if len(style.CellXfs.Xf) == MaxCellStyles {
  2591. return 0, ErrCellStyles
  2592. }
  2593. style.CellXfs.Count = len(style.CellXfs.Xf) + 1
  2594. xf.Alignment = alignment
  2595. if alignment != nil {
  2596. xf.ApplyAlignment = boolPtr(applyAlignment)
  2597. }
  2598. if applyProtection {
  2599. xf.ApplyProtection = boolPtr(applyProtection)
  2600. xf.Protection = protection
  2601. }
  2602. xfID := 0
  2603. xf.XfID = &xfID
  2604. style.CellXfs.Xf = append(style.CellXfs.Xf, xf)
  2605. return style.CellXfs.Count - 1, nil
  2606. }
  2607. // GetCellStyle provides a function to get cell style index by given worksheet
  2608. // name and cell reference.
  2609. func (f *File) GetCellStyle(sheet, cell string) (int, error) {
  2610. ws, err := f.workSheetReader(sheet)
  2611. if err != nil {
  2612. return 0, err
  2613. }
  2614. col, row, err := CellNameToCoordinates(cell)
  2615. if err != nil {
  2616. return 0, err
  2617. }
  2618. prepareSheetXML(ws, col, row)
  2619. ws.Lock()
  2620. defer ws.Unlock()
  2621. return f.prepareCellStyle(ws, col, row, ws.SheetData.Row[row-1].C[col-1].S), err
  2622. }
  2623. // SetCellStyle provides a function to add style attribute for cells by given
  2624. // worksheet name, range reference and style ID. This function is concurrency
  2625. // safe. Note that diagonalDown and diagonalUp type border should be use same
  2626. // color in the same range. SetCellStyle will overwrite the existing
  2627. // styles for the cell, it won't append or merge style with existing styles.
  2628. //
  2629. // For example create a borders of cell H9 on Sheet1:
  2630. //
  2631. // style, err := f.NewStyle(&excelize.Style{
  2632. // Border: []excelize.Border{
  2633. // {Type: "left", Color: "0000FF", Style: 3},
  2634. // {Type: "top", Color: "00FF00", Style: 4},
  2635. // {Type: "bottom", Color: "FFFF00", Style: 5},
  2636. // {Type: "right", Color: "FF0000", Style: 6},
  2637. // {Type: "diagonalDown", Color: "A020F0", Style: 7},
  2638. // {Type: "diagonalUp", Color: "A020F0", Style: 8},
  2639. // },
  2640. // })
  2641. // if err != nil {
  2642. // fmt.Println(err)
  2643. // }
  2644. // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
  2645. //
  2646. // Set gradient fill with vertical variants shading styles for cell H9 on
  2647. // Sheet1:
  2648. //
  2649. // style, err := f.NewStyle(&excelize.Style{
  2650. // Fill: excelize.Fill{Type: "gradient", Color: []string{"FFFFFF", "E0EBF5"}, Shading: 1},
  2651. // })
  2652. // if err != nil {
  2653. // fmt.Println(err)
  2654. // }
  2655. // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
  2656. //
  2657. // Set solid style pattern fill for cell H9 on Sheet1:
  2658. //
  2659. // style, err := f.NewStyle(&excelize.Style{
  2660. // Fill: excelize.Fill{Type: "pattern", Color: []string{"E0EBF5"}, Pattern: 1},
  2661. // })
  2662. // if err != nil {
  2663. // fmt.Println(err)
  2664. // }
  2665. // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
  2666. //
  2667. // Set alignment style for cell H9 on Sheet1:
  2668. //
  2669. // style, err := f.NewStyle(&excelize.Style{
  2670. // Alignment: &excelize.Alignment{
  2671. // Horizontal: "center",
  2672. // Indent: 1,
  2673. // JustifyLastLine: true,
  2674. // ReadingOrder: 0,
  2675. // RelativeIndent: 1,
  2676. // ShrinkToFit: true,
  2677. // TextRotation: 45,
  2678. // Vertical: "",
  2679. // WrapText: true,
  2680. // },
  2681. // })
  2682. // if err != nil {
  2683. // fmt.Println(err)
  2684. // }
  2685. // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
  2686. //
  2687. // Dates and times in Excel are represented by real numbers, for example "Apr 7
  2688. // 2017 12:00 PM" is represented by the number 42920.5. Set date and time format
  2689. // for cell H9 on Sheet1:
  2690. //
  2691. // f.SetCellValue("Sheet1", "H9", 42920.5)
  2692. // style, err := f.NewStyle(&excelize.Style{NumFmt: 22})
  2693. // if err != nil {
  2694. // fmt.Println(err)
  2695. // }
  2696. // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
  2697. //
  2698. // Set font style for cell H9 on Sheet1:
  2699. //
  2700. // style, err := f.NewStyle(&excelize.Style{
  2701. // Font: &excelize.Font{
  2702. // Bold: true,
  2703. // Italic: true,
  2704. // Family: "Times New Roman",
  2705. // Size: 36,
  2706. // Color: "777777",
  2707. // },
  2708. // })
  2709. // if err != nil {
  2710. // fmt.Println(err)
  2711. // }
  2712. // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
  2713. //
  2714. // Hide and lock for cell H9 on Sheet1:
  2715. //
  2716. // style, err := f.NewStyle(&excelize.Style{
  2717. // Protection: &excelize.Protection{
  2718. // Hidden: true,
  2719. // Locked: true,
  2720. // },
  2721. // })
  2722. // if err != nil {
  2723. // fmt.Println(err)
  2724. // }
  2725. // err = f.SetCellStyle("Sheet1", "H9", "H9", style)
  2726. func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error {
  2727. hCol, hRow, err := CellNameToCoordinates(hCell)
  2728. if err != nil {
  2729. return err
  2730. }
  2731. vCol, vRow, err := CellNameToCoordinates(vCell)
  2732. if err != nil {
  2733. return err
  2734. }
  2735. // Normalize the range, such correct C1:B3 to B1:C3.
  2736. if vCol < hCol {
  2737. vCol, hCol = hCol, vCol
  2738. }
  2739. if vRow < hRow {
  2740. vRow, hRow = hRow, vRow
  2741. }
  2742. hColIdx := hCol - 1
  2743. hRowIdx := hRow - 1
  2744. vColIdx := vCol - 1
  2745. vRowIdx := vRow - 1
  2746. ws, err := f.workSheetReader(sheet)
  2747. if err != nil {
  2748. return err
  2749. }
  2750. prepareSheetXML(ws, vCol, vRow)
  2751. makeContiguousColumns(ws, hRow, vRow, vCol)
  2752. ws.Lock()
  2753. defer ws.Unlock()
  2754. s, err := f.stylesReader()
  2755. if err != nil {
  2756. return err
  2757. }
  2758. s.Lock()
  2759. defer s.Unlock()
  2760. if styleID < 0 || s.CellXfs == nil || len(s.CellXfs.Xf) <= styleID {
  2761. return newInvalidStyleID(styleID)
  2762. }
  2763. for r := hRowIdx; r <= vRowIdx; r++ {
  2764. for k := hColIdx; k <= vColIdx; k++ {
  2765. ws.SheetData.Row[r].C[k].S = styleID
  2766. }
  2767. }
  2768. return err
  2769. }
  2770. // SetConditionalFormat provides a function to create conditional formatting
  2771. // rule for cell value. Conditional formatting is a feature of Excel which
  2772. // allows you to apply a format to a cell or a range of cells based on certain
  2773. // criteria.
  2774. //
  2775. // The type option is a required parameter and it has no default value.
  2776. // Allowable type values and their associated parameters are:
  2777. //
  2778. // Type | Parameters
  2779. // ---------------+------------------------------------
  2780. // cell | Criteria
  2781. // | Value
  2782. // | MinValue
  2783. // | MaxValue
  2784. // date | Criteria
  2785. // | Value
  2786. // | MinValue
  2787. // | MaxValue
  2788. // time_period | Criteria
  2789. // text | Criteria
  2790. // | Value
  2791. // average | Criteria
  2792. // duplicate | (none)
  2793. // unique | (none)
  2794. // top | Criteria
  2795. // | Value
  2796. // bottom | Criteria
  2797. // | Value
  2798. // blanks | (none)
  2799. // no_blanks | (none)
  2800. // errors | (none)
  2801. // no_errors | (none)
  2802. // 2_color_scale | MinType
  2803. // | MaxType
  2804. // | MinValue
  2805. // | MaxValue
  2806. // | MinColor
  2807. // | MaxColor
  2808. // 3_color_scale | MinType
  2809. // | MidType
  2810. // | MaxType
  2811. // | MinValue
  2812. // | MidValue
  2813. // | MaxValue
  2814. // | MinColor
  2815. // | MidColor
  2816. // | MaxColor
  2817. // data_bar | MinType
  2818. // | MaxType
  2819. // | MinValue
  2820. // | MaxValue
  2821. // | BarBorderColor
  2822. // | BarColor
  2823. // | BarDirection
  2824. // | BarOnly
  2825. // | BarSolid
  2826. // icon_set | IconStyle
  2827. // | ReverseIcons
  2828. // | IconsOnly
  2829. // formula | Criteria
  2830. //
  2831. // The 'Criteria' parameter is used to set the criteria by which the cell data
  2832. // will be evaluated. It has no default value. The most common criteria as
  2833. // applied to {"type":"cell"} are:
  2834. //
  2835. // between |
  2836. // not between |
  2837. // equal to | ==
  2838. // not equal to | !=
  2839. // greater than | >
  2840. // less than | <
  2841. // greater than or equal to | >=
  2842. // less than or equal to | <=
  2843. //
  2844. // You can either use Excel's textual description strings, in the first column
  2845. // above, or the more common symbolic alternatives.
  2846. //
  2847. // Additional criteria which are specific to other conditional format types are
  2848. // shown in the relevant sections below.
  2849. //
  2850. // value: The value is generally used along with the criteria parameter to set
  2851. // the rule by which the cell data will be evaluated:
  2852. //
  2853. // err := f.SetConditionalFormat("Sheet1", "D1:D10",
  2854. // []excelize.ConditionalFormatOptions{
  2855. // {
  2856. // Type: "cell",
  2857. // Criteria: ">",
  2858. // Format: format,
  2859. // Value: "6",
  2860. // },
  2861. // },
  2862. // )
  2863. //
  2864. // The value property can also be an cell reference:
  2865. //
  2866. // err := f.SetConditionalFormat("Sheet1", "D1:D10",
  2867. // []excelize.ConditionalFormatOptions{
  2868. // {
  2869. // Type: "cell",
  2870. // Criteria: ">",
  2871. // Format: format,
  2872. // Value: "$C$1",
  2873. // },
  2874. // },
  2875. // )
  2876. //
  2877. // type: format - The format parameter is used to specify the format that will
  2878. // be applied to the cell when the conditional formatting criterion is met. The
  2879. // format is created using the NewConditionalStyle function in the same way as
  2880. // cell formats:
  2881. //
  2882. // format, err := f.NewConditionalStyle(
  2883. // &excelize.Style{
  2884. // Font: &excelize.Font{Color: "9A0511"},
  2885. // Fill: excelize.Fill{
  2886. // Type: "pattern", Color: []string{"FEC7CE"}, Pattern: 1,
  2887. // },
  2888. // },
  2889. // )
  2890. // if err != nil {
  2891. // fmt.Println(err)
  2892. // }
  2893. // err = f.SetConditionalFormat("Sheet1", "D1:D10",
  2894. // []excelize.ConditionalFormatOptions{
  2895. // {Type: "cell", Criteria: ">", Format: format, Value: "6"},
  2896. // },
  2897. // )
  2898. //
  2899. // Note: In Excel, a conditional format is superimposed over the existing cell
  2900. // format and not all cell format properties can be modified. Properties that
  2901. // cannot be modified in a conditional format are font name, font size,
  2902. // superscript and subscript, diagonal borders, all alignment properties and all
  2903. // protection properties.
  2904. //
  2905. // Excel specifies some default formats to be used with conditional formatting.
  2906. // These can be replicated using the following excelize formats:
  2907. //
  2908. // // Rose format for bad conditional.
  2909. // format1, err := f.NewConditionalStyle(
  2910. // &excelize.Style{
  2911. // Font: &excelize.Font{Color: "9A0511"},
  2912. // Fill: excelize.Fill{
  2913. // Type: "pattern", Color: []string{"#FEC7CE"}, Pattern: 1,
  2914. // },
  2915. // },
  2916. // )
  2917. //
  2918. // // Light yellow format for neutral conditional.
  2919. // format2, err := f.NewConditionalStyle(
  2920. // &excelize.Style{
  2921. // Font: &excelize.Font{Color: "9B5713"},
  2922. // Fill: excelize.Fill{
  2923. // Type: "pattern", Color: []string{"FEEAA0"}, Pattern: 1,
  2924. // },
  2925. // },
  2926. // )
  2927. //
  2928. // // Light green format for good conditional.
  2929. // format3, err := f.NewConditionalStyle(
  2930. // &excelize.Style{
  2931. // Font: &excelize.Font{Color: "09600B"},
  2932. // Fill: excelize.Fill{
  2933. // Type: "pattern", Color: []string{"C7EECF"}, Pattern: 1,
  2934. // },
  2935. // },
  2936. // )
  2937. //
  2938. // type: MinValue - The 'MinValue' parameter is used to set the lower limiting
  2939. // value when the criteria is either "between" or "not between".
  2940. //
  2941. // // Highlight cells rules: between...
  2942. // err := f.SetConditionalFormat("Sheet1", "A1:A10",
  2943. // []excelize.ConditionalFormatOptions{
  2944. // {
  2945. // Type: "cell",
  2946. // Criteria: "between",
  2947. // Format: format,
  2948. // MinValue: 6",
  2949. // MaxValue: 8",
  2950. // },
  2951. // },
  2952. // )
  2953. //
  2954. // type: MaxValue - The 'MaxValue' parameter is used to set the upper limiting
  2955. // value when the criteria is either "between" or "not between". See the
  2956. // previous example.
  2957. //
  2958. // type: average - The average type is used to specify Excel's "Average" style
  2959. // conditional format:
  2960. //
  2961. // // Top/Bottom rules: Above Average...
  2962. // err := f.SetConditionalFormat("Sheet1", "A1:A10",
  2963. // []excelize.ConditionalFormatOptions{
  2964. // {
  2965. // Type: "average",
  2966. // Criteria: "=",
  2967. // Format: format1,
  2968. // AboveAverage: true,
  2969. // },
  2970. // },
  2971. // )
  2972. //
  2973. // // Top/Bottom rules: Below Average...
  2974. // err := f.SetConditionalFormat("Sheet1", "B1:B10",
  2975. // []excelize.ConditionalFormatOptions{
  2976. // {
  2977. // Type: "average",
  2978. // Criteria: "=",
  2979. // Format: format2,
  2980. // AboveAverage: false,
  2981. // },
  2982. // },
  2983. // )
  2984. //
  2985. // type: duplicate - The duplicate type is used to highlight duplicate cells in
  2986. // a range:
  2987. //
  2988. // // Highlight cells rules: Duplicate Values...
  2989. // err := f.SetConditionalFormat("Sheet1", "A1:A10",
  2990. // []excelize.ConditionalFormatOptions{
  2991. // {Type: "duplicate", Criteria: "=", Format: format},
  2992. // },
  2993. // )
  2994. //
  2995. // type: unique - The unique type is used to highlight unique cells in a range:
  2996. //
  2997. // // Highlight cells rules: Not Equal To...
  2998. // err := f.SetConditionalFormat("Sheet1", "A1:A10",
  2999. // []excelize.ConditionalFormatOptions{
  3000. // {Type: "unique", Criteria: "=", Format: format},
  3001. // },
  3002. // )
  3003. //
  3004. // type: top - The top type is used to specify the top n values by number or
  3005. // percentage in a range:
  3006. //
  3007. // // Top/Bottom rules: Top 10.
  3008. // err := f.SetConditionalFormat("Sheet1", "H1:H10",
  3009. // []excelize.ConditionalFormatOptions{
  3010. // {
  3011. // Type: "top",
  3012. // Criteria: "=",
  3013. // Format: format,
  3014. // Value: "6",
  3015. // },
  3016. // },
  3017. // )
  3018. //
  3019. // The criteria can be used to indicate that a percentage condition is required:
  3020. //
  3021. // err := f.SetConditionalFormat("Sheet1", "A1:A10",
  3022. // []excelize.ConditionalFormatOptions{
  3023. // {
  3024. // Type: "top",
  3025. // Criteria: "=",
  3026. // Format: format,
  3027. // Value: "6",
  3028. // Percent: true,
  3029. // },
  3030. // },
  3031. // )
  3032. //
  3033. // type: 2_color_scale - The 2_color_scale type is used to specify Excel's "2
  3034. // Color Scale" style conditional format:
  3035. //
  3036. // // Color scales: 2 color.
  3037. // err := f.SetConditionalFormat("Sheet1", "A1:A10",
  3038. // []excelize.ConditionalFormatOptions{
  3039. // {
  3040. // Type: "2_color_scale",
  3041. // Criteria: "=",
  3042. // MinType: "min",
  3043. // MaxType: "max",
  3044. // MinColor: "#F8696B",
  3045. // MaxColor: "#63BE7B",
  3046. // },
  3047. // },
  3048. // )
  3049. //
  3050. // This conditional type can be modified with MinType, MaxType, MinValue,
  3051. // MaxValue, MinColor and MaxColor, see below.
  3052. //
  3053. // type: 3_color_scale - The 3_color_scale type is used to specify Excel's "3
  3054. // Color Scale" style conditional format:
  3055. //
  3056. // // Color scales: 3 color.
  3057. // err := f.SetConditionalFormat("Sheet1", "A1:A10",
  3058. // []excelize.ConditionalFormatOptions{
  3059. // {
  3060. // Type: "3_color_scale",
  3061. // Criteria: "=",
  3062. // MinType: "min",
  3063. // MidType: "percentile",
  3064. // MaxType: "max",
  3065. // MinColor: "#F8696B",
  3066. // MidColor: "#FFEB84",
  3067. // MaxColor: "#63BE7B",
  3068. // },
  3069. // },
  3070. // )
  3071. //
  3072. // This conditional type can be modified with MinType, MidType, MaxType,
  3073. // MinValue, MidValue, MaxValue, MinColor, MidColor and MaxColor, see
  3074. // below.
  3075. //
  3076. // type: data_bar - The data_bar type is used to specify Excel's "Data Bar"
  3077. // style conditional format.
  3078. //
  3079. // MinType - The MinType and MaxType properties are available when the
  3080. // conditional formatting type is 2_color_scale, 3_color_scale or data_bar.
  3081. // The MidType is available for 3_color_scale. The properties are used as
  3082. // follows:
  3083. //
  3084. // // Data Bars: Gradient Fill.
  3085. // err := f.SetConditionalFormat("Sheet1", "K1:K10",
  3086. // []excelize.ConditionalFormatOptions{
  3087. // {
  3088. // Type: "data_bar",
  3089. // Criteria: "=",
  3090. // MinType: "min",
  3091. // MaxType: "max",
  3092. // BarColor: "#638EC6",
  3093. // },
  3094. // },
  3095. // )
  3096. //
  3097. // The available min/mid/max types are:
  3098. //
  3099. // min (for MinType only)
  3100. // num
  3101. // percent
  3102. // percentile
  3103. // formula
  3104. // max (for MaxType only)
  3105. //
  3106. // MidType - Used for 3_color_scale. Same as MinType, see above.
  3107. //
  3108. // MaxType - Same as MinType, see above.
  3109. //
  3110. // MinValue - The MinValue and MaxValue properties are available when the
  3111. // conditional formatting type is 2_color_scale, 3_color_scale or data_bar.
  3112. //
  3113. // MidValue - The MidValue is available for 3_color_scale. Same as MinValue,
  3114. // see above.
  3115. //
  3116. // MaxValue - Same as MinValue, see above.
  3117. //
  3118. // MinColor - The MinColor and MaxColor properties are available when the
  3119. // conditional formatting type is 2_color_scale, 3_color_scale or data_bar.
  3120. //
  3121. // MidColor - The MidColor is available for 3_color_scale. The properties
  3122. // are used as follows:
  3123. //
  3124. // // Color scales: 3 color.
  3125. // err := f.SetConditionalFormat("Sheet1", "B1:B10",
  3126. // []excelize.ConditionalFormatOptions{
  3127. // {
  3128. // Type: "3_color_scale",
  3129. // Criteria: "=",
  3130. // MinType: "min",
  3131. // MidType: "percentile",
  3132. // MaxType: "max",
  3133. // MinColor: "#F8696B",
  3134. // MidColor: "#FFEB84",
  3135. // MaxColor: "#63BE7B",
  3136. // },
  3137. // },
  3138. // )
  3139. //
  3140. // MaxColor - Same as MinColor, see above.
  3141. //
  3142. // BarColor - Used for data_bar. Same as MinColor, see above.
  3143. //
  3144. // BarBorderColor - Used for sets the color for the border line of a data bar,
  3145. // this is only visible in Excel 2010 and later.
  3146. //
  3147. // BarDirection - sets the direction for data bars. The available options are:
  3148. //
  3149. // context - Data bar direction is set by spreadsheet application based on the context of the data displayed.
  3150. // leftToRight - Data bar direction is from right to left.
  3151. // rightToLeft - Data bar direction is from left to right.
  3152. //
  3153. // BarOnly - Used for set displays a bar data but not the data in the cells.
  3154. //
  3155. // BarSolid - Used for turns on a solid (non-gradient) fill for data bars, this
  3156. // is only visible in Excel 2010 and later.
  3157. //
  3158. // IconStyle - The available options are:
  3159. //
  3160. // 3Arrows
  3161. // 3ArrowsGray
  3162. // 3Flags
  3163. // 3Signs
  3164. // 3Symbols
  3165. // 3Symbols2
  3166. // 3TrafficLights1
  3167. // 3TrafficLights2
  3168. // 4Arrows
  3169. // 4ArrowsGray
  3170. // 4Rating
  3171. // 4RedToBlack
  3172. // 4TrafficLights
  3173. // 5Arrows
  3174. // 5ArrowsGray
  3175. // 5Quarters
  3176. // 5Rating
  3177. //
  3178. // ReverseIcons - Used for set reversed icons sets.
  3179. //
  3180. // IconsOnly - Used for set displayed without the cell value.
  3181. //
  3182. // StopIfTrue - used to set the "stop if true" feature of a conditional
  3183. // formatting rule when more than one rule is applied to a cell or a range of
  3184. // cells. When this parameter is set then subsequent rules are not evaluated
  3185. // if the current rule is true.
  3186. func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFormatOptions) error {
  3187. drawContFmtFunc := map[string]func(p int, ct, GUID string, fmtCond *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule){
  3188. "cellIs": drawCondFmtCellIs,
  3189. "top10": drawCondFmtTop10,
  3190. "aboveAverage": drawCondFmtAboveAverage,
  3191. "duplicateValues": drawCondFmtDuplicateUniqueValues,
  3192. "uniqueValues": drawCondFmtDuplicateUniqueValues,
  3193. "2_color_scale": drawCondFmtColorScale,
  3194. "3_color_scale": drawCondFmtColorScale,
  3195. "dataBar": drawCondFmtDataBar,
  3196. "expression": drawCondFmtExp,
  3197. "iconSet": drawCondFmtIconSet,
  3198. }
  3199. ws, err := f.workSheetReader(sheet)
  3200. if err != nil {
  3201. return err
  3202. }
  3203. // Create a pseudo GUID for each unique rule.
  3204. var rules int
  3205. for _, cf := range ws.ConditionalFormatting {
  3206. rules += len(cf.CfRule)
  3207. }
  3208. GUID := fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), rules)
  3209. var cfRule []*xlsxCfRule
  3210. for p, v := range opts {
  3211. var vt, ct string
  3212. var ok bool
  3213. // "type" is a required parameter, check for valid validation types.
  3214. vt, ok = validType[v.Type]
  3215. if ok {
  3216. // Check for valid criteria types.
  3217. ct, ok = criteriaType[v.Criteria]
  3218. if ok || vt == "expression" || vt == "iconSet" {
  3219. drawFunc, ok := drawContFmtFunc[vt]
  3220. if ok {
  3221. rule, x14rule := drawFunc(p, ct, GUID, &v)
  3222. if rule == nil {
  3223. return ErrParameterInvalid
  3224. }
  3225. if x14rule != nil {
  3226. if err = f.appendCfRule(ws, x14rule); err != nil {
  3227. return err
  3228. }
  3229. f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14)
  3230. }
  3231. cfRule = append(cfRule, rule)
  3232. }
  3233. }
  3234. }
  3235. }
  3236. ws.ConditionalFormatting = append(ws.ConditionalFormatting, &xlsxConditionalFormatting{
  3237. SQRef: rangeRef,
  3238. CfRule: cfRule,
  3239. })
  3240. return err
  3241. }
  3242. // appendCfRule provides a function to append rules to conditional formatting.
  3243. func (f *File) appendCfRule(ws *xlsxWorksheet, rule *xlsxX14CfRule) error {
  3244. var (
  3245. err error
  3246. idx int
  3247. appendMode bool
  3248. decodeExtLst = new(decodeWorksheetExt)
  3249. condFmts *xlsxX14ConditionalFormattings
  3250. decodeCondFmts *decodeX14ConditionalFormattings
  3251. ext *xlsxWorksheetExt
  3252. condFmtBytes, condFmtsBytes, extLstBytes []byte
  3253. )
  3254. condFmtBytes, _ = xml.Marshal([]*xlsxX14ConditionalFormatting{
  3255. {XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value, CfRule: []*xlsxX14CfRule{rule}},
  3256. })
  3257. if ws.ExtLst != nil { // append mode ext
  3258. if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
  3259. Decode(decodeExtLst); err != nil && err != io.EOF {
  3260. return err
  3261. }
  3262. for idx, ext = range decodeExtLst.Ext {
  3263. if ext.URI == ExtURIConditionalFormattings {
  3264. decodeCondFmts = new(decodeX14ConditionalFormattings)
  3265. _ = f.xmlNewDecoder(strings.NewReader(ext.Content)).Decode(decodeCondFmts)
  3266. if condFmts == nil {
  3267. condFmts = &xlsxX14ConditionalFormattings{}
  3268. }
  3269. condFmts.Content = decodeCondFmts.Content + string(condFmtBytes)
  3270. condFmtsBytes, _ = xml.Marshal(condFmts)
  3271. decodeExtLst.Ext[idx].Content = string(condFmtsBytes)
  3272. appendMode = true
  3273. }
  3274. }
  3275. }
  3276. if !appendMode {
  3277. condFmtsBytes, _ = xml.Marshal(&xlsxX14ConditionalFormattings{Content: string(condFmtBytes)})
  3278. decodeExtLst.Ext = append(decodeExtLst.Ext, &xlsxWorksheetExt{
  3279. URI: ExtURIConditionalFormattings, Content: string(condFmtsBytes),
  3280. })
  3281. }
  3282. sort.Slice(decodeExtLst.Ext, func(i, j int) bool {
  3283. return inStrSlice(extensionURIPriority, decodeExtLst.Ext[i].URI, false) <
  3284. inStrSlice(extensionURIPriority, decodeExtLst.Ext[j].URI, false)
  3285. })
  3286. extLstBytes, err = xml.Marshal(decodeExtLst)
  3287. ws.ExtLst = &xlsxExtLst{Ext: strings.TrimSuffix(strings.TrimPrefix(string(extLstBytes), "<extLst>"), "</extLst>")}
  3288. return err
  3289. }
  3290. // extractCondFmtCellIs provides a function to extract conditional format
  3291. // settings for cell value (include between, not between, equal, not equal,
  3292. // greater than and less than) by given conditional formatting rule.
  3293. func extractCondFmtCellIs(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3294. format := ConditionalFormatOptions{StopIfTrue: c.StopIfTrue, Type: "cell", Criteria: operatorType[c.Operator], Format: *c.DxfID}
  3295. if len(c.Formula) == 2 {
  3296. format.MinValue, format.MaxValue = c.Formula[0], c.Formula[1]
  3297. return format
  3298. }
  3299. format.Value = c.Formula[0]
  3300. return format
  3301. }
  3302. // extractCondFmtTop10 provides a function to extract conditional format
  3303. // settings for top N (default is top 10) by given conditional formatting
  3304. // rule.
  3305. func extractCondFmtTop10(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3306. format := ConditionalFormatOptions{
  3307. StopIfTrue: c.StopIfTrue,
  3308. Type: "top",
  3309. Criteria: "=",
  3310. Format: *c.DxfID,
  3311. Percent: c.Percent,
  3312. Value: strconv.Itoa(c.Rank),
  3313. }
  3314. if c.Bottom {
  3315. format.Type = "bottom"
  3316. }
  3317. return format
  3318. }
  3319. // extractCondFmtAboveAverage provides a function to extract conditional format
  3320. // settings for above average and below average by given conditional formatting
  3321. // rule.
  3322. func extractCondFmtAboveAverage(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3323. return ConditionalFormatOptions{
  3324. StopIfTrue: c.StopIfTrue,
  3325. Type: "average",
  3326. Criteria: "=",
  3327. Format: *c.DxfID,
  3328. AboveAverage: *c.AboveAverage,
  3329. }
  3330. }
  3331. // extractCondFmtDuplicateUniqueValues provides a function to extract
  3332. // conditional format settings for duplicate and unique values by given
  3333. // conditional formatting rule.
  3334. func extractCondFmtDuplicateUniqueValues(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3335. return ConditionalFormatOptions{
  3336. StopIfTrue: c.StopIfTrue,
  3337. Type: map[string]string{
  3338. "duplicateValues": "duplicate",
  3339. "uniqueValues": "unique",
  3340. }[c.Type],
  3341. Criteria: "=",
  3342. Format: *c.DxfID,
  3343. }
  3344. }
  3345. // extractCondFmtColorScale provides a function to extract conditional format
  3346. // settings for color scale (include 2 color scale and 3 color scale) by given
  3347. // conditional formatting rule.
  3348. func extractCondFmtColorScale(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3349. format := ConditionalFormatOptions{StopIfTrue: c.StopIfTrue}
  3350. format.Type, format.Criteria = "2_color_scale", "="
  3351. values := len(c.ColorScale.Cfvo)
  3352. colors := len(c.ColorScale.Color)
  3353. if colors > 1 && values > 1 {
  3354. format.MinType = c.ColorScale.Cfvo[0].Type
  3355. if c.ColorScale.Cfvo[0].Val != "0" {
  3356. format.MinValue = c.ColorScale.Cfvo[0].Val
  3357. }
  3358. format.MinColor = "#" + strings.TrimPrefix(strings.ToUpper(c.ColorScale.Color[0].RGB), "FF")
  3359. format.MaxType = c.ColorScale.Cfvo[1].Type
  3360. if c.ColorScale.Cfvo[1].Val != "0" {
  3361. format.MaxValue = c.ColorScale.Cfvo[1].Val
  3362. }
  3363. format.MaxColor = "#" + strings.TrimPrefix(strings.ToUpper(c.ColorScale.Color[1].RGB), "FF")
  3364. }
  3365. if colors == 3 {
  3366. format.Type = "3_color_scale"
  3367. format.MidType = c.ColorScale.Cfvo[1].Type
  3368. if c.ColorScale.Cfvo[1].Val != "0" {
  3369. format.MidValue = c.ColorScale.Cfvo[1].Val
  3370. }
  3371. format.MidColor = "#" + strings.TrimPrefix(strings.ToUpper(c.ColorScale.Color[1].RGB), "FF")
  3372. format.MaxType = c.ColorScale.Cfvo[2].Type
  3373. if c.ColorScale.Cfvo[2].Val != "0" {
  3374. format.MaxValue = c.ColorScale.Cfvo[2].Val
  3375. }
  3376. format.MaxColor = "#" + strings.TrimPrefix(strings.ToUpper(c.ColorScale.Color[2].RGB), "FF")
  3377. }
  3378. return format
  3379. }
  3380. // extractCondFmtDataBar provides a function to extract conditional format
  3381. // settings for data bar by given conditional formatting rule.
  3382. func extractCondFmtDataBar(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3383. format := ConditionalFormatOptions{Type: "data_bar", Criteria: "="}
  3384. if c.DataBar != nil {
  3385. format.StopIfTrue = c.StopIfTrue
  3386. format.MinType = c.DataBar.Cfvo[0].Type
  3387. format.MinValue = c.DataBar.Cfvo[0].Val
  3388. format.MaxType = c.DataBar.Cfvo[1].Type
  3389. format.MaxValue = c.DataBar.Cfvo[1].Val
  3390. format.BarColor = "#" + strings.TrimPrefix(strings.ToUpper(c.DataBar.Color[0].RGB), "FF")
  3391. if c.DataBar.ShowValue != nil {
  3392. format.BarOnly = !*c.DataBar.ShowValue
  3393. }
  3394. }
  3395. extractDataBarRule := func(condFmts []decodeX14ConditionalFormatting) {
  3396. for _, condFmt := range condFmts {
  3397. for _, rule := range condFmt.CfRule {
  3398. if rule.DataBar != nil {
  3399. format.BarSolid = !rule.DataBar.Gradient
  3400. format.BarDirection = rule.DataBar.Direction
  3401. if rule.DataBar.BorderColor != nil {
  3402. format.BarBorderColor = "#" + strings.TrimPrefix(strings.ToUpper(rule.DataBar.BorderColor.RGB), "FF")
  3403. }
  3404. }
  3405. }
  3406. }
  3407. }
  3408. extractExtLst := func(extLst *decodeWorksheetExt) {
  3409. for _, ext := range extLst.Ext {
  3410. if ext.URI == ExtURIConditionalFormattings {
  3411. decodeCondFmts := new(decodeX14ConditionalFormattings)
  3412. if err := xml.Unmarshal([]byte(ext.Content), &decodeCondFmts); err == nil {
  3413. condFmts := []decodeX14ConditionalFormatting{}
  3414. if err = xml.Unmarshal([]byte(decodeCondFmts.Content), &condFmts); err == nil {
  3415. extractDataBarRule(condFmts)
  3416. }
  3417. }
  3418. }
  3419. }
  3420. }
  3421. if c.ExtLst != nil {
  3422. ext := decodeX14ConditionalFormattingExt{}
  3423. if err := xml.Unmarshal([]byte(c.ExtLst.Ext), &ext); err == nil && extLst != nil {
  3424. decodeExtLst := new(decodeWorksheetExt)
  3425. if err = xml.Unmarshal([]byte("<extLst>"+extLst.Ext+"</extLst>"), decodeExtLst); err == nil {
  3426. extractExtLst(decodeExtLst)
  3427. }
  3428. }
  3429. }
  3430. return format
  3431. }
  3432. // extractCondFmtExp provides a function to extract conditional format settings
  3433. // for expression by given conditional formatting rule.
  3434. func extractCondFmtExp(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3435. format := ConditionalFormatOptions{StopIfTrue: c.StopIfTrue, Type: "formula", Format: *c.DxfID}
  3436. if len(c.Formula) > 0 {
  3437. format.Criteria = c.Formula[0]
  3438. }
  3439. return format
  3440. }
  3441. // extractCondFmtIconSet provides a function to extract conditional format
  3442. // settings for icon sets by given conditional formatting rule.
  3443. func extractCondFmtIconSet(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
  3444. format := ConditionalFormatOptions{Type: "icon_set"}
  3445. if c.IconSet != nil {
  3446. if c.IconSet.ShowValue != nil {
  3447. format.IconsOnly = !*c.IconSet.ShowValue
  3448. }
  3449. format.IconStyle = c.IconSet.IconSet
  3450. format.ReverseIcons = c.IconSet.Reverse
  3451. }
  3452. return format
  3453. }
  3454. // GetConditionalFormats returns conditional format settings by given worksheet
  3455. // name.
  3456. func (f *File) GetConditionalFormats(sheet string) (map[string][]ConditionalFormatOptions, error) {
  3457. extractContFmtFunc := map[string]func(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions{
  3458. "cellIs": extractCondFmtCellIs,
  3459. "top10": extractCondFmtTop10,
  3460. "aboveAverage": extractCondFmtAboveAverage,
  3461. "duplicateValues": extractCondFmtDuplicateUniqueValues,
  3462. "uniqueValues": extractCondFmtDuplicateUniqueValues,
  3463. "colorScale": extractCondFmtColorScale,
  3464. "dataBar": extractCondFmtDataBar,
  3465. "expression": extractCondFmtExp,
  3466. "iconSet": extractCondFmtIconSet,
  3467. }
  3468. conditionalFormats := make(map[string][]ConditionalFormatOptions)
  3469. ws, err := f.workSheetReader(sheet)
  3470. if err != nil {
  3471. return conditionalFormats, err
  3472. }
  3473. for _, cf := range ws.ConditionalFormatting {
  3474. var opts []ConditionalFormatOptions
  3475. for _, cr := range cf.CfRule {
  3476. if extractFunc, ok := extractContFmtFunc[cr.Type]; ok {
  3477. opts = append(opts, extractFunc(cr, ws.ExtLst))
  3478. }
  3479. }
  3480. conditionalFormats[cf.SQRef] = opts
  3481. }
  3482. return conditionalFormats, err
  3483. }
  3484. // UnsetConditionalFormat provides a function to unset the conditional format
  3485. // by given worksheet name and range reference.
  3486. func (f *File) UnsetConditionalFormat(sheet, rangeRef string) error {
  3487. ws, err := f.workSheetReader(sheet)
  3488. if err != nil {
  3489. return err
  3490. }
  3491. for i, cf := range ws.ConditionalFormatting {
  3492. if cf.SQRef == rangeRef {
  3493. ws.ConditionalFormatting = append(ws.ConditionalFormatting[:i], ws.ConditionalFormatting[i+1:]...)
  3494. return nil
  3495. }
  3496. }
  3497. return nil
  3498. }
  3499. // drawCondFmtCellIs provides a function to create conditional formatting rule
  3500. // for cell value (include between, not between, equal, not equal, greater
  3501. // than and less than) by given priority, criteria type and format settings.
  3502. func drawCondFmtCellIs(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3503. c := &xlsxCfRule{
  3504. Priority: p + 1,
  3505. StopIfTrue: format.StopIfTrue,
  3506. Type: validType[format.Type],
  3507. Operator: ct,
  3508. DxfID: intPtr(format.Format),
  3509. }
  3510. // "between" and "not between" criteria require 2 values.
  3511. if ct == "between" || ct == "notBetween" {
  3512. c.Formula = append(c.Formula, []string{format.MinValue, format.MaxValue}...)
  3513. }
  3514. if idx := inStrSlice([]string{"equal", "notEqual", "greaterThan", "lessThan", "greaterThanOrEqual", "lessThanOrEqual", "containsText", "notContains", "beginsWith", "endsWith"}, ct, true); idx != -1 {
  3515. c.Formula = append(c.Formula, format.Value)
  3516. }
  3517. return c, nil
  3518. }
  3519. // drawCondFmtTop10 provides a function to create conditional formatting rule
  3520. // for top N (default is top 10) by given priority, criteria type and format
  3521. // settings.
  3522. func drawCondFmtTop10(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3523. c := &xlsxCfRule{
  3524. Priority: p + 1,
  3525. StopIfTrue: format.StopIfTrue,
  3526. Bottom: format.Type == "bottom",
  3527. Type: validType[format.Type],
  3528. Rank: 10,
  3529. DxfID: intPtr(format.Format),
  3530. Percent: format.Percent,
  3531. }
  3532. if rank, err := strconv.Atoi(format.Value); err == nil {
  3533. c.Rank = rank
  3534. }
  3535. return c, nil
  3536. }
  3537. // drawCondFmtAboveAverage provides a function to create conditional
  3538. // formatting rule for above average and below average by given priority,
  3539. // criteria type and format settings.
  3540. func drawCondFmtAboveAverage(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3541. return &xlsxCfRule{
  3542. Priority: p + 1,
  3543. StopIfTrue: format.StopIfTrue,
  3544. Type: validType[format.Type],
  3545. AboveAverage: boolPtr(format.AboveAverage),
  3546. DxfID: intPtr(format.Format),
  3547. }, nil
  3548. }
  3549. // drawCondFmtDuplicateUniqueValues provides a function to create conditional
  3550. // formatting rule for duplicate and unique values by given priority, criteria
  3551. // type and format settings.
  3552. func drawCondFmtDuplicateUniqueValues(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3553. return &xlsxCfRule{
  3554. Priority: p + 1,
  3555. StopIfTrue: format.StopIfTrue,
  3556. Type: validType[format.Type],
  3557. DxfID: intPtr(format.Format),
  3558. }, nil
  3559. }
  3560. // drawCondFmtColorScale provides a function to create conditional formatting
  3561. // rule for color scale (include 2 color scale and 3 color scale) by given
  3562. // priority, criteria type and format settings.
  3563. func drawCondFmtColorScale(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3564. minValue := format.MinValue
  3565. if minValue == "" {
  3566. minValue = "0"
  3567. }
  3568. maxValue := format.MaxValue
  3569. if maxValue == "" {
  3570. maxValue = "0"
  3571. }
  3572. midValue := format.MidValue
  3573. if midValue == "" {
  3574. midValue = "50"
  3575. }
  3576. c := &xlsxCfRule{
  3577. Priority: p + 1,
  3578. StopIfTrue: format.StopIfTrue,
  3579. Type: "colorScale",
  3580. ColorScale: &xlsxColorScale{
  3581. Cfvo: []*xlsxCfvo{
  3582. {Type: format.MinType, Val: minValue},
  3583. },
  3584. Color: []*xlsxColor{
  3585. {RGB: getPaletteColor(format.MinColor)},
  3586. },
  3587. },
  3588. }
  3589. if validType[format.Type] == "3_color_scale" {
  3590. c.ColorScale.Cfvo = append(c.ColorScale.Cfvo, &xlsxCfvo{Type: format.MidType, Val: midValue})
  3591. c.ColorScale.Color = append(c.ColorScale.Color, &xlsxColor{RGB: getPaletteColor(format.MidColor)})
  3592. }
  3593. c.ColorScale.Cfvo = append(c.ColorScale.Cfvo, &xlsxCfvo{Type: format.MaxType, Val: maxValue})
  3594. c.ColorScale.Color = append(c.ColorScale.Color, &xlsxColor{RGB: getPaletteColor(format.MaxColor)})
  3595. return c, nil
  3596. }
  3597. // drawCondFmtDataBar provides a function to create conditional formatting
  3598. // rule for data bar by given priority, criteria type and format settings.
  3599. func drawCondFmtDataBar(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3600. var x14CfRule *xlsxX14CfRule
  3601. var extLst *xlsxExtLst
  3602. if format.BarSolid || format.BarDirection == "leftToRight" || format.BarDirection == "rightToLeft" || format.BarBorderColor != "" {
  3603. extLst = &xlsxExtLst{Ext: fmt.Sprintf(`<ext uri="%s" xmlns:x14="%s"><x14:id>%s</x14:id></ext>`, ExtURIConditionalFormattingRuleID, NameSpaceSpreadSheetX14.Value, GUID)}
  3604. x14CfRule = &xlsxX14CfRule{
  3605. Type: validType[format.Type],
  3606. ID: GUID,
  3607. DataBar: &xlsx14DataBar{
  3608. MaxLength: 100,
  3609. Border: format.BarBorderColor != "",
  3610. Gradient: !format.BarSolid,
  3611. Direction: format.BarDirection,
  3612. Cfvo: []*xlsxCfvo{{Type: "autoMin"}, {Type: "autoMax"}},
  3613. NegativeFillColor: &xlsxColor{RGB: "FFFF0000"},
  3614. AxisColor: &xlsxColor{RGB: "FFFF0000"},
  3615. },
  3616. }
  3617. if x14CfRule.DataBar.Border {
  3618. x14CfRule.DataBar.BorderColor = &xlsxColor{RGB: getPaletteColor(format.BarBorderColor)}
  3619. }
  3620. }
  3621. return &xlsxCfRule{
  3622. Priority: p + 1,
  3623. StopIfTrue: format.StopIfTrue,
  3624. Type: validType[format.Type],
  3625. DataBar: &xlsxDataBar{
  3626. ShowValue: boolPtr(!format.BarOnly),
  3627. Cfvo: []*xlsxCfvo{{Type: format.MinType, Val: format.MinValue}, {Type: format.MaxType, Val: format.MaxValue}},
  3628. Color: []*xlsxColor{{RGB: getPaletteColor(format.BarColor)}},
  3629. },
  3630. ExtLst: extLst,
  3631. }, x14CfRule
  3632. }
  3633. // drawCondFmtExp provides a function to create conditional formatting rule
  3634. // for expression by given priority, criteria type and format settings.
  3635. func drawCondFmtExp(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3636. return &xlsxCfRule{
  3637. Priority: p + 1,
  3638. StopIfTrue: format.StopIfTrue,
  3639. Type: validType[format.Type],
  3640. Formula: []string{format.Criteria},
  3641. DxfID: intPtr(format.Format),
  3642. }, nil
  3643. }
  3644. // drawCondFmtIconSet provides a function to create conditional formatting rule
  3645. // for icon set by given priority, criteria type and format settings.
  3646. func drawCondFmtIconSet(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
  3647. cfvo3 := &xlsxCfRule{IconSet: &xlsxIconSet{Cfvo: []*xlsxCfvo{
  3648. {Type: "percent", Val: "0"},
  3649. {Type: "percent", Val: "33"},
  3650. {Type: "percent", Val: "67"},
  3651. }}}
  3652. cfvo4 := &xlsxCfRule{IconSet: &xlsxIconSet{Cfvo: []*xlsxCfvo{
  3653. {Type: "percent", Val: "0"},
  3654. {Type: "percent", Val: "25"},
  3655. {Type: "percent", Val: "50"},
  3656. {Type: "percent", Val: "75"},
  3657. }}}
  3658. cfvo5 := &xlsxCfRule{IconSet: &xlsxIconSet{Cfvo: []*xlsxCfvo{
  3659. {Type: "percent", Val: "0"},
  3660. {Type: "percent", Val: "20"},
  3661. {Type: "percent", Val: "40"},
  3662. {Type: "percent", Val: "60"},
  3663. {Type: "percent", Val: "80"},
  3664. }}}
  3665. presets := map[string]*xlsxCfRule{
  3666. "3Arrows": cfvo3,
  3667. "3ArrowsGray": cfvo3,
  3668. "3Flags": cfvo3,
  3669. "3Signs": cfvo3,
  3670. "3Symbols": cfvo3,
  3671. "3Symbols2": cfvo3,
  3672. "3TrafficLights1": cfvo3,
  3673. "3TrafficLights2": cfvo3,
  3674. "4Arrows": cfvo4,
  3675. "4ArrowsGray": cfvo4,
  3676. "4Rating": cfvo4,
  3677. "4RedToBlack": cfvo4,
  3678. "4TrafficLights": cfvo4,
  3679. "5Arrows": cfvo5,
  3680. "5ArrowsGray": cfvo5,
  3681. "5Quarters": cfvo5,
  3682. "5Rating": cfvo5,
  3683. }
  3684. cfRule, ok := presets[format.IconStyle]
  3685. if !ok {
  3686. return nil, nil
  3687. }
  3688. cfRule.Priority = p + 1
  3689. cfRule.IconSet.IconSet = format.IconStyle
  3690. cfRule.IconSet.Reverse = format.ReverseIcons
  3691. cfRule.IconSet.ShowValue = boolPtr(!format.IconsOnly)
  3692. cfRule.Type = validType[format.Type]
  3693. return cfRule, nil
  3694. }
  3695. // getPaletteColor provides a function to convert the RBG color by given
  3696. // string.
  3697. func getPaletteColor(color string) string {
  3698. return "FF" + strings.ReplaceAll(strings.ToUpper(color), "#", "")
  3699. }
  3700. // themeReader provides a function to get the pointer to the xl/theme/theme1.xml
  3701. // structure after deserialization.
  3702. func (f *File) themeReader() (*xlsxTheme, error) {
  3703. if _, ok := f.Pkg.Load(defaultXMLPathTheme); !ok {
  3704. return nil, nil
  3705. }
  3706. theme := xlsxTheme{XMLNSa: NameSpaceDrawingML.Value, XMLNSr: SourceRelationship.Value}
  3707. if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathTheme)))).
  3708. Decode(&theme); err != nil && err != io.EOF {
  3709. return &theme, err
  3710. }
  3711. return &theme, nil
  3712. }
  3713. // ThemeColor applied the color with tint value.
  3714. func ThemeColor(baseColor string, tint float64) string {
  3715. if tint == 0 {
  3716. return "FF" + baseColor
  3717. }
  3718. r, _ := strconv.ParseUint(baseColor[:2], 16, 64)
  3719. g, _ := strconv.ParseUint(baseColor[2:4], 16, 64)
  3720. b, _ := strconv.ParseUint(baseColor[4:6], 16, 64)
  3721. var h, s, l float64
  3722. if r <= math.MaxUint8 && g <= math.MaxUint8 && b <= math.MaxUint8 {
  3723. h, s, l = RGBToHSL(uint8(r), uint8(g), uint8(b))
  3724. }
  3725. if tint < 0 {
  3726. l *= 1 + tint
  3727. } else {
  3728. l = l*(1-tint) + (1 - (1 - tint))
  3729. }
  3730. br, bg, bb := HSLToRGB(h, s, l)
  3731. return fmt.Sprintf("FF%02X%02X%02X", br, bg, bb)
  3732. }