SF_Calc.xba 214 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
  3. <script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Calc" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
  4. REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
  5. REM === The SFDocuments library is one of the associated libraries. ===
  6. REM === Full documentation is available on https://help.libreoffice.org/ ===
  7. REM =======================================================================================================================
  8. Option Compatible
  9. Option ClassModule
  10. Option Explicit
  11. &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
  12. &apos;&apos;&apos; SF_Calc
  13. &apos;&apos;&apos; =======
  14. &apos;&apos;&apos;
  15. &apos;&apos;&apos; The SFDocuments library gathers a number of methods and properties making easy
  16. &apos;&apos;&apos; managing and manipulating LibreOffice documents
  17. &apos;&apos;&apos;
  18. &apos;&apos;&apos; Some methods are generic for all types of documents: they are combined in the SF_Document module.
  19. &apos;&apos;&apos; Specific properties and methods are implemented in the concerned subclass(es) SF_Calc, SF_Base, ...
  20. &apos;&apos;&apos;
  21. &apos;&apos;&apos; To workaround the absence of class inheritance in LibreOffice Basic, some redundancy is necessary
  22. &apos;&apos;&apos; Each subclass MUST implement also the generic methods and properties, even if they only call
  23. &apos;&apos;&apos; the parent methods and properties.
  24. &apos;&apos;&apos; They should also duplicate some generic private members as a subset of their own set of members
  25. &apos;&apos;&apos;
  26. &apos;&apos;&apos; The SF_Calc module is focused on :
  27. &apos;&apos;&apos; - management (copy, insert, move, ...) of sheets within a Calc document
  28. &apos;&apos;&apos; - exchange of data between Basic data structures and Calc ranges of values
  29. &apos;&apos;&apos;
  30. &apos;&apos;&apos; The current module is closely related to the &quot;UI&quot; service of the ScriptForge library
  31. &apos;&apos;&apos;
  32. &apos;&apos;&apos; Service invocation examples:
  33. &apos;&apos;&apos; 1) From the UI service
  34. &apos;&apos;&apos; Dim ui As Object, oDoc As Object
  35. &apos;&apos;&apos; Set ui = CreateScriptService(&quot;UI&quot;)
  36. &apos;&apos;&apos; Set oDoc = ui.CreateDocument(&quot;Calc&quot;, ...)
  37. &apos;&apos;&apos; &apos; or Set oDoc = ui.OpenDocument(&quot;C:\Me\MyFile.ods&quot;)
  38. &apos;&apos;&apos; 2) Directly if the document is already opened
  39. &apos;&apos;&apos; Dim oDoc As Object
  40. &apos;&apos;&apos; Set oDoc = CreateScriptService(&quot;SFDocuments.Calc&quot;, &quot;Untitled 1&quot;) &apos; Default = ActiveWindow
  41. &apos;&apos;&apos; &apos; or Set oDoc = CreateScriptService(&quot;SFDocuments.Calc&quot;, &quot;Untitled 1&quot;) &apos; Untitled 1 is presumed a Calc document
  42. &apos;&apos;&apos; &apos; The substring &quot;SFDocuments.&quot; in the service name is optional
  43. &apos;&apos;&apos;
  44. &apos;&apos;&apos; Definitions:
  45. &apos;&apos;&apos;
  46. &apos;&apos;&apos; Many methods require a &quot;Sheet&quot; or a &quot;Range&quot; as argument. (NB: a single cell is considered as a special case of a Range)
  47. &apos;&apos;&apos; Usually, within a specific Calc instance, sheets and ranges are given as a string: &quot;SheetX&quot; and &quot;D2:F6&quot;
  48. &apos;&apos;&apos; Multiple ranges are not supported in this context.
  49. &apos;&apos;&apos; Additionally, the .Sheet and .Range methods return a reference that may be used
  50. &apos;&apos;&apos; as argument of a method called from another instance of the Calc service
  51. &apos;&apos;&apos; Example:
  52. &apos;&apos;&apos; Dim oDocA As Object : Set oDocA = ui.OpenDocument(&quot;C:\FileA.ods&quot;, Hidden := True, ReadOnly := True)
  53. &apos;&apos;&apos; Dim oDocB As Object : Set oDocB = ui.OpenDocument(&quot;C:\FileB.ods&quot;)
  54. &apos;&apos;&apos; oDocB.CopyToRange(oDocA.Range(&quot;SheetX.D4:F8&quot;), &quot;D2:F6&quot;) &apos; CopyToRange(source, target)
  55. &apos;&apos;&apos;
  56. &apos;&apos;&apos; Sheet: the sheet name as a string or an object produced by .Sheet()
  57. &apos;&apos;&apos; &quot;~&quot; = current sheet
  58. &apos;&apos;&apos; Range: a string designating a set of contiguous cells located in a sheet of the current instance
  59. &apos;&apos;&apos; &quot;~&quot; = current selection (if multiple selections, its 1st component)
  60. &apos;&apos;&apos; or an object produced by .Range()
  61. &apos;&apos;&apos; The sheet name is optional (default = active sheet). Surrounding quotes and $ signs are optional
  62. &apos;&apos;&apos; ~.~, ~ The current selection in the active sheet
  63. &apos;&apos;&apos; &apos;$SheetX&apos;.D2 or $D$2 A single cell
  64. &apos;&apos;&apos; &apos;$SheetX&apos;.D2:F6, D2:D10 Multiple cells
  65. &apos;&apos;&apos; &apos;$SheetX&apos;.A:A or 3:5 All cells in the same column or row up to the last active cell
  66. &apos;&apos;&apos; SheetX.* All cells up to the last active cell
  67. &apos;&apos;&apos; myRange A range name at spreadsheet level
  68. &apos;&apos;&apos; ~.yourRange, SheetX.someRange A range name at sheet level
  69. &apos;&apos;&apos; myDoc.Range(&quot;SheetX.D2:F6&quot;)
  70. &apos;&apos;&apos; A range within the sheet SheetX in file associated with the myDoc Calc instance
  71. &apos;&apos;&apos;
  72. &apos;&apos;&apos; Several methods may receive a &quot;FilterFormula&quot; as argument.
  73. &apos;&apos;&apos; A FilterFormula may be associated with a FilterScope: &quot;row&quot;, &quot;column&quot; or &quot;cell&quot;.
  74. &apos;&apos;&apos; These arguments determines on which rows/columns/cells of a range the method should be applied
  75. &apos;&apos;&apos; Examples:
  76. &apos;&apos;&apos; oDoc.ClearAll(&quot;A1:J10&quot;, FilterFormula := &quot;=(A1&lt;=0)&quot;, FilterScope := &quot;CELL&quot;) &apos; Clear all negative values
  77. &apos;&apos;&apos; oDoc.ClearAll(&quot;A2:J10&quot;, FilterFormula := &quot;=(A2&lt;&gt;A1)&quot;, FilterScope := &quot;COLUMN&quot;) &apos; Clear when identical to above cell
  78. &apos;&apos;&apos;
  79. &apos;&apos;&apos; FilterFormula: a Calc formula that returns TRUE or FALSE
  80. &apos;&apos;&apos; the formula is expressed in terms of
  81. &apos;&apos;&apos; - the top-left cell of the range when FilterScope = &quot;CELL&quot;
  82. &apos;&apos;&apos; - the topmost row of the range when FilterScope = &quot;ROW&quot;
  83. &apos;&apos;&apos; - the leftmost column of the range when FilterScope = &quot;COLUMN&quot;
  84. &apos;&apos;&apos; relative and absolute references will be interpreted correctly
  85. &apos;&apos;&apos; FilterScope: the way the formula is applied, once by row, by column, or by individual cell
  86. &apos;&apos;&apos;
  87. &apos;&apos;&apos; Detailed user documentation:
  88. &apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_calc.html?DbPAR=BASIC
  89. &apos;&apos;&apos;
  90. &apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
  91. REM ================================================================== EXCEPTIONS
  92. Private Const UNKNOWNFILEERROR = &quot;UNKNOWNFILEERROR&quot;
  93. Private Const BASEDOCUMENTOPENERROR = &quot;BASEDOCUMENTOPENERROR&quot;
  94. Private Const CALCADDRESSERROR = &quot;CALCADDRESSERROR&quot;
  95. Private Const DUPLICATESHEETERROR = &quot;DUPLICATESHEETERROR&quot;
  96. Private Const OFFSETADDRESSERROR = &quot;OFFSETADDRESSERROR&quot;
  97. Private Const CALCFORMNOTFOUNDERROR = &quot;CALCFORMNOTFOUNDERROR&quot;
  98. Private Const DUPLICATECHARTERROR = &quot;DUPLICATECHARTERROR&quot;
  99. Private Const RANGEEXPORTERROR = &quot;RANGEEXPORTERROR&quot;
  100. REM ============================================================= PRIVATE MEMBERS
  101. Private [Me] As Object
  102. Private [_Super] As Object &apos; Document superclass, which the current instance is a subclass of
  103. Private ObjectType As String &apos; Must be CALC
  104. Private ServiceName As String
  105. &apos; Window component
  106. Private _Component As Object &apos; com.sun.star.lang.XComponent
  107. Type _Address
  108. ObjectType As String &apos; Must be &quot;SF_CalcReference&quot;
  109. ServiceName As String &apos; Must be &quot;SFDocuments.CalcReference&quot;
  110. RawAddress As String
  111. Component As Object &apos; com.sun.star.lang.XComponent
  112. SheetName As String
  113. SheetIndex As Integer
  114. RangeName As String
  115. Height As Long
  116. Width As Long
  117. XSpreadSheet As Object &apos; com.sun.star.sheet.XSpreadsheet
  118. XCellRange As Object &apos; com.sun.star.table.XCellRange
  119. End Type
  120. Private _LastParsedAddress As Object &apos; _Address type - parsed ranges are cached
  121. REM ============================================================ MODULE CONSTANTS
  122. Private Const cstSHEET = 1
  123. Private Const cstRANGE = 2
  124. Private Const MAXCOLS = 2^14 &apos; Max number of columns in a sheet
  125. Private Const MAXROWS = 2^20 &apos; Max number of rows in a sheet
  126. Private Const CALCREFERENCE = &quot;SF_CalcReference&quot; &apos; Object type of _Address
  127. Private Const SERVICEREFERENCE = &quot;SFDocuments.CalcReference&quot;
  128. &apos; Service name of _Address (used in Python)
  129. Private Const ISCALCFORM = 2 &apos; Form is stored in a Calc document
  130. Private Const cstSPECIALCHARS = &quot; `~!@#$%^&amp;()-_=+{}|;,&lt;.&gt;&quot;&quot;&quot;
  131. &apos; Presence of a special character forces surrounding the sheet name with single quotes in absolute addresses
  132. REM ====================================================== CONSTRUCTOR/DESTRUCTOR
  133. REM -----------------------------------------------------------------------------
  134. Private Sub Class_Initialize()
  135. Set [Me] = Nothing
  136. Set [_Super] = Nothing
  137. ObjectType = &quot;CALC&quot;
  138. ServiceName = &quot;SFDocuments.Calc&quot;
  139. Set _Component = Nothing
  140. Set _LastParsedAddress = Nothing
  141. End Sub &apos; SFDocuments.SF_Calc Constructor
  142. REM -----------------------------------------------------------------------------
  143. Private Sub Class_Terminate()
  144. Call Class_Initialize()
  145. End Sub &apos; SFDocuments.SF_Calc Destructor
  146. REM -----------------------------------------------------------------------------
  147. Public Function Dispose() As Variant
  148. If Not IsNull([_Super]) Then Set [_Super] = [_Super].Dispose()
  149. Call Class_Terminate()
  150. Set Dispose = Nothing
  151. End Function &apos; SFDocuments.SF_Calc Explicit Destructor
  152. REM ================================================================== PROPERTIES
  153. REM -----------------------------------------------------------------------------
  154. Property Get CurrentSelection() As Variant
  155. &apos;&apos;&apos; Returns as a string the currently selected range or as an array the list of the currently selected ranges
  156. CurrentSelection = _PropertyGet(&quot;CurrentSelection&quot;)
  157. End Property &apos; SFDocuments.SF_Calc.CurrentSelection (get)
  158. REM -----------------------------------------------------------------------------
  159. Property Let CurrentSelection(Optional ByVal pvSelection As Variant)
  160. &apos;&apos;&apos; Set the selection to a single or a multiple range
  161. &apos;&apos;&apos; The argument is a string or an array of strings
  162. Dim sRange As String &apos; A single selection
  163. Dim oCellRanges As Object &apos; com.sun.star.sheet.SheetCellRanges
  164. Dim vRangeAddresses As Variant &apos; Array of com.sun.star.table.CellRangeAddress
  165. Dim i As Long
  166. Const cstThisSub = &quot;SFDocuments.Calc.setCurrentSelection&quot;
  167. Const cstSubArgs = &quot;Selection&quot;
  168. On Local Error GoTo Catch
  169. Check:
  170. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  171. If Not _IsStillAlive(True) Then GoTo Finally
  172. If IsArray(pvSelection) Then
  173. If Not ScriptForge.SF_Utils._ValidateArray(pvSelection, &quot;pvSelection&quot;, 1, V_STRING, True) Then GoTo Finally
  174. Else
  175. If Not ScriptForge.SF_Utils._Validate(pvSelection, &quot;pvSelection&quot;, V_STRING) Then GoTo Finally
  176. End If
  177. End If
  178. Try:
  179. If IsArray(pvSelection) Then
  180. Set oCellRanges = _Component.createInstance(&quot;com.sun.star.sheet.SheetCellRanges&quot;)
  181. vRangeAddresses = Array()
  182. ReDim vRangeAddresses(0 To UBound(pvSelection))
  183. For i = 0 To UBound(pvSelection)
  184. vRangeAddresses(i) = Range(pvSelection(i)).XCellRange.RangeAddress
  185. Next i
  186. oCellRanges.addRangeAddresses(vRangeAddresses, False)
  187. _Component.CurrentController.select(oCellRanges)
  188. Else
  189. _Component.CurrentController.select(_ParseAddress(pvSelection).XCellRange)
  190. End If
  191. Finally:
  192. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  193. Exit Property
  194. Catch:
  195. GoTo Finally
  196. End Property &apos; SFDocuments.SF_Calc.CurrentSelection (let)
  197. REM -----------------------------------------------------------------------------
  198. Property Get FirstCell(Optional ByVal RangeName As Variant) As String
  199. &apos;&apos;&apos; Returns the First used cell in a given range or sheet
  200. &apos;&apos;&apos; When the argument is a sheet it will always return the &quot;sheet.$A$1&quot; cell
  201. FirstCell = _PropertyGet(&quot;FirstCell&quot;, RangeName)
  202. End Property &apos; SFDocuments.SF_Calc.FirstCell
  203. REM -----------------------------------------------------------------------------
  204. Property Get FirstColumn(Optional ByVal RangeName As Variant) As Long
  205. &apos;&apos;&apos; Returns the leftmost column in a given sheet or range
  206. &apos;&apos;&apos; When the argument is a sheet it will always return 1
  207. FirstColumn = _PropertyGet(&quot;FirstColumn&quot;, RangeName)
  208. End Property &apos; SFDocuments.SF_Calc.FirstColumn
  209. REM -----------------------------------------------------------------------------
  210. Property Get FirstRow(Optional ByVal RangeName As Variant) As Long
  211. &apos;&apos;&apos; Returns the First used column in a given range
  212. &apos;&apos;&apos; When the argument is a sheet it will always return 1
  213. FirstRow = _PropertyGet(&quot;FirstRow&quot;, RangeName)
  214. End Property &apos; SFDocuments.SF_Calc.FirstRow
  215. REM -----------------------------------------------------------------------------
  216. Property Get Height(Optional ByVal RangeName As Variant) As Long
  217. &apos;&apos;&apos; Returns the height in # of rows of the given range
  218. Height = _PropertyGet(&quot;Height&quot;, RangeName)
  219. End Property &apos; SFDocuments.SF_Calc.Height
  220. REM -----------------------------------------------------------------------------
  221. Property Get LastCell(Optional ByVal RangeName As Variant) As String
  222. &apos;&apos;&apos; Returns the last used cell in a given sheet or range
  223. LastCell = _PropertyGet(&quot;LastCell&quot;, RangeName)
  224. End Property &apos; SFDocuments.SF_Calc.LastCell
  225. REM -----------------------------------------------------------------------------
  226. Property Get LastColumn(Optional ByVal RangeName As Variant) As Long
  227. &apos;&apos;&apos; Returns the last used column in a given sheet
  228. LastColumn = _PropertyGet(&quot;LastColumn&quot;, RangeName)
  229. End Property &apos; SFDocuments.SF_Calc.LastColumn
  230. REM -----------------------------------------------------------------------------
  231. Property Get LastRow(Optional ByVal RangeName As Variant) As Long
  232. &apos;&apos;&apos; Returns the last used column in a given sheet
  233. LastRow = _PropertyGet(&quot;LastRow&quot;, RangeName)
  234. End Property &apos; SFDocuments.SF_Calc.LastRow
  235. REM -----------------------------------------------------------------------------
  236. Property Get Range(Optional ByVal RangeName As Variant) As Variant
  237. &apos;&apos;&apos; Returns a (internal) range object
  238. Range = _PropertyGet(&quot;Range&quot;, RangeName)
  239. End Property &apos; SFDocuments.SF_Calc.Range
  240. REM -----------------------------------------------------------------------------
  241. Property Get Region(Optional ByVal RangeName As Variant) As String
  242. &apos;&apos;&apos; Returns the smallest area as a range string that contains the given range
  243. &apos;&apos;&apos; and which is completely surrounded with empty cells
  244. Region = _PropertyGet(&quot;Region&quot;, RangeName)
  245. End Property &apos; SFDocuments.SF_Calc.Region
  246. REM -----------------------------------------------------------------------------
  247. Property Get Sheet(Optional ByVal SheetName As Variant) As Variant
  248. &apos;&apos;&apos; Returns a (internal) sheet object
  249. Sheet = _PropertyGet(&quot;Sheet&quot;, SheetName)
  250. End Property &apos; SFDocuments.SF_Calc.Sheet
  251. REM -----------------------------------------------------------------------------
  252. Property Get SheetName(Optional ByVal RangeName As Variant) As String
  253. &apos;&apos;&apos; Returns the sheet name part of a range
  254. SheetName = _PropertyGet(&quot;SheetName&quot;, RangeName)
  255. End Property &apos; SFDocuments.SF_Calc.SheetName
  256. REM -----------------------------------------------------------------------------
  257. Property Get Sheets() As Variant
  258. &apos;&apos;&apos; Returns an array listing the existing sheet names
  259. Sheets = _PropertyGet(&quot;Sheets&quot;)
  260. End Property &apos; SFDocuments.SF_Calc.Sheets
  261. REM -----------------------------------------------------------------------------
  262. Property Get Width(Optional ByVal RangeName As Variant) As Long
  263. &apos;&apos;&apos; Returns the width in # of columns of the given range
  264. Width = _PropertyGet(&quot;Width&quot;, RangeName)
  265. End Property &apos; SFDocuments.SF_Calc.Width
  266. REM -----------------------------------------------------------------------------
  267. Property Get XCellRange(Optional ByVal RangeName As Variant) As Variant
  268. &apos;&apos;&apos; Returns a UNO object of type com.sun.star.Table.CellRange
  269. XCellRange = _PropertyGet(&quot;XCellRange&quot;, RangeName)
  270. End Property &apos; SFDocuments.SF_Calc.XCellRange
  271. REM -----------------------------------------------------------------------------
  272. Property Get XSheetCellCursor(Optional ByVal RangeName As Variant) As Variant
  273. &apos;&apos;&apos; Returns a UNO object of type com.sun.star.sheet.XSheetCellCursor
  274. &apos;&apos; After having moved the cursor (gotoNext(), ...) the resulting range can be got
  275. &apos;&apos;&apos; back as a string with the cursor.AbsoluteName UNO property.
  276. XSheetCellCursor = _PropertyGet(&quot;XSheetCellCursor&quot;, RangeName)
  277. End Property &apos; SFDocuments.SF_Calc.XSheetCellCursor
  278. REM -----------------------------------------------------------------------------
  279. Property Get XSpreadsheet(Optional ByVal SheetName As Variant) As Variant
  280. &apos;&apos;&apos; Returns a UNO object of type com.sun.star.sheet.XSpreadsheet
  281. XSpreadsheet = _PropertyGet(&quot;XSpreadsheet&quot;, SheetName)
  282. End Property &apos; SFDocuments.SF_Calc.XSpreadsheet
  283. REM ===================================================================== METHODS
  284. REM -----------------------------------------------------------------------------
  285. Public Function A1Style(Optional ByVal Row1 As Variant _
  286. , Optional ByVal Column1 As Variant _
  287. , Optional ByVal Row2 As Variant _
  288. , Optional ByVal Column2 As Variant _
  289. , Optional ByVal SheetName As Variant _
  290. ) As String
  291. &apos;&apos;&apos; Returns a range expressed in A1-style as defined by its coordinates
  292. &apos;&apos;&apos; If only one pair of coordinates is given, the range will embrace only a single cell
  293. &apos;&apos;&apos; Args:
  294. &apos;&apos;&apos; Row1 : the row number of the first coordinate
  295. &apos;&apos;&apos; Column1 : the column number of the first coordinates
  296. &apos;&apos;&apos; Row2 : the row number of the second coordinate
  297. &apos;&apos;&apos; Column2 : the column number of the second coordinates
  298. &apos;&apos;&apos; SheetName: Default = the current sheet. If present, the sheet must exist.
  299. &apos;&apos;&apos; Returns:
  300. &apos;&apos;&apos; A range as a string
  301. &apos;&apos;&apos; Exceptions:
  302. &apos;&apos;&apos; Examples:
  303. &apos;&apos;&apos; range = oDoc.A1Style(5, 2, 10, 4, &quot;SheetX&quot;) &apos; &quot;&apos;$SheetX&apos;.$E$2:$J$4&quot;
  304. Dim sA1Style As String &apos; Return value
  305. Dim vSheetName As Variant &apos; Alias of SheetName - necessary see [Bug 145279]
  306. Dim lTemp As Long &apos; To switch 2 values
  307. Dim i As Long
  308. Const cstThisSub = &quot;SFDocuments.Calc.A1Style&quot;
  309. Const cstSubArgs = &quot;Row1, Column1, [Row2], [Column2], [SheetName]=&quot;&quot;&quot;&quot;&quot;
  310. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  311. sA1Style = &quot;&quot;
  312. Check:
  313. If IsMissing(Row2) Or IsEmpty(Row2) Then Row2 = 0
  314. If IsMissing(Column2) Or IsEmpty(Column2) Then Column2 = 0
  315. If IsMissing(SheetName) Or IsEmpty(SheetName) Then SheetName = &quot;~&quot;
  316. vSheetName = SheetName
  317. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  318. If Not _IsStillAlive() Then GoTo Finally
  319. If Not ScriptForge.SF_Utils._Validate(Row1, &quot;Row1&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  320. If Not ScriptForge.SF_Utils._Validate(Column1, &quot;Column1&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  321. If Not ScriptForge.SF_Utils._Validate(Row2, &quot;Row2&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  322. If Not ScriptForge.SF_Utils._Validate(Column2, &quot;Column2&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  323. If Not _ValidateSheet(vSheetName, &quot;SheetName&quot;, , True, True, , , True) Then GoTo Finally
  324. End If
  325. If Row1 &gt; MAXROWS Then Row1 = MAXROWS
  326. If Row2 &gt; MAXROWS Then Row2 = MAXROWS
  327. If Column1 &gt; MAXCOLS Then Column1 = MAXCOLS
  328. If Column2 &gt; MAXCOLS Then Column2 = MAXCOLS
  329. If Row2 &gt; 0 And Row2 &lt; Row1 Then
  330. lTemp = Row2 : Row2 = Row1 : Row1 = lTemp
  331. End If
  332. If Column2 &gt; 0 And Column2 &lt; Column1 Then
  333. lTemp = Column2 : Column2 = Column1 : Column1 = lTemp
  334. End If
  335. Try:
  336. &apos; Surround the sheet name with single quotes when required by the presence of special characters
  337. vSheetName = _QuoteSheetName(vSheetName)
  338. &apos; Define the new range string
  339. sA1Style = &quot;$&quot; &amp; vSheetName &amp; &quot;.&quot; _
  340. &amp; &quot;$&quot; &amp; _GetColumnName(Column1) &amp; &quot;$&quot; &amp; CLng(Row1) _
  341. &amp; Iif(Row2 &gt; 0 And Column2 &gt; 0, &quot;:$&quot; &amp; _GetColumnName(Column2) &amp; &quot;$&quot; &amp; CLng(Row2), &quot;&quot;)
  342. Finally:
  343. A1Style = sA1Style
  344. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  345. Exit Function
  346. Catch:
  347. GoTo Finally
  348. End Function &apos; SFDocuments.SF_Calc.A1Style
  349. REM -----------------------------------------------------------------------------
  350. Public Function Activate(Optional ByVal SheetName As Variant) As Boolean
  351. &apos;&apos;&apos; Make the current document or the given sheet active
  352. &apos;&apos;&apos; Args:
  353. &apos;&apos;&apos; SheetName: Default = the Calc document as a whole
  354. &apos;&apos;&apos; Returns:
  355. &apos;&apos;&apos; True if the document or the sheet could be made active
  356. &apos;&apos;&apos; Otherwise, there is no change in the actual user interface
  357. &apos;&apos;&apos; Examples:
  358. &apos;&apos;&apos; oDoc.Activate(&quot;SheetX&quot;)
  359. Dim bActive As Boolean &apos; Return value
  360. Dim oSheet As Object &apos; Reference to sheet
  361. Const cstThisSub = &quot;SFDocuments.Calc.Activate&quot;
  362. Const cstSubArgs = &quot;[SheetName]&quot;
  363. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  364. bActive = False
  365. Check:
  366. If IsMissing(SheetName) Or IsEmpty(SheetName) Then SheetName = &quot;&quot;
  367. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  368. If Not _IsStillAlive() Then GoTo Finally
  369. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , , True) Then GoTo Finally
  370. End If
  371. Try:
  372. &apos; Sheet activation, to do only when meaningful, precedes document activation
  373. If Len(SheetName) &gt; 0 Then
  374. With _Component
  375. Set oSheet = .getSheets.getByName(SheetName)
  376. Set .CurrentController.ActiveSheet = oSheet
  377. End With
  378. End If
  379. bActive = [_Super].Activate()
  380. Finally:
  381. Activate = bActive
  382. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  383. Exit Function
  384. Catch:
  385. GoTo Finally
  386. End Function &apos; SFDocuments.SF_Calc.Activate
  387. REM -----------------------------------------------------------------------------
  388. Public Function Charts(Optional ByVal SheetName As Variant _
  389. , Optional ByVal ChartName As Variant _
  390. ) As Variant
  391. &apos;&apos;&apos; Return either the list of charts present in the given sheet or a chart object
  392. &apos;&apos;&apos; Args:
  393. &apos;&apos;&apos; SheetName: The name of an existing sheet
  394. &apos;&apos;&apos; ChartName: The user-defined name of the targeted chart or the zero-length string
  395. &apos;&apos;&apos; Returns:
  396. &apos;&apos;&apos; When ChartName = &quot;&quot;, return the list of the charts present in the sheet,
  397. &apos;&apos;&apos; otherwise, return a new chart service instance
  398. &apos;&apos;&apos; Examples:
  399. &apos;&apos;&apos; Dim oChart As Object
  400. &apos;&apos;&apos; Set oChart = oDoc.Charts(&quot;SheetX&quot;, &quot;myChart&quot;)
  401. Dim vCharts As Variant &apos; Return value when array of chart names
  402. Dim oChart As Object &apos; Return value when new chart instance
  403. Dim oSheet As Object &apos; Alias of SheetName as reference
  404. Dim oDrawPage As Object &apos; com.sun.star.drawing.XDrawPage
  405. Dim oNextShape As Object &apos; com.sun.star.drawing.XShape
  406. Dim sChartName As String &apos; Some chart name
  407. Dim lCount As Long &apos; Counter for charts among all drawing objects
  408. Dim i As Long
  409. Const cstChartShape = &quot;com.sun.star.drawing.OLE2Shape&quot;
  410. Const cstThisSub = &quot;SFDocuments.Calc.Charts&quot;
  411. Const cstSubArgs = &quot;SheetName, [ChartName=&quot;&quot;&quot;&quot;]&quot;
  412. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  413. vCharts = Array()
  414. Check:
  415. If IsMissing(ChartName) Or IsEmpty(ChartName) Then ChartName = &quot;&quot;
  416. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  417. If Not _IsStillAlive(True) Then GoTo Finally
  418. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True) Then GoTo Finally
  419. If Not ScriptForge.SF_Utils._Validate(ChartName, &quot;ChartName&quot;, V_STRING) Then GoTo Finally
  420. End If
  421. Try:
  422. &apos; Because the user can change it constantly, the list of valid charts has to be rebuilt at each time
  423. &apos; Explore charts starting from the draw page
  424. Set oSheet = _Component.getSheets.getByName(SheetName)
  425. Set oDrawPage = oSheet.getDrawPage()
  426. vCharts = Array()
  427. Set oChart = Nothing
  428. lCount = -1
  429. For i = 0 To oDrawPage.Count - 1
  430. Set oNextShape = oDrawPage.getByIndex(i)
  431. if oNextShape.supportsService(cstChartShape) Then &apos; Ignore other shapes
  432. sChartName = oNextShape.Name &apos; User-defined name
  433. If Len(sChartName) = 0 Then sChartName = oNextShape.PersistName &apos; Internal name
  434. &apos; Is chart found ?
  435. If Len(ChartName) &gt; 0 Then
  436. If ChartName = sChartName Then
  437. Set oChart = New SF_Chart
  438. With oChart
  439. Set .[Me] = oChart
  440. Set .[_Parent] = [Me]
  441. ._SheetName = SheetName
  442. ._DrawIndex = i
  443. ._ChartName = ChartName
  444. ._PersistentName = oNextShape.PersistName
  445. Set ._Shape = oNextShape
  446. Set ._Chart = oSheet.getCharts().getByName(._PersistentName)
  447. Set ._ChartObject = ._Chart.EmbeddedObject
  448. Set ._Diagram = ._ChartObject.Diagram
  449. End With
  450. Exit For
  451. End If
  452. End If
  453. &apos; Build stack of chart names
  454. lCount = lCount + 1
  455. If UBound(vCharts) &lt; 0 Then
  456. vCharts = Array(sChartName)
  457. Else
  458. ReDim Preserve vCharts(0 To UBound(vCharts) + 1)
  459. vCharts(lCount) = sChartName
  460. End If
  461. End If
  462. Next i
  463. &apos; Raise error when chart not found
  464. If Len(ChartName) &gt; 0 And IsNull(oChart) Then
  465. If Not ScriptForge.SF_Utils._Validate(ChartName, &quot;ChartName&quot;, V_STRING, vCharts) Then GoTo Finally
  466. End If
  467. Finally:
  468. If Len(ChartName) = 0 Then Charts = vCharts Else Set Charts = oChart
  469. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  470. Exit Function
  471. Catch:
  472. GoTo Finally
  473. End Function &apos; SFDocuments.SF_Calc.Charts
  474. REM -----------------------------------------------------------------------------
  475. Public Sub ClearAll(Optional ByVal Range As Variant _
  476. , Optional FilterFormula As Variant _
  477. , Optional FilterScope As Variant _
  478. )
  479. &apos;&apos;&apos; Clear entirely the given range
  480. &apos;&apos;&apos; Args:
  481. &apos;&apos;&apos; Range : the cell or the range as a string that should be cleared
  482. &apos;&apos;&apos; FilterFormula: a Calc formula to select among the given Range
  483. &apos;&apos;&apos; When left empty, all the cells of the range are cleared
  484. &apos;&apos;&apos; FilterScope: &quot;CELL&quot; (default value), &quot;ROW&quot; or &quot;COLUMN&quot;
  485. &apos;&apos;&apos; When FilterFormula is present, FilterScope is mandatory
  486. &apos;&apos;&apos; Examples:
  487. &apos;&apos;&apos; oDoc.ClearAll(&quot;SheetX&quot;) &apos; Clears the used area of the sheet
  488. &apos;&apos;&apos; oDoc.ClearAll(&quot;A1:J20&quot;, &quot;=($A1=0)&quot;, &quot;ROW&quot;) &apos; Clears all rows when 1st cell is zero
  489. _ClearRange(&quot;All&quot;, Range, FilterFormula, FilterScope)
  490. End Sub &apos; SFDocuments.SF_Calc.ClearAll
  491. REM -----------------------------------------------------------------------------
  492. Public Sub ClearFormats(Optional ByVal Range As Variant _
  493. , Optional FilterFormula As Variant _
  494. , Optional FilterScope As Variant _
  495. )
  496. &apos;&apos;&apos; Clear all the formatting elements of the given range
  497. &apos;&apos;&apos; Args:
  498. &apos;&apos;&apos; Range : the cell or the range as a string that should be cleared
  499. &apos;&apos;&apos; FilterFormula: a Calc formula to select among the given Range
  500. &apos;&apos;&apos; When left empty, all the cells of the range are cleared
  501. &apos;&apos;&apos; FilterScope: &quot;CELL&quot; (default value), &quot;ROW&quot; or &quot;COLUMN&quot;
  502. &apos;&apos;&apos; When FilterFormula is present, FilterScope is mandatory
  503. &apos;&apos;&apos; Examples:
  504. &apos;&apos;&apos; oDoc.ClearFormats(&quot;SheetX.*&quot;) &apos; Clears the used area of the sheet
  505. &apos;&apos;&apos; oDoc.ClearFormats(&quot;A1:J20&quot;, &quot;=(MOD(A1;0)=0)&quot;, &quot;CELL&quot;) &apos; Clears all even cells
  506. _ClearRange(&quot;Formats&quot;, Range, FilterFormula, FilterScope)
  507. End Sub &apos; SFDocuments.SF_Calc.ClearFormats
  508. REM -----------------------------------------------------------------------------
  509. Public Sub ClearValues(Optional ByVal Range As Variant _
  510. , Optional FilterFormula As Variant _
  511. , Optional FilterScope As Variant _
  512. )
  513. &apos;&apos;&apos; Clear values and formulas in the given range
  514. &apos;&apos;&apos; Args:
  515. &apos;&apos;&apos; Range : the cell or the range as a string that should be cleared
  516. &apos;&apos;&apos; FilterFormula: a Calc formula to select among the given Range
  517. &apos;&apos;&apos; When left empty, all the cells of the range are cleared
  518. &apos;&apos;&apos; FilterScope: &quot;CELL&quot; (default value), &quot;ROW&quot; or &quot;COLUMN&quot;
  519. &apos;&apos;&apos; When FilterFormula is present, FilterScope is mandatory
  520. &apos;&apos;&apos; Examples:
  521. &apos;&apos;&apos; oDoc.ClearValues(&quot;SheetX.*&quot;) &apos; Clears the used area of the sheet
  522. &apos;&apos;&apos; oDoc.ClearValues(&quot;A2:A20&quot;, &quot;=(A2=A1)&quot;, &quot;CELL&quot;) &apos; Clears all duplicate cells
  523. _ClearRange(&quot;Values&quot;, Range, FilterFormula, FilterScope)
  524. End Sub &apos; SFDocuments.SF_Calc.ClearValues
  525. REM -----------------------------------------------------------------------------
  526. Public Function CompactLeft(Optional ByVal Range As Variant _
  527. , Optional ByVal WholeColumn As Variant _
  528. , Optional ByVal FilterFormula As Variant _
  529. ) As String
  530. &apos;&apos;&apos; Delete the columns of a specified range matching a filter expressed as a formula
  531. &apos;&apos;&apos; applied on each column.
  532. &apos;&apos;&apos; The deleted cells can span whole columns or be limited to the height of the range
  533. &apos;&apos;&apos; The execution of the method has no effect on the current selection
  534. &apos;&apos;&apos; Args:
  535. &apos;&apos;&apos; Range: the range in which cells have to be erased, as a string
  536. &apos;&apos;&apos; WholeColumn: when True (default = False), erase whole columns
  537. &apos;&apos;&apos; FilterFormula: the formula to be applied on each column.
  538. &apos;&apos;&apos; The column is erased when the formula results in True,
  539. &apos;&apos;&apos; The formula shall probably involve one or more cells of the first column of the range.
  540. &apos;&apos;&apos; By default, a column is erased when all the cells of the column are empty,
  541. &apos;&apos;&apos; i.e. suppose the range is &quot;A1:J200&quot; (height = 200) the default value becomes
  542. &apos;&apos;&apos; &quot;=(COUNTBLANK(A1:A200)=200)&quot;
  543. &apos;&apos;&apos; Returns:
  544. &apos;&apos;&apos; A string representing the location of the initial range after compaction,
  545. &apos;&apos;&apos; or the zero-length string if the whole range has been deleted
  546. &apos;&apos;&apos; Examples:
  547. &apos;&apos;&apos; newrange = oDoc.CompactLeft(&quot;SheetX.G1:L10&quot;) &apos; All empty columns of the range are suppressed
  548. &apos;&apos;&apos; newrange = oDoc.CompactLeft(&quot;SheetX.G1:L10&quot;, WholeColumn := True, FilterFormula := &quot;=(G$7=&quot;&quot;X&quot;&quot;)&quot;)
  549. &apos;&apos;&apos; &apos; The columns having a &quot;X&quot; in row 7 are completely suppressed
  550. Dim sCompact As String &apos; Return value
  551. Dim oCompact As Object &apos; Return value as an _Address type
  552. Dim lCountDeleted As Long &apos; Count the deleted columns
  553. Dim vCompactRanges As Variant &apos; Array of ranges to be compacted based on the formula
  554. Dim oSourceAddress As Object &apos; Alias of Range as _Address
  555. Dim oPartialRange As Object &apos; Contiguous columns to be deleted
  556. Dim sShiftRange As String &apos; Contiguous columns to be shifted
  557. Dim i As Long
  558. Const cstThisSub = &quot;SFDocuments.Calc.CompactLeft&quot;
  559. Const cstSubArgs = &quot;Range, [WholeColumn=False], [FilterFormula=&quot;&quot;&quot;&quot;]&quot;
  560. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  561. sCompact = &quot;&quot;
  562. Check:
  563. If IsMissing(WholeColumn) Or IsEmpty(WholeColumn) Then WholeColumn = False
  564. If IsMissing(FilterFormula) Or IsEmpty(FilterFormula) Then FilterFormula = &quot;&quot;
  565. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  566. If Not _IsStillAlive(True) Then GoTo Finally
  567. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  568. If Not ScriptForge.SF_Utils._Validate(WholeColumn, &quot;WholeColumn&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  569. If Not ScriptForge.SF_Utils._Validate(FilterFormula, &quot;FilterFormula&quot;, V_STRING) Then GoTo Finally
  570. End If
  571. Try:
  572. Set oSourceAddress = _ParseAddress(Range)
  573. lCountDeleted = 0
  574. With oSourceAddress
  575. &apos; Set the default formula =&gt; all cells are blank
  576. If FilterFormula = &quot;&quot; Then FilterFormula = Printf(&quot;=(COUNTBLANK(%C1%R1:%C1%R2)-&quot; &amp; .Height &amp; &quot;=0)&quot;, Range)
  577. &apos; Identify the ranges to compact based on the given formula
  578. vCompactRanges = _ComputeFilter(oSourceAddress, FilterFormula, &quot;COLUMN&quot;)
  579. &apos; Iterate through the ranges from bottom to top and shift them up
  580. For i = UBound(vCompactRanges) To 0 Step -1
  581. Set oPartialRange = vCompactRanges(i)
  582. ShiftLeft(oPartialRange.RangeName, WholeColumn)
  583. lCountDeleted = lCountDeleted + oPartialRange.Width
  584. Next i
  585. &apos; Compute the final range position
  586. If lCountDeleted &lt; .Width Then sCompact = Offset(Range, 0, 0, 0, .Width - lCountDeleted)
  587. &apos; Push to the right the cells that migrated leftwards irrelevantly
  588. If Not WholeColumn Then
  589. If Len(sCompact) &gt; 0 Then
  590. sShiftRange = Offset(sCompact, 0, .Width - lCountDeleted, , lCountDeleted)
  591. Else
  592. sShiftRange = .RangeName
  593. End If
  594. ShiftRight(sShiftRange, WholeColumn := False)
  595. End If
  596. End With
  597. Finally:
  598. CompactLeft = sCompact
  599. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  600. Exit Function
  601. Catch:
  602. &apos; When error, return the original range
  603. If Not IsNull(oSourceAddress) Then sCompact = oSourceAddress.RangeName
  604. GoTo Finally
  605. End Function &apos; SFDocuments.SF_Calc.CompactLeft
  606. REM -----------------------------------------------------------------------------
  607. Public Function CompactUp(Optional ByVal Range As Variant _
  608. , Optional ByVal WholeRow As Variant _
  609. , Optional ByVal FilterFormula As Variant _
  610. ) As String
  611. &apos;&apos;&apos; Delete the rows of a specified range matching a filter expressed as a formula
  612. &apos;&apos;&apos; applied on each row.
  613. &apos;&apos;&apos; The deleted cells can span whole rows or be limited to the width of the range
  614. &apos;&apos;&apos; The execution of the method has no effect on the current selection
  615. &apos;&apos;&apos; Args:
  616. &apos;&apos;&apos; Range: the range in which cells have to be erased, as a string
  617. &apos;&apos;&apos; WholeRow: when True (default = False), erase whole rows
  618. &apos;&apos;&apos; FilterFormula: the formula to be applied on each row.
  619. &apos;&apos;&apos; The row is erased when the formula results in True,
  620. &apos;&apos;&apos; The formula shall probably involve one or more cells of the first row of the range.
  621. &apos;&apos;&apos; By default, a row is erased when all the cells of the row are empty,
  622. &apos;&apos;&apos; i.e. suppose the range is &quot;A1:J200&quot; (width = 10) the default value becomes
  623. &apos;&apos;&apos; &quot;=(COUNTBLANK(A1:J1)=10)&quot;
  624. &apos;&apos;&apos; Returns:
  625. &apos;&apos;&apos; A string representing the location of the initial range after compaction,
  626. &apos;&apos;&apos; or the zero-length string if the whole range has been deleted
  627. &apos;&apos;&apos; Examples:
  628. &apos;&apos;&apos; newrange = oDoc.CompactUp(&quot;SheetX.G1:L10&quot;) &apos; All empty rows of the range are suppressed
  629. &apos;&apos;&apos; newrange = oDoc.CompactUp(&quot;SheetX.G1:L10&quot;, WholeRow := True, FilterFormula := &quot;=(G1=&quot;&quot;X&quot;&quot;)&quot;)
  630. &apos;&apos;&apos; &apos; The rows having a &quot;X&quot; in column G are completely suppressed
  631. Dim sCompact As String &apos; Return value
  632. Dim oCompact As Object &apos; Return value as an _Address type
  633. Dim lCountDeleted As Long &apos; Count the deleted rows
  634. Dim vCompactRanges As Variant &apos; Array of ranges to be compacted based on the formula
  635. Dim oSourceAddress As Object &apos; Alias of Range as _Address
  636. Dim oPartialRange As Object &apos; Contiguous rows to be deleted
  637. Dim sShiftRange As String &apos; Contiguous rows to be shifted
  638. Dim i As Long
  639. Const cstThisSub = &quot;SFDocuments.Calc.CompactUp&quot;
  640. Const cstSubArgs = &quot;Range, [WholeRow=False], [FilterFormula=&quot;&quot;&quot;&quot;]&quot;
  641. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  642. sCompact = &quot;&quot;
  643. Check:
  644. If IsMissing(WholeRow) Or IsEmpty(WholeRow) Then WholeRow = False
  645. If IsMissing(FilterFormula) Or IsEmpty(FilterFormula) Then FilterFormula = &quot;&quot;
  646. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  647. If Not _IsStillAlive(True) Then GoTo Finally
  648. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  649. If Not ScriptForge.SF_Utils._Validate(WholeRow, &quot;WholeRow&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  650. If Not ScriptForge.SF_Utils._Validate(FilterFormula, &quot;FilterFormula&quot;, V_STRING) Then GoTo Finally
  651. End If
  652. Try:
  653. Set oSourceAddress = _ParseAddress(Range)
  654. lCountDeleted = 0
  655. With oSourceAddress
  656. &apos; Set the default formula =&gt; all cells are blank
  657. If FilterFormula = &quot;&quot; Then FilterFormula = Printf(&quot;=(COUNTBLANK(%C1%R1:%C2%R1)-&quot; &amp; .Width &amp; &quot;=0)&quot;, Range)
  658. &apos; Identify the ranges to compact based on the given formula
  659. vCompactRanges = _ComputeFilter(oSourceAddress, FilterFormula, &quot;ROW&quot;)
  660. &apos; Iterate through the ranges from bottom to top and shift them up
  661. For i = UBound(vCompactRanges) To 0 Step -1
  662. Set oPartialRange = vCompactRanges(i)
  663. ShiftUp(oPartialRange.RangeName, WholeRow)
  664. lCountDeleted = lCountDeleted + oPartialRange.Height
  665. Next i
  666. &apos; Compute the final range position
  667. If lCountDeleted &lt; .Height Then sCompact = Offset(Range, 0, 0, .Height - lCountDeleted, 0)
  668. &apos; Push downwards the cells that migrated upwards irrelevantly
  669. If Not WholeRow Then
  670. If Len(sCompact) &gt; 0 Then
  671. sShiftRange = Offset(sCompact, .Height - lCountDeleted, 0, lCountDeleted)
  672. Else
  673. sShiftRange = .RangeName
  674. End If
  675. ShiftDown(sShiftRange, WholeRow := False)
  676. End If
  677. End With
  678. Finally:
  679. CompactUp = sCompact
  680. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  681. Exit Function
  682. Catch:
  683. &apos; When error, return the original range
  684. If Not IsNull(oSourceAddress) Then sCompact = oSourceAddress.RangeName
  685. GoTo Finally
  686. End Function &apos; SFDocuments.SF_Calc.CompactUp
  687. REM -----------------------------------------------------------------------------
  688. Public Function CopySheet(Optional ByVal SheetName As Variant _
  689. , Optional ByVal NewName As Variant _
  690. , Optional ByVal BeforeSheet As Variant _
  691. ) As Boolean
  692. &apos;&apos;&apos; Copy a specified sheet before an existing sheet or at the end of the list of sheets
  693. &apos;&apos;&apos; The sheet to copy may be inside any open Calc document
  694. &apos;&apos;&apos; Args:
  695. &apos;&apos;&apos; SheetName: The name of the sheet to copy or its reference
  696. &apos;&apos;&apos; NewName: Must not exist
  697. &apos;&apos;&apos; BeforeSheet: The name (string) or index (numeric, starting from 1) of the sheet before which to insert
  698. &apos;&apos;&apos; Returns:
  699. &apos;&apos;&apos; True if the sheet could be copied successfully
  700. &apos;&apos;&apos; Exceptions:
  701. &apos;&apos;&apos; DUPLICATESHEETERROR A sheet with the given name exists already
  702. &apos;&apos;&apos; Examples:
  703. &apos;&apos;&apos; oDoc.CopySheet(&quot;SheetX&quot;, &quot;SheetY&quot;)
  704. &apos;&apos;&apos; &apos; Copy within the same document
  705. &apos;&apos;&apos; Dim oDocA As Object : Set oDocA = ui.OpenDocument(&quot;C:\Temp\FileA.ods&quot;, Hidden := True, ReadOnly := True)
  706. &apos;&apos;&apos; Dim oDocB As Object : Set oDocB = ui.OpenDocument(&quot;C:\Temp\FileB.ods&quot;)
  707. &apos;&apos;&apos; oDocB.CopySheet(oDocA.Sheet(&quot;SheetX&quot;), &quot;SheetY&quot;)
  708. &apos;&apos;&apos; &apos; Copy from 1 file to another and put the new sheet at the end
  709. Dim bCopy As Boolean &apos; Return value
  710. Dim oSheets As Object &apos; com.sun.star.sheet.XSpreadsheets
  711. Dim vSheets As Variant &apos; List of existing sheets
  712. Dim lSheetIndex As Long &apos; Index of a sheet
  713. Dim oSheet As Object &apos; Alias of SheetName as reference
  714. Dim lRandom As Long &apos; Output of random number generator
  715. Dim sRandom &apos; Random sheet name
  716. Const cstThisSub = &quot;SFDocuments.Calc.CopySheet&quot;
  717. Const cstSubArgs = &quot;SheetName, NewName, [BeforeSheet=&quot;&quot;&quot;&quot;]&quot;
  718. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  719. bCopy = False
  720. Check:
  721. If IsMissing(BeforeSheet) Or IsEmpty(BeforeSheet) Then BeforeSheet = 32768
  722. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  723. If Not _IsStillAlive(True) Then GoTo Finally
  724. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True, , , True) Then GoTo Finally
  725. If Not _ValidateSheet(NewName, &quot;NewName&quot;, True) Then GoTo Finally
  726. If Not _ValidateSheet(BeforeSheet, &quot;BeforeSheet&quot;, , True, , True) Then GoTo Finally
  727. End If
  728. Try:
  729. &apos; Determine the index of the sheet before which to insert the copy
  730. Set oSheets = _Component.getSheets
  731. vSheets = oSheets.getElementNames()
  732. If VarType(BeforeSheet) = V_STRING Then
  733. lSheetIndex = ScriptForge.SF_Array.IndexOf(vSheets, BeforeSheet)
  734. Else
  735. lSheetIndex = BeforeSheet - 1
  736. If lSheetIndex &lt; 0 Then lSheetIndex = 0
  737. If lSheetIndex &gt; UBound(vSheets) Then lSheetIndex = UBound(vSheets) + 1
  738. End If
  739. &apos; Copy sheet inside the same document OR import from another document
  740. If VarType(SheetName) = V_STRING Then
  741. _Component.getSheets.copyByName(SheetName, NewName, lSheetIndex)
  742. Else
  743. Set oSheet = SheetName
  744. With oSheet
  745. &apos; If a sheet with same name as input exists in the target sheet, rename it first with a random name
  746. sRandom = &quot;&quot;
  747. If ScriptForge.SF_Array.Contains(vSheets, .SheetName) Then
  748. lRandom = ScriptForge.SF_Session.ExecuteCalcFunction(&quot;RANDBETWEEN.NV&quot;, 1, 9999999)
  749. sRandom = &quot;SF_&quot; &amp; Right(&quot;0000000&quot; &amp; lRandom, 7)
  750. oSheets.getByName(.SheetName).setName(sRandom)
  751. End If
  752. &apos; Import i.o. Copy
  753. oSheets.importSheet(oSheet.Component, .SheetName, lSheetIndex)
  754. &apos; Rename to new sheet name
  755. oSheets.getByName(.SheetName).setName(NewName)
  756. &apos; Reset random name
  757. If Len(sRandom) &gt; 0 Then oSheets.getByName(sRandom).setName(.SheetName)
  758. End With
  759. End If
  760. bCopy = True
  761. Finally:
  762. CopySheet = bCopy
  763. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  764. Exit Function
  765. Catch:
  766. GoTo Finally
  767. CatchDuplicate:
  768. ScriptForge.SF_Exception.RaiseFatal(DUPLICATESHEETERROR, &quot;NewName&quot;, NewName, &quot;Document&quot;, [_Super]._FileIdent())
  769. GoTo Finally
  770. End Function &apos; SFDocuments.SF_Calc.CopySheet
  771. REM -----------------------------------------------------------------------------
  772. Public Function CopySheetFromFile(Optional ByVal FileName As Variant _
  773. , Optional ByVal SheetName As Variant _
  774. , Optional ByVal NewName As Variant _
  775. , Optional ByVal BeforeSheet As Variant _
  776. ) As Boolean
  777. &apos;&apos;&apos; Copy a specified sheet before an existing sheet or at the end of the list of sheets
  778. &apos;&apos;&apos; The sheet to copy is located inside any closed Calc document
  779. &apos;&apos;&apos; Args:
  780. &apos;&apos;&apos; FileName: Identifies the file to open. It must follow the SF_FileSystem.FileNaming notation
  781. &apos;&apos;&apos; The file must not be protected with a password
  782. &apos;&apos;&apos; SheetName: The name of the sheet to copy
  783. &apos;&apos;&apos; NewName: Must not exist
  784. &apos;&apos;&apos; BeforeSheet: The name (string) or index (numeric, starting from 1) of the sheet before which to insert
  785. &apos;&apos;&apos; Returns:
  786. &apos;&apos;&apos; True if the sheet could be created
  787. &apos;&apos;&apos; The created sheet is blank when the input file is not a Calc file
  788. &apos;&apos;&apos; The created sheet contains an error message when the input sheet was not found
  789. &apos;&apos;&apos; Exceptions:
  790. &apos;&apos;&apos; DUPLICATESHEETERROR A sheet with the given name exists already
  791. &apos;&apos;&apos; UNKNOWNFILEERROR The input file is unknown
  792. &apos;&apos;&apos; Examples:
  793. &apos;&apos;&apos; oDoc.CopySheetFromFile(&quot;C:\MyFile.ods&quot;, &quot;SheetX&quot;, &quot;SheetY&quot;, 3)
  794. Dim bCopy As Boolean &apos; Return value
  795. Dim oSheet As Object &apos; com.sun.star.sheet.XSpreadsheet
  796. Dim sFileName As String &apos; URL alias of FileName
  797. Dim FSO As Object &apos; SF_FileSystem
  798. Const cstThisSub = &quot;SFDocuments.Calc.CopySheetFromFile&quot;
  799. Const cstSubArgs = &quot;FileName, SheetName, NewName, [BeforeSheet=&quot;&quot;&quot;&quot;]&quot;
  800. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  801. bCopy = False
  802. Check:
  803. If IsMissing(BeforeSheet) Or IsEmpty(BeforeSheet) Then BeforeSheet = 32768
  804. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  805. If Not _IsStillAlive(True) Then GoTo Finally
  806. If Not ScriptForge.SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  807. If Not ScriptForge.SF_Utils._Validate(SheetName, &quot;SheetName&quot;, V_STRING) Then GoTo Finally
  808. If Not _ValidateSheet(NewName, &quot;NewName&quot;, True) Then GoTo Finally
  809. If Not _ValidateSheet(BeforeSheet, &quot;BeforeSheet&quot;, , True, , True) Then GoTo Finally
  810. End If
  811. Try:
  812. Set FSO = ScriptForge.SF_FileSystem
  813. &apos; Does the input file exist ?
  814. If Not FSO.FileExists(FileName) Then GoTo CatchNotExists
  815. sFileName = FSO._ConvertToUrl(FileName)
  816. &apos; Insert a blank new sheet and import sheet from file via link setting and deletion
  817. If Not InsertSheet(Newname, BeforeSheet) Then GoTo Finally
  818. Set oSheet = _Component.getSheets.getByName(NewName)
  819. With oSheet
  820. .link(sFileName,SheetName, &quot;&quot;, &quot;&quot;, com.sun.star.sheet.SheetLinkMode.NORMAL)
  821. .LinkMode = com.sun.star.sheet.SheetLinkMode.NONE
  822. .LinkURL = &quot;&quot;
  823. End With
  824. bCopy = True
  825. Finally:
  826. CopySheetFromFile = bCopy
  827. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  828. Exit Function
  829. Catch:
  830. GoTo Finally
  831. CatchNotExists:
  832. ScriptForge.SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, FileName)
  833. GoTo Finally
  834. End Function &apos; SFDocuments.SF_Calc.CopySheetFromFile
  835. REM -----------------------------------------------------------------------------
  836. Public Function CopyToCell(Optional ByVal SourceRange As Variant _
  837. , Optional ByVal DestinationCell As Variant _
  838. ) As String
  839. &apos;&apos;&apos; Copy a specified source range to a destination range or cell
  840. &apos;&apos;&apos; The source range may belong to another open document
  841. &apos;&apos;&apos; The method imitates the behaviour of a Copy/Paste from a range to a single cell
  842. &apos;&apos;&apos; Args:
  843. &apos;&apos;&apos; SourceRange: the source range as a string if it belongs to the same document
  844. &apos;&apos;&apos; or as a reference if it belongs to another open Calc document
  845. &apos;&apos;&apos; DestinationCell: the destination of the copied range of cells, as a string
  846. &apos;&apos;&apos; If given as a range of cells, the destination will be reduced to its top-left cell
  847. &apos;&apos;&apos; Returns:
  848. &apos;&apos;&apos; A string representing the modified range of cells
  849. &apos;&apos;&apos; The modified area depends only on the size of the source area
  850. &apos;&apos;&apos; Examples:
  851. &apos;&apos;&apos; oDoc.CopyToCell(&quot;SheetX.A1:F10&quot;, &quot;SheetY.C5&quot;)
  852. &apos;&apos;&apos; &apos; Copy within the same document
  853. &apos;&apos;&apos; Dim oDocA As Object : Set oDocA = ui.OpenDocument(&quot;C:\Temp\FileA.ods&quot;, Hidden := True, ReadOnly := True)
  854. &apos;&apos;&apos; Dim oDocB As Object : Set oDocB = ui.OpenDocument(&quot;C:\Temp\FileB.ods&quot;)
  855. &apos;&apos;&apos; oDocB.CopyToCell(oDocA.Range(&quot;SheetX.A1:F10&quot;), &quot;SheetY.C5&quot;)
  856. &apos;&apos;&apos; &apos; Copy from 1 file to another
  857. Dim sCopy As String &apos; Return value
  858. Dim oSource As Object &apos; Alias of SourceRange to avoid &quot;Object variable not set&quot; run-time error
  859. Dim oSourceAddress As Object &apos; com.sun.star.table.CellRangeAddress
  860. Dim oDestRange As Object &apos; Destination as a range
  861. Dim oDestAddress As Object &apos; com.sun.star.table.CellRangeAddress
  862. Dim oDestCell As Object &apos; com.sun.star.table.CellAddress
  863. Dim oSelect As Object &apos; Current selection in source
  864. Dim oClipboard As Object &apos; com.sun.star.datatransfer.XTransferable
  865. Const cstThisSub = &quot;SFDocuments.Calc.CopyToCell&quot;
  866. Const cstSubArgs = &quot;SourceRange, DestinationCell&quot;
  867. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  868. sCopy = &quot;&quot;
  869. Check:
  870. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  871. If Not _IsStillAlive(True) Then GoTo Finally
  872. If Not ScriptForge.SF_Utils._Validate(SourceRange, &quot;SourceRange&quot;, Array(V_STRING, ScriptForge.V_OBJECT), , , CALCREFERENCE) Then GoTo Finally
  873. If Not ScriptForge.SF_Utils._Validate(DestinationCell, &quot;DestinationCell&quot;, V_STRING) Then GoTo Finally
  874. End If
  875. Try:
  876. If VarType(SourceRange) = V_STRING Then &apos; Same document - Use UNO copyRange method
  877. Set oSourceAddress = _ParseAddress(SourceRange).XCellRange.RangeAddress
  878. Set oDestRange = _ParseAddress(DestinationCell)
  879. Set oDestAddress = oDestRange.XCellRange.RangeAddress
  880. Set oDestCell = New com.sun.star.table.CellAddress
  881. With oDestAddress
  882. oDestCell.Sheet = .Sheet
  883. oDestCell.Column = .StartColumn
  884. oDestCell.Row = .StartRow
  885. End With
  886. oDestRange.XSpreadsheet.copyRange(oDestCell, oSourceAddress)
  887. Else &apos; Use clipboard to copy - current selection in Source should be preserved
  888. Set oSource = SourceRange
  889. With oSource
  890. &apos; Keep current selection in source document
  891. Set oSelect = .Component.CurrentController.getSelection()
  892. &apos; Select, copy the source range and paste in the top-left cell of the destination
  893. .Component.CurrentController.select(.XCellRange)
  894. Set oClipboard = .Component.CurrentController.getTransferable()
  895. _Component.CurrentController.select(_Offset(DestinationCell, 0, 0, 1, 1).XCellRange)
  896. _Component.CurrentController.insertTransferable(oClipBoard)
  897. &apos; Restore previous selection in Source
  898. _RestoreSelections(.Component, oSelect)
  899. Set oSourceAddress = .XCellRange.RangeAddress
  900. End With
  901. End If
  902. With oSourceAddress
  903. sCopy = _Offset(DestinationCell, 0, 0, .EndRow - .StartRow + 1, .EndColumn - .StartColumn + 1).RangeName
  904. End With
  905. Finally:
  906. CopyToCell = sCopy
  907. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  908. Exit Function
  909. Catch:
  910. GoTo Finally
  911. End Function &apos; SFDocuments.SF_Calc.CopyToCell
  912. REM -----------------------------------------------------------------------------
  913. Public Function CopyToRange(Optional ByVal SourceRange As Variant _
  914. , Optional ByVal DestinationRange As Variant _
  915. ) As String
  916. &apos;&apos;&apos; Copy downwards and/or rightwards a specified source range to a destination range
  917. &apos;&apos;&apos; The source range may belong to another open document
  918. &apos;&apos;&apos; The method imitates the behaviour of a Copy/Paste from a range to a larger range
  919. &apos;&apos;&apos; If the height (resp. width) of the destination area is &gt; 1 row (resp. column)
  920. &apos;&apos;&apos; then the height (resp. width) of the source must be &lt;= the height (resp. width)
  921. &apos;&apos;&apos; of the destination. Otherwise nothing happens
  922. &apos;&apos;&apos; If the height (resp.width) of the destination is = 1 then the destination
  923. &apos;&apos;&apos; is expanded downwards (resp. rightwards) up to the height (resp. width)
  924. &apos;&apos;&apos; of the source range
  925. &apos;&apos;&apos; Args:
  926. &apos;&apos;&apos; SourceRange: the source range as a string if it belongs to the same document
  927. &apos;&apos;&apos; or as a reference if it belongs to another open Calc document
  928. &apos;&apos;&apos; DestinationRange: the destination of the copied range of cells, as a string
  929. &apos;&apos;&apos; Returns:
  930. &apos;&apos;&apos; A string representing the modified range of cells
  931. &apos;&apos;&apos; Examples:
  932. &apos;&apos;&apos; oDoc.CopyToRange(&quot;SheetX.A1:F10&quot;, &quot;SheetY.C5:J5&quot;)
  933. &apos;&apos;&apos; &apos; Copy within the same document
  934. &apos;&apos;&apos; &apos; Returned range: $SheetY.$C$5:$J$14
  935. &apos;&apos;&apos; Dim oDocA As Object : Set oDocA = ui.OpenDocument(&quot;C:\Temp\FileA.ods&quot;, Hidden := True, ReadOnly := True)
  936. &apos;&apos;&apos; Dim oDocB As Object : Set oDocB = ui.OpenDocument(&quot;C:\Temp\FileB.ods&quot;)
  937. &apos;&apos;&apos; oDocB.CopyToRange(oDocA.Range(&quot;SheetX.A1:F10&quot;), &quot;SheetY.C5:J5&quot;)
  938. &apos;&apos;&apos; &apos; Copy from 1 file to another
  939. Dim sCopy As String &apos; Return value
  940. Dim oSource As Object &apos; Alias of SourceRange to avoid &quot;Object variable not set&quot; run-time error
  941. Dim oDestRange As Object &apos; Destination as a range
  942. Dim oDestCell As Object &apos; com.sun.star.table.CellAddress
  943. Dim oSelect As Object &apos; Current selection in source
  944. Dim oClipboard As Object &apos; com.sun.star.datatransfer.XTransferable
  945. Dim bSameDocument As Boolean &apos; True when source in same document as destination
  946. Dim lHeight As Long &apos; Height of destination
  947. Dim lWidth As Long &apos; Width of destination
  948. Const cstThisSub = &quot;SFDocuments.Calc.CopyToRange&quot;
  949. Const cstSubArgs = &quot;SourceRange, DestinationRange&quot;
  950. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  951. sCopy = &quot;&quot;
  952. Check:
  953. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  954. If Not _IsStillAlive(True) Then GoTo Finally
  955. If Not ScriptForge.SF_Utils._Validate(SourceRange, &quot;SourceRange&quot;, Array(V_STRING, ScriptForge.V_OBJECT), , , CALCREFERENCE) Then GoTo Finally
  956. If Not ScriptForge.SF_Utils._Validate(DestinationRange, &quot;DestinationRange&quot;, V_STRING) Then GoTo Finally
  957. End If
  958. Try:
  959. &apos; Copy done via clipboard
  960. &apos; Check Height/Width destination = 1 or &gt; Height/Width of source
  961. bSameDocument = ( VarType(SourceRange) = V_STRING )
  962. If bSameDocument Then Set oSource = _ParseAddress(SourceRange) Else Set oSource = SourceRange
  963. Set oDestRange = _ParseAddress(DestinationRange)
  964. With oDestRange
  965. lHeight = .Height
  966. lWidth = .Width
  967. If lHeight = 1 Then
  968. lHeight = oSource.Height &apos; Future height
  969. ElseIf lHeight &lt; oSource.Height Then
  970. GoTo Finally
  971. End If
  972. If lWidth = 1 Then
  973. lWidth = oSource.Width &apos; Future width
  974. ElseIf lWidth &lt; oSource.Width Then
  975. GoTo Finally
  976. End If
  977. End With
  978. With oSource
  979. &apos; Store actual selection in source
  980. Set oSelect = .Component.CurrentController.getSelection()
  981. &apos; Select, copy the source range and paste in the destination
  982. .Component.CurrentController.select(.XCellRange)
  983. Set oClipboard = .Component.CurrentController.getTransferable()
  984. _Component.CurrentController.select(oDestRange.XCellRange)
  985. _Component.CurrentController.insertTransferable(oClipBoard)
  986. &apos; Restore selection in source
  987. _RestoreSelections(.Component, oSelect)
  988. End With
  989. sCopy = _Offset(oDestRange, 0, 0, lHeight, lWidth).RangeName
  990. Finally:
  991. CopyToRange = sCopy
  992. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  993. Exit Function
  994. Catch:
  995. GoTo Finally
  996. End Function &apos; SFDocuments.SF_Calc.CopyToRange
  997. REM -----------------------------------------------------------------------------
  998. Public Function CreateChart(Optional ByVal ChartName As Variant _
  999. , Optional ByVal SheetName As Variant _
  1000. , Optional ByVal Range As Variant _
  1001. , Optional ColumnHeader As Variant _
  1002. , Optional RowHeader As Variant _
  1003. ) As Variant
  1004. &apos;&apos;&apos; Return a new chart instance initialized with default values
  1005. &apos;&apos;&apos; Args:
  1006. &apos;&apos;&apos; ChartName: The user-defined name of the new chart
  1007. &apos;&apos;&apos; SheetName: The name of an existing sheet
  1008. &apos;&apos;&apos; Range: the cell or the range as a string that should be drawn
  1009. &apos;&apos;&apos; ColumnHeader: when True, the topmost row of the range will be used to set labels for the category axis or the legend.
  1010. &apos;&apos;&apos; Default = False
  1011. &apos;&apos;&apos; RowHeader: when True, the leftmost column of the range will be used to set labels for the category axis or the legend.
  1012. &apos;&apos;&apos; Default = False
  1013. &apos;&apos;&apos; Returns:
  1014. &apos;&apos;&apos; A new chart service instance
  1015. &apos;&apos;&apos; Exceptions:
  1016. &apos;&apos;&apos; DUPLICATECHARTERROR A chart with the same name exists already in the given sheet
  1017. &apos;&apos;&apos; Examples:
  1018. &apos;&apos;&apos; Dim oChart As Object
  1019. &apos;&apos;&apos; Set oChart = oDoc.CreateChart(&quot;myChart&quot;, &quot;SheetX&quot;, &quot;A1:C8&quot;, ColumnHeader := True)
  1020. Dim oChart As Object &apos; Return value
  1021. Dim vCharts As Variant &apos; List of pre-existing charts
  1022. Dim oSheet As Object &apos; Alias of SheetName as reference
  1023. Dim oRange As Object &apos; Alias of Range
  1024. Dim oRectangle as new com.sun.star.awt.Rectangle &apos; Simple shape
  1025. Const cstThisSub = &quot;SFDocuments.Calc.CreateChart&quot;
  1026. Const cstSubArgs = &quot;ChartName, SheetName, Range, [ColumnHeader=False], [RowHeader=False]&quot;
  1027. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1028. Set oChart = Nothing
  1029. Check:
  1030. If IsMissing(RowHeader) Or IsEmpty(RowHeader) Then Rowheader = False
  1031. If IsMissing(ColumnHeader) Or IsEmpty(ColumnHeader) Then ColumnHeader = False
  1032. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1033. If Not _IsStillAlive(True) Then GoTo Finally
  1034. If Not ScriptForge.SF_Utils._Validate(ChartName, &quot;ChartName&quot;, V_STRING) Then GoTo Finally
  1035. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True) Then GoTo Finally
  1036. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  1037. If Not ScriptForge.SF_Utils._Validate(ColumnHeader, &quot;ColumnHeader&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  1038. If Not ScriptForge.SF_Utils._Validate(RowHeader, &quot;RowHeader&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  1039. End If
  1040. vCharts = Charts(SheetName)
  1041. If ScriptForge.SF_Array.Contains(vCharts, ChartName, CaseSensitive := True) Then GoTo CatchDuplicate
  1042. Try:
  1043. &apos; The rectangular shape receives arbitrary values. User can Resize() it later
  1044. With oRectangle
  1045. .X = 0 : .Y = 0
  1046. .Width = 8000 : .Height = 6000
  1047. End With
  1048. &apos; Initialize sheet and range
  1049. Set oSheet = _Component.getSheets.getByName(SheetName)
  1050. Set oRange = _ParseAddress(Range)
  1051. &apos; Create the chart and get ihe corresponding chart instance
  1052. oSheet.getCharts.addNewByName(ChartName, oRectangle, Array(oRange.XCellRange.RangeAddress), ColumnHeader, RowHeader)
  1053. Set oChart = Charts(SheetName, ChartName)
  1054. oChart._Shape.Name = ChartName &apos; Both user-defined and internal names match ChartName
  1055. oChart._Diagram.Wall.FillColor = RGB(255, 255, 255) &apos; Align on background color set by the user interface by default
  1056. Finally:
  1057. Set CreateChart = oChart
  1058. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1059. Exit Function
  1060. Catch:
  1061. GoTo Finally
  1062. CatchDuplicate:
  1063. ScriptForge.SF_Exception.RaiseFatal(DUPLICATECHARTERROR, &quot;ChartName&quot;, ChartName, &quot;SheetName&quot;, SheetName, &quot;Document&quot;, [_Super]._FileIdent())
  1064. GoTo Finally
  1065. End Function &apos; SFDocuments.SF_Calc.CreateChart
  1066. REM -----------------------------------------------------------------------------
  1067. Public Function CreatePivotTable(Optional ByVal PivotTableName As Variant _
  1068. , Optional ByVal SourceRange As Variant _
  1069. , Optional ByVal TargetCell As Variant _
  1070. , Optional ByRef DataFields As Variant _
  1071. , Optional ByRef RowFields As Variant _
  1072. , Optional ByRef ColumnFields As Variant _
  1073. , Optional ByVal FilterButton As Variant _
  1074. , Optional ByVal RowTotals As Variant _
  1075. , Optional ByVal ColumnTotals As Variant _
  1076. ) As String
  1077. &apos;&apos;&apos; Create a new pivot table with the properties defined by the arguments.
  1078. &apos;&apos;&apos; If a pivot table with the same name exists already in the targeted sheet, it will be erased without warning.
  1079. &apos;&apos;&apos; Args:
  1080. &apos;&apos;&apos; PivotTableName: The user-defined name of the new pivottable
  1081. &apos;&apos;&apos; SourceRange: The range as a string containing the raw data.
  1082. &apos;&apos;&apos; The first row of the range is presumed to contain the field names of the new pivot table
  1083. &apos;&apos;&apos; TargetCell: the top left cell or the range as a string where to locate the pivot table.
  1084. &apos;&apos;&apos; Only the top left cell of the range will be considered.
  1085. &apos;&apos;&apos; DataFields: A single string or an array of field name + function to apply, formatted like:
  1086. &apos;&apos;&apos; Array(&quot;FieldName[;Function]&quot;, ...)
  1087. &apos;&apos;&apos; The allowed functions are: Sum, Count, Average, Max, Min, Product, CountNums, StDev, StDevP, Var, VarP and Median.
  1088. &apos;&apos;&apos; The default function is: When the values are all numerical, Sum is used, otherwise Count
  1089. &apos;&apos;&apos; RowFields: A single string or an array of the field names heading the pivot table rows
  1090. &apos;&apos;&apos; ColumnFields: A single string or an array of the field names heading the pivot table columns
  1091. &apos;&apos;&apos; FilterButton: When True (default), display a &quot;Filter&quot; button above the pivot table
  1092. &apos;&apos;&apos; RowTotals: When True (default), display a separate column for row totals
  1093. &apos;&apos;&apos; ColumnTotals: When True (default), display a separate row for column totals
  1094. &apos;&apos;&apos; Returns:
  1095. &apos;&apos;&apos; Return the range where the new pivot table is deployed.
  1096. &apos;&apos;&apos; Examples:
  1097. &apos;&apos;&apos; Dim vData As Variant, oDoc As Object, sTable As String, sPivot As String
  1098. &apos;&apos;&apos; vData = Array(Array(&quot;Item&quot;, &quot;State&quot;, &quot;Team&quot;, &quot;2002&quot;, &quot;2003&quot;, &quot;2004&quot;), _
  1099. &apos;&apos;&apos; Array(&quot;Books&quot;, &quot;Michigan&quot;, &quot;Jean&quot;, 14788, 30222, 23490), _
  1100. &apos;&apos;&apos; Array(&quot;Candy&quot;, &quot;Michigan&quot;, &quot;Jean&quot;, 26388, 15641, 32849), _
  1101. &apos;&apos;&apos; Array(&quot;Pens&quot;, &quot;Michigan&quot;, &quot;Jean&quot;, 16569, 32675, 25396), _
  1102. &apos;&apos;&apos; Array(&quot;Books&quot;, &quot;Michigan&quot;, &quot;Volker&quot;, 21961, 21242, 29009), _
  1103. &apos;&apos;&apos; Array(&quot;Candy&quot;, &quot;Michigan&quot;, &quot;Volker&quot;, 26142, 22407, 32841))
  1104. &apos;&apos;&apos; Set oDoc = ui.CreateDocument(&quot;Calc&quot;)
  1105. &apos;&apos;&apos; sTable = oDoc.SetArray(&quot;A1&quot;, vData)
  1106. &apos;&apos;&apos; sPivot = oDoc.CreatePivotTable(&quot;PT1&quot;, sTable, &quot;H1&quot;, Array(&quot;2002&quot;, &quot;2003;count&quot;, &quot;2004;average&quot;), &quot;Item&quot;, Array(&quot;State&quot;, &quot;Team&quot;), False)
  1107. Dim sPivotTable As String &apos; Return value
  1108. Dim vData As Variant &apos; Alias of DataFields
  1109. Dim vRows As Variant &apos; Alias of RowFields
  1110. Dim vColumns As Variant &apos; Alias of ColumnFields
  1111. Dim oSourceAddress As Object &apos; Source as an _Address
  1112. Dim oTargetAddress As Object &apos; Target as an _Address
  1113. Dim vHeaders As Variant &apos; Array of header fields in the source range
  1114. Dim oPivotTables As Object &apos; com.sun.star.sheet.XDataPilotTables
  1115. Dim oDescriptor As Object &apos; com.sun.star.sheet.DataPilotDescriptor
  1116. Dim oFields As Object &apos; ScDataPilotFieldsObj - Collection of fields
  1117. Dim oField As Object &apos; ScDataPilotFieldsObj - A single field
  1118. Dim sField As String &apos; A single field name
  1119. Dim sData As String &apos; A single data field name + function
  1120. Dim vDataField As Variant &apos; A single vData element, split on semicolon
  1121. Dim sFunction As String &apos; Function to apply on a data field (string)
  1122. Dim iFunction As Integer &apos; Equivalent of sFunction as com.sun.star.sheet.GeneralFunction2 constant
  1123. Dim oOutputRange As Object &apos; com.sun.star.table.CellRangeAddress
  1124. Dim i As Integer
  1125. Const cstThisSub = &quot;SFDocuments.Calc.CreatePivotTable&quot;
  1126. Const cstSubArgs = &quot;PivotTableName, SourceRange, TargetCell, DataFields, [RowFields], [ColumnFields]&quot; _
  1127. &amp; &quot;, [FilterButton=True], [RowTotals=True], [ColumnTotals=True]&quot;
  1128. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1129. sPivotTable = &quot;&quot;
  1130. Check:
  1131. If IsMissing(RowFields) Or IsEmpty(RowFields) Then RowFields = Array()
  1132. If IsMissing(ColumnFields) Or IsEmpty(ColumnFields) Then ColumnFields = Array()
  1133. If IsMissing(FilterButton) Or IsEmpty(FilterButton) Then FilterButton = True
  1134. If IsMissing(RowTotals) Or IsEmpty(RowTotals) Then RowTotals = True
  1135. If IsMissing(ColumnTotals) Or IsEmpty(ColumnTotals) Then ColumnTotals = True
  1136. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1137. If Not _IsStillAlive(True) Then GoTo Finally
  1138. If Not ScriptForge.SF_Utils._Validate(PivotTableName, &quot;PivotTableName&quot;, V_STRING) Then GoTo Finally
  1139. If Not ScriptForge.SF_Utils._Validate(SourceRange, &quot;SourceRange&quot;, V_STRING) Then GoTo Finally
  1140. If Not ScriptForge.SF_Utils._Validate(TargetCell, &quot;TargetCell&quot;, V_STRING) Then GoTo Finally
  1141. If IsArray(DataFields) Then
  1142. If Not ScriptForge.SF_Utils._ValidateArray(DataFields, &quot;DataFields&quot;, 1, V_STRING, True) Then GoTo Finally
  1143. Else
  1144. If Not ScriptForge.SF_Utils._Validate(DataFields, &quot;DataFields&quot;, V_STRING) Then GoTo Finally
  1145. End If
  1146. If IsArray(RowFields) Then
  1147. If Not ScriptForge.SF_Utils._ValidateArray(RowFields, &quot;RowFields&quot;, 1, V_STRING, True) Then GoTo Finally
  1148. Else
  1149. If Not ScriptForge.SF_Utils._Validate(RowFields, &quot;RowFields&quot;, V_STRING) Then GoTo Finally
  1150. End If
  1151. If IsArray(ColumnFields) Then
  1152. If Not ScriptForge.SF_Utils._ValidateArray(ColumnFields, &quot;ColumnFields&quot;, 1, V_STRING, True) Then GoTo Finally
  1153. Else
  1154. If Not ScriptForge.SF_Utils._Validate(ColumnFields, &quot;ColumnFields&quot;, V_STRING) Then GoTo Finally
  1155. End If
  1156. If Not ScriptForge.SF_Utils._Validate(FilterButton, &quot;FilterButton&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  1157. If Not ScriptForge.SF_Utils._Validate(RowTotals, &quot;RowTotals&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  1158. If Not ScriptForge.SF_Utils._Validate(ColumnTotals, &quot;ColumnTotals&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  1159. End If
  1160. &apos; Next statements must be outside previous If-block to force their execution even in case of internal call
  1161. If IsArray(DataFields) Then vData = DataFields Else vData = Array(DataFields)
  1162. If IsArray(RowFields) Then vRows = RowFields Else vRows = Array(RowFields)
  1163. If IsArray(ColumnFields) Then vColumns = ColumnFields Else vColumns = Array(ColumnFields)
  1164. Try:
  1165. Set oSourceAddress = _ParseAddress(SourceRange)
  1166. vHeaders = GetValue(Offset(SourceRange, 0, 0, 1)) &apos; Content of the first row of the source
  1167. Set oTargetAddress = _Offset(TargetCell, 0, 0, 1, 1) &apos; Retain the top left cell only
  1168. Set oPivotTables = oTargetAddress.XSpreadsheet.getDataPilotTables()
  1169. &apos; Initialize new pivot table
  1170. Set oDescriptor = oPivotTables.createDataPilotDescriptor()
  1171. oDescriptor.setSourceRange(oSourceAddress.XCellRange.RangeAddress)
  1172. Set oFields = oDescriptor.getDataPilotFields()
  1173. &apos; Set row fields
  1174. For i = 0 To UBound(vRows)
  1175. sField = vRows(i)
  1176. If Len(sField) &gt; 0 Then
  1177. If Not ScriptForge.SF_Utils._Validate(sField, &quot;RowFields&quot;, V_STRING, vHeaders) Then GoTo Finally
  1178. Set oField = oFields.getByName(sField)
  1179. oField.Orientation = com.sun.star.sheet.DataPilotFieldOrientation.ROW
  1180. End If
  1181. Next i
  1182. &apos; Set column fields
  1183. For i = 0 To UBound(vColumns)
  1184. sField = vColumns(i)
  1185. If Len(sField) &gt; 0 Then
  1186. If Not ScriptForge.SF_Utils._Validate(sField, &quot;ColumnFields&quot;, V_STRING, vHeaders) Then GoTo Finally
  1187. Set oField = oFields.getByName(sField)
  1188. oField.Orientation = com.sun.star.sheet.DataPilotFieldOrientation.COLUMN
  1189. End If
  1190. Next i
  1191. &apos; Set data fields
  1192. For i = 0 To UBound(vData)
  1193. sData = vData(i)
  1194. &apos; Minimal parsing
  1195. If Right(sData, 1) = &quot;;&quot; Then sData = Left(sData, Len(sData) - 1)
  1196. vDataField = Split(sData, &quot;;&quot;)
  1197. sField = vDataField(0)
  1198. If UBound(vDataField) &gt; 0 Then sFunction = vDataField(1) Else sFunction = &quot;&quot;
  1199. &apos; Define field properties
  1200. If Len(sField) &gt; 0 Then
  1201. If Not ScriptForge.SF_Utils._Validate(sField, &quot;DataFields&quot;, V_STRING, vHeaders) Then GoTo Finally
  1202. Set oField = oFields.getByName(sField)
  1203. oField.Orientation = com.sun.star.sheet.DataPilotFieldOrientation.DATA
  1204. &apos; Associate the correct function
  1205. With com.sun.star.sheet.GeneralFunction2
  1206. Select Case UCase(sFunction)
  1207. Case &quot;&quot; : iFunction = .AUTO
  1208. Case &quot;SUM&quot; : iFunction = .SUM
  1209. Case &quot;COUNT&quot; : iFunction = .COUNT
  1210. Case &quot;AVERAGE&quot; : iFunction = .AVERAGE
  1211. Case &quot;MAX&quot; : iFunction = .MAX
  1212. Case &quot;MIN&quot; : iFunction = .MIN
  1213. Case &quot;PRODUCT&quot; : iFunction = .PRODUCT
  1214. Case &quot;COUNTNUMS&quot;: iFunction = .COUNTNUMS
  1215. Case &quot;STDEV&quot; : iFunction = .STDEV
  1216. Case &quot;STDEVP&quot; : iFunction = .STDEVP
  1217. Case &quot;VAR&quot; : iFunction = .VAR
  1218. Case &quot;VARP&quot; : iFunction = .VARP
  1219. Case &quot;MEDIAN&quot; : iFunction = .MEDIAN
  1220. Case Else
  1221. If Not ScriptForge.SF_Utils._Validate(sFunction, &quot;DataFields/Function&quot;, V_STRING _
  1222. , Array(&quot;Sum&quot;, &quot;Count&quot;, &quot;Average&quot;, &quot;Max&quot;, &quot;Min&quot;, &quot;Product&quot;, &quot;CountNums&quot; _
  1223. , &quot;StDev&quot;, &quot;StDevP&quot;, &quot;Var&quot;, &quot;VarP&quot;, &quot;Median&quot;) _
  1224. ) Then GoTo Finally
  1225. End Select
  1226. End With
  1227. oField.Function2 = iFunction
  1228. End If
  1229. Next i
  1230. &apos; Remove any pivot table with same name
  1231. If oPivotTables.hasByName(PivotTableName) Then oPivotTables.removeByName(PivotTableName)
  1232. &apos; Finalize the new pivot table
  1233. oDescriptor.ShowFilterButton = FilterButton
  1234. oDescriptor.RowGrand = RowTotals
  1235. oDescriptor.ColumnGrand = ColumnTotals
  1236. oPivotTables.insertNewByName(PivotTableName, oTargetAddress.XCellRange.getCellByPosition(0, 0).CellAddress, oDescriptor)
  1237. &apos; Determine the range of the new pivot table
  1238. Set oOutputRange = oPivotTables.getByName(PivotTableName).OutputRange
  1239. With oOutputRange
  1240. sPivotTable = _Component.getSheets().getCellRangeByPosition(.StartColumn, .StartRow, .EndColumn, .EndRow, .Sheet).AbsoluteName
  1241. End With
  1242. Finally:
  1243. CreatePivotTable = sPivotTable
  1244. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1245. Exit Function
  1246. Catch:
  1247. GoTo Finally
  1248. End Function &apos; SFDocuments.SF_Calc.CreatePivotTable
  1249. REM -----------------------------------------------------------------------------
  1250. Public Function DAvg(Optional ByVal Range As Variant) As Double
  1251. &apos;&apos;&apos; Get the average of the numeric values stored in the given range
  1252. &apos;&apos;&apos; Args:
  1253. &apos;&apos;&apos; Range : the range as a string where to get the values from
  1254. &apos;&apos;&apos; Returns:
  1255. &apos;&apos;&apos; The average of the numeric values as a double
  1256. &apos;&apos;&apos; Examples:
  1257. &apos;&apos;&apos; Val = oDoc.DAvg(&quot;~.A1:A1000&quot;)
  1258. Try:
  1259. DAvg = _DFunction(&quot;DAvg&quot;, Range)
  1260. Finally:
  1261. Exit Function
  1262. End Function &apos; SFDocuments.SF_Calc.DAvg
  1263. REM -----------------------------------------------------------------------------
  1264. Public Function DCount(Optional ByVal Range As Variant) As Long
  1265. &apos;&apos;&apos; Get the number of numeric values stored in the given range
  1266. &apos;&apos;&apos; Args:
  1267. &apos;&apos;&apos; Range : the range as a string where to get the values from
  1268. &apos;&apos;&apos; Returns:
  1269. &apos;&apos;&apos; The number of numeric values as a Long
  1270. &apos;&apos;&apos; Examples:
  1271. &apos;&apos;&apos; Val = oDoc.DCount(&quot;~.A1:A1000&quot;)
  1272. Try:
  1273. DCount = _DFunction(&quot;DCount&quot;, Range)
  1274. Finally:
  1275. Exit Function
  1276. End Function &apos; SFDocuments.SF_Calc.DCount
  1277. REM -----------------------------------------------------------------------------
  1278. Public Function DMax(Optional ByVal Range As Variant) As Double
  1279. &apos;&apos;&apos; Get the greatest of the numeric values stored in the given range
  1280. &apos;&apos;&apos; Args:
  1281. &apos;&apos;&apos; Range : the range as a string where to get the values from
  1282. &apos;&apos;&apos; Returns:
  1283. &apos;&apos;&apos; The greatest of the numeric values as a double
  1284. &apos;&apos;&apos; Examples:
  1285. &apos;&apos;&apos; Val = oDoc.DMax(&quot;~.A1:A1000&quot;)
  1286. Try:
  1287. DMax = _DFunction(&quot;DMax&quot;, Range)
  1288. Finally:
  1289. Exit Function
  1290. End Function &apos; SFDocuments.SF_Calc.DMax
  1291. REM -----------------------------------------------------------------------------
  1292. Public Function DMin(Optional ByVal Range As Variant) As Double
  1293. &apos;&apos;&apos; Get the smallest of the numeric values stored in the given range
  1294. &apos;&apos;&apos; Args:
  1295. &apos;&apos;&apos; Range : the range as a string where to get the values from
  1296. &apos;&apos;&apos; Returns:
  1297. &apos;&apos;&apos; The smallest of the numeric values as a double
  1298. &apos;&apos;&apos; Examples:
  1299. &apos;&apos;&apos; Val = oDoc.DMin(&quot;~.A1:A1000&quot;)
  1300. Try:
  1301. DMin = _DFunction(&quot;DMin&quot;, Range)
  1302. Finally:
  1303. Exit Function
  1304. End Function &apos; SFDocuments.SF_Calc.DMin
  1305. REM -----------------------------------------------------------------------------
  1306. Public Function DSum(Optional ByVal Range As Variant) As Double
  1307. &apos;&apos;&apos; Get sum of the numeric values stored in the given range
  1308. &apos;&apos;&apos; Args:
  1309. &apos;&apos;&apos; Range : the range as a string where to get the values from
  1310. &apos;&apos;&apos; Returns:
  1311. &apos;&apos;&apos; The sum of the numeric values as a double
  1312. &apos;&apos;&apos; Examples:
  1313. &apos;&apos;&apos; Val = oDoc.DSum(&quot;~.A1:A1000&quot;)
  1314. Try:
  1315. DSum = _DFunction(&quot;DSum&quot;, Range)
  1316. Finally:
  1317. Exit Function
  1318. End Function &apos; SFDocuments.SF_Calc.DSum
  1319. REM -----------------------------------------------------------------------------
  1320. Public Function ExportRangeToFile(Optional ByVal Range As Variant _
  1321. , Optional ByVal FileName As Variant _
  1322. , Optional ByVal ImageType As Variant _
  1323. , Optional ByVal Overwrite As Variant _
  1324. ) As Boolean
  1325. &apos;&apos;&apos; Store the given range as an image to the given file location
  1326. &apos;&apos;&apos; Actual selections are not impacted
  1327. &apos;&apos;&apos; Inspired by https://stackoverflow.com/questions/30509532/how-to-export-cell-range-to-pdf-file
  1328. &apos;&apos;&apos; Args:
  1329. &apos;&apos;&apos; Range: sheet name or cell range to be exported, as a string
  1330. &apos;&apos;&apos; FileName: Identifies the file where to save. It must follow the SF_FileSystem.FileNaming notation
  1331. &apos;&apos;&apos; ImageType: the name of the targeted media type
  1332. &apos;&apos;&apos; Allowed values: jpeg, pdf (default) and png
  1333. &apos;&apos;&apos; Overwrite: True if the destination file may be overwritten (default = False)
  1334. &apos;&apos;&apos; Returns:
  1335. &apos;&apos;&apos; False if the document could not be saved
  1336. &apos;&apos;&apos; Exceptions:
  1337. &apos;&apos;&apos; RANGEEXPORTERROR The destination has its readonly attribute set or overwriting rejected
  1338. &apos;&apos;&apos; Examples:
  1339. &apos;&apos;&apos; oDoc.ExportRangeToFile(&apos;SheetX.B2:J15&quot;, &quot;C:\Me\Range2.png&quot;, ImageType := &quot;png&quot;, Overwrite := True)
  1340. Dim bSaved As Boolean &apos; return value
  1341. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  1342. Dim sFile As String &apos; Alias of FileName
  1343. Dim vStoreArguments As Variant &apos; Array of com.sun.star.beans.PropertyValue
  1344. Dim vFilterData As Variant &apos; Array of com.sun.star.beans.PropertyValue
  1345. Dim FSO As Object &apos; SF_FileSystem
  1346. Dim vImageTypes As Variant &apos; Array of permitted image types
  1347. Dim vFilters As Variant &apos; Array of corresponding filters in the same order as vImageTypes
  1348. Dim sFilter As String &apos; The filter to apply
  1349. Dim oSelect As Object &apos; Currently selected range(s)
  1350. Dim oAddress As Object &apos; Alias of Range
  1351. Const cstImageTypes = &quot;jpeg,pdf,png&quot;
  1352. Const cstFilters = &quot;calc_jpg_Export,calc_pdf_Export,calc_png_Export&quot;
  1353. Const cstThisSub = &quot;SFDocuments.Calc.ExportRangeToFile&quot;
  1354. Const cstSubArgs = &quot;Range, FileName, [ImageType=&quot;&quot;pdf&quot;&quot;|&quot;&quot;jpeg&quot;&quot;|&quot;&quot;png&quot;&quot;], [Overwrite=False]&quot;
  1355. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo CatchError
  1356. bSaved = False
  1357. Check:
  1358. If IsMissing(ImageType) Or IsEmpty(ImageType) Then ImageType = &quot;pdf&quot;
  1359. If IsMissing(Overwrite) Or IsEmpty(Overwrite) Then Overwrite = False
  1360. vImageTypes = Split(cstImageTypes, &quot;,&quot;)
  1361. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1362. If Not _IsStillAlive() Then GoTo Finally
  1363. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  1364. If Not ScriptForge.SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  1365. If Not ScriptForge.SF_Utils._Validate(ImageType, &quot;ImageType&quot;, V_STRING, vImageTypes) Then GoTo Finally
  1366. If Not ScriptForge.SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  1367. End If
  1368. &apos; Check destination file overwriting
  1369. Set FSO = CreateScriptService(&quot;FileSystem&quot;)
  1370. sFile = FSO._ConvertToUrl(FileName)
  1371. If FSO.FileExists(FileName) Then
  1372. If Overwrite = False Then GoTo CatchError
  1373. Set oSfa = ScriptForge.SF_Utils._GetUNOService(&quot;FileAccess&quot;)
  1374. If oSfa.isReadonly(sFile) Then GoTo CatchError
  1375. End If
  1376. Try:
  1377. &apos; Setup arguments
  1378. vFilters = Split(cstFilters, &quot;,&quot;)
  1379. sFilter = vFilters(ScriptForge.SF_Array.IndexOf(vImageTypes, ImageType, CaseSensitive := False))
  1380. Set oAddress = _ParseAddress(Range)
  1381. &apos; The filter arguments differ between
  1382. &apos; 1) pdf : store range in Selection property value
  1383. &apos; 2) png, jpeg : save current selection, select range, restore initial selection
  1384. If LCase(ImageType) = &quot;pdf&quot; Then
  1385. vFilterData = Array(ScriptForge.SF_Utils._MakePropertyValue(&quot;Selection&quot;, oAddress.XCellRange) )
  1386. vStoreArguments = Array( _
  1387. ScriptForge.SF_Utils._MakePropertyValue(&quot;FilterName&quot;, sFilter) _
  1388. , ScriptForge.SF_Utils._MakePropertyValue(&quot;FilterData&quot;, vFilterData) _
  1389. )
  1390. Else &apos; png, jpeg
  1391. &apos; Save the current selection(s)
  1392. Set oSelect = _Component.CurrentController.getSelection()
  1393. _Component.CurrentController.select(oAddress.XCellRange)
  1394. vStoreArguments = Array( _
  1395. ScriptForge.SF_Utils._MakePropertyValue(&quot;FilterName&quot;, sFilter) _
  1396. , ScriptForge.SF_Utils._MakePropertyValue(&quot;SelectionOnly&quot;, True) _
  1397. )
  1398. End If
  1399. &apos; Apply the filter and export
  1400. _Component.storeToUrl(sFile, vStoreArguments)
  1401. If LCase(ImageType) &lt;&gt; &quot;pdf&quot; Then _RestoreSelections(_Component, oSelect)
  1402. bSaved = True
  1403. Finally:
  1404. ExportRangeToFile = bSaved
  1405. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1406. Exit Function
  1407. Catch:
  1408. GoTo Finally
  1409. CatchError:
  1410. ScriptForge.SF_Exception.RaiseFatal(RANGEEXPORTERROR, &quot;FileName&quot;, FileName, &quot;Overwrite&quot;, Overwrite)
  1411. GoTo Finally
  1412. End Function &apos; SFDocuments.SF_Chart.ExportRangeToFile
  1413. REM -----------------------------------------------------------------------------
  1414. Public Function Forms(Optional ByVal SheetName As Variant _
  1415. , Optional ByVal Form As Variant _
  1416. ) As Variant
  1417. &apos;&apos;&apos; Return either
  1418. &apos;&apos;&apos; - the list of the Forms contained in the given sheet
  1419. &apos;&apos;&apos; - a SFDocuments.Form object based on its name or its index
  1420. &apos;&apos;&apos; Args:
  1421. &apos;&apos;&apos; SheetName: the name of the sheet containing the requested form or forms
  1422. &apos;&apos;&apos; Form: a form stored in the document given by its name or its index
  1423. &apos;&apos;&apos; When absent, the list of available forms is returned
  1424. &apos;&apos;&apos; To get the first (unique ?) form stored in the form document, set Form = 0
  1425. &apos;&apos;&apos; Exceptions:
  1426. &apos;&apos;&apos; CALCFORMNOTFOUNDERROR Form not found
  1427. &apos;&apos;&apos; Returns:
  1428. &apos;&apos;&apos; A zero-based array of strings if Form is absent
  1429. &apos;&apos;&apos; An instance of the SF_Form class if Form exists
  1430. &apos;&apos;&apos; Example:
  1431. &apos;&apos;&apos; Dim myForm As Object, myList As Variant
  1432. &apos;&apos;&apos; myList = oDoc.Forms(&quot;ThisSheet&quot;)
  1433. &apos;&apos;&apos; Set myForm = oDoc.Forms(&quot;ThisSheet&quot;, 0)
  1434. Dim oForm As Object &apos; The new Form class instance
  1435. Dim oMainForm As Object &apos; com.sun.star.comp.sdb.Content
  1436. Dim oXForm As Object &apos; com.sun.star.form.XForm or com.sun.star.comp.forms.ODatabaseForm
  1437. Dim vFormNames As Variant &apos; Array of form names
  1438. Dim oForms As Object &apos; Forms collection
  1439. Const cstDrawPage = -1 &apos; There is no DrawPages collection in Calc sheets
  1440. Const cstThisSub = &quot;SFDocuments.Calc.Forms&quot;
  1441. Const cstSubArgs = &quot;SheetName, [Form=&quot;&quot;&quot;&quot;]&quot;
  1442. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1443. Check:
  1444. If IsMissing(Form) Or IsEmpty(Form) Then Form = &quot;&quot;
  1445. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1446. If Not _IsStillAlive() Then GoTo Finally
  1447. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True) Then GoTo Finally
  1448. If Not ScriptForge.SF_Utils._Validate(Form, &quot;Form&quot;, Array(V_STRING, ScriptForge.V_NUMERIC)) Then GoTo Finally
  1449. End If
  1450. Try:
  1451. &apos; Start from the Calc sheet and go down to forms
  1452. Set oForms = _Component.getSheets.getByName(SheetName).DrawPage.Forms
  1453. vFormNames = oForms.getElementNames()
  1454. If Len(Form) = 0 Then &apos; Return the list of valid form names
  1455. Forms = vFormNames
  1456. Else
  1457. If VarType(Form) = V_STRING Then &apos; Find the form by name
  1458. If Not ScriptForge.SF_Utils._Validate(Form, &quot;Form&quot;, V_STRING, vFormNames) Then GoTo Finally
  1459. Set oXForm = oForms.getByName(Form)
  1460. Else &apos; Find the form by index
  1461. If Form &lt; 0 Or Form &gt;= oForms.Count Then GoTo CatchNotFound
  1462. Set oXForm = oForms.getByIndex(Form)
  1463. End If
  1464. &apos; Create the new Form class instance
  1465. Set oForm = SF_Register._NewForm(oXForm)
  1466. With oForm
  1467. Set .[_Parent] = [Me]
  1468. ._SheetName = SheetName
  1469. ._FormType = ISCALCFORM
  1470. Set ._Component = _Component
  1471. ._Initialize()
  1472. End With
  1473. Set Forms = oForm
  1474. End If
  1475. Finally:
  1476. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1477. Exit Function
  1478. Catch:
  1479. GoTo Finally
  1480. CatchNotFound:
  1481. ScriptForge.SF_Exception.RaiseFatal(CALCFORMNOTFOUNDERROR, Form, _FileIdent())
  1482. End Function &apos; SFDocuments.SF_Calc.Forms
  1483. REM -----------------------------------------------------------------------------
  1484. Function GetColumnName(Optional ByVal ColumnNumber As Variant) As String
  1485. &apos;&apos;&apos; Convert a column number (range 1, 2,..1024) into its letter counterpart (range &apos;A&apos;, &apos;B&apos;,..&apos;AMJ&apos;).
  1486. &apos;&apos;&apos; Args:
  1487. &apos;&apos;&apos; ColumnNumber: the column number, must be in the interval 1 ... 1024
  1488. &apos;&apos;&apos; Returns:
  1489. &apos;&apos;&apos; a string representation of the column name, in range &apos;A&apos;..&apos;AMJ&apos;
  1490. &apos;&apos;&apos; If ColumnNumber is not in the allowed range, returns a zero-length string
  1491. &apos;&apos;&apos; Example:
  1492. &apos;&apos;&apos; MsgBox oDoc.GetColumnName(1022) &apos; &quot;AMH&quot;
  1493. &apos;&apos;&apos; Adapted from a Python function by sundar nataraj
  1494. &apos;&apos;&apos; http://stackoverflow.com/questions/23861680/convert-spreadsheet-number-to-column-letter
  1495. Dim sCol As String &apos; Return value
  1496. Const cstThisSub = &quot;SFDocuments.Calc.GetColumnName&quot;
  1497. Const cstSubArgs = &quot;ColumnNumber&quot;
  1498. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1499. sCol = &quot;&quot;
  1500. Check:
  1501. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1502. If Not SF_Utils._Validate(ColumnNumber, &quot;ColumnNumber&quot;, V_NUMERIC) Then GoTo Finally
  1503. End If
  1504. Try:
  1505. If (ColumnNumber &gt; 0) And (ColumnNumber &lt;= MAXCOLS) Then sCol = _GetColumnName(ColumnNumber)
  1506. Finally:
  1507. GetColumnName = sCol
  1508. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1509. Exit Function
  1510. Catch:
  1511. GoTo Finally
  1512. End Function &apos; SFDocuments.SF_Calc.GetColumnName
  1513. REM -----------------------------------------------------------------------------
  1514. Public Function GetFormula(Optional ByVal Range As Variant) As Variant
  1515. &apos;&apos;&apos; Get the formula(e) stored in the given range of cells
  1516. &apos;&apos;&apos; Args:
  1517. &apos;&apos;&apos; Range : the range as a string where to get the formula from
  1518. &apos;&apos;&apos; Returns:
  1519. &apos;&apos;&apos; A scalar, a zero-based 1D array or a zero-based 2D array of strings
  1520. &apos;&apos;&apos; Examples:
  1521. &apos;&apos;&apos; Val = oDoc.GetFormula(&quot;~.A1:A1000&quot;)
  1522. Dim vGet As Variant &apos; Return value
  1523. Dim oAddress As Object &apos; Alias of Range
  1524. Dim vDataArray As Variant &apos; DataArray compatible with .DataArray UNO property
  1525. Const cstThisSub = &quot;SFDocuments.Calc.GetFormula&quot;
  1526. Const cstSubArgs = &quot;Range&quot;
  1527. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1528. vGet = Empty
  1529. Check:
  1530. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1531. If Not _IsStillAlive() Then GoTo Finally
  1532. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  1533. End If
  1534. Try:
  1535. &apos; Get the data
  1536. Set oAddress = _ParseAddress(Range)
  1537. vDataArray = oAddress.XCellRange.getFormulaArray()
  1538. &apos; Convert the data array to scalar, vector or array
  1539. vGet = _ConvertFromDataArray(vDataArray)
  1540. Finally:
  1541. GetFormula = vGet
  1542. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1543. Exit Function
  1544. Catch:
  1545. GoTo Finally
  1546. End Function &apos; SFDocuments.SF_Calc.GetFormula
  1547. REM -----------------------------------------------------------------------------
  1548. Public Function GetProperty(Optional ByVal PropertyName As Variant _
  1549. , Optional ObjectName As Variant _
  1550. ) As Variant
  1551. &apos;&apos;&apos; Return the actual value of the given property
  1552. &apos;&apos;&apos; Args:
  1553. &apos;&apos;&apos; PropertyName: the name of the property as a string
  1554. &apos;&apos;&apos; ObjectName: a sheet or range name
  1555. &apos;&apos;&apos; Returns:
  1556. &apos;&apos;&apos; The actual value of the property
  1557. &apos;&apos;&apos; Exceptions:
  1558. &apos;&apos;&apos; ARGUMENTERROR The property does not exist
  1559. Const cstThisSub = &quot;SFDocuments.Calc.GetProperty&quot;
  1560. Const cstSubArgs = &quot;&quot;
  1561. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1562. GetProperty = Null
  1563. Check:
  1564. If IsMissing(ObjectName) Or IsEMpty(ObjectName) Then ObjectName = &quot;&quot;
  1565. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1566. If Not ScriptForge.SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
  1567. If Not ScriptForge.SF_Utils._Validate(ObjectName, &quot;ObjectName&quot;, V_STRING) Then GoTo Catch
  1568. End If
  1569. Try:
  1570. &apos; Superclass or subclass property ?
  1571. If ScriptForge.SF_Array.Contains([_Super].Properties(), PropertyName) Then
  1572. GetProperty = [_Super].GetProperty(PropertyName)
  1573. ElseIf Len(ObjectName) = 0 Then
  1574. GetProperty = _PropertyGet(PropertyName)
  1575. Else
  1576. GetProperty = _PropertyGet(PropertyName, ObjectName)
  1577. End If
  1578. Finally:
  1579. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1580. Exit Function
  1581. Catch:
  1582. GoTo Finally
  1583. End Function &apos; SFDocuments.SF_Calc.GetProperty
  1584. REM -----------------------------------------------------------------------------
  1585. Public Function GetValue(Optional ByVal Range As Variant) As Variant
  1586. &apos;&apos;&apos; Get the value(s) stored in the given range of cells
  1587. &apos;&apos;&apos; Args:
  1588. &apos;&apos;&apos; Range : the range as a string where to get the value from
  1589. &apos;&apos;&apos; Returns:
  1590. &apos;&apos;&apos; A scalar, a zero-based 1D array or a zero-based 2D array of strings and doubles
  1591. &apos;&apos;&apos; To convert doubles to dates, use the CDate builtin function
  1592. &apos;&apos;&apos; Examples:
  1593. &apos;&apos;&apos; Val = oDoc.GetValue(&quot;~.A1:A1000&quot;)
  1594. Dim vGet As Variant &apos; Return value
  1595. Dim oAddress As Object &apos; Alias of Range
  1596. Dim vDataArray As Variant &apos; DataArray compatible with .DataArray UNO property
  1597. Const cstThisSub = &quot;SFDocuments.Calc.GetValue&quot;
  1598. Const cstSubArgs = &quot;Range&quot;
  1599. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1600. vGet = Empty
  1601. Check:
  1602. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1603. If Not _IsStillAlive() Then GoTo Finally
  1604. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  1605. End If
  1606. Try:
  1607. &apos; Get the data
  1608. Set oAddress = _ParseAddress(Range)
  1609. vDataArray = oAddress.XCellRange.getDataArray()
  1610. &apos; Convert the data array to scalar, vector or array
  1611. vGet = _ConvertFromDataArray(vDataArray)
  1612. Finally:
  1613. GetValue = vGet
  1614. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1615. Exit Function
  1616. Catch:
  1617. GoTo Finally
  1618. End Function &apos; SFDocuments.SF_Calc.GetValue
  1619. REM -----------------------------------------------------------------------------
  1620. Public Function ImportFromCSVFile(Optional ByVal FileName As Variant _
  1621. , Optional ByVal DestinationCell As Variant _
  1622. , Optional ByVal FilterOptions As Variant _
  1623. ) As String
  1624. &apos;&apos;&apos; Import the content of a CSV-formatted text file starting from a given cell
  1625. &apos;&apos;&apos; Beforehand the destination area will be cleared from any content and format
  1626. &apos;&apos;&apos; Args:
  1627. &apos;&apos;&apos; FileName: Identifies the file to open. It must follow the SF_FileSystem.FileNaming notation
  1628. &apos;&apos;&apos; DestinationCell: the destination of the copied range of cells, as a string
  1629. &apos;&apos;&apos; If given as range, the destination will be reduced to its top-left cell
  1630. &apos;&apos;&apos; FilterOptions: The arguments of the CSV input filter.
  1631. &apos;&apos;&apos; Read https://wiki.documentfoundation.org/Documentation/DevGuide/Spreadsheet_Documents#Filter_Options_for_the_CSV_Filter
  1632. &apos;&apos;&apos; Default: input file encoding is UTF8
  1633. &apos;&apos;&apos; separator = comma, semi-colon or tabulation
  1634. &apos;&apos;&apos; string delimiter = double quote
  1635. &apos;&apos;&apos; all lines are included
  1636. &apos;&apos;&apos; quoted strings are formatted as texts
  1637. &apos;&apos;&apos; special numbers are detected
  1638. &apos;&apos;&apos; all columns are presumed texts
  1639. &apos;&apos;&apos; language = english/US =&gt; decimal separator is &quot;.&quot;, thousands separator = &quot;,&quot;
  1640. &apos;&apos;&apos; Returns:
  1641. &apos;&apos;&apos; A string representing the modified range of cells
  1642. &apos;&apos;&apos; The modified area depends only on the content of the source file
  1643. &apos;&apos;&apos; Exceptions:
  1644. &apos;&apos;&apos; DOCUMENTOPENERROR The csv file could not be opened
  1645. &apos;&apos;&apos; Examples:
  1646. &apos;&apos;&apos; oDoc.ImportFromCSVFile(&quot;C:\Temp\myCsvFile.csv&quot;, &quot;SheetY.C5&quot;)
  1647. Dim sImport As String &apos; Return value
  1648. Dim oUI As Object &apos; UI service
  1649. Dim oSource As Object &apos; New Calc document with csv loaded
  1650. Dim oSelect As Object &apos; Current selection in destination
  1651. Const cstFilter = &quot;Text - txt - csv (StarCalc)&quot;
  1652. Const cstFilterOptions = &quot;9/44/59/MRG,34,76,1,,1033,true,true&quot;
  1653. Const cstThisSub = &quot;SFDocuments.Calc.ImportFromCSVFile&quot;
  1654. Const cstSubArgs = &quot;FileName, DestinationCell, [FilterOptions]=&quot;&quot;9/44/59/MRG,34,76,1,,1033,true,true&quot;&quot;&quot;
  1655. &apos; If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1656. sImport = &quot;&quot;
  1657. Check:
  1658. If IsMissing(FilterOptions) Or IsEmpty(FilterOptions) Then FilterOptions = cstFilterOptions
  1659. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1660. If Not _IsStillAlive(True) Then GoTo Finally
  1661. If Not ScriptForge.SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  1662. If Not ScriptForge.SF_Utils._Validate(DestinationCell, &quot;DestinationCell&quot;, V_STRING) Then GoTo Finally
  1663. End If
  1664. Try:
  1665. &apos; Input file is loaded in an empty worksheet. Data are copied to destination cell
  1666. Set oUI = CreateScriptService(&quot;UI&quot;)
  1667. Set oSource = oUI.OpenDocument(FileName _
  1668. , ReadOnly := True _
  1669. , Hidden := True _
  1670. , FilterName := cstFilter _
  1671. , FilterOptions := FilterOptions _
  1672. )
  1673. &apos; Remember current selection and restore it after copy
  1674. Set oSelect = _Component.CurrentController.getSelection()
  1675. sImport = CopyToCell(oSource.Range(&quot;*&quot;), DestinationCell)
  1676. _RestoreSelections(_Component, oSelect)
  1677. Finally:
  1678. If Not IsNull(oSource) Then oSource.CloseDocument(False)
  1679. ImportFromCSVFile = sImport
  1680. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1681. Exit Function
  1682. Catch:
  1683. GoTo Finally
  1684. End Function &apos; SFDocuments.SF_Calc.ImportFromCSVFile
  1685. REM -----------------------------------------------------------------------------
  1686. Public Sub ImportFromDatabase(Optional ByVal FileName As Variant _
  1687. , Optional ByVal RegistrationName As Variant _
  1688. , Optional ByVal DestinationCell As Variant _
  1689. , Optional ByVal SQLCommand As Variant _
  1690. , Optional ByVal DirectSQL As Variant _
  1691. )
  1692. &apos;&apos;&apos; Import the content of a database table, query or resultset, i.e. the result of a SELECT SQL command,
  1693. &apos;&apos;&apos; starting from a given cell
  1694. &apos;&apos;&apos; Beforehand the destination area will be cleared from any content and format
  1695. &apos;&apos;&apos; The modified area depends only on the content of the source data
  1696. &apos;&apos;&apos; Args:
  1697. &apos;&apos;&apos; FileName: Identifies the file to open. It must follow the SF_FileSystem.FileNaming notation
  1698. &apos;&apos;&apos; RegistrationName: the name of a registered database
  1699. &apos;&apos;&apos; It is ignored if FileName &lt;&gt; &quot;&quot;
  1700. &apos;&apos;&apos; DestinationCell: the destination of the copied range of cells, as a string
  1701. &apos;&apos;&apos; If given as a range of cells, the destination will be reduced to its top-left cell
  1702. &apos;&apos;&apos; SQLCommand: either a table or query name (without square brackets)
  1703. &apos;&apos;&apos; or a full SQL commands where table and fieldnames are preferably surrounded with square brackets
  1704. &apos;&apos;&apos; Returns:
  1705. &apos;&apos;&apos; Implemented as a Sub because the doImport UNO method does not return any error
  1706. &apos;&apos;&apos; Exceptions:
  1707. &apos;&apos;&apos; BASEDOCUMENTOPENERROR The database file could not be opened
  1708. &apos;&apos;&apos; Examples:
  1709. &apos;&apos;&apos; oDoc.ImportFromDatabase(&quot;C:\Temp\myDbFile.odb&quot;, , &quot;SheetY.C5&quot;, &quot;SELECT * FROM [Employees] ORDER BY [LastName]&quot;)
  1710. Dim oDBContext As Object &apos; com.sun.star.sdb.DatabaseContext
  1711. Dim oDatabase As Object &apos; SFDatabases.Database service
  1712. Dim lCommandType As Long &apos; A com.sun.star.sheet.DataImportMode.xxx constant
  1713. Dim oQuery As Object &apos; com.sun.star.ucb.XContent
  1714. Dim bDirect As Boolean &apos; Alias of DirectSQL
  1715. Dim oDestRange As Object &apos; Destination as a range
  1716. Dim oDestAddress As Object &apos; com.sun.star.table.CellRangeAddress
  1717. Dim oDestCell As Object &apos; com.sun.star.table.XCell
  1718. Dim oSelect As Object &apos; Current selection in destination
  1719. Dim vImportOptions As Variant &apos; Array of PropertyValues
  1720. Const cstThisSub = &quot;SFDocuments.Calc.ImportFromDatabase&quot;
  1721. Const cstSubArgs = &quot;[FileName=&quot;&quot;&quot;&quot;], [RegistrationName=&quot;&quot;&quot;&quot;], DestinationCell, SQLCommand, [DirectSQL=False]&quot;
  1722. &apos; If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1723. Check:
  1724. If IsMissing(FileName) Or IsEmpty(FileName) Then FileName = &quot;&quot;
  1725. If IsMissing(RegistrationName) Or IsEmpty(RegistrationName) Then RegistrationName = &quot;&quot;
  1726. If IsMissing(DirectSQL) Or IsEmpty(DirectSQL) Then DirectSQL = False
  1727. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1728. If Not _IsStillAlive(True) Then GoTo Finally
  1729. If Not ScriptForge.SF_Utils._ValidateFile(FileName, &quot;FileName&quot;, , True) Then GoTo Finally
  1730. If Not ScriptForge.SF_Utils._Validate(DestinationCell, &quot;DestinationCell&quot;, V_STRING) Then GoTo Finally
  1731. If Not ScriptForge.SF_Utils._Validate(SQLCommand, &quot;SQLCommand&quot;, V_STRING) Then GoTo Finally
  1732. If Not ScriptForge.SF_Utils._Validate(DirectSQL, &quot;DirectSQL&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  1733. End If
  1734. &apos; Check the existence of FileName
  1735. If Len(FileName) = 0 Then &apos; FileName has precedence over RegistrationName
  1736. If Len(RegistrationName) = 0 Then GoTo CatchError
  1737. Set oDBContext = ScriptForge.SF_Utils._GetUNOService(&quot;DatabaseContext&quot;)
  1738. If Not oDBContext.hasRegisteredDatabase(RegistrationName) Then GoTo CatchError
  1739. FileName = ScriptForge.SF_FileSystem._ConvertFromUrl(oDBContext.getDatabaseLocation(RegistrationName))
  1740. End If
  1741. If Not ScriptForge.SF_FileSystem.FileExists(FileName) Then GoTo CatchError
  1742. Try:
  1743. &apos; Check command type
  1744. Set oDatabase = ScriptForge.SF_Services.CreateScriptService(&quot;SFDatabases.Database&quot;, FileName, , True) &apos; Read-only
  1745. If IsNull(oDatabase) Then GoTo CatchError
  1746. With oDatabase
  1747. If ScriptForge.SF_Array.Contains(.Tables, SQLCommand) Then
  1748. bDirect = True
  1749. lCommandType = com.sun.star.sheet.DataImportMode.TABLE
  1750. ElseIf ScriptForge.SF_Array.Contains(.Queries, SQLCommand) Then
  1751. Set oQuery = .XConnection.Queries.getByName(SQLCommand)
  1752. bDirect = Not oQuery.EscapeProcessing
  1753. lCommandType = com.sun.star.sheet.DataImportMode.QUERY
  1754. Else
  1755. bDirect = DirectSQL
  1756. lCommandType = com.sun.star.sheet.DataImportMode.SQL
  1757. SQLCommand = ._ReplaceSquareBrackets(SQLCommand)
  1758. End If
  1759. .CloseDatabase()
  1760. Set oDatabase = oDatabase.Dispose()
  1761. End With
  1762. &apos; Determine the destination cell as the top-left coordinates of the given range
  1763. Set oDestRange = _ParseAddress(DestinationCell)
  1764. Set oDestAddress = oDestRange.XCellRange.RangeAddress
  1765. Set oDestCell = oDestRange.XSpreadsheet.getCellByPosition(oDestAddress.StartColumn, oDestAddress.StartRow)
  1766. &apos; Remember current selection
  1767. Set oSelect = _Component.CurrentController.getSelection()
  1768. &apos; Import arguments
  1769. vImportOptions = Array(_
  1770. ScriptForge.SF_Utils._MakePropertyValue(&quot;DatabaseName&quot;, ScriptForge.SF_FileSystem._ConvertToUrl(FileName)) _
  1771. , ScriptForge.SF_Utils._MakePropertyValue(&quot;SourceObject&quot;, SQLCommand) _
  1772. , ScriptForge.SF_Utils._MakePropertyValue(&quot;SourceType&quot;, lCommandType) _
  1773. , ScriptForge.SF_Utils._MakePropertyValue(&quot;IsNative&quot;, bDirect) _
  1774. )
  1775. oDestCell.doImport(vImportOptions)
  1776. &apos; Restore selection after import_
  1777. _RestoreSelections(_Component, oSelect)
  1778. Finally:
  1779. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1780. Exit Sub
  1781. Catch:
  1782. GoTo Finally
  1783. CatchError:
  1784. SF_Exception.RaiseFatal(BASEDOCUMENTOPENERROR, &quot;FileName&quot;, FileName, &quot;RegistrationName&quot;, RegistrationName)
  1785. GoTo Finally
  1786. End Sub &apos; SFDocuments.SF_Calc.ImportFromDatabase
  1787. REM -----------------------------------------------------------------------------
  1788. Public Function InsertSheet(Optional ByVal SheetName As Variant _
  1789. , Optional ByVal BeforeSheet As Variant _
  1790. ) As Boolean
  1791. &apos;&apos;&apos; Insert a new empty sheet before an existing sheet or at the end of the list of sheets
  1792. &apos;&apos;&apos; Args:
  1793. &apos;&apos;&apos; SheetName: The name of the new sheet
  1794. &apos;&apos;&apos; BeforeSheet: The name (string) or index (numeric, starting from 1) of the sheet before which to insert
  1795. &apos;&apos;&apos; Returns:
  1796. &apos;&apos;&apos; True if the sheet could be inserted successfully
  1797. &apos;&apos;&apos; Examples:
  1798. &apos;&apos;&apos; oDoc.InsertSheet(&quot;SheetX&quot;, &quot;SheetY&quot;)
  1799. Dim bInsert As Boolean &apos; Return value
  1800. Dim vSheets As Variant &apos; List of existing sheets
  1801. Dim lSheetIndex As Long &apos; Index of a sheet
  1802. Const cstThisSub = &quot;SFDocuments.Calc.InsertSheet&quot;
  1803. Const cstSubArgs = &quot;SheetName, [BeforeSheet=&quot;&quot;&quot;&quot;]&quot;
  1804. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1805. bInsert = False
  1806. Check:
  1807. If IsMissing(BeforeSheet) Or IsEmpty(BeforeSheet) Then BeforeSheet = 32768
  1808. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1809. If Not _IsStillAlive(True) Then GoTo Finally
  1810. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, True) Then GoTo Finally
  1811. If Not _ValidateSheet(BeforeSheet, &quot;BeforeSheet&quot;, , True, , True) Then GoTo Finally
  1812. End If
  1813. vSheets = _Component.getSheets.getElementNames()
  1814. Try:
  1815. If VarType(BeforeSheet) = V_STRING Then
  1816. lSheetIndex = ScriptForge.SF_Array.IndexOf(vSheets, BeforeSheet)
  1817. Else
  1818. lSheetIndex = BeforeSheet - 1
  1819. If lSheetIndex &lt; 0 Then lSheetIndex = 0
  1820. If lSheetIndex &gt; UBound(vSheets) Then lSheetIndex = UBound(vSheets) + 1
  1821. End If
  1822. _Component.getSheets.insertNewByName(SheetName, lSheetIndex)
  1823. bInsert = True
  1824. Finally:
  1825. InsertSheet = binsert
  1826. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1827. Exit Function
  1828. Catch:
  1829. GoTo Finally
  1830. End Function &apos; SFDocuments.SF_Calc.InsertSheet
  1831. REM -----------------------------------------------------------------------------
  1832. Public Function Methods() As Variant
  1833. &apos;&apos;&apos; Return the list of public methods of the Calc service as an array
  1834. Methods = Array( _
  1835. &quot;A1Style&quot; _
  1836. , &quot;Charts&quot; _
  1837. , &quot;ClearAll&quot; _
  1838. , &quot;ClearFormats&quot; _
  1839. , &quot;ClearValues&quot; _
  1840. , &quot;CopySheet&quot; _
  1841. , &quot;CopySheetFromFile&quot; _
  1842. , &quot;CopyToCell&quot; _
  1843. , &quot;CopyToRange&quot; _
  1844. , &quot;CreateChart&quot; _
  1845. , &quot;DAvg&quot; _
  1846. , &quot;DCount&quot; _
  1847. , &quot;DMax&quot; _
  1848. , &quot;DMin&quot; _
  1849. , &quot;DSum&quot; _
  1850. , &quot;ExportRangeToFile&quot; _
  1851. , &quot;GetColumnName&quot; _
  1852. , &quot;GetFormula&quot; _
  1853. , &quot;GetValue&quot; _
  1854. , &quot;ImportFromCSVFile&quot; _
  1855. , &quot;ImportFromDatabase&quot; _
  1856. , &quot;InsertSheet&quot; _
  1857. , &quot;MoveRange&quot; _
  1858. , &quot;MoveSheet&quot; _
  1859. , &quot;Offset&quot; _
  1860. , &quot;OpenRangeSelector&quot; _
  1861. , &quot;Printf&quot; _
  1862. , &quot;PrintOut&quot; _
  1863. , &quot;RemoveSheet&quot; _
  1864. , &quot;RenameSheet&quot; _
  1865. , &quot;SetArray&quot; _
  1866. , &quot;SetCellStyle&quot; _
  1867. , &quot;SetFormula&quot; _
  1868. , &quot;SetValue&quot; _
  1869. , &quot;ShiftDown&quot; _
  1870. , &quot;ShiftLeft&quot; _
  1871. , &quot;ShiftRight&quot; _
  1872. , &quot;ShiftUp&quot; _
  1873. , &quot;SortRange&quot; _
  1874. )
  1875. End Function &apos; SFDocuments.SF_Calc.Methods
  1876. REM -----------------------------------------------------------------------------
  1877. Public Function MoveRange(Optional ByVal Source As Variant _
  1878. , Optional ByVal Destination As Variant _
  1879. ) As String
  1880. &apos;&apos;&apos; Move a specified source range to a destination range
  1881. &apos;&apos;&apos; Args:
  1882. &apos;&apos;&apos; Source: the source range of cells as a string
  1883. &apos;&apos;&apos; Destination: the destination of the moved range of cells, as a string
  1884. &apos;&apos;&apos; If given as a range of cells, the destination will be reduced to its top-left cell
  1885. &apos;&apos;&apos; Returns:
  1886. &apos;&apos;&apos; A string representing the modified range of cells
  1887. &apos;&apos;&apos; The modified area depends only on the size of the source area
  1888. &apos;&apos;&apos; Examples:
  1889. &apos;&apos;&apos; oDoc.MoveRange(&quot;SheetX.A1:F10&quot;, &quot;SheetY.C5&quot;)
  1890. Dim sMove As String &apos; Return value
  1891. Dim oSource As Object &apos; Alias of Source to avoid &quot;Object variable not set&quot; run-time error
  1892. Dim oSourceAddress As Object &apos; com.sun.star.table.CellRangeAddress
  1893. Dim oDestRange As Object &apos; Destination as a range
  1894. Dim oDestAddress As Object &apos; com.sun.star.table.CellRangeAddress
  1895. Dim oDestCell As Object &apos; com.sun.star.table.CellAddress
  1896. Dim oSelect As Object &apos; Current selection in source
  1897. Dim oClipboard As Object &apos; com.sun.star.datatransfer.XTransferable
  1898. Dim oCellRanges As Object &apos; com.sun.star.sheet.SheetCellRanges
  1899. Dim vRangeAddresses As Variant &apos; Array of com.sun.star.table.CellRangeAddress
  1900. Dim i As Long
  1901. Const cstThisSub = &quot;SFDocuments.Calc.MoveRange&quot;
  1902. Const cstSubArgs = &quot;Source, Destination&quot;
  1903. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1904. sMove = &quot;&quot;
  1905. Check:
  1906. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1907. If Not _IsStillAlive(True) Then GoTo Finally
  1908. If Not _Validate(Source, &quot;Source&quot;, V_STRING) Then GoTo Finally
  1909. If Not _Validate(Destination, &quot;Destination&quot;, V_STRING) Then GoTo Finally
  1910. End If
  1911. Try:
  1912. Set oSourceAddress = _ParseAddress(Source).XCellRange.RangeAddress
  1913. Set oDestRange = _ParseAddress(Destination)
  1914. Set oDestAddress = oDestRange.XCellRange.RangeAddress
  1915. Set oDestCell = New com.sun.star.table.CellAddress
  1916. With oDestAddress
  1917. oDestCell.Sheet = .Sheet
  1918. oDestCell.Column = .StartColumn
  1919. oDestCell.Row = .StartRow
  1920. End With
  1921. oDestRange.XSpreadsheet.moveRange(oDestCell, oSourceAddress)
  1922. With oSourceAddress
  1923. sMove = _Offset(Destination, 0, 0, .EndRow - .StartRow + 1, .EndColumn - .StartColumn + 1).RangeName
  1924. End With
  1925. Finally:
  1926. MoveRange = sMove
  1927. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1928. Exit Function
  1929. Catch:
  1930. GoTo Finally
  1931. End Function &apos; SFDocuments.SF_Calc.MoveRange
  1932. REM -----------------------------------------------------------------------------
  1933. Public Function MoveSheet(Optional ByVal SheetName As Variant _
  1934. , Optional ByVal BeforeSheet As Variant _
  1935. ) As Boolean
  1936. &apos;&apos;&apos; Move a sheet before an existing sheet or at the end of the list of sheets
  1937. &apos;&apos;&apos; Args:
  1938. &apos;&apos;&apos; SheetName: The name of the sheet to move
  1939. &apos;&apos;&apos; BeforeSheet: The name (string) or index (numeric, starting from 1) of the sheet before which to move the sheet
  1940. &apos;&apos;&apos; Returns:
  1941. &apos;&apos;&apos; True if the sheet could be moved successfully
  1942. &apos;&apos;&apos; Examples:
  1943. &apos;&apos;&apos; oDoc.MoveSheet(&quot;SheetX&quot;, &quot;SheetY&quot;)
  1944. Dim bMove As Boolean &apos; Return value
  1945. Dim vSheets As Variant &apos; List of existing sheets
  1946. Dim lSheetIndex As Long &apos; Index of a sheet
  1947. Const cstThisSub = &quot;SFDocuments.Calc.MoveSheet&quot;
  1948. Const cstSubArgs = &quot;SheetName, [BeforeSheet=&quot;&quot;&quot;&quot;]&quot;
  1949. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1950. bMove = False
  1951. Check:
  1952. If IsMissing(BeforeSheet) Or IsEmpty(BeforeSheet) Then BeforeSheet = 32768
  1953. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1954. If Not _IsStillAlive(True) Then GoTo Finally
  1955. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True) Then GoTo Finally
  1956. If Not _ValidateSheet(BeforeSheet, &quot;BeforeSheet&quot;, , True, , True) Then GoTo Finally
  1957. End If
  1958. vSheets = _Component.getSheets.getElementNames()
  1959. Try:
  1960. If VarType(BeforeSheet) = V_STRING Then
  1961. lSheetIndex = ScriptForge.SF_Array.IndexOf(vSheets, BeforeSheet)
  1962. Else
  1963. lSheetIndex = BeforeSheet - 1
  1964. If lSheetIndex &lt; 0 Then lSheetIndex = 0
  1965. If lSheetIndex &gt; UBound(vSheets) Then lSheetIndex = UBound(vSheets) + 1
  1966. End If
  1967. _Component.getSheets.MoveByName(SheetName, lSheetIndex)
  1968. bMove = True
  1969. Finally:
  1970. MoveSheet = bMove
  1971. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  1972. Exit Function
  1973. Catch:
  1974. GoTo Finally
  1975. End Function &apos; SFDocuments.SF_Calc.MoveSheet
  1976. REM -----------------------------------------------------------------------------
  1977. Public Function Offset(Optional ByRef Range As Variant _
  1978. , Optional ByVal Rows As Variant _
  1979. , Optional ByVal Columns As Variant _
  1980. , Optional ByVal Height As Variant _
  1981. , Optional ByVal Width As Variant _
  1982. ) As String
  1983. &apos;&apos;&apos; Returns a new range offset by a certain number of rows and columns from a given range
  1984. &apos;&apos;&apos; Args:
  1985. &apos;&apos;&apos; Range : the range, as a string, from which the function searches for the new range
  1986. &apos;&apos;&apos; Rows : the number of rows by which the reference was corrected up (negative value) or down.
  1987. &apos;&apos;&apos; Use 0 (default) to stay in the same row.
  1988. &apos;&apos;&apos; Columns : the number of columns by which the reference was corrected to the left (negative value) or to the right.
  1989. &apos;&apos;&apos; Use 0 (default) to stay in the same column
  1990. &apos;&apos;&apos; Height : the vertical height for an area that starts at the new reference position.
  1991. &apos;&apos;&apos; Default = no vertical resizing
  1992. &apos;&apos;&apos; Width : the horizontal width for an area that starts at the new reference position.
  1993. &apos;&apos;&apos; Default - no horizontal resizing
  1994. &apos;&apos;&apos; Arguments Rows and Columns must not lead to zero or negative start row or column.
  1995. &apos;&apos;&apos; Arguments Height and Width must not lead to zero or negative count of rows or columns.
  1996. &apos;&apos;&apos; Returns:
  1997. &apos;&apos;&apos; A new range as a string
  1998. &apos;&apos;&apos; Exceptions:
  1999. &apos;&apos;&apos; OFFSETADDRESSERROR The computed range of cells falls beyond the sheet boundaries
  2000. &apos;&apos;&apos; Examples:
  2001. &apos;&apos;&apos; oDoc.Offset(&quot;A1&quot;, 2, 2) &apos; &quot;&apos;SheetX&apos;.$C$3&quot; (A1 moved by two rows and two columns down)
  2002. &apos;&apos;&apos; oDoc.Offset(&quot;A1&quot;, 2, 2, 5, 6) &apos; &quot;&apos;SheetX&apos;.$C$3:$H$7&quot;
  2003. Dim sOffset As String &apos; Return value
  2004. Dim oAddress As Object &apos; Alias of Range
  2005. Const cstThisSub = &quot;SFDocuments.Calc.Offset&quot;
  2006. Const cstSubArgs = &quot;Range, [Rows=0], [Columns=0], [Height], [Width]&quot;
  2007. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2008. sOffset = &quot;&quot;
  2009. Check:
  2010. If IsMissing(Rows) Or IsEmpty(Rows) Then Rows = 0
  2011. If IsMissing(Columns) Or IsEmpty(Columns) Then Columns = 0
  2012. If IsMissing(Height) Or IsEmpty(Height) Then Height = 0
  2013. If IsMissing(Width) Or IsEmpty(Width) Then Width = 0
  2014. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2015. If Not _IsStillAlive() Then GoTo Finally
  2016. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  2017. If Not ScriptForge.SF_Utils._Validate(Rows, &quot;Rows&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2018. If Not ScriptForge.SF_Utils._Validate(Columns, &quot;Columns&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2019. If Not ScriptForge.SF_Utils._Validate(Height, &quot;Height&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2020. If Not ScriptForge.SF_Utils._Validate(Width, &quot;Width&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2021. End If
  2022. Try:
  2023. &apos; Define the new range string
  2024. Set oAddress = _Offset(Range, Rows, Columns, Height, Width)
  2025. sOffset = oAddress.RangeName
  2026. Finally:
  2027. Offset = sOffset
  2028. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2029. Exit Function
  2030. Catch:
  2031. GoTo Finally
  2032. End Function &apos; SFDocuments.SF_Calc.Offset
  2033. REM -----------------------------------------------------------------------------
  2034. Public Function OpenRangeSelector(Optional ByVal Title As Variant _
  2035. , Optional ByVal Selection As Variant _
  2036. , Optional ByVal SingleCell As Variant _
  2037. , Optional ByVal CloseAfterSelect As Variant _
  2038. ) As String
  2039. &apos;&apos;&apos; Activates the Calc document, opens a non-modal dialog with a text box,
  2040. &apos;&apos;&apos; let the user make a selection in the current or another sheet and
  2041. &apos;&apos;&apos; returns the selected area as a string.
  2042. &apos;&apos;&apos; This method does not change the current selection.
  2043. &apos;&apos;&apos; Args:
  2044. &apos;&apos;&apos; Title: the title to display on the top of the dialog
  2045. &apos;&apos;&apos; Selection: a default preselection as a String. When absent, the first element of the
  2046. &apos;&apos;&apos; current selection is preselected.
  2047. &apos;&apos;&apos; SingleCell: When True, only a single cell may be selected. Default = False
  2048. &apos;&apos;&apos; CloseAfterSelect: When True (default-, the dialog is closed immediately after
  2049. &apos;&apos;&apos; the selection. When False, the user may change his/her mind and must close
  2050. &apos;&apos;&apos; the dialog manually.
  2051. &apos;&apos;&apos; Returns:
  2052. &apos;&apos;&apos; The selected range as a string, or the empty string when the user cancelled the request (close window button)
  2053. &apos;&apos;&apos; Exceptions:
  2054. &apos;&apos;&apos; Examples:
  2055. &apos;&apos;&apos; Dim sSelect As String, vValues As Variant
  2056. &apos;&apos;&apos; sSelect = oDoc.OpenRangeSelector(&quot;Select a range ...&quot;)
  2057. &apos;&apos;&apos; If sSelect = &quot;&quot; Then Exit Function
  2058. &apos;&apos;&apos; vValues = oDoc.GetValue(sSelect)
  2059. Dim sSelector As String &apos; Return value
  2060. Dim vPropertyValues As Variant &apos; Array of com.sun.star.beans.PropertyValue
  2061. Dim oSelection As Object &apos; The current selection before opening the selector
  2062. Dim oAddress As Object &apos; Preselected address as _Address
  2063. Const cstThisSub = &quot;SFDocuments.Calc.OpenRangeSelector&quot;
  2064. Const cstSubArgs = &quot;[Title=&quot;&quot;&quot;&quot;], [Selection=&quot;&quot;~&quot;&quot;], [SingleCell=False], [CloseAfterSelect=True]&quot;
  2065. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2066. sSelector = &quot;&quot;
  2067. Check:
  2068. If IsMissing(Title) Or IsEmpty(Title) Then Title = &quot;&quot;
  2069. If IsMissing(Selection) Or IsEmpty(Selection) Then Selection = &quot;~&quot;
  2070. If IsMissing(SingleCell) Or IsEmpty(SingleCell) Then SingleCell = False
  2071. If IsMissing(CloseAfterSelect) Or IsEmpty(CloseAfterSelect) Then CloseAfterSelect = True
  2072. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2073. If Not _IsStillAlive() Then GoTo Finally
  2074. If Not ScriptForge.SF_Utils._Validate(Title, &quot;Title&quot;, V_STRING) Then GoTo Finally
  2075. If Not ScriptForge.SF_Utils._Validate(Selection, &quot;Selection&quot;, V_STRING) Then GoTo Finally
  2076. If Not ScriptForge.SF_Utils._Validate(SingleCell, &quot;SingleCell&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2077. If Not ScriptForge.SF_Utils._Validate(CloseAfterSelect, &quot;CloseAfterSelect&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2078. End If
  2079. Try:
  2080. &apos; Save the current selections
  2081. Set oSelection = _Component.CurrentController.getSelection()
  2082. &apos; Process preselection and select its containing sheet
  2083. Set oAddress = _ParseAddress(Selection)
  2084. Activate(oAddress.SheetName)
  2085. &apos; Build arguments array and execute the dialog box
  2086. With ScriptForge.SF_Utils
  2087. vPropertyValues = Array( _
  2088. ._MakePropertyValue(&quot;Title&quot;, Title) _
  2089. , ._MakePropertyValue(&quot;CloseOnMouseRelease&quot;, CloseAfterSelect) _
  2090. , ._MakePropertyValue(&quot;InitialValue&quot;, oAddress.XCellRange.AbsoluteName) _
  2091. , ._MakePropertyValue(&quot;SingleCellMode&quot;, SingleCell) _
  2092. )
  2093. End With
  2094. sSelector = SF_DocumentListener.RunRangeSelector(_Component, vPropertyValues)
  2095. &apos; Restore the saved selections
  2096. _RestoreSelections(_Component, oSelection)
  2097. Finally:
  2098. OpenRangeSelector = sSelector
  2099. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2100. Exit Function
  2101. Catch:
  2102. GoTo Finally
  2103. End Function &apos; SFDocuments.SF_Calc.OpenRangeSelector
  2104. REM -----------------------------------------------------------------------------
  2105. Public Function Printf(Optional ByVal InputStr As Variant _
  2106. , Optional ByVal Range As Variant _
  2107. , Optional ByVal TokenCharacter As Variant _
  2108. ) As String
  2109. &apos;&apos;&apos; Returns the input string after substitution of its tokens by
  2110. &apos;&apos;&apos; their values in the given range
  2111. &apos;&apos;&apos; This method is usually used in combination with SetFormula()
  2112. &apos;&apos;&apos; The accepted tokens are:
  2113. &apos;&apos;&apos; - %S The sheet name containing the range, including single quotes when necessary
  2114. &apos;&apos;&apos; - %R1 The row number of the topleft part of the range
  2115. &apos;&apos;&apos; - %C1 The column letter of the topleft part of the range
  2116. &apos;&apos;&apos; - %R2 The row number of the bottomright part of the range
  2117. &apos;&apos;&apos; - %C2 The column letter of the bottomright part of the range
  2118. &apos;&apos;&apos; Args:
  2119. &apos;&apos;&apos; InputStr: usually a Calc formula or a part of a formula, but may be any string
  2120. &apos;&apos;&apos; Range: the range, as a string from which the values of the tokens are derived
  2121. &apos;&apos;&apos; TokenCharacter: the character identifying tokens. Default = &quot;%&quot;.
  2122. &apos;&apos;&apos; Double the TokenCharacter to not consider it as a token.
  2123. &apos;&apos;&apos; Returns:
  2124. &apos;&apos;&apos; The input string after substitution of the contained tokens
  2125. &apos;&apos;&apos; Exceptions:
  2126. &apos;&apos;&apos; Examples:
  2127. &apos;&apos;&apos; Assume we have in A1:E10 a matrix of numbers. To obtain the sum by row in F1:F10 ...
  2128. &apos;&apos;&apos; Dim range As String, formula As String
  2129. &apos;&apos;&apos; range = &quot;$A$1:$E$10&quot;)
  2130. &apos;&apos;&apos; formula = &quot;=SUM($%C1%R1:$%C2%R1)&quot; &apos; &quot;=SUM($A1:$E1)&quot;, note the relative references
  2131. &apos;&apos;&apos; oDoc.SetFormula(&quot;$F$1:$F$10&quot;, formula)
  2132. &apos;&apos;&apos; &apos;F1 will contain =Sum($A1:$E1)
  2133. &apos;&apos;&apos; &apos;F2 =Sum($A2:$E2)
  2134. &apos;&apos;&apos; &apos; ...
  2135. Dim sPrintf As String &apos; Return value
  2136. Dim vSubstitute As Variants &apos; Array of strings representing the token values
  2137. Dim oAddress As Object &apos; A range as an _Address object
  2138. Dim sSheetName As String &apos; The %S token value
  2139. Dim sC1 As String &apos; The %C1 token value
  2140. Dim sR1 As String &apos; The %R1 token value
  2141. Dim sC2 As String &apos; The %C2 token value
  2142. Dim sR2 As String &apos; The %R2 token value
  2143. Dim i As Long
  2144. Const cstPseudoToken = &quot;@#@&quot;
  2145. Const cstThisSub = &quot;SFDocuments.Calc.Printf&quot;
  2146. Const cstSubArgs = &quot;InputStr, Range, TokenCharacter=&quot;&quot;%&quot;&quot;&quot;
  2147. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2148. sPrintf = &quot;&quot;
  2149. Check:
  2150. If IsMissing(TokenCharacter) Or IsEmpty(TokenCharacter) Then TokenCharacter = &quot;%&quot;
  2151. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2152. If Not _IsStillAlive() Then GoTo Finally
  2153. If Not ScriptForge.SF_Utils._Validate(InputStr, &quot;InputStr&quot;, V_STRING) Then GoTo Finally
  2154. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  2155. If Not ScriptForge.SF_Utils._Validate(TokenCharacter, &quot;TokenCharacter&quot;, V_STRING) Then GoTo Finally
  2156. End If
  2157. Try:
  2158. &apos; Define the token values
  2159. Set oAddress = _ParseAddress(Range)
  2160. With oAddress.XCellRange
  2161. sC1 = _GetColumnName(.RangeAddress.StartColumn + 1)
  2162. sR1 = CStr(.RangeAddress.StartRow + 1)
  2163. sC2 = _GetColumnName(.RangeAddress.EndColumn + 1)
  2164. sR2 = CStr(.RangeAddress.EndRow + 1)
  2165. sSheetName = _QuoteSheetName(oAddress.XSpreadsheet.Name)
  2166. End With
  2167. &apos; Substitute tokens by their values
  2168. sPrintf = ScriptForge.SF_String.ReplaceStr(InputStr _
  2169. , Array(TokenCharacter &amp; TokenCharacter _
  2170. , TokenCharacter &amp; &quot;R1&quot; _
  2171. , TokenCharacter &amp; &quot;C1&quot; _
  2172. , TokenCharacter &amp; &quot;R2&quot; _
  2173. , TokenCharacter &amp; &quot;C2&quot; _
  2174. , TokenCharacter &amp; &quot;S&quot; _
  2175. , cstPseudoToken _
  2176. ) _
  2177. , Array(cstPseudoToken _
  2178. , sR1 _
  2179. , sC1 _
  2180. , sR2 _
  2181. , sC2 _
  2182. , sSheetName _
  2183. , TokenCharacter _
  2184. ) _
  2185. )
  2186. Finally:
  2187. Printf = sPrintf
  2188. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2189. Exit Function
  2190. Catch:
  2191. GoTo Finally
  2192. End Function &apos; SFDocuments.SF_Calc.Printf
  2193. REM -----------------------------------------------------------------------------
  2194. Public Function PrintOut(Optional ByVal SheetName As Variant _
  2195. , Optional ByVal Pages As Variant _
  2196. , Optional ByVal Copies As Variant _
  2197. ) As Boolean
  2198. &apos;&apos;&apos; Send the content of the given sheet to the printer.
  2199. &apos;&apos;&apos; The printer might be defined previously by default, by the user or by the SetPrinter() method
  2200. &apos;&apos;&apos; Args:
  2201. &apos;&apos;&apos; SheetName: the sheet to print. Default = the active sheet
  2202. &apos;&apos;&apos; Pages: the pages to print as a string, like in the user interface. Example: &quot;1-4;10;15-18&quot;. Default = all pages
  2203. &apos;&apos;&apos; Copies: the number of copies
  2204. &apos;&apos;&apos; Returns:
  2205. &apos;&apos;&apos; True when successful
  2206. &apos;&apos;&apos; Examples:
  2207. &apos;&apos;&apos; oDoc.PrintOut(&quot;SheetX&quot;, &quot;1-4;10;15-18&quot;, Copies := 2)
  2208. Dim bPrint As Boolean &apos; Return value
  2209. Dim oSheet As Object &apos; SheetName as a reference
  2210. Const cstThisSub = &quot;SFDocuments.Calc.PrintOut&quot;
  2211. Const cstSubArgs = &quot;[SheetName=&quot;&quot;~&quot;&quot;], [Pages=&quot;&quot;&quot;&quot;], [Copies=1]&quot;
  2212. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2213. bPrint = False
  2214. Check:
  2215. If IsMissing(SheetName) Or IsEmpty(SheetName) Then SheetName = &quot;&quot;
  2216. If IsMissing(Pages) Or IsEmpty(Pages) Then Pages = &quot;&quot;
  2217. If IsMissing(Copies) Or IsEmpty(Copies) Then Copies = 1
  2218. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2219. If Not _IsStillAlive() Then GoTo Finally
  2220. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True, True) Then GoTo Finally
  2221. If Not ScriptForge.SF_Utils._Validate(Pages, &quot;Pages&quot;, V_STRING) Then GoTo Finally
  2222. If Not ScriptForge.SF_Utils._Validate(Copies, &quot;Copies&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2223. End If
  2224. Try:
  2225. If SheetName = &quot;~&quot; Then SheetName = &quot;&quot;
  2226. &apos; Make given sheet active
  2227. If Len(SheetName) &gt; 0 Then
  2228. With _Component
  2229. Set oSheet = .getSheets.getByName(SheetName)
  2230. Set .CurrentController.ActiveSheet = oSheet
  2231. End With
  2232. End If
  2233. bPrint = [_Super].PrintOut(Pages, Copies, _Component)
  2234. Finally:
  2235. PrintOut = bPrint
  2236. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2237. Exit Function
  2238. Catch:
  2239. GoTo Finally
  2240. End Function &apos; SFDocuments.SF_Calc.PrintOut
  2241. REM -----------------------------------------------------------------------------
  2242. Public Function Properties() As Variant
  2243. &apos;&apos;&apos; Return the list or properties of the Calc class as an array
  2244. Properties = Array( _
  2245. &quot;CurrentSelection&quot; _
  2246. , &quot;CustomProperties&quot; _
  2247. , &quot;Description&quot; _
  2248. , &quot;DocumentProperties&quot; _
  2249. , &quot;DocumentType&quot; _
  2250. , &quot;ExportFilters&quot; _
  2251. , &quot;FirstCell&quot; _
  2252. , &quot;FirstColumn&quot; _
  2253. , &quot;FirstRow&quot; _
  2254. , &quot;Height&quot; _
  2255. , &quot;ImportFilters&quot; _
  2256. , &quot;IsBase&quot; _
  2257. , &quot;IsCalc&quot; _
  2258. , &quot;IsDraw&quot; _
  2259. , &quot;IsImpress&quot; _
  2260. , &quot;IsMath&quot; _
  2261. , &quot;IsWriter&quot; _
  2262. , &quot;Keywords&quot; _
  2263. , &quot;LastCell&quot; _
  2264. , &quot;LastColumn&quot; _
  2265. , &quot;LastRow&quot; _
  2266. , &quot;Range&quot; _
  2267. , &quot;Readonly&quot; _
  2268. , &quot;Region&quot; _
  2269. , &quot;Sheet&quot; _
  2270. , &quot;SheetName&quot; _
  2271. , &quot;Sheets&quot; _
  2272. , &quot;Subject&quot; _
  2273. , &quot;Title&quot; _
  2274. , &quot;Width&quot; _
  2275. , &quot;XCellRange&quot; _
  2276. , &quot;XComponent&quot; _
  2277. , &quot;XSheetCellCursor&quot; _
  2278. , &quot;XSpreadsheet&quot; _
  2279. )
  2280. End Function &apos; SFDocuments.SF_Calc.Properties
  2281. REM -----------------------------------------------------------------------------
  2282. Public Function RemoveSheet(Optional ByVal SheetName As Variant) As Boolean
  2283. &apos;&apos;&apos; Remove an existing sheet from the document
  2284. &apos;&apos;&apos; Args:
  2285. &apos;&apos;&apos; SheetName: The name of the sheet to remove
  2286. &apos;&apos;&apos; Returns:
  2287. &apos;&apos;&apos; True if the sheet could be removed successfully
  2288. &apos;&apos;&apos; Examples:
  2289. &apos;&apos;&apos; oDoc.RemoveSheet(&quot;SheetX&quot;)
  2290. Dim bRemove As Boolean &apos; Return value
  2291. Const cstThisSub = &quot;SFDocuments.Calc.RemoveSheet&quot;
  2292. Const cstSubArgs = &quot;SheetName&quot;
  2293. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2294. bRemove = False
  2295. Check:
  2296. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2297. If Not _IsStillAlive(True) Then GoTo Finally
  2298. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True) Then GoTo Finally
  2299. End If
  2300. Try:
  2301. _Component.getSheets.RemoveByName(SheetName)
  2302. bRemove = True
  2303. Finally:
  2304. RemoveSheet = bRemove
  2305. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2306. Exit Function
  2307. Catch:
  2308. GoTo Finally
  2309. End Function &apos; SFDocuments.SF_Calc.RemoveSheet
  2310. REM -----------------------------------------------------------------------------
  2311. Public Function RenameSheet(Optional ByVal SheetName As Variant _
  2312. , Optional ByVal NewName As Variant _
  2313. ) As Boolean
  2314. &apos;&apos;&apos; Rename a specified sheet
  2315. &apos;&apos;&apos; Args:
  2316. &apos;&apos;&apos; SheetName: The name of the sheet to rename
  2317. &apos;&apos;&apos; NewName: Must not exist
  2318. &apos;&apos;&apos; Returns:
  2319. &apos;&apos;&apos; True if the sheet could be renamed successfully
  2320. &apos;&apos;&apos; Exceptions:
  2321. &apos;&apos;&apos; DUPLICATESHEETERROR A sheet with the given name exists already
  2322. &apos;&apos;&apos; Examples:
  2323. &apos;&apos;&apos; oDoc.RenameSheet(&quot;SheetX&quot;, &quot;SheetY&quot;)
  2324. Dim bRename As Boolean &apos; Return value
  2325. Const cstThisSub = &quot;SFDocuments.Calc.RenameSheet&quot;
  2326. Const cstSubArgs = &quot;SheetName, NewName&quot;
  2327. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2328. bRename = False
  2329. Check:
  2330. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2331. If Not _IsStillAlive(True) Then GoTo Finally
  2332. If Not _ValidateSheet(SheetName, &quot;SheetName&quot;, , True) Then GoTo Finally
  2333. If Not _ValidateSheet(NewName, &quot;NewName&quot;, True) Then GoTo Finally
  2334. End If
  2335. Try:
  2336. _Component.getSheets.getByName(SheetName).setName(NewName)
  2337. bRename = True
  2338. Finally:
  2339. RenameSheet = bRename
  2340. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2341. Exit Function
  2342. Catch:
  2343. GoTo Finally
  2344. End Function &apos; SFDocuments.SF_Calc.RenameSheet
  2345. REM -----------------------------------------------------------------------------
  2346. Public Function SetArray(Optional ByVal TargetCell As Variant _
  2347. , Optional ByRef Value As Variant _
  2348. ) As String
  2349. &apos;&apos;&apos; Set the given (array of) values starting from the target cell
  2350. &apos;&apos;&apos; The updated area expands itself from the target cell or from the top-left corner of the given range
  2351. &apos;&apos;&apos; as far as determined by the size of the input Value.
  2352. &apos;&apos;&apos; Vectors are always expanded vertically
  2353. &apos;&apos;&apos; Args:
  2354. &apos;&apos;&apos; TargetCell : the cell or the range as a string that should receive a new value
  2355. &apos;&apos;&apos; Value: a scalar, a vector or an array with the new values
  2356. &apos;&apos;&apos; The new values should be strings, numeric values or dates. Other types empty the corresponding cell
  2357. &apos;&apos;&apos; Returns:
  2358. &apos;&apos;&apos; A string representing the updated range
  2359. &apos;&apos;&apos; Exceptions:
  2360. &apos;&apos;&apos; OFFSETADDRESSERROR The computed range of cells falls beyond the sheet boundaries
  2361. &apos;&apos;&apos; Examples:
  2362. &apos;&apos;&apos; oDoc.SetArray(&quot;SheetX.A1&quot;, SF_Array.RangeInit(1, 1000))
  2363. Dim sSet As String &apos; Return value
  2364. Dim oSet As Object &apos; _Address alias of sSet
  2365. Dim vDataArray As Variant &apos; DataArray compatible with .DataArray UNO property
  2366. Const cstThisSub = &quot;SFDocuments.Calc.SetArray&quot;
  2367. Const cstSubArgs = &quot;TargetCell, Value&quot;
  2368. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2369. sSet = &quot;&quot;
  2370. Check:
  2371. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2372. If Not _IsStillAlive() Then GoTo Finally
  2373. If Not ScriptForge.SF_Utils._Validate(TargetCell, &quot;TargetCell&quot;, V_STRING) Then GoTo Finally
  2374. If IsArray(Value) Then
  2375. If Not ScriptForge.SF_Utils._ValidateArray(Value, &quot;Value&quot;) Then GoTo Finally
  2376. Else
  2377. If Not ScriptForge.SF_Utils._Validate(Value, &quot;Value&quot;) Then GoTo Finally
  2378. End If
  2379. End If
  2380. Try:
  2381. &apos; Convert argument to data array and derive new range from its size
  2382. vDataArray = _ConvertToDataArray(Value)
  2383. If UBound(vDataArray) &lt; LBound(vDataArray) Then GoTo Finally
  2384. Set oSet = _Offset(TargetCell, 0, 0, plHeight := UBound(vDataArray) + 1, plWidth := UBound(vDataArray(0)) + 1) &apos; +1 : vDataArray is zero-based
  2385. With oSet
  2386. .XCellRange.setDataArray(vDataArray)
  2387. sSet = .RangeName
  2388. End With
  2389. Finally:
  2390. SetArray = sSet
  2391. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2392. Exit Function
  2393. Catch:
  2394. GoTo Finally
  2395. End Function &apos; SFDocuments.SF_Calc.SetArray
  2396. REM -----------------------------------------------------------------------------
  2397. Public Function SetCellStyle(Optional ByVal TargetRange As Variant _
  2398. , Optional ByVal Style As Variant _
  2399. , Optional ByVal FilterFormula As Variant _
  2400. , Optional ByVal FilterScope As Variant _
  2401. ) As String
  2402. &apos;&apos;&apos; Apply the given cell style in the given range
  2403. &apos;&apos;&apos; If the cell style does not exist, an error is raised
  2404. &apos;&apos;&apos; The range is updated and the remainder of the sheet is left untouched
  2405. &apos;&apos;&apos; Either the full range is updated or a selection based on a FilterFormula
  2406. &apos;&apos;&apos; Args:
  2407. &apos;&apos;&apos; TargetRange : the range as a string that should receive a new cell style
  2408. &apos;&apos;&apos; Style: the style name as a string
  2409. &apos;&apos;&apos; FilterFormula: a Calc formula to select among the given Range
  2410. &apos;&apos;&apos; When left empty, all the cells of the range are formatted with the new style
  2411. &apos;&apos;&apos; FilterScope: &quot;CELL&quot; (default value), &quot;ROW&quot; or &quot;COLUMN&quot;
  2412. &apos;&apos;&apos; When FilterFormula is present, FilterScope is mandatory
  2413. &apos;&apos;&apos; Returns:
  2414. &apos;&apos;&apos; A string representing the updated range
  2415. &apos;&apos;&apos; Examples:
  2416. &apos;&apos;&apos; oDoc.SetCellStyle(&quot;A1:F1&quot;, &quot;Heading 2&quot;)
  2417. &apos;&apos;&apos; oDoc.SetCellStype(&quot;A1:J20&quot;, &quot;Wrong&quot;, &quot;=(A1&lt;0)&quot;, &quot;CELL&quot;)
  2418. Dim sSet As String &apos; Return value
  2419. Dim oAddress As _Address &apos; Alias of TargetRange
  2420. Dim oStyleFamilies As Object &apos; com.sun.star.container.XNameAccess
  2421. Dim vStyles As Variant &apos; Array of existing cell styles
  2422. Dim vRanges() As Variant &apos; Array of filtered ranges
  2423. Dim i As Long
  2424. Const cstStyle = &quot;CellStyles&quot;
  2425. Const cstThisSub = &quot;SFDocuments.Calc.SetCellStyle&quot;
  2426. Const cstSubArgs = &quot;TargetRange, Style, [FilterFormula=&quot;&quot;], [FilterScope=&quot;&quot;CELL&quot;&quot;|&quot;&quot;ROW&quot;&quot;|&quot;&quot;COLUMN&quot;&quot;]&quot;
  2427. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2428. sSet = &quot;&quot;
  2429. Check:
  2430. If IsMissing(FilterFormula) Or IsEmpty(FilterFormula) Then FilterFormula = &quot;&quot;
  2431. If IsMissing(FilterScope) Or IsEmpty(FilterScope) Then FilterScope = &quot;CELL&quot;
  2432. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2433. If Not _IsStillAlive() Then GoTo Finally
  2434. If Not ScriptForge.SF_Utils._Validate(TargetRange, &quot;TargetRange&quot;, Array(V_STRING, ScriptForge.V_OBJECT)) Then GoTo Finally
  2435. &apos; Check that the given style really exists
  2436. Set oStyleFamilies = _Component.StyleFamilies
  2437. If oStyleFamilies.hasByName(cstStyle) Then vStyles = oStyleFamilies.getByName(cstStyle).getElementNames() Else vStyles = Array()
  2438. If Not ScriptForge.SF_Utils._Validate(Style, &quot;Style&quot;, V_STRING, vStyles) Then GoTo Finally
  2439. &apos; Filter formula
  2440. If Not ScriptForge.SF_Utils._Validate(FilterFormula, &quot;FilterFormula&quot;, V_STRING) Then GoTo Finally
  2441. If Len(FilterFormula) &gt; 0 Then
  2442. If Not ScriptForge.SF_Utils._Validate(FilterScope, &quot;FilterScope&quot;, V_STRING, Array(&quot;CELL&quot;, &quot;ROW&quot;, &quot;COLUMN&quot;)) Then GoTo Finally
  2443. Else
  2444. If Not ScriptForge.SF_Utils._Validate(FilterScope, &quot;FilterScope&quot;, V_STRING) Then GoTo Finally
  2445. End If
  2446. End If
  2447. Try:
  2448. If VarType(TargetRange) = V_STRING Then Set oAddress = _ParseAddress(TargetRange) Else Set oAddress = TargetRange
  2449. With oAddress
  2450. If Len(FilterFormula) = 0 Then &apos; When the full range should be updated
  2451. .XCellRange.CellStyle = Style
  2452. Else &apos; When the range has to be cut in subranges
  2453. vRanges() = _ComputeFilter(oAddress, FilterFormula, UCase(FilterScope))
  2454. For i = 0 To UBound(vRanges)
  2455. vRanges(i).XCellRange.CellStyle = Style
  2456. Next i
  2457. End If
  2458. sSet = .RangeName
  2459. End With
  2460. Finally:
  2461. SetCellStyle = sSet
  2462. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2463. Exit Function
  2464. Catch:
  2465. GoTo Finally
  2466. End Function &apos; SFDocuments.SF_Calc.SetCellStyle
  2467. REM -----------------------------------------------------------------------------
  2468. Public Function SetFormula(Optional ByVal TargetRange As Variant _
  2469. , Optional ByRef Formula As Variant _
  2470. ) As String
  2471. &apos;&apos;&apos; Set the given (array of) formulae in the given range
  2472. &apos;&apos;&apos; The full range is updated and the remainder of the sheet is left untouched
  2473. &apos;&apos;&apos; If the given formula is a string:
  2474. &apos;&apos;&apos; the unique formula is pasted across the whole range with adjustment of the relative references
  2475. &apos;&apos;&apos; Otherwise
  2476. &apos;&apos;&apos; If the size of Formula &lt; the size of Range, then the other cells are emptied
  2477. &apos;&apos;&apos; If the size of Formula &gt; the size of Range, then Formula is only partially copied
  2478. &apos;&apos;&apos; Vectors are always expanded vertically, except if the range has a height of exactly 1 row
  2479. &apos;&apos;&apos; Args:
  2480. &apos;&apos;&apos; TargetRange : the range as a string that should receive a new Formula
  2481. &apos;&apos;&apos; Formula: a scalar, a vector or an array with the new formula(e) as strings for each cell of the range.
  2482. &apos;&apos;&apos; Returns:
  2483. &apos;&apos;&apos; A string representing the updated range
  2484. &apos;&apos;&apos; Examples:
  2485. &apos;&apos;&apos; oDoc.SetFormula(&quot;A1&quot;, &quot;=A2&quot;)
  2486. &apos;&apos;&apos; oDoc.SetFormula(&quot;A1:F1&quot;, Array(&quot;=A2&quot;, &quot;=B2&quot;, &quot;=C2+10&quot;)) &apos; Horizontal vector, partially empty
  2487. &apos;&apos;&apos; oDoc.SetFormula(&quot;A1:D2&quot;, &quot;=E1&quot;) &apos; D2 contains the formula &quot;=H2&quot;
  2488. Dim sSet As String &apos; Return value.XSpreadsheet.Name)
  2489. Dim oAddress As Object &apos; Alias of TargetRange
  2490. Dim vDataArray As Variant &apos; DataArray compatible with .DataArray UNO property
  2491. Const cstThisSub = &quot;SFDocuments.Calc.SetFormula&quot;
  2492. Const cstSubArgs = &quot;TargetRange, Formula&quot;
  2493. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2494. sSet = &quot;&quot;
  2495. Check:
  2496. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2497. If Not _IsStillAlive() Then GoTo Finally
  2498. If Not ScriptForge.SF_Utils._Validate(TargetRange, &quot;TargetRange&quot;, Array(V_STRING, ScriptForge.V_OBJECT)) Then GoTo Finally
  2499. If IsArray(Formula) Then
  2500. If Not ScriptForge.SF_Utils._ValidateArray(Formula, &quot;Formula&quot;, 0, V_STRING) Then GoTo Finally
  2501. Else
  2502. If Not ScriptForge.SF_Utils._Validate(Formula, &quot;Formula&quot;, V_STRING) Then GoTo Finally
  2503. End If
  2504. End If
  2505. Try:
  2506. If VarType(TargetRange) = V_STRING Then Set oAddress = _ParseAddress(TargetRange) Else Set oAddress = TargetRange
  2507. With oAddress
  2508. If IsArray(Formula) Then
  2509. &apos; Convert to data array and limit its size to the size of the initial range
  2510. vDataArray = _ConvertToDataArray(Formula, .Height - 1, .Width - 1)
  2511. If UBound(vDataArray) &lt; LBound(vDataArray) Then GoTo Finally
  2512. .XCellRange.setFormulaArray(vDataArray)
  2513. Else
  2514. With .XCellRange
  2515. &apos; Store formula in top-left cell and paste it along the whole range
  2516. .getCellByPosition(0, 0).setFormula(Formula)
  2517. .fillSeries(com.sun.star.sheet.FillDirection.TO_BOTTOM, com.sun.star.sheet.FillMode.SIMPLE, 0, 0, 0)
  2518. .fillSeries(com.sun.star.sheet.FillDirection.TO_RIGHT, com.sun.star.sheet.FillMode.SIMPLE, 0, 0, 0)
  2519. End With
  2520. End If
  2521. sSet = .RangeName
  2522. End With
  2523. Finally:
  2524. SetFormula = sSet
  2525. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2526. Exit Function
  2527. Catch:
  2528. GoTo Finally
  2529. End Function &apos; SFDocuments.SF_Calc.SetFormula
  2530. REM -----------------------------------------------------------------------------
  2531. Private Function SetProperty(Optional ByVal psProperty As String _
  2532. , Optional ByVal pvValue As Variant _
  2533. ) As Boolean
  2534. &apos;&apos;&apos; Set the new value of the named property
  2535. &apos;&apos;&apos; Args:
  2536. &apos;&apos;&apos; psProperty: the name of the property
  2537. &apos;&apos;&apos; pvValue: the new value of the given property
  2538. &apos;&apos;&apos; Returns:
  2539. &apos;&apos;&apos; True if successful
  2540. Dim bSet As Boolean &apos; Return value
  2541. Static oSession As Object &apos; Alias of SF_Session
  2542. Dim cstThisSub As String
  2543. Const cstSubArgs = &quot;Value&quot;
  2544. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2545. bSet = False
  2546. cstThisSub = &quot;SFDocuments.Calc.set&quot; &amp; psProperty
  2547. If IsMissing(pvValue) Then pvValue = Empty
  2548. &apos;ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) &apos; Validation done in Property Lets
  2549. If IsNull(oSession) Then Set oSession = ScriptForge.SF_Services.CreateScriptService(&quot;Session&quot;)
  2550. bSet = True
  2551. Select Case UCase(psProperty)
  2552. Case UCase(&quot;CurrentSelection&quot;)
  2553. CurrentSelection = pvValue
  2554. Case UCase(&quot;CustomProperties&quot;)
  2555. CustomProperties = pvValue
  2556. Case UCase(&quot;Description&quot;)
  2557. Description = pvValue
  2558. Case UCase(&quot;Keywords&quot;)
  2559. Keywords = pvValue
  2560. Case UCase(&quot;Subject&quot;)
  2561. Subject = pvValue
  2562. Case UCase(&quot;Title&quot;)
  2563. Title = pvValue
  2564. Case Else
  2565. bSet = False
  2566. End Select
  2567. Finally:
  2568. SetProperty = bSet
  2569. &apos;ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2570. Exit Function
  2571. Catch:
  2572. GoTo Finally
  2573. End Function &apos; SFDocuments.SF_Calc.SetProperty
  2574. REM -----------------------------------------------------------------------------
  2575. Public Function SetValue(Optional ByVal TargetRange As Variant _
  2576. , Optional ByRef Value As Variant _
  2577. ) As String
  2578. &apos;&apos;&apos; Set the given value in the given range
  2579. &apos;&apos;&apos; The full range is updated and the remainder of the sheet is left untouched
  2580. &apos;&apos;&apos; If the size of Value &lt; the size of Range, then the other cells are emptied
  2581. &apos;&apos;&apos; If the size of Value &gt; the size of Range, then Value is only partially copied
  2582. &apos;&apos;&apos; Vectors are always expanded vertically, except if the range has a height of exactly 1 row
  2583. &apos;&apos;&apos; Args:
  2584. &apos;&apos;&apos; TargetRange : the range as a string that should receive a new value
  2585. &apos;&apos;&apos; Value: a scalar, a vector or an array with the new values for each cell o.XSpreadsheet.Name)f the range.
  2586. &apos;&apos;&apos; The new values should be strings, numeric values or dates. Other types empty the corresponding cell
  2587. &apos;&apos;&apos; Returns:
  2588. &apos;&apos;&apos; A string representing the updated range
  2589. &apos;&apos;&apos; Examples:
  2590. &apos;&apos;&apos; oDoc.SetValue(&quot;A1&quot;, 2)
  2591. &apos;&apos;&apos; oDoc.SetValue(&quot;A1:F1&quot;, Array(1, 2, 3)) &apos; Horizontal vector, partially empty
  2592. &apos;&apos;&apos; oDoc.SetValue(&quot;A1:D2&quot;, SF_Array.AppendRow(Array(1, 2, 3, 4), Array(5, 6, 7, 8)))
  2593. Dim sSet As String &apos; Return value
  2594. Dim oAddress As Object &apos; Alias of TargetRange
  2595. Dim vDataArray As Variant &apos; DataArray compatible with .DataArray UNO property
  2596. Const cstThisSub = &quot;SFDocuments.Calc.SetValue&quot;
  2597. Const cstSubArgs = &quot;TargetRange, Value&quot;
  2598. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2599. sSet = &quot;&quot;
  2600. Check:
  2601. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2602. If Not _IsStillAlive() Then GoTo Finally
  2603. If Not ScriptForge.SF_Utils._Validate(TargetRange, &quot;TargetRange&quot;, V_STRING) Then GoTo Finally
  2604. If IsArray(Value) Then
  2605. If Not ScriptForge.SF_Utils._ValidateArray(Value, &quot;Value&quot;) Then GoTo Finally
  2606. Else
  2607. If Not ScriptForge.SF_Utils._Validate(Value, &quot;Value&quot;) Then GoTo Finally
  2608. End If
  2609. End If
  2610. Try:
  2611. Set oAddress = _ParseAddress(TargetRange)
  2612. With oAddress
  2613. &apos; Convert to data array and limit its size to the size of the initial range
  2614. vDataArray = _ConvertToDataArray(Value, .Height - 1, .Width - 1)
  2615. If UBound(vDataArray) &lt; LBound(vDataArray) Then GoTo Finally
  2616. .XCellRange.setDataArray(vDataArray)
  2617. sSet = .RangeName
  2618. End With
  2619. Finally:
  2620. SetValue = sSet
  2621. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2622. Exit Function
  2623. Catch:
  2624. GoTo Finally
  2625. End Function &apos; SFDocuments.SF_Calc.SetValue
  2626. REM -----------------------------------------------------------------------------
  2627. Public Function ShiftDown(Optional ByVal Range As Variant _
  2628. , Optional ByVal WholeRow As Variant _
  2629. , Optional ByVal Rows As Variant _
  2630. ) As String
  2631. &apos;&apos;&apos; Move a specified range and all cells below in the same columns downwards by inserting empty cells
  2632. &apos;&apos;&apos; The inserted cells can span whole rows or be limited to the width of the range
  2633. &apos;&apos;&apos; The height of the inserted area is provided by the Rows argument
  2634. &apos;&apos;&apos; Nothing happens if the range shift crosses one of the edges of the worksheet
  2635. &apos;&apos;&apos; The execution of the method has no effect on the current selection
  2636. &apos;&apos;&apos; Args:
  2637. &apos;&apos;&apos; Range: the range above which cells have to be inserted, as a string
  2638. &apos;&apos;&apos; WholeRow: when True (default = False), insert whole rows
  2639. &apos;&apos;&apos; Rows: the height of the area to insert. Default = the height of the Range argument
  2640. &apos;&apos;&apos; Returns:
  2641. &apos;&apos;&apos; A string representing the new location of the initial range
  2642. &apos;&apos;&apos; Examples:
  2643. &apos;&apos;&apos; newrange = oDoc.ShiftDown(&quot;SheetX.A1:F10&quot;) &apos; &quot;$SheetX.$A$11:$F$20&quot;
  2644. &apos;&apos;&apos; newrange = oDoc.ShiftDown(&quot;SheetX.A1:F10&quot;, Rows := 3) &apos; &quot;$SheetX.$A$4:$F$13&quot;
  2645. Dim sShift As String &apos; Return value
  2646. Dim oSourceAddress As Object &apos; Alias of Range as _Address
  2647. Dim lHeight As Long &apos; Range height
  2648. Dim oShiftAddress As Object &apos; com.sun.star.table.CellRangeAddress - Range adjusted to the right width
  2649. Dim lShiftMode As Long &apos; One of the com.sun.star.sheet.CellInsertMode enum values
  2650. Const cstThisSub = &quot;SFDocuments.Calc.ShiftDown&quot;
  2651. Const cstSubArgs = &quot;Range, [WholeRow=False], [Rows]&quot;
  2652. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2653. sShift = &quot;&quot;
  2654. Check:
  2655. If IsMissing(WholeRow) Or IsEmpty(WholeRow) Then WholeRow = False
  2656. If IsMissing(Rows) Or IsEmpty(Rows) Then Rows = 0
  2657. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2658. If Not _IsStillAlive(True) Then GoTo Finally
  2659. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  2660. If Not ScriptForge.SF_Utils._Validate(WholeRow, &quot;WholeRow&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2661. If Not ScriptForge.SF_Utils._Validate(Rows, &quot;Rows&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2662. End If
  2663. Try:
  2664. Set oSourceAddress = _ParseAddress(Range)
  2665. With oSourceAddress
  2666. &apos; Manage the height of the area to shift
  2667. &apos; The insertCells() method inserts a number of rows equal to the height of the cell range to shift
  2668. lHeight = .Height
  2669. If Rows &lt;= 0 Then Rows = lHeight
  2670. If _LastCell(.XSpreadsheet)(1) + Rows &gt; MAXROWS Then GoTo Catch
  2671. If Rows &lt;&gt; lHeight Then
  2672. Set oShiftAddress = _Offset(oSourceAddress, 0, 0, Rows, 0).XCellRange.RangeAddress
  2673. Else
  2674. Set oShiftAddress = .XCellRange.RangeAddress
  2675. End If
  2676. &apos; Determine the shift mode
  2677. With com.sun.star.sheet.CellInsertMode
  2678. If WholeRow Then lShiftMode = .ROWS Else lShiftMode = .DOWN
  2679. End With
  2680. &apos; Move the cells as requested. This modifies .XCellRange
  2681. .XSpreadsheet.insertCells(oShiftAddress, lShiftMode)
  2682. &apos; Determine the receiving area
  2683. sShift = .XCellRange.AbsoluteName
  2684. End With
  2685. Finally:
  2686. ShiftDown = sShift
  2687. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2688. Exit Function
  2689. Catch:
  2690. &apos; When error, return the original range
  2691. If Not IsNull(oSourceAddress) Then sShift = oSourceAddress.RangeName
  2692. GoTo Finally
  2693. End Function &apos; SFDocuments.SF_Calc.ShiftDown
  2694. REM -----------------------------------------------------------------------------
  2695. Public Function ShiftLeft(Optional ByVal Range As Variant _
  2696. , Optional ByVal WholeColumn As Variant _
  2697. , Optional ByVal Columns As Variant _
  2698. ) As String
  2699. &apos;&apos;&apos; Delete the leftmost columns of a specified range and move all cells at their right leftwards
  2700. &apos;&apos;&apos; The deleted cells can span whole columns or be limited to the height of the range
  2701. &apos;&apos;&apos; The width of the deleted area is provided by the Columns argument
  2702. &apos;&apos;&apos; The execution of the method has no effect on the current selection
  2703. &apos;&apos;&apos; Args:
  2704. &apos;&apos;&apos; Range: the range in which cells have to be erased, as a string
  2705. &apos;&apos;&apos; WholeColumn: when True (default = False), erase whole columns
  2706. &apos;&apos;&apos; Columns: the width of the area to delete.
  2707. &apos;&apos;&apos; Default = the width of the Range argument, it is also its maximum value
  2708. &apos;&apos;&apos; Returns:
  2709. &apos;&apos;&apos; A string representing the location of the remaining part of the initial range,
  2710. &apos;&apos;&apos; or the zero-length string if the whole range has been deleted
  2711. &apos;&apos;&apos; Examples:
  2712. &apos;&apos;&apos; newrange = oDoc.ShiftLeft(&quot;SheetX.G1:L10&quot;) &apos; &quot;&quot;&quot;
  2713. &apos;&apos;&apos; newrange = oDoc.ShiftLeft(&quot;SheetX.G1:L10&quot;, Columns := 3) &apos; &quot;$SheetX.$G$1:$I$10&quot;
  2714. Dim sShift As String &apos; Return value
  2715. Dim oSourceAddress As Object &apos; Alias of Range as _Address
  2716. Dim lWidth As Long &apos; Range width
  2717. Dim oShiftAddress As Object &apos; com.sun.star.table.CellRangeAddress - Range adjusted to the right width
  2718. Dim lShiftMode As Long &apos; One of the com.sun.star.sheet.CellDeleteMode enum values
  2719. Const cstThisSub = &quot;SFDocuments.Calc.ShiftLeft&quot;
  2720. Const cstSubArgs = &quot;Range, [WholeColumn=False], [Columns]&quot;
  2721. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2722. sShift = &quot;&quot;
  2723. Check:
  2724. If IsMissing(WholeColumn) Or IsEmpty(WholeColumn) Then WholeColumn = False
  2725. If IsMissing(Columns) Or IsEmpty(Columns) Then Columns = 0
  2726. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2727. If Not _IsStillAlive(True) Then GoTo Finally
  2728. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  2729. If Not ScriptForge.SF_Utils._Validate(WholeColumn, &quot;WholeColumn&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2730. If Not ScriptForge.SF_Utils._Validate(Columns, &quot;Columns&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2731. End If
  2732. Try:
  2733. Set oSourceAddress = _ParseAddress(Range)
  2734. Set _LastParsedAddress = Nothing &apos; Range will be erased. Force re-parsing next time
  2735. With oSourceAddress
  2736. &apos; Manage the width of the area to delete
  2737. &apos; The removeRange() method erases a number of columns equal to the width of the cell range to delete
  2738. lWidth = .Width
  2739. If Columns &lt;= 0 Then Columns = lWidth
  2740. If Columns &lt; lWidth Then
  2741. Set oShiftAddress = _Offset(oSourceAddress, 0, 0, 0, Columns).XCellRange.RangeAddress
  2742. Else &apos; Columns is capped at the range width
  2743. Set oShiftAddress = .XCellRange.RangeAddress
  2744. End If
  2745. &apos; Determine the Delete mode
  2746. With com.sun.star.sheet.CellDeleteMode
  2747. If WholeColumn Then lShiftMode = .COLUMNS Else lShiftMode = .LEFT
  2748. End With
  2749. &apos; Move the cells as requested. This modifies .XCellRange
  2750. .XSpreadsheet.removeRange(oShiftAddress, lShiftMode)
  2751. &apos; Determine the remaining area
  2752. If Columns &lt; lWidth Then sShift = .XCellRange.AbsoluteName
  2753. End With
  2754. Finally:
  2755. ShiftLeft = sShift
  2756. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2757. Exit Function
  2758. Catch:
  2759. &apos; When error, return the original range
  2760. If Not IsNull(oSourceAddress) Then sShift = oSourceAddress.RangeName
  2761. GoTo Finally
  2762. End Function &apos; SFDocuments.SF_Calc.ShiftLeft
  2763. REM -----------------------------------------------------------------------------
  2764. Public Function ShiftRight(Optional ByVal Range As Variant _
  2765. , Optional ByVal WholeColumn As Variant _
  2766. , Optional ByVal Columns As Variant _
  2767. ) As String
  2768. &apos;&apos;&apos; Move a specified range and all next cells in the same rows to the right by inserting empty cells
  2769. &apos;&apos;&apos; The inserted cells can span whole columns or be limited to the height of the range
  2770. &apos;&apos;&apos; The width of the inserted area is provided by the Columns argument
  2771. &apos;&apos;&apos; Nothing happens if the range shift crosses one of the edges of the worksheet
  2772. &apos;&apos;&apos; The execution of the method has no effect on the current selection
  2773. &apos;&apos;&apos; Args:
  2774. &apos;&apos;&apos; Range: the range before which cells have to be inserted, as a string
  2775. &apos;&apos;&apos; WholeColumn: when True (default = False), insert whole columns
  2776. &apos;&apos;&apos; Columns: the width of the area to insert. Default = the width of the Range argument
  2777. &apos;&apos;&apos; Returns:
  2778. &apos;&apos;&apos; A string representing the new location of the initial range
  2779. &apos;&apos;&apos; Examples:
  2780. &apos;&apos;&apos; newrange = oDoc.ShiftRight(&quot;SheetX.A1:F10&quot;) &apos; &quot;$SheetX.$G$1:$L$10&quot;
  2781. &apos;&apos;&apos; newrange = oDoc.ShiftRight(&quot;SheetX.A1:F10&quot;, Columns := 3) &apos; &quot;$SheetX.$D$1:$I$10&quot;
  2782. Dim sShift As String &apos; Return value
  2783. Dim oSourceAddress As Object &apos; Alias of Range as _Address
  2784. Dim lWidth As Long &apos; Range width
  2785. Dim oShiftAddress As Object &apos; com.sun.star.table.CellRangeAddress - Range adjusted to the right width
  2786. Dim lShiftMode As Long &apos; One of the com.sun.star.sheet.CellInsertMode enum values
  2787. Const cstThisSub = &quot;SFDocuments.Calc.ShiftRight&quot;
  2788. Const cstSubArgs = &quot;Range, [WholeColumn=False], [Columns]&quot;
  2789. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2790. sShift = &quot;&quot;
  2791. Check:
  2792. If IsMissing(WholeColumn) Or IsEmpty(WholeColumn) Then WholeColumn = False
  2793. If IsMissing(Columns) Or IsEmpty(Columns) Then Columns = 0
  2794. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2795. If Not _IsStillAlive(True) Then GoTo Finally
  2796. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  2797. If Not ScriptForge.SF_Utils._Validate(WholeColumn, &quot;WholeColumn&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2798. If Not ScriptForge.SF_Utils._Validate(Columns, &quot;Columns&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2799. End If
  2800. Try:
  2801. Set oSourceAddress = _ParseAddress(Range)
  2802. With oSourceAddress
  2803. &apos; Manage the width of the area to Shift
  2804. &apos; The insertCells() method inserts a number of columns equal to the width of the cell range to Shift
  2805. lWidth = .Width
  2806. If Columns &lt;= 0 Then Columns = lWidth
  2807. If _LastCell(.XSpreadsheet)(0) + Columns &gt; MAXCOLS Then GoTo Catch
  2808. If Columns &lt;&gt; lWidth Then
  2809. Set oShiftAddress = _Offset(oSourceAddress, 0, 0, 0, Columns).XCellRange.RangeAddress
  2810. Else
  2811. Set oShiftAddress = .XCellRange.RangeAddress
  2812. End If
  2813. &apos; Determine the Shift mode
  2814. With com.sun.star.sheet.CellInsertMode
  2815. If WholeColumn Then lShiftMode = .COLUMNS Else lShiftMode = .RIGHT
  2816. End With
  2817. &apos; Move the cells as requested. This modifies .XCellRange
  2818. .XSpreadsheet.insertCells(oShiftAddress, lShiftMode)
  2819. &apos; Determine the receiving area
  2820. sShift = .XCellRange.AbsoluteName
  2821. End With
  2822. Finally:
  2823. ShiftRight = sShift
  2824. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2825. Exit Function
  2826. Catch:
  2827. &apos; When error, return the original range
  2828. If Not IsNull(oSourceAddress) Then sShift = oSourceAddress.RangeName
  2829. GoTo Finally
  2830. End Function &apos; SFDocuments.SF_Calc.ShiftRight
  2831. REM -----------------------------------------------------------------------------
  2832. Public Function ShiftUp(Optional ByVal Range As Variant _
  2833. , Optional ByVal WholeRow As Variant _
  2834. , Optional ByVal Rows As Variant _
  2835. ) As String
  2836. &apos;&apos;&apos; Delete the topmost rows of a specified range and move all cells below upwards
  2837. &apos;&apos;&apos; The deleted cells can span whole rows or be limited to the width of the range
  2838. &apos;&apos;&apos; The height of the deleted area is provided by the Rows argument
  2839. &apos;&apos;&apos; The execution of the method has no effect on the current selection
  2840. &apos;&apos;&apos; Args:
  2841. &apos;&apos;&apos; Range: the range in which cells have to be erased, as a string
  2842. &apos;&apos;&apos; WholeRow: when True (default = False), erase whole rows
  2843. &apos;&apos;&apos; Rows: the height of the area to delete.
  2844. &apos;&apos;&apos; Default = the height of the Range argument, it is also its maximum value
  2845. &apos;&apos;&apos; Returns:
  2846. &apos;&apos;&apos; A string representing the location of the remaining part of the initial range,
  2847. &apos;&apos;&apos; or the zero-length string if the whole range has been deleted
  2848. &apos;&apos;&apos; Examples:
  2849. &apos;&apos;&apos; newrange = oDoc.ShiftUp(&quot;SheetX.G1:L10&quot;) &apos; &quot;&quot;
  2850. &apos;&apos;&apos; newrange = oDoc.ShiftUp(&quot;SheetX.G1:L10&quot;, Rows := 3) &apos; &quot;$SheetX.$G$1:$I$10&quot;
  2851. Dim sShift As String &apos; Return value
  2852. Dim oSourceAddress As Object &apos; Alias of Range as _Address
  2853. Dim lHeight As Long &apos; Range height
  2854. Dim oShiftAddress As Object &apos; com.sun.star.table.CellRangeAddress - Range adjusted to the right height
  2855. Dim lShiftMode As Long &apos; One of the com.sun.star.sheet.CellDeleteMode enum values
  2856. Const cstThisSub = &quot;SFDocuments.Calc.ShiftUp&quot;
  2857. Const cstSubArgs = &quot;Range, [WholeRow=False], [Rows]&quot;
  2858. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2859. sShift = &quot;&quot;
  2860. Check:
  2861. If IsMissing(WholeRow) Or IsEmpty(WholeRow) Then WholeRow = False
  2862. If IsMissing(Rows) Or IsEmpty(Rows) Then Rows = 0
  2863. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2864. If Not _IsStillAlive(True) Then GoTo Finally
  2865. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  2866. If Not ScriptForge.SF_Utils._Validate(WholeRow, &quot;WholeRow&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2867. If Not ScriptForge.SF_Utils._Validate(Rows, &quot;Rows&quot;, ScriptForge.V_NUMERIC) Then GoTo Finally
  2868. End If
  2869. Try:
  2870. Set oSourceAddress = _ParseAddress(Range)
  2871. Set _LastParsedAddress = Nothing &apos; Range will be erased. Force re-parsing next time
  2872. With oSourceAddress
  2873. &apos; Manage the height of the area to delete
  2874. &apos; The removeRange() method erases a number of rows equal to the height of the cell range to delete
  2875. lHeight = .Height
  2876. If Rows &lt;= 0 Then Rows = lHeight
  2877. If Rows &lt; lHeight Then
  2878. Set oShiftAddress = _Offset(oSourceAddress, 0, 0, Rows, 0).XCellRange.RangeAddress
  2879. Else &apos; Rows is capped at the range height
  2880. Set oShiftAddress = .XCellRange.RangeAddress
  2881. End If
  2882. &apos; Determine the Delete mode
  2883. With com.sun.star.sheet.CellDeleteMode
  2884. If WholeRow Then lShiftMode = .ROWS Else lShiftMode = .UP
  2885. End With
  2886. &apos; Move the cells as requested. This modifies .XCellRange
  2887. .XSpreadsheet.removeRange(oShiftAddress, lShiftMode)
  2888. &apos; Determine the remaining area
  2889. If Rows &lt; lHeight Then sShift = .XCellRange.AbsoluteName
  2890. End With
  2891. Finally:
  2892. ShiftUp = sShift
  2893. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  2894. Exit Function
  2895. Catch:
  2896. &apos; When error, return the original range
  2897. If Not IsNull(oSourceAddress) Then sShift = oSourceAddress.RangeName
  2898. GoTo Finally
  2899. End Function &apos; SFDocuments.SF_Calc.ShiftUp
  2900. REM -----------------------------------------------------------------------------
  2901. Public Function SortRange(Optional ByVal Range As Variant _
  2902. , Optional ByVal SortKeys As Variant _
  2903. , Optional ByVal SortOrder As Variant _
  2904. , Optional ByVal DestinationCell As Variant _
  2905. , Optional ByVal ContainsHeader As Variant _
  2906. , Optional ByVal CaseSensitive As Variant _
  2907. , Optional ByVal SortColumns As Variant _
  2908. ) As Variant
  2909. &apos;&apos;&apos; Sort the given range on maximum 3 columns/rows. The sorting order may vary by column/row
  2910. &apos;&apos;&apos; Args:
  2911. &apos;&apos;&apos; Range: the range to sort as a string
  2912. &apos;&apos;&apos; SortKeys: a scalar (if 1 column/row) or an array of column/row numbers starting from 1
  2913. &apos;&apos;&apos; SortOrder: a scalar or an array of strings: &quot;ASC&quot; or &quot;DESC&quot;
  2914. &apos;&apos;&apos; Each item is paired with the corresponding item in SortKeys
  2915. &apos;&apos;&apos; If the SortOrder array is shorter than SortKeys, the remaining keys are sorted
  2916. &apos;&apos;&apos; in ascending order
  2917. &apos;&apos;&apos; DestinationCell: the destination of the sorted range of cells, as a string
  2918. &apos;&apos;&apos; If given as range, the destination will be reduced to its top-left cell
  2919. &apos;&apos;&apos; By default, Range is overwritten with its sorted content
  2920. &apos;&apos;&apos; ContainsHeader: when True, the first row/column is not sorted. Default = False
  2921. &apos;&apos;&apos; CaseSensitive: only for string comparisons, default = False
  2922. &apos;&apos;&apos; SortColumns: when True, the columns are sorted from left to right
  2923. &apos;&apos;&apos; Default = False: rows are sorted from top to bottom.
  2924. &apos;&apos;&apos; Returns:
  2925. &apos;&apos;&apos; The modified range of cells as a string
  2926. &apos;&apos;&apos; Example:
  2927. &apos;&apos;&apos; oDoc.SortRange(&quot;A2:J200&quot;, Array(1, 3), , Array(&quot;ASC&quot;, &quot;DESC&quot;), CaseSensitive := True)
  2928. &apos;&apos;&apos; &apos; Sort on columns A (ascending) and C (descending)
  2929. Dim sSort As String &apos; Return value
  2930. Dim oRangeAddress As _Address &apos; Parsed range
  2931. Dim oRange As Object &apos; com.sun.star.table.XCellRange
  2932. Dim oDestRange As Object &apos; Destination as a range
  2933. Dim oDestAddress As Object &apos; com.sun.star.table.CellRangeAddress
  2934. Dim oDestCell As Object &apos; com.sun.star.table.CellAddress
  2935. Dim vSortDescriptor As Variant &apos; Array of com.sun.star.beans.PropertyValue
  2936. Dim vSortFields As Variant &apos; Array of com.sun.star.table.TableSortField
  2937. Dim sOrder As String &apos; Item in SortOrder
  2938. Dim i As Long
  2939. Const cstThisSub = &quot;SFDocuments.Calc.SortRange&quot;
  2940. Const cstSubArgs = &quot;Range, SortKeys, [TargetRange=&quot;&quot;&quot;&quot;], [SortOrder=&quot;&quot;ASC&quot;&quot;], [DestinationCell=&quot;&quot;&quot;&quot;], [ContainsHeader=False], [CaseSensitive=False], [SortColumns=False]&quot;
  2941. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  2942. sSort = &quot;&quot;
  2943. Check:
  2944. If IsMissing(SortKeys) Or IsEmpty(SortKeys) Then
  2945. SortKeys = Array(1)
  2946. ElseIf Not IsArray(SortKeys) Then
  2947. SortKeys = Array(SortKeys)
  2948. End If
  2949. If IsMissing(DestinationCell) Or IsEmpty(DestinationCell) Then DestinationCell = &quot;&quot;
  2950. If IsMissing(SortOrder) Or IsEmpty(SortOrder) Then
  2951. SortOrder = Array(&quot;ASC&quot;)
  2952. ElseIf Not IsArray(SortOrder) Then
  2953. SortOrder = Array(SortOrder)
  2954. End If
  2955. If IsMissing(ContainsHeader) Or IsEmpty(ContainsHeader) Then ContainsHeader = False
  2956. If IsMissing(CaseSensitive) Or IsEmpty(CaseSensitive) Then CaseSensitive = False
  2957. If IsMissing(SortColumns) Or IsEmpty(SortColumns) Then SortColumns = False
  2958. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  2959. If Not _IsStillAlive() Then GoTo Finally
  2960. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  2961. If Not ScriptForge.SF_Utils._ValidateArray(SortKeys, &quot;SortKeys&quot;, 1, V_NUMERIC, True) Then GoTo Finally
  2962. If Not ScriptForge.SF_Utils._Validate(DestinationCell, &quot;DestinationCell&quot;, V_STRING) Then GoTo Finally
  2963. If Not ScriptForge.SF_Utils._ValidateArray(SortOrder, &quot;SortOrder&quot;, 1, V_STRING, True) Then GoTo Finally
  2964. If Not ScriptForge.SF_Utils._Validate(ContainsHeader, &quot;ContainsHeader&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2965. If Not ScriptForge.SF_Utils._Validate(CaseSensitive, &quot;CaseSensitive&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2966. If Not ScriptForge.SF_Utils._Validate(SortColumns, &quot;SortColumns&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
  2967. End If
  2968. Set oRangeAddress = _ParseAddress(Range)
  2969. If Len(DestinationCell) &gt; 0 Then Set oDestRange = _ParseAddress(DestinationCell)
  2970. Try:
  2971. &apos; Initialize the sort descriptor
  2972. Set oRange = oRangeAddress.XCellRange
  2973. vSortDescriptor = oRange.createSortDescriptor
  2974. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;IsSortColumns&quot;, SortColumns)
  2975. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;ContainsHeader&quot;, ContainsHeader)
  2976. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;BindFormatsToContent&quot;, True)
  2977. If Len(DestinationCell) = 0 Then
  2978. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;CopyOutputData&quot;, False)
  2979. Else
  2980. Set oDestAddress = oDestRange.XCellRange.RangeAddress
  2981. Set oDestCell = New com.sun.star.table.CellAddress
  2982. With oDestAddress
  2983. oDestCell.Sheet = .Sheet
  2984. oDestCell.Column = .StartColumn
  2985. oDestCell.Row = .StartRow
  2986. End With
  2987. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;CopyOutputData&quot;, True)
  2988. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;OutputPosition&quot;, oDestCell)
  2989. End If
  2990. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;IsUserListEnabled&quot;, False)
  2991. &apos; Define the sorting keys
  2992. vSortFields = Array()
  2993. ReDim vSortFields(0 To UBound(SortKeys))
  2994. For i = 0 To UBound(SortKeys)
  2995. vSortFields(i) = New com.sun.star.table.TableSortField
  2996. If i &gt; UBound(SortOrder) Then sOrder = &quot;&quot; Else sOrder = SortOrder(i)
  2997. If Len(sOrder) = 0 Then sOrder = &quot;ASC&quot;
  2998. With vSortFields(i)
  2999. .Field = SortKeys(i) - 1
  3000. .IsAscending = ( UCase(sOrder) = &quot;ASC&quot; )
  3001. .IsCaseSensitive = CaseSensitive
  3002. End With
  3003. Next i
  3004. &apos; Associate the keys and the descriptor, and sort
  3005. vSortDescriptor = ScriptForge.SF_Utils._SetPropertyValue(vSortDescriptor, &quot;SortFields&quot;, vSortFields)
  3006. oRange.sort(vSortDescriptor)
  3007. &apos; Compute the changed area
  3008. If Len(DestinationCell) = 0 Then
  3009. sSort = oRangeAddress.RangeName
  3010. Else
  3011. With oRangeAddress
  3012. sSort = _Offset(oDestRange, 0, 0, .Height, .Width).RangeName
  3013. End With
  3014. End If
  3015. Finally:
  3016. SortRange = sSort
  3017. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  3018. Exit Function
  3019. Catch:
  3020. GoTo Finally
  3021. End Function &apos; SFDocuments.SF_Calc.SortRange
  3022. REM ======================================================= SUPERCLASS PROPERTIES
  3023. REM -----------------------------------------------------------------------------
  3024. Property Get CustomProperties() As Variant
  3025. CustomProperties = [_Super].GetProperty(&quot;CustomProperties&quot;)
  3026. End Property &apos; SFDocuments.SF_Calc.CustomProperties
  3027. REM -----------------------------------------------------------------------------
  3028. Property Let CustomProperties(Optional ByVal pvCustomProperties As Variant)
  3029. [_Super].CustomProperties = pvCustomProperties
  3030. End Property &apos; SFDocuments.SF_Calc.CustomProperties
  3031. REM -----------------------------------------------------------------------------
  3032. Property Get Description() As Variant
  3033. Description = [_Super].GetProperty(&quot;Description&quot;)
  3034. End Property &apos; SFDocuments.SF_Calc.Description
  3035. REM -----------------------------------------------------------------------------
  3036. Property Let Description(Optional ByVal pvDescription As Variant)
  3037. [_Super].Description = pvDescription
  3038. End Property &apos; SFDocuments.SF_Calc.Description
  3039. REM -----------------------------------------------------------------------------
  3040. Property Get DocumentProperties() As Variant
  3041. DocumentProperties = [_Super].GetProperty(&quot;DocumentProperties&quot;)
  3042. End Property &apos; SFDocuments.SF_Calc.DocumentProperties
  3043. REM -----------------------------------------------------------------------------
  3044. Property Get DocumentType() As String
  3045. DocumentType = [_Super].GetProperty(&quot;DocumentType&quot;)
  3046. End Property &apos; SFDocuments.SF_Calc.DocumentType
  3047. REM -----------------------------------------------------------------------------
  3048. Property Get ExportFilters() As Variant
  3049. ExportFilters = [_Super].GetProperty(&quot;ExportFilters&quot;)
  3050. End Property &apos; SFDocuments.SF_Calc.ExportFilters
  3051. REM -----------------------------------------------------------------------------
  3052. Property Get ImportFilters() As Variant
  3053. ImportFilters = [_Super].GetProperty(&quot;ImportFilters&quot;)
  3054. End Property &apos; SFDocuments.SF_Calc.ImportFilters
  3055. REM -----------------------------------------------------------------------------
  3056. Property Get IsBase() As Boolean
  3057. IsBase = [_Super].GetProperty(&quot;IsBase&quot;)
  3058. End Property &apos; SFDocuments.SF_Calc.IsBase
  3059. REM -----------------------------------------------------------------------------
  3060. Property Get IsCalc() As Boolean
  3061. IsCalc = [_Super].GetProperty(&quot;IsCalc&quot;)
  3062. End Property &apos; SFDocuments.SF_Calc.IsCalc
  3063. REM -----------------------------------------------------------------------------
  3064. Property Get IsDraw() As Boolean
  3065. IsDraw = [_Super].GetProperty(&quot;IsDraw&quot;)
  3066. End Property &apos; SFDocuments.SF_Calc.IsDraw
  3067. REM -----------------------------------------------------------------------------
  3068. Property Get IsImpress() As Boolean
  3069. IsImpress = [_Super].GetProperty(&quot;IsImpress&quot;)
  3070. End Property &apos; SFDocuments.SF_Calc.IsImpress
  3071. REM -----------------------------------------------------------------------------
  3072. Property Get IsMath() As Boolean
  3073. IsMath = [_Super].GetProperty(&quot;IsMath&quot;)
  3074. End Property &apos; SFDocuments.SF_Calc.IsMath
  3075. REM -----------------------------------------------------------------------------
  3076. Property Get IsWriter() As Boolean
  3077. IsWriter = [_Super].GetProperty(&quot;IsWriter&quot;)
  3078. End Property &apos; SFDocuments.SF_Calc.IsWriter
  3079. REM -----------------------------------------------------------------------------
  3080. Property Get Keywords() As Variant
  3081. Keywords = [_Super].GetProperty(&quot;Keywords&quot;)
  3082. End Property &apos; SFDocuments.SF_Calc.Keywords
  3083. REM -----------------------------------------------------------------------------
  3084. Property Let Keywords(Optional ByVal pvKeywords As Variant)
  3085. [_Super].Keywords = pvKeywords
  3086. End Property &apos; SFDocuments.SF_Calc.Keywords
  3087. REM -----------------------------------------------------------------------------
  3088. Property Get Readonly() As Variant
  3089. Readonly = [_Super].GetProperty(&quot;Readonly&quot;)
  3090. End Property &apos; SFDocuments.SF_Calc.Readonly
  3091. REM -----------------------------------------------------------------------------
  3092. Property Get Subject() As Variant
  3093. Subject = [_Super].GetProperty(&quot;Subject&quot;)
  3094. End Property &apos; SFDocuments.SF_Calc.Subject
  3095. REM -----------------------------------------------------------------------------
  3096. Property Let Subject(Optional ByVal pvSubject As Variant)
  3097. [_Super].Subject = pvSubject
  3098. End Property &apos; SFDocuments.SF_Calc.Subject
  3099. REM -----------------------------------------------------------------------------
  3100. Property Get Title() As Variant
  3101. Title = [_Super].GetProperty(&quot;Title&quot;)
  3102. End Property &apos; SFDocuments.SF_Calc.Title
  3103. REM -----------------------------------------------------------------------------
  3104. Property Let Title(Optional ByVal pvTitle As Variant)
  3105. [_Super].Title = pvTitle
  3106. End Property &apos; SFDocuments.SF_Calc.Title
  3107. REM -----------------------------------------------------------------------------
  3108. Property Get XComponent() As Variant
  3109. XComponent = [_Super].GetProperty(&quot;XComponent&quot;)
  3110. End Property &apos; SFDocuments.SF_Calc.XComponent
  3111. REM ========================================================== SUPERCLASS METHODS
  3112. REM -----------------------------------------------------------------------------
  3113. &apos;Public Function Activate() As Boolean
  3114. &apos; Activate = [_Super].Activate()
  3115. &apos;End Function &apos; SFDocuments.SF_Calc.Activate
  3116. REM -----------------------------------------------------------------------------
  3117. Public Function CloseDocument(Optional ByVal SaveAsk As Variant) As Boolean
  3118. CloseDocument = [_Super].CloseDocument(SaveAsk)
  3119. End Function &apos; SFDocuments.SF_Calc.CloseDocument
  3120. REM -----------------------------------------------------------------------------
  3121. Public Function CreateMenu(Optional ByVal MenuHeader As Variant _
  3122. , Optional ByVal Before As Variant _
  3123. , Optional ByVal SubmenuChar As Variant _
  3124. ) As Object
  3125. Set CreateMenu = [_Super].CreateMenu(MenuHeader, Before, SubmenuChar)
  3126. End Function &apos; SFDocuments.SF_Calc.CreateMenu
  3127. REM -----------------------------------------------------------------------------
  3128. Public Function ExportAsPDF(Optional ByVal FileName As Variant _
  3129. , Optional ByVal Overwrite As Variant _
  3130. , Optional ByVal Pages As Variant _
  3131. , Optional ByVal Password As Variant _
  3132. , Optional ByVal Watermark As Variant _
  3133. ) As Boolean
  3134. ExportAsPDF = [_Super].ExportAsPDF(FileName, Overwrite, Pages, Password, Watermark)
  3135. End Function &apos; SFDocuments.SF_Calc.ExportAsPDF
  3136. REM -----------------------------------------------------------------------------
  3137. Public Function RemoveMenu(Optional ByVal MenuHeader As Variant) As Boolean
  3138. RemoveMenu = [_Super].RemoveMenu(MenuHeader)
  3139. End Function &apos; SFDocuments.SF_Calc.RemoveMenu
  3140. REM -----------------------------------------------------------------------------
  3141. Public Sub RunCommand(Optional ByVal Command As Variant _
  3142. , ParamArray Args As Variant _
  3143. )
  3144. [_Super].RunCommand(Command, Args)
  3145. End Sub &apos; SFDocuments.SF_Calc.RunCommand
  3146. REM -----------------------------------------------------------------------------
  3147. Public Function Save() As Boolean
  3148. Save = [_Super].Save()
  3149. End Function &apos; SFDocuments.SF_Calc.Save
  3150. REM -----------------------------------------------------------------------------
  3151. Public Function SaveAs(Optional ByVal FileName As Variant _
  3152. , Optional ByVal Overwrite As Variant _
  3153. , Optional ByVal Password As Variant _
  3154. , Optional ByVal FilterName As Variant _
  3155. , Optional ByVal FilterOptions As Variant _
  3156. ) As Boolean
  3157. SaveAs = [_Super].SaveAs(FileName, Overwrite, Password, FilterName, FilterOptions)
  3158. End Function &apos; SFDocuments.SF_Calc.SaveAs
  3159. REM -----------------------------------------------------------------------------
  3160. Public Function SaveCopyAs(Optional ByVal FileName As Variant _
  3161. , Optional ByVal Overwrite As Variant _
  3162. , Optional ByVal Password As Variant _
  3163. , Optional ByVal FilterName As Variant _
  3164. , Optional ByVal FilterOptions As Variant _
  3165. ) As Boolean
  3166. SaveCopyAs = [_Super].SaveCopyAs(FileName, Overwrite, Password, FilterName, FilterOptions)
  3167. End Function &apos; SFDocuments.SF_Calc.SaveCopyAs
  3168. REM -----------------------------------------------------------------------------
  3169. Public Function SetPrinter(Optional ByVal Printer As Variant _
  3170. , Optional ByVal Orientation As Variant _
  3171. , Optional ByVal PaperFormat As Variant _
  3172. ) As Boolean
  3173. SetPrinter = [_Super].SetPrinter(Printer, Orientation, PaperFormat)
  3174. End Function &apos; SFDocuments.SF_Calc.SetPrinter
  3175. REM =========================================================== PRIVATE FUNCTIONS
  3176. REM -----------------------------------------------------------------------------
  3177. Private Sub _ClearRange(ByVal psTarget As String _
  3178. , Optional ByVal Range As Variant _
  3179. , Optional FilterFormula As Variant _
  3180. , Optional FilterScope As Variant _
  3181. )
  3182. &apos;&apos;&apos; Clear the given range with the given options
  3183. &apos;&apos;&apos; The range may be filtered by a formula for a selective clearance
  3184. &apos;&apos;&apos; Arguments checking is done in this Sub, not in the calling one
  3185. &apos;&apos;&apos; Args:
  3186. &apos;&apos;&apos; psTarget: &quot;All&quot;, &quot;Formats&quot; or &quot;Values&quot;
  3187. &apos;&apos;&apos; Range: the range to clear as a string
  3188. &apos;&apos;&apos; FilterFormula: a selection of cells based on a Calc formula
  3189. &apos;&apos;&apos; When left empty, all the cells of the range are cleared
  3190. &apos;&apos;&apos; psFilterScope: &quot;CELL&quot;, &quot;ROW&quot; or &quot;COLUMN&quot;
  3191. Dim lClear As Long &apos; A combination of com.sun.star.sheet.CellFlags
  3192. Dim oRange As Object &apos; Alias of Range
  3193. Dim vRanges() As Variant &apos; Array of subranges resulting from the application of the filter
  3194. Dim i As Long
  3195. Dim cstThisSub As String : cstThisSub = &quot;SFDocuments.Calc.Clear&quot; &amp; psTarget
  3196. Const cstSubArgs = &quot;Range, [FilterFormula=&quot;&quot;], [FilterScope=&quot;&quot;CELL&quot;&quot;|&quot;&quot;ROW&quot;&quot;|&quot;&quot;COLUMN&quot;&quot;]&quot;
  3197. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  3198. Check:
  3199. If IsMissing(FilterFormula) Or IsEmpty(FilterFormula) Then FilterFormula = &quot;&quot;
  3200. If IsMissing(FilterScope) Or IsEmpty(FilterScope) Then FilterScope = &quot;CELL&quot;
  3201. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  3202. If Not _IsStillAlive() Then GoTo Finally
  3203. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, Array(V_STRING, ScriptForge.V_OBJECT)) Then GoTo Finally
  3204. If Not ScriptForge.SF_Utils._Validate(FilterFormula, &quot;FilterFormula&quot;, V_STRING) Then GoTo Finally
  3205. If Len(FilterFormula) &gt; 0 Then
  3206. If Not ScriptForge.SF_Utils._Validate(FilterScope, &quot;FilterScope&quot;, V_STRING, Array(&quot;CELL&quot;, &quot;ROW&quot;, &quot;COLUMN&quot;)) Then GoTo Finally
  3207. Else
  3208. If Not ScriptForge.SF_Utils._Validate(FilterScope, &quot;FilterScope&quot;, V_STRING) Then GoTo Finally
  3209. End If
  3210. End If
  3211. Try:
  3212. With com.sun.star.sheet.CellFlags
  3213. Select Case psTarget
  3214. Case &quot;All&quot;
  3215. lClear = .VALUE + .DATETIME + .STRING + .ANNOTATION + .FORMULA _
  3216. + .HARDATTR + .STYLES + .OBJECTS + .EDITATTR + .FORMATTED
  3217. Case &quot;Formats&quot;
  3218. lClear = .HARDATTR + .STYLES + .EDITATTR + .FORMATTED
  3219. Case &quot;Values&quot;
  3220. lClear = .VALUE + .DATETIME + .STRING + .FORMULA
  3221. End Select
  3222. End With
  3223. If VarType(Range) = V_STRING Then Set oRange = _ParseAddress(Range) Else Set oRange = Range
  3224. &apos; Without filter, the whole range is cleared
  3225. &apos; Otherwise the filter cuts the range in subranges and clears them one by one
  3226. If Len(FilterFormula) = 0 Then
  3227. oRange.XCellRange.clearContents(lClear)
  3228. Else
  3229. vRanges() = _ComputeFilter(oRange, FilterFormula, UCase(FilterScope))
  3230. For i = 0 To UBound(vRanges)
  3231. vRanges(i).XCellRange.clearContents(lClear)
  3232. Next i
  3233. End If
  3234. Finally:
  3235. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  3236. Exit Sub
  3237. Catch:
  3238. GoTo Finally
  3239. End Sub &apos; SFDocuments.SF_Calc._ClearRange
  3240. REM -----------------------------------------------------------------------------
  3241. Private Function _ComputeFilter(ByRef poRange As Object _
  3242. , ByVal psFilterFormula As String _
  3243. , ByVal psFilterScope As String _
  3244. ) As Variant
  3245. &apos;&apos;&apos; Compute in the given range the cells, rows or columns for which
  3246. &apos;&apos;&apos; the given formula returns TRUE
  3247. &apos;&apos;&apos; Args:
  3248. &apos;&apos;&apos; poRange: the range on which to compute the filter as an _Address type
  3249. &apos;&apos;&apos; psFilterFormula: the formula to be applied on each row, column or cell
  3250. &apos;&apos;&apos; psFilterSCope: &quot;ROW&quot;, &quot;COLUMN&quot; or &quot;CELL&quot;
  3251. &apos;&apos;&apos; Returns:
  3252. &apos;&apos;&apos; An array of ranges as objects of type _Address
  3253. Dim vRanges As Variant &apos; Return value
  3254. Dim oRange As Object &apos; A single vRanges() item
  3255. Dim lLast As Long &apos; Last used row or column number in the sheet containing Range
  3256. Dim oFormulaRange As _Address &apos; Range where the FilterFormula must be stored
  3257. Dim sFormulaDirection As String &apos; Either V(ertical), H(orizontal) or B(oth)
  3258. Dim vDataArray As Variant &apos; DataArray compatible with .DataArray UNO property
  3259. Dim vFilter As Variant &apos; Array of Boolean values indicating which rows should be erased
  3260. Dim bFilter As Boolean &apos; A single item in vFilter
  3261. Dim iDims As Integer &apos; Number of dimensions of vFilter()
  3262. Dim lLower As Long &apos; Lower level of contiguous True filter values
  3263. Dim lUpper As Long &apos; Upper level of contiguous True filter values
  3264. Dim i As Long, j As Long
  3265. Check:
  3266. &apos; Error handling is determined by the calling method
  3267. vRanges = Array()
  3268. Try:
  3269. With poRange
  3270. &apos; Compute the range where to apply the formula
  3271. &apos; Determine the direction of the range containing the formula vertical, horizontal or both
  3272. Select Case psFilterScope
  3273. Case &quot;ROW&quot;
  3274. lLast = LastColumn(.SheetName)
  3275. &apos; Put formulas as a single column in the unused area at the right of the range to filter
  3276. Set oFormulaRange = _Offset(poRange, 0, lLast - .XCellRange.RangeAddress.StartColumn + 1, 0, 1)
  3277. sFormulaDirection = &quot;V&quot;
  3278. Case &quot;COLUMN&quot;
  3279. lLast = LastRow(.SheetName)
  3280. &apos; Put formulas as a single row in the unused area at the bottom of the range to filter
  3281. Set oFormulaRange = _Offset(poRange, lLast - .XCellRange.RangeAddress.StartRow + 1, 0, 1, 0)
  3282. sFormulaDirection = &quot;H&quot;
  3283. Case &quot;CELL&quot;
  3284. lLast = LastRow(.SheetName)
  3285. &apos; Put formulas as a matrix in the unused area at the bottom of the range to filter
  3286. Set oFormulaRange = _Offset(poRange, lLast - .XCellRange.RangeAddress.StartRow + 1, 0, 0, 0)
  3287. sFormulaDirection = &quot;B&quot;
  3288. If oFormulaRange.Width = 1 Then
  3289. sFormulaDirection = &quot;V&quot;
  3290. ElseIf oFormulaRange.Height = 1 Then
  3291. sFormulaDirection = &quot;H&quot;
  3292. End If
  3293. End Select
  3294. &apos; Apply the formula and get the result as an array of Boolean values. Clean up
  3295. SetFormula(oFormulaRange, psFilterFormula)
  3296. vDataArray = oFormulaRange.XCellRange.getDataArray()
  3297. vFilter = _ConvertFromDataArray(vDataArray)
  3298. iDims = ScriptForge.SF_Array.CountDims(vFilter)
  3299. ClearAll(oFormulaRange)
  3300. &apos; Convert the filter values (0 = False, 1 = True) to a set of ranges
  3301. Select Case iDims
  3302. Case -1 &apos; Scalar
  3303. If vFilter = 1 Then vRanges = ScriptForge.SF_Array.Append(vRanges, poRange)
  3304. Case 0 &apos; Empty array
  3305. &apos; Nothing to do
  3306. Case 1, 2 &apos; Vector or Array
  3307. &apos; Strategy: group contiguous applicable rows/columns to optimize heavy operations like CompactUp, CompactLeft
  3308. &apos; Stack the contiguous ranges of True values in vRanges()
  3309. &apos; To manage vector and array with same code, setup a single fictitious loop when vector, otherwise scan array by row
  3310. For i = 0 To Iif(iDims = 1, 0, UBound(vFilter, 1))
  3311. lLower = -1 : lUpper = -1
  3312. For j = 0 To UBound(vFilter, iDims)
  3313. If iDims = 1 Then bFilter = CBool(vFilter(j)) Else bFilter = CBool(vFilter(i, j))
  3314. If j = UBound(vFilter, iDims) And bFilter Then &apos; Don&apos;t forget the last item
  3315. If lLower &lt; 0 Then lLower = j
  3316. lUpper = j
  3317. ElseIf Not bFilter Then
  3318. If lLower &gt;= 0 Then lUpper = j - 1
  3319. ElseIf bFilter Then
  3320. If lLower &lt; 0 Then lLower = j
  3321. End If
  3322. &apos; Determine the next applicable range when one found and limit reached
  3323. If lUpper &gt; -1 Then
  3324. If sFormulaDirection = &quot;V&quot; Then &apos; ROW
  3325. Set oRange = _Offset(poRange, lLower, 0, lUpper - lLower + 1, 0)
  3326. ElseIf sFormulaDirection = &quot;H&quot; Then &apos; COLUMN
  3327. Set oRange = _Offset(poRange, 0, lLower, 0, lUpper - lLower + 1)
  3328. Else &apos; CELL
  3329. Set oRange = _Offset(poRange, i, lLower, 1, lUpper - lLower + 1)
  3330. End If
  3331. If Not IsNull(oRange) Then vRanges = ScriptForge.SF_Array.Append(vRanges, oRange)
  3332. lLower = -1 : lUpper = -1
  3333. End If
  3334. Next j
  3335. Next i
  3336. Case Else
  3337. &apos; Should not happen
  3338. End Select
  3339. End With
  3340. Finally:
  3341. _ComputeFilter = vRanges()
  3342. Exit Function
  3343. End Function &apos; SFDocuments.SF_Calc._ComputeFilter
  3344. REM -----------------------------------------------------------------------------
  3345. Public Function _ConvertFromDataArray(ByRef pvDataArray As Variant) As Variant
  3346. &apos;&apos;&apos; Convert a data array to a scalar, a vector or a 2D array
  3347. &apos;&apos;&apos; Args:
  3348. &apos;&apos;&apos; pvDataArray: an array as returned by the XCellRange.getDataArray or .getFormulaArray methods
  3349. &apos;&apos;&apos; Returns:
  3350. &apos;&apos;&apos; A scalar, a zero-based 1D array or a zero-based 2D array of strings and/or doubles
  3351. &apos;&apos;&apos; To convert doubles to dates, use the CDate builtin function
  3352. Dim vArray As Variant &apos; Return value
  3353. Dim lMax1 As Long &apos; UBound of pvDataArray
  3354. Dim lMax2 As Long &apos; UBound of pvDataArray items
  3355. Dim i As Long
  3356. Dim j As Long
  3357. vArray = Empty
  3358. Try:
  3359. &apos; Convert the data array to scalar, vector or array
  3360. lMax1 = UBound(pvDataArray)
  3361. If lMax1 &gt;= 0 Then
  3362. lMax2 = UBound(pvDataArray(0))
  3363. If lMax2 &gt;= 0 Then
  3364. If lMax1 + lMax2 &gt; 0 Then vArray = Array()
  3365. Select Case True
  3366. Case lMax1 = 0 And lMax2 = 0 &apos; Scalar
  3367. vArray = pvDataArray(0)(0)
  3368. Case lMax1 &gt; 0 And lMax2 = 0 &apos; Vertical vector
  3369. ReDim vArray(0 To lMax1)
  3370. For i = 0 To lMax1
  3371. vArray(i) = pvDataArray(i)(0)
  3372. Next i
  3373. Case lMax1 = 0 And lMax2 &gt; 0 &apos; Horizontal vector
  3374. ReDim vArray(0 To lMax2)
  3375. For j = 0 To lMax2
  3376. vArray(j) = pvDataArray(0)(j)
  3377. Next j
  3378. Case Else &apos; Array
  3379. ReDim vArray(0 To lMax1, 0 To lMax2)
  3380. For i = 0 To lMax1
  3381. For j = 0 To lMax2
  3382. vArray(i, j) = pvDataArray(i)(j)
  3383. Next j
  3384. Next i
  3385. End Select
  3386. End If
  3387. End If
  3388. Finally:
  3389. _ConvertFromDataArray = vArray
  3390. End Function &apos; SFDocuments.SF_Calc._ConvertFromDataArray
  3391. REM -----------------------------------------------------------------------------
  3392. Private Function _ConvertToCellValue(ByVal pvItem As Variant) As Variant
  3393. &apos;&apos;&apos; Convert the argument to a valid Calc cell content
  3394. Dim vCell As Variant &apos; Return value
  3395. Try:
  3396. Select Case ScriptForge.SF_Utils._VarTypeExt(pvItem)
  3397. Case V_STRING : vCell = pvItem
  3398. Case V_DATE : vCell = CDbl(pvItem)
  3399. Case ScriptForge.V_NUMERIC : vCell = CDbl(pvItem)
  3400. Case ScriptForge.V_BOOLEAN : vCell = CDbl(Iif(pvItem, 1, 0))
  3401. Case Else : vCell = &quot;&quot;
  3402. End Select
  3403. Finally:
  3404. _ConvertToCellValue = vCell
  3405. Exit Function
  3406. End Function &apos; SFDocuments.SF_Calc._ConvertToCellValue
  3407. REM -----------------------------------------------------------------------------
  3408. Private Function _ConvertToDataArray(ByRef pvArray As Variant _
  3409. , Optional ByVal plRows As Long _
  3410. , Optional ByVal plColumns As Long _
  3411. ) As Variant
  3412. &apos;&apos;&apos; Create a 2-dimensions nested array (compatible with the ranges .DataArray property)
  3413. &apos;&apos;&apos; from a scalar, a 1D array or a 2D array
  3414. &apos;&apos;&apos; Input may be a 1D array of arrays, typically when call issued by a Python script
  3415. &apos;&apos;&apos; Array items are converted to (possibly empty) strings or doubles
  3416. &apos;&apos;&apos; Args:
  3417. &apos;&apos;&apos; pvArray: the input scalar or array. If array, must be 1 or 2D otherwise it is ignored.
  3418. &apos;&apos;&apos; plRows, plColumns: the upper bounds of the data array
  3419. &apos;&apos;&apos; If bigger than input array, fill with zero-length strings
  3420. &apos;&apos;&apos; If smaller than input array, truncate
  3421. &apos;&apos;&apos; If plRows = 0 and the input array is a vector, the data array is aligned horizontally
  3422. &apos;&apos;&apos; They are either both present or both absent
  3423. &apos;&apos;&apos; When absent
  3424. &apos;&apos;&apos; The size of the output is fully determined by the input array
  3425. &apos;&apos;&apos; Vectors are aligned vertically
  3426. &apos;&apos;&apos; Returns:
  3427. &apos;&apos;&apos; A data array compatible with ranges .DataArray property
  3428. &apos;&apos;&apos; The output is always an array of nested arrays
  3429. Dim vDataArray() As Variant &apos; Return value
  3430. Dim vVector() As Variant &apos; A temporary 1D array
  3431. Dim vItem As Variant &apos; A single input item
  3432. Dim iDims As Integer &apos; Number of dimensions of the input argument
  3433. Dim lMin1 As Long &apos; Lower bound (1) of input array
  3434. Dim lMax1 As Long &apos; Upper bound (1)
  3435. Dim lMin2 As Long &apos; Lower bound (2)
  3436. Dim lMax2 As Long &apos; Upper bound (2)
  3437. Dim lRows As Long &apos; Upper bound of vDataArray
  3438. Dim lCols As Long &apos; Upper bound of vVector
  3439. Dim bHorizontal As Boolean &apos; Horizontal vector
  3440. Dim bDataArray As Boolean &apos; Input array is already an array of arrays
  3441. Dim i As Long
  3442. Dim j As Long
  3443. Const cstEmpty = &quot;&quot; &apos; Empty cell
  3444. If IsMissing(plRows) Or IsEmpty(plRows) Then plRows = -1
  3445. If IsMissing(plColumns) Or IsEmpty(plColumns) Then plColumns = -1
  3446. vDataArray = Array()
  3447. Try:
  3448. &apos; Check the input argument and know its boundaries
  3449. iDims = ScriptForge.SF_Array.CountDims(pvArray)
  3450. If iDims = 0 Or iDims &gt; 2 Then Exit Function
  3451. lMin1 = 0 : lMax1 = 0 &apos; Default values
  3452. lMin2 = 0 : lMax2 = 0
  3453. Select Case iDims
  3454. Case -1 &apos; Scalar value
  3455. Case 1
  3456. bHorizontal = ( plRows = 0 And plColumns &gt; 0 )
  3457. bDataArray = IsArray(pvArray(0))
  3458. If Not bDataArray Then
  3459. If Not bHorizontal Then
  3460. lMin1 = LBound(pvArray) : lMax1 = UBound(pvArray)
  3461. Else
  3462. lMin2 = LBound(pvArray) : lMax2 = UBound(pvArray)
  3463. End If
  3464. Else
  3465. iDims = 2
  3466. lMin1 = LBound(pvArray) : lMax1 = UBound(pvArray)
  3467. lMin2 = LBound(pvArray(0)) : lMax2 = UBound(pvArray(0))
  3468. End If
  3469. Case 2
  3470. lMin1 = LBound(pvArray, 1) : lMax1 = UBound(pvArray, 1)
  3471. lMin2 = LBound(pvArray, 2) : lMax2 = UBound(pvArray, 2)
  3472. End Select
  3473. &apos; Set the output dimensions accordingly
  3474. If plRows &gt;= 0 Then &apos; Dimensions of output are imposed
  3475. lRows = plRows
  3476. lCols = plColumns
  3477. Else &apos; Dimensions of output determined by input argument
  3478. lRows = 0 : lCols = 0 &apos; Default values
  3479. Select Case iDims
  3480. Case -1 &apos; Scalar value
  3481. Case 1 &apos; Vectors are aligned vertically
  3482. lRows = lMax1 - lMin1
  3483. Case 2
  3484. lRows = lMax1 - lMin1
  3485. lCols = lMax2 - lMin2
  3486. End Select
  3487. End If
  3488. ReDim vDataArray(0 To lRows)
  3489. &apos; Feed the output array row by row, each row being a vector
  3490. For i = 0 To lRows
  3491. ReDim vVector(0 To lCols)
  3492. For j = 0 To lCols
  3493. If i &gt; lMax1 - lMin1 Then
  3494. vVector(j) = cstEmpty
  3495. ElseIf j &gt; lMax2 - lMin2 Then
  3496. vVector(j) = cstEmpty
  3497. Else
  3498. Select Case iDims
  3499. Case -1 : vItem = _ConvertToCellValue(pvArray)
  3500. Case 1
  3501. If bHorizontal Then
  3502. vItem = _ConvertToCellValue(pvArray(j + lMin2))
  3503. Else
  3504. vItem = _ConvertToCellValue(pvArray(i + lMin1))
  3505. End If
  3506. Case 2
  3507. If bDataArray Then
  3508. vItem = _ConvertToCellValue(pvArray(i + lMin1)(j + lMin2))
  3509. Else
  3510. vItem = _ConvertToCellValue(pvArray(i + lMin1, j + lMin2))
  3511. End If
  3512. End Select
  3513. vVector(j) = vItem
  3514. End If
  3515. vDataArray(i) = vVector
  3516. Next j
  3517. Next i
  3518. Finally:
  3519. _ConvertToDataArray = vDataArray
  3520. Exit Function
  3521. End Function &apos; SFDocuments.SF_Calc._ConvertToDataArray
  3522. REM -----------------------------------------------------------------------------
  3523. Private Function _DFunction(ByVal psFunction As String _
  3524. , Optional ByVal Range As Variant _
  3525. ) As Double
  3526. &apos;&apos;&apos; Apply the given function on all the numeric values stored in the given range
  3527. &apos;&apos;&apos; Args:
  3528. &apos;&apos;&apos; Range : the range as a string where to apply the function on
  3529. &apos;&apos;&apos; Returns:
  3530. &apos;&apos;&apos; The resulting value as a double
  3531. Dim dblGet As Double &apos; Return value
  3532. Dim oAddress As Object &apos; Alias of Range
  3533. Dim vFunction As Variant &apos; com.sun.star.sheet.GeneralFunction.XXX
  3534. Dim cstThisSub As String : cstThisSub = &quot;SFDocuments.Calc.&quot; &amp; psFunction
  3535. Const cstSubArgs = &quot;Range&quot;
  3536. If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  3537. dblGet = 0
  3538. Check:
  3539. If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  3540. If Not _IsStillAlive() Then GoTo Finally
  3541. If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3542. End If
  3543. Try:
  3544. &apos; Get the data
  3545. Set oAddress = _ParseAddress(Range)
  3546. Select Case psFunction
  3547. Case &quot;DAvg&quot; : vFunction = com.sun.star.sheet.GeneralFunction.AVERAGE
  3548. Case &quot;DCount&quot; : vFunction = com.sun.star.sheet.GeneralFunction.COUNTNUMS
  3549. Case &quot;DMax&quot; : vFunction = com.sun.star.sheet.GeneralFunction.MAX
  3550. Case &quot;DMin&quot; : vFunction = com.sun.star.sheet.GeneralFunction.MIN
  3551. Case &quot;DSum&quot; : vFunction = com.sun.star.sheet.GeneralFunction.SUM
  3552. Case Else : GoTo Finally
  3553. End Select
  3554. dblGet = oAddress.XCellRange.computeFunction(vFunction)
  3555. Finally:
  3556. _DFunction = dblGet
  3557. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  3558. Exit Function
  3559. Catch:
  3560. GoTo Finally
  3561. End Function &apos; SFDocuments.SF_Calc._DFunction
  3562. REM -----------------------------------------------------------------------------
  3563. Private Function _FileIdent() As String
  3564. &apos;&apos;&apos; Returns a file identification from the information that is currently available
  3565. &apos;&apos;&apos; Useful e.g. for display in error messages
  3566. _FileIdent = [_Super]._FileIdent()
  3567. End Function &apos; SFDocuments.SF_Calc._FileIdent
  3568. REM -----------------------------------------------------------------------------
  3569. Function _GetColumnName(ByVal plColumnNumber As Long) As String
  3570. &apos;&apos;&apos; Convert a column number (range 1, 2,..16384) into its letter counterpart (range &apos;A&apos;, &apos;B&apos;,..&apos;XFD&apos;).
  3571. &apos;&apos;&apos; Args:
  3572. &apos;&apos;&apos; ColumnNumber: the column number, must be in the interval 1 ... 16384
  3573. &apos;&apos;&apos; Returns:
  3574. &apos;&apos;&apos; a string representation of the column name, in range &apos;A&apos;..&apos;XFD&apos;
  3575. &apos;&apos;&apos; Adapted from a Python function by sundar nataraj
  3576. &apos;&apos;&apos; http://stackoverflow.com/questions/23861680/convert-spreadsheet-number-to-column-letter
  3577. Dim sCol As String &apos; Return value
  3578. Dim lDiv As Long &apos; Intermediate result
  3579. Dim lMod As Long &apos; Result of modulo 26 operation
  3580. Try:
  3581. sCol = &quot;&quot;
  3582. lDiv = plColumnNumber
  3583. Do While lDiv &gt; 0
  3584. lMod = (lDiv - 1) Mod 26
  3585. sCol = Chr(65 + lMod) &amp; sCol
  3586. lDiv = (lDiv - lMod) \ 26
  3587. Loop
  3588. Finally:
  3589. _GetColumnName = sCol
  3590. End Function &apos; SFDocuments.SF_Calc._GetColumnName
  3591. REM -----------------------------------------------------------------------------
  3592. Private Function _IsStillAlive(Optional ByVal pbForUpdate As Boolean _
  3593. , Optional ByVal pbError As Boolean _
  3594. ) As Boolean
  3595. &apos;&apos;&apos; Returns True if the document has not been closed manually or incidentally since the last use
  3596. &apos;&apos;&apos; If dead the actual instance is disposed. The execution is cancelled when pbError = True (default)
  3597. &apos;&apos;&apos; Args:
  3598. &apos;&apos;&apos; pbForUpdate: if True (default = False), check additionally if document is open for editing
  3599. &apos;&apos;&apos; pbError: if True (default), raise a fatal error
  3600. Dim bAlive As Boolean &apos; Return value
  3601. If IsMissing(pbForUpdate) Then pbForUpdate = False
  3602. If IsMissing(pbError) Then pbError = True
  3603. Try:
  3604. bAlive = [_Super]._IsStillAlive(pbForUpdate, pbError)
  3605. Finally:
  3606. _IsStillAlive = bAlive
  3607. Exit Function
  3608. End Function &apos; SFDocuments.SF_Calc._IsStillAlive
  3609. REM -----------------------------------------------------------------------------
  3610. Private Function _LastCell(ByRef poSheet As Object) As Variant
  3611. &apos;&apos;&apos; Returns in an array the coordinates of the last used cell in the given sheet
  3612. Dim oCursor As Object &apos; Cursor on the cell
  3613. Dim oRange As Object &apos; The used range
  3614. Dim vCoordinates(0 To 1) As Long &apos; Return value: (0) = Column, (1) = Row
  3615. Try:
  3616. Set oCursor = poSheet.createCursorByRange(poSheet.getCellRangeByName(&quot;A1&quot;))
  3617. oCursor.gotoEndOfUsedArea(True)
  3618. Set oRange = poSheet.getCellRangeByName(oCursor.AbsoluteName)
  3619. vCoordinates(0) = oRange.RangeAddress.EndColumn + 1
  3620. vCoordinates(1) = oRange.RangeAddress.EndRow + 1
  3621. Finally:
  3622. _LastCell = vCoordinates
  3623. End Function &apos; SFDocuments.SF_Calc._LastCell
  3624. REM -----------------------------------------------------------------------------
  3625. Public Function _Offset(ByRef pvRange As Variant _
  3626. , ByVal plRows As Long _
  3627. , ByVal plColumns As Long _
  3628. , ByVal plHeight As Long _
  3629. , ByVal plWidth As Long _
  3630. ) As Object
  3631. &apos;&apos;&apos; Returns a new range offset by a certain number of rows and columns from a given range
  3632. &apos;&apos;&apos; Args:
  3633. &apos;&apos;&apos; pvRange : the range, as a string or an object, from which the function searches for the new range
  3634. &apos;&apos;&apos; plRows : the number of rows by which the reference was corrected up (negative value) or down.
  3635. &apos;&apos;&apos; plColumns : the number of columns by which the reference was corrected to the left (negative value) or to the right.
  3636. &apos;&apos;&apos; plHeight : the vertical height for an area that starts at the new reference position.
  3637. &apos;&apos;&apos; plWidth : the horizontal width for an area that starts at the new reference position.
  3638. &apos;&apos;&apos; Arguments Rows and Columns must not lead to zero or negative start row or column.
  3639. &apos;&apos;&apos; Arguments Height and Width must not lead to zero or negative count of rows or columns.
  3640. &apos;&apos;&apos; Returns:
  3641. &apos;&apos;&apos; A new range as object of type _Address
  3642. &apos;&apos;&apos; Exceptions:
  3643. &apos;&apos;&apos; OFFSETADDRESSERROR The computed range of cells falls beyond the sheet boundaries
  3644. Dim oOffset As Object &apos; Return value
  3645. Dim oAddress As Object &apos; Alias of Range
  3646. Dim oSheet As Object &apos; com.sun.star.sheet.XSpreadsheet
  3647. Dim oRange As Object &apos; com.sun.star.table.XCellRange
  3648. Dim oNewRange As Object &apos; com.sun.star.table.XCellRange
  3649. Dim lLeft As Long &apos; New range coordinates
  3650. Dim lTop As Long
  3651. Dim lRight As Long
  3652. Dim lBottom As Long
  3653. Set oOffset = Nothing
  3654. Check:
  3655. If plHeight &lt; 0 Or plWidth &lt; 0 Then GoTo CatchAddress
  3656. Try:
  3657. If VarType(pvRange) = V_STRING Then Set oAddress = _ParseAddress(pvRange) Else Set oAddress = pvRange
  3658. Set oSheet = oAddress.XSpreadSheet
  3659. Set oRange = oAddress.XCellRange.RangeAddress
  3660. &apos; Compute and validate new coordinates
  3661. With oRange
  3662. lLeft = .StartColumn + plColumns
  3663. lTop = .StartRow + plRows
  3664. lRight = lLeft + Iif(plWidth = 0, .EndColumn - .StartColumn, plWidth - 1)
  3665. lBottom = lTop + Iif(plHeight = 0, .EndRow - .StartRow, plHeight - 1)
  3666. If lLeft &lt; 0 Or lRight &lt; 0 Or lTop &lt; 0 Or lBottom &lt; 0 _
  3667. Or lLeft &gt;= MAXCOLS Or lRight &gt;= MAXCOLS _
  3668. Or lTop &gt;= MAXROWS Or lBottom &gt;= MAXROWS _
  3669. Then GoTo CatchAddress
  3670. Set oNewRange = oSheet.getCellRangeByPosition(lLeft, lTop, lRight, lBottom)
  3671. End With
  3672. &apos; Define the new range address
  3673. Set oOffset = New _Address
  3674. With oOffset
  3675. .ObjectType = CALCREFERENCE
  3676. .ServiceName = SERVICEREFERENCE
  3677. .RawAddress = oNewRange.AbsoluteName
  3678. .Component = _Component
  3679. .XSpreadsheet = oNewRange.Spreadsheet
  3680. .SheetName = .XSpreadsheet.Name
  3681. .SheetIndex = .XSpreadsheet.RangeAddress.Sheet
  3682. .RangeName = .RawAddress
  3683. .XCellRange = oNewRange
  3684. .Height = oNewRange.RangeAddress.EndRow - oNewRange.RangeAddress.StartRow + 1
  3685. .Width = oNewRange.RangeAddress.EndColumn - oNewRange.RangeAddress.StartColumn + 1
  3686. End With
  3687. Finally:
  3688. Set _Offset = oOffset
  3689. Exit Function
  3690. Catch:
  3691. GoTo Finally
  3692. CatchAddress:
  3693. ScriptForge.SF_Exception.RaiseFatal(OFFSETADDRESSERROR, &quot;Range&quot;, oAddress.RawAddress _
  3694. , &quot;Rows&quot;, plRows, &quot;Columns&quot;, plColumns, &quot;Height&quot;, plHeight, &quot;Width&quot;, plWidth _
  3695. , &quot;Document&quot;, [_Super]._FileIdent())
  3696. GoTo Finally
  3697. End Function &apos; SFDocuments.SF_Calc._Offset
  3698. REM -----------------------------------------------------------------------------
  3699. Private Function _ParseAddress(ByVal psAddress As String) As Object
  3700. &apos;&apos;&apos; Parse and validate a sheet or range reference
  3701. &apos;&apos;&apos; Syntax to parse:
  3702. &apos;&apos;&apos; [Sheet].[Range]
  3703. &apos;&apos;&apos; Sheet =&gt; [&apos;][$]sheet[&apos;] or document named range or ~
  3704. &apos;&apos;&apos; Range =&gt; A1:D10, A1, A:D, 10:10 ($ ignored), or sheet named range or ~
  3705. &apos;&apos;&apos; Returns:
  3706. &apos;&apos;&apos; An object of type _Address
  3707. &apos;&apos;&apos; Exceptions:
  3708. &apos;&apos;&apos; CALCADDRESSERROR &apos; Address could not be parsed to a valid address
  3709. Dim oAddress As Object &apos; Return value
  3710. Dim sAddress As String &apos; Alias of psAddress
  3711. Dim vRangeName As Variant &apos; Array Sheet/Range
  3712. Dim lStart As Long &apos; Position of found regex
  3713. Dim sSheet As String &apos; Sheet component
  3714. Dim sRange As String &apos; Range component
  3715. Dim oSheets As Object &apos; com.sun.star.sheet.XSpreadsheets
  3716. Dim oNamedRanges As Object &apos; com.sun.star.sheet.XNamedRanges
  3717. Dim oRangeAddress As Object &apos; Alias for rangeaddress
  3718. Dim vLastCell As Variant &apos; Result of _LastCell() method
  3719. Dim oSelect As Object &apos; Current selection
  3720. &apos; If psAddress has already been parsed, get the result back
  3721. If Not IsNull(_LastParsedAddress) Then
  3722. &apos; Given argument must contain an explicit reference to a sheet
  3723. If (InStr(psAddress, &quot;~.&quot;) = 0 And InStr(psAddress, &quot;.&quot;) &gt; 0 And psAddress = _LastParsedAddress.RawAddress) _
  3724. Or psAddress = _LastParsedAddress.RangeName Then
  3725. Set _ParseAddress = _LastParsedAddress
  3726. Exit Function
  3727. Else
  3728. Set _LastParsedAddress = Nothing
  3729. End If
  3730. End If
  3731. &apos; Reinitialize a new _Address object
  3732. Set oAddress = New _Address
  3733. With oAddress
  3734. sSheet = &quot;&quot; : sRange = &quot;&quot;
  3735. .SheetName = &quot;&quot; : .RangeName = &quot;&quot;
  3736. .ObjectType = CALCREFERENCE
  3737. .ServiceName = SERVICEREFERENCE
  3738. .RawAddress = psAddress
  3739. Set .XSpreadSheet = Nothing : Set .XCellRange = Nothing
  3740. &apos; Remove leading &quot;$&apos; when followed with an apostrophe
  3741. If Left(psAddress, 2) = &quot;$&apos;&quot; Then sAddress = Mid(psAddress, 2) Else sAddress = psAddress
  3742. &apos; Split in sheet and range components on dot not enclosed in single quotes
  3743. vRangeName = ScriptForge.SF_String.SplitNotQuoted(sAddress, Delimiter := &quot;.&quot;, QuoteChar := &quot;&apos;&quot;)
  3744. sSheet = ScriptForge.SF_String.Unquote(Replace(vRangeName(0), &quot;&apos;&apos;&quot;, &quot;\&apos;&quot;), QuoteChar := &quot;&apos;&quot;)
  3745. &apos; Keep a leading &quot;$&quot; in the sheet name only if name enclosed in single quotes
  3746. &apos; Notes:
  3747. &apos; sheet names may contain &quot;$&quot; (even &quot;$&quot; is a valid sheet name), named ranges must not
  3748. &apos; sheet names may contain apostrophes (except in 1st and last positions), range names must not
  3749. If Left(vRangeName(0), 2) &lt;&gt; &quot;&apos;$&quot; And Left(sSheet, 1) = &quot;$&quot; And Len(sSheet) &gt; 1 Then sSheet = Mid(sSheet, 2)
  3750. If UBound(vRangeName) &gt; 0 Then sRange = vRangeName(1)
  3751. &apos; Resolve sheet part: either a document named range, or the active sheet or a real sheet
  3752. Set oSheets = _Component.getSheets()
  3753. Set oNamedRanges = _Component.NamedRanges
  3754. If oSheets.hasByName(sSheet) Then
  3755. ElseIf sSheet = &quot;~&quot; And Len(sRange) &gt; 0 Then
  3756. sSheet = _Component.CurrentController.ActiveSheet.Name
  3757. ElseIf oNamedRanges.hasByName(sSheet) Then
  3758. .XCellRange = oNamedRanges.getByName(sSheet).ReferredCells
  3759. sSheet = oSheets.getByIndex(oNamedRanges.getByName(sSheet).ReferencePosition.Sheet).Name
  3760. Else
  3761. sRange = sSheet
  3762. sSheet = _Component.CurrentController.ActiveSheet.Name
  3763. End If
  3764. .SheetName = sSheet
  3765. .XSpreadSheet = oSheets.getByName(sSheet)
  3766. .SheetIndex = .XSpreadSheet.RangeAddress.Sheet
  3767. &apos; Resolve range part - either a sheet named range or the current selection or a real range or &quot;&quot;
  3768. If IsNull(.XCellRange) Then
  3769. Set oNamedRanges = .XSpreadSheet.NamedRanges
  3770. If sRange = &quot;~&quot; Then
  3771. Set oSelect = _Component.CurrentController.getSelection()
  3772. If oSelect.supportsService(&quot;com.sun.star.sheet.SheetCellRanges&quot;) Then &apos; Multiple selections
  3773. Set .XCellRange = oSelect.getByIndex(0)
  3774. Else
  3775. Set .XCellRange = oSelect
  3776. End If
  3777. ElseIf sRange = &quot;*&quot; Or sRange = &quot;&quot; Then
  3778. vLastCell = _LastCell(.XSpreadSheet)
  3779. sRange = &quot;A1:&quot; &amp; _GetColumnName(vLastCell(0)) &amp; CStr(vLastCell(1))
  3780. Set .XCellRange = .XSpreadSheet.getCellRangeByName(sRange)
  3781. ElseIf oNamedRanges.hasByName(sRange) Then
  3782. .XCellRange = oNamedRanges.getByName(sRange).ReferredCells
  3783. Else
  3784. On Local Error GoTo CatchError
  3785. Set .XCellRange = .XSpreadSheet.getCellRangeByName(sRange)
  3786. &apos; If range reaches the limits of the sheets, reduce it up to the used area
  3787. Set oRangeAddress = .XCellRange.RangeAddress
  3788. If oRangeAddress.StartColumn = 0 And oRangeAddress.EndColumn = MAXCOLS - 1 Then
  3789. vLastCell = _LastCell(.XSpreadSheet)
  3790. sRange = &quot;A&quot; &amp; CStr(oRangeAddress.StartRow + 1) &amp; &quot;:&quot; _
  3791. &amp; _GetColumnName(vLastCell(0)) &amp; CStr(oRangeAddress.EndRow + 1)
  3792. Set .XCellRange = .XSpreadSheet.getCellRangeByName(sRange)
  3793. ElseIf oRangeAddress.StartRow = 0 And oRangeAddress.EndRow = MAXROWS - 1 Then
  3794. vLastCell = _LastCell(.XSpreadSheet)
  3795. sRange = _GetColumnName(oRangeAddress.StartColumn + 1) &amp; &quot;1&quot; &amp; &quot;:&quot; _
  3796. &amp; _GetColumnName(oRangeAddress.EndColumn + 1) &amp; CStr(_LastCell(.XSpreadSheet)(1))
  3797. Set .XCellRange = .XSpreadSheet.getCellRangeByName(sRange)
  3798. End If
  3799. End If
  3800. End If
  3801. If IsNull(.XCellRange) Then GoTo CatchAddress
  3802. Set oRangeAddress = .XCellRange.RangeAddress
  3803. .RangeName = .XCellRange.AbsoluteName
  3804. .Height = oRangeAddress.EndRow - oRangeAddress.StartRow + 1
  3805. .Width = oRangeAddress.EndColumn - oRangeAddress.StartColumn + 1
  3806. &apos; Remember the current component in case of use outside the current instance
  3807. Set .Component = _Component
  3808. End With
  3809. &apos; Store last parsed address for reuse
  3810. Set _LastParsedAddress = oAddress
  3811. Finally:
  3812. Set _ParseAddress = oAddress
  3813. Exit Function
  3814. CatchError:
  3815. ScriptForge.SF_Exception.Clear()
  3816. CatchAddress:
  3817. ScriptForge.SF_Exception.RaiseFatal(CALCADDRESSERROR, &quot;Range&quot;, psAddress _
  3818. , &quot;Document&quot;, [_Super]._FileIdent())
  3819. GoTo Finally
  3820. End Function &apos; SFDocuments.SF_Calc._ParseAddress
  3821. REM -----------------------------------------------------------------------------
  3822. Private Function _PropertyGet(Optional ByVal psProperty As String _
  3823. , Optional ByVal pvArg As Variant _
  3824. ) As Variant
  3825. &apos;&apos;&apos; Return the value of the named property
  3826. &apos;&apos;&apos; Args:
  3827. &apos;&apos;&apos; psProperty: the name of the property
  3828. Dim oProperties As Object &apos; Document or Custom properties
  3829. Dim vLastCell As Variant &apos; Coordinates of last used cell in a sheet
  3830. Dim oSelect As Object &apos; Current selection
  3831. Dim vRanges As Variant &apos; List of selected ranges
  3832. Dim oAddress As Object &apos; _Address type for range description
  3833. Dim oCursor As Object &apos; com.sun.star.sheet.XSheetCellCursor
  3834. Dim i As Long
  3835. Dim cstThisSub As String
  3836. Const cstSubArgs = &quot;&quot;
  3837. _PropertyGet = False
  3838. cstThisSub = &quot;SFDocuments.Calc.get&quot; &amp; psProperty
  3839. ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
  3840. If Not _IsStillAlive() Then GoTo Finally
  3841. Select Case UCase(psProperty)
  3842. Case UCase(&quot;CurrentSelection&quot;)
  3843. Set oSelect = _Component.CurrentController.getSelection()
  3844. If IsNull(oSelect) Then
  3845. _PropertyGet = Array()
  3846. ElseIf oSelect.supportsService(&quot;com.sun.star.sheet.SheetCellRanges&quot;) Then &apos; Multiple selections
  3847. vRanges = Array()
  3848. For i = 0 To oSelect.Count - 1
  3849. vRanges = ScriptForge.SF_Array.Append(vRanges, oSelect.getByIndex(i).AbsoluteName)
  3850. Next i
  3851. _PropertyGet = vRanges
  3852. Else
  3853. _PropertyGet = oSelect.AbsoluteName
  3854. End If
  3855. Case UCase(&quot;Height&quot;)
  3856. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3857. _PropertyGet = 0
  3858. Else
  3859. If Not ScriptForge.SF_Utils._Validate(pvArg, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3860. _PropertyGet = _ParseAddress(pvArg).Height
  3861. End If
  3862. Case UCase(&quot;FirstCell&quot;), UCase(&quot;FirstRow&quot;), UCase(&quot;FirstColumn&quot;) _
  3863. , UCase(&quot;LastCell&quot;), UCase(&quot;LastColumn&quot;), UCase(&quot;LastRow&quot;) _
  3864. , UCase(&quot;SheetName&quot;)
  3865. If IsMissing(pvArg) Or IsEmpty(pvArg) Then &apos; Avoid errors when instance is watched in Basic IDE
  3866. If InStr(UCase(psProperty), &quot;CELL&quot;) &gt; 0 Then _PropertyGet = &quot;&quot; Else _PropertyGet = -1
  3867. Else
  3868. If Not ScriptForge.SF_Utils._Validate(pvArg, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3869. Set oAddress = _ParseAddress(pvArg)
  3870. With oAddress.XCellRange
  3871. Select Case UCase(psProperty)
  3872. Case UCase(&quot;FirstCell&quot;)
  3873. _PropertyGet = A1Style(.RangeAddress.StartRow + 1, .RangeAddress.StartColumn + 1, , , oAddress.XSpreadsheet.Name)
  3874. Case UCase(&quot;FirstColumn&quot;) : _PropertyGet = CLng(.RangeAddress.StartColumn + 1)
  3875. Case UCase(&quot;FirstRow&quot;) : _PropertyGet = CLng(.RangeAddress.StartRow + 1)
  3876. Case UCase(&quot;LastCell&quot;)
  3877. _PropertyGet = A1Style(.RangeAddress.EndRow + 1, .RangeAddress.EndColumn + 1, , , oAddress.XSpreadsheet.Name)
  3878. Case UCase(&quot;LastColumn&quot;) : _PropertyGet = CLng(.RangeAddress.EndColumn + 1)
  3879. Case UCase(&quot;LastRow&quot;) : _PropertyGet = CLng(.RangeAddress.EndRow + 1)
  3880. Case UCase(&quot;SheetName&quot;) : _PropertyGet = oAddress.XSpreadsheet.Name
  3881. End Select
  3882. End With
  3883. End If
  3884. Case UCase(&quot;Range&quot;)
  3885. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3886. Set _PropertyGet = Nothing
  3887. Else
  3888. If Not ScriptForge.SF_Utils._Validate(pvArg, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3889. Set _PropertyGet = _ParseAddress(pvArg)
  3890. End If
  3891. Case UCase(&quot;Region&quot;)
  3892. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3893. _PropertyGet = &quot;&quot;
  3894. Else
  3895. If Not ScriptForge.SF_Utils._Validate(pvArg, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3896. Set oAddress = _ParseAddress(pvArg)
  3897. With oAddress
  3898. Set oCursor = .XSpreadsheet.createCursorByRange(.XCellRange)
  3899. oCursor.collapseToCurrentRegion()
  3900. _PropertyGet = oCursor.AbsoluteName
  3901. End With
  3902. End If
  3903. Case UCase(&quot;Sheet&quot;)
  3904. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3905. Set _PropertyGet = Nothing
  3906. Else
  3907. If Not _ValidateSheet(pvArg, &quot;SheetName&quot;, , True) Then GoTo Finally
  3908. Set _PropertyGet = _ParseAddress(pvArg)
  3909. End If
  3910. Case UCase(&quot;Sheets&quot;)
  3911. _PropertyGet = _Component.getSheets.getElementNames()
  3912. Case UCase(&quot;Width&quot;)
  3913. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3914. _PropertyGet = 0
  3915. Else
  3916. If Not ScriptForge.SF_Utils._Validate(pvArg, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3917. _PropertyGet = _ParseAddress(pvArg).Width
  3918. End If
  3919. Case UCase(&quot;XCellRange&quot;)
  3920. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3921. Set _PropertyGet = Nothing
  3922. Else
  3923. If Not ScriptForge.SF_Utils._Validate(pvArg, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3924. Set _PropertyGet = _ParseAddress(pvArg).XCellRange
  3925. End If
  3926. Case UCase(&quot;XSheetCellCursor&quot;)
  3927. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3928. Set _PropertyGet = Nothing
  3929. Else
  3930. If Not ScriptForge.SF_Utils._Validate(pvArg, &quot;Range&quot;, V_STRING) Then GoTo Finally
  3931. Set oAddress = _ParseAddress(pvArg)
  3932. Set _PropertyGet = oAddress.XSpreadsheet.createCursorByRange(oAddress.XCellRange)
  3933. End If
  3934. Case UCase(&quot;XSpreadsheet&quot;)
  3935. If IsMissing(pvArg) Or IsEmpty(pvArg) Then
  3936. Set _PropertyGet = Nothing
  3937. Else
  3938. If Not _ValidateSheet(pvArg, &quot;SheetName&quot;, , True) Then GoTo Finally
  3939. Set _PropertyGet = _Component.getSheets.getByName(pvArg)
  3940. End If
  3941. Case Else
  3942. _PropertyGet = Null
  3943. End Select
  3944. Finally:
  3945. ScriptForge.SF_Utils._ExitFunction(cstThisSub)
  3946. Exit Function
  3947. End Function &apos; SFDocuments.SF_Calc._PropertyGet
  3948. REM -----------------------------------------------------------------------------
  3949. Private Function _QuoteSheetName(ByVal psSheetName As String) As String
  3950. &apos;&apos;&apos; Return the given sheet name surrounded with single quotes
  3951. &apos;&apos;&apos; when required to insert the sheet name into a Calc formula
  3952. &apos;&apos;&apos; Enclosed single quotes are doubled
  3953. &apos;&apos;&apos; Args:
  3954. &apos;&apos;&apos; psSheetName: the name to quote
  3955. &apos;&apos;&apos; Returns:
  3956. &apos;&apos;&apos; The quoted or unchanged sheet name
  3957. Dim sSheetName As String &apos; Return value
  3958. Dim i As Long
  3959. Try:
  3960. &apos; Surround the sheet name with single quotes when required by the presence of single quotes
  3961. If InStr(psSheetName, &quot;&apos;&quot;) &gt; 0 Then
  3962. sSheetName = &quot;&apos;&quot; &amp; Replace(psSheetName, &quot;&apos;&quot;, &quot;&apos;&apos;&quot;) &amp; &quot;&apos;&quot;
  3963. Else
  3964. &apos; Surround the sheet name with single quotes when required by the presence of at least one of the special characters
  3965. sSheetName = psSheetName
  3966. For i = 1 To Len(cstSPECIALCHARS)
  3967. If InStr(sSheetName, Mid(cstSPECIALCHARS, i, 1)) &gt; 0 Then
  3968. sSheetName = &quot;&apos;&quot; &amp; sSheetName &amp; &quot;&apos;&quot;
  3969. Exit For
  3970. End If
  3971. Next i
  3972. End If
  3973. Finally:
  3974. _QuoteSheetName = sSheetName
  3975. Exit Function
  3976. End Function &apos; SFDocuments.SF_Calc._QuoteSheetName
  3977. REM -----------------------------------------------------------------------------
  3978. Private Function _Repr() As String
  3979. &apos;&apos;&apos; Convert the SF_Calc instance to a readable string, typically for debugging purposes (DebugPrint ...)
  3980. &apos;&apos;&apos; Args:
  3981. &apos;&apos;&apos; Return:
  3982. &apos;&apos;&apos; &quot;[DOCUMENT]: Type/File&quot;
  3983. _Repr = &quot;[Calc]: &quot; &amp; [_Super]._FileIdent()
  3984. End Function &apos; SFDocuments.SF_Calc._Repr
  3985. REM -----------------------------------------------------------------------------
  3986. Private Sub _RestoreSelections(ByRef pvComponent As Variant _
  3987. , ByRef pvSelection As Variant _
  3988. )
  3989. &apos;&apos;&apos; Set the selection to a single or a multiple range
  3990. &apos;&apos;&apos; Does not work well when multiple selections and macro terminating in Basic IDE
  3991. &apos;&apos;&apos; Called by the CopyToCell and CopyToRange methods
  3992. &apos;&apos;&apos; Args:
  3993. &apos;&apos;&apos; pvComponent: should work for foreign instances as well
  3994. &apos;&apos;&apos; pvSelection: the stored selection done previously by Component.CurrentController.getSelection()
  3995. Dim oCellRanges As Object &apos; com.sun.star.sheet.SheetCellRanges
  3996. Dim vRangeAddresses As Variant &apos; Array of com.sun.star.table.CellRangeAddress
  3997. Dim i As Long
  3998. Try:
  3999. If IsArray(pvSelection) Then
  4000. Set oCellRanges = pvComponent.createInstance(&quot;com.sun.star.sheet.SheetCellRanges&quot;)
  4001. vRangeAddresses = Array()
  4002. ReDim vRangeAddresses(0 To UBound(pvSelection))
  4003. For i = 0 To UBound(pvSelection)
  4004. vRangeAddresses(i) = pvSelection.getByIndex(i).RangeAddress
  4005. Next i
  4006. oCellRanges.addRangeAddresses(vRangeAddresses, False)
  4007. pvComponent.CurrentController.select(oCellRanges)
  4008. Else
  4009. pvComponent.CurrentController.select(pvSelection)
  4010. End If
  4011. Finally:
  4012. Exit Sub
  4013. End Sub &apos; SFDocuments.SF_Calc._RestoreSelections
  4014. REM -----------------------------------------------------------------------------
  4015. Private Function _ValidateSheet(Optional ByRef pvSheetName As Variant _
  4016. , Optional ByVal psArgName As String _
  4017. , Optional ByVal pvNew As Variant _
  4018. , Optional ByVal pvActive As Variant _
  4019. , Optional ByVal pvOptional as Variant _
  4020. , Optional ByVal pvNumeric As Variant _
  4021. , Optional ByVal pvReference As Variant _
  4022. , Optional ByVal pvResetSheet As Variant _
  4023. ) As Boolean
  4024. &apos;&apos;&apos; Sheet designation validation function similar to the SF_Utils._ValidateXXX functions
  4025. &apos;&apos;&apos; Args:
  4026. &apos;&apos;&apos; pvSheetName: string or numeric position
  4027. &apos;&apos;&apos; pvArgName: the name of the variable to be used in the error message
  4028. &apos;&apos;&apos; pvNew: if True, sheet must not exist (default = False)
  4029. &apos;&apos;&apos; pvActive: if True, the shortcut &quot;~&quot; is accepted (default = False)
  4030. &apos;&apos;&apos; pvOptional: if True, a zero-length string is accepted (default = False)
  4031. &apos;&apos;&apos; pvNumeric: if True, the sheet position is accepted (default = False)
  4032. &apos;&apos;&apos; pvReference: if True, a sheet reference is acceptable (default = False)
  4033. &apos;&apos;&apos; pvNumeric and pvReference must not both be = True
  4034. &apos;&apos;&apos; pvResetSheet: if True, return in pvSheetName the correct (case-sensitive) sheet name (default = False)
  4035. &apos;&apos;&apos; Returns
  4036. &apos;&apos;&apos; True if valid. SheetName is reset to current value if = &quot;~&quot;
  4037. &apos;&apos;&apos; Exceptions
  4038. &apos;&apos;&apos; DUPLICATESHEETERROR A sheet with the given name exists already
  4039. Dim vSheets As Variant &apos; List of sheets
  4040. Dim lSheet As Long &apos; Index in list of sheets
  4041. Dim vTypes As Variant &apos; Array of accepted variable types
  4042. Dim bValid As Boolean &apos; Return value
  4043. Check:
  4044. If IsMissing(pvNew) Or IsEmpty(pvNew) Then pvNew = False
  4045. If IsMissing(pvActive) Or IsEmpty(pvActive) Then pvActive = False
  4046. If IsMissing(pvOptional) Or IsEmpty(pvOptional) Then pvOptional = False
  4047. If IsMissing(pvNumeric) Or IsEmpty(pvNumeric) Then pvNumeric = False
  4048. If IsMissing(pvReference) Or IsEmpty(pvReference) Then pvReference = False
  4049. If IsMissing(pvResetSheet) Or IsEmpty(pvResetSheet) Then pvResetSheet = False
  4050. &apos; Define the acceptable variable types
  4051. If pvNumeric Then
  4052. vTypes = Array(V_STRING, V_NUMERIC)
  4053. ElseIf pvReference Then
  4054. vTypes = Array(V_STRING, ScriptForge.V_OBJECT)
  4055. Else
  4056. vTypes = V_STRING
  4057. End If
  4058. If Not ScriptForge.SF_Utils._Validate(pvSheetName, psArgName, vTypes, , , Iif(pvReference, CALCREFERENCE, &quot;&quot;)) Then GoTo Finally
  4059. bValid = False
  4060. Try:
  4061. If VarType(pvSheetName) = V_STRING Then
  4062. If pvOptional And Len(pvSheetName) = 0 Then
  4063. ElseIf pvActive And pvSheetName = &quot;~&quot; Then
  4064. pvSheetName = _Component.CurrentController.ActiveSheet.Name
  4065. Else
  4066. vSheets = _Component.getSheets.getElementNames()
  4067. If pvNew Then
  4068. &apos; ScriptForge.SF_String.FindRegex(sAddress, &quot;^&apos;[^\[\]*?:\/\\]+&apos;&quot;)
  4069. If ScriptForge.SF_Array.Contains(vSheets, pvSheetName) Then GoTo CatchDuplicate
  4070. Else
  4071. If Not ScriptForge.SF_Utils._Validate(pvSheetName, psArgName, V_STRING, vSheets) Then GoTo Finally
  4072. If pvResetSheet Then
  4073. lSheet = ScriptForge.SF_Array.IndexOf(vSheets, pvSheetName, CaseSensitive := False)
  4074. pvSheetName = vSheets(lSheet)
  4075. End If
  4076. End If
  4077. End If
  4078. End If
  4079. bValid = True
  4080. Finally:
  4081. _ValidateSheet = bValid
  4082. Exit Function
  4083. CatchDuplicate:
  4084. ScriptForge.SF_Exception.RaiseFatal(DUPLICATESHEETERROR, psArgName, pvSheetName, &quot;Document&quot;, [_Super]._FileIdent())
  4085. GoTo Finally
  4086. End Function &apos; SFDocuments.SF_Calc._ValidateSheet
  4087. REM -----------------------------------------------------------------------------
  4088. Private Function _ValidateSheetName(ByRef psSheetName As String _
  4089. , ByVal psArgName As String _
  4090. ) As Boolean
  4091. &apos;&apos;&apos; Check the validity of the sheet name:
  4092. &apos;&apos;&apos; A sheet name - must not be empty
  4093. &apos;&apos;&apos; - must not contain next characters: []*?:/\
  4094. &apos;&apos;&apos; - must not use &apos; (the apostrophe) as first or last character
  4095. &apos;&apos;&apos; Args:
  4096. &apos;&apos;&apos; psSheetName: the name to check
  4097. &apos;&apos;&apos; psArgName: the name of the argument to appear in error messages
  4098. &apos;&apos;&apos; Returns:
  4099. &apos;&apos;&apos; True when the sheet name is valid
  4100. &apos;&apos;&apos; Exceptions:
  4101. &apos;&apos;&apos; CALCADDRESSERROR &apos; Sheet name could not be parsed to a valid name
  4102. Dim bValid As Boolean &apos; Return value
  4103. Try:
  4104. bValid = ( Len(psSheetName) &gt; 0 )
  4105. If bValid Then bValid = ( Left(psSheetName, 1) &lt;&gt; &quot;&apos;&quot; And Right(psSheetName, 1) &lt;&gt; &quot;&apos;&quot; )
  4106. If bValid Then bValid = ( Len(ScriptForge.SF_String.FindRegex(psSheetName, &quot;^[^\[\]*?:\/\\]+$&quot;, 1, CaseSensitive := False)) &gt; 0 )
  4107. If Not bValid Then GoTo CatchSheet
  4108. Finally:
  4109. _ValidateSheetName = bValid
  4110. Exit Function
  4111. CatchSheet:
  4112. ScriptForge.SF_Exception.RaiseFatal(CALCADDRESSERROR, psArgName, psSheetName _
  4113. , &quot;Document&quot;, [_Super]._FileIdent())
  4114. GoTo Finally
  4115. End Function &apos; SFDocuments.SF_Calc._ValidateSheetName
  4116. REM ============================================ END OF SFDOCUMENTS.SF_CALC
  4117. </script:module>