SF_FileSystem.xba 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084
  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_FileSystem" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
  4. REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
  5. REM === Full documentation is available on https://help.libreoffice.org/ ===
  6. REM =======================================================================================================================
  7. Option Compatible
  8. Option Explicit
  9. &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;
  10. &apos;&apos;&apos; SF_FileSystem
  11. &apos;&apos;&apos; =============
  12. &apos;&apos;&apos; Class implementing the file system service
  13. &apos;&apos;&apos; for common file and folder handling routines
  14. &apos;&apos;&apos; Including copy and move of files and folders, with or without wildcards
  15. &apos;&apos;&apos; The design choices are largely inspired by
  16. &apos;&apos;&apos; https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/filesystemobject-object
  17. &apos;&apos;&apos; The File and Folder classes have been found redundant with the current class and have not been implemented
  18. &apos;&apos;&apos; The implementation is mainly based on the XSimpleFileAccess UNO interface
  19. &apos;&apos;&apos; https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1ucb_1_1XSimpleFileAccess.html
  20. &apos;&apos;&apos;
  21. &apos;&apos;&apos; Subclasses:
  22. &apos;&apos;&apos; SF_TextStream
  23. &apos;&apos;&apos;
  24. &apos;&apos;&apos; Definitions:
  25. &apos;&apos;&apos; File and folder names may be expressed either in the (preferable because portable) URL form
  26. &apos;&apos;&apos; or in the more usual operating system notation (e.g. C:\... for Windows)
  27. &apos;&apos;&apos; The notation, both for arguments and for returned values
  28. &apos;&apos;&apos; is determined by the FileNaming property: either &quot;URL&quot; (default) or &quot;SYS&quot;
  29. &apos;&apos;&apos;
  30. &apos;&apos;&apos; FileName: the full name of the file including the path without any ending path separator
  31. &apos;&apos;&apos; FolderName: the full name of the folder including the path and the ending path separator
  32. &apos;&apos;&apos; Name: the last component of the File- or FolderName including its extension
  33. &apos;&apos;&apos; BaseName: the last component of the File- or FolderName without its extension
  34. &apos;&apos;&apos; NamePattern: any of the above names containing wildcards in its last component
  35. &apos;&apos;&apos; Admitted wildcards are: the &quot;?&quot; represents any single character
  36. &apos;&apos;&apos; the &quot;*&quot; represents zero, one, or multiple characters
  37. &apos;&apos;&apos;
  38. &apos;&apos;&apos; Service invocation example:
  39. &apos;&apos;&apos; Dim FSO As Variant
  40. &apos;&apos;&apos; Set FSO = CreateScriptService(&quot;FileSystem&quot;)
  41. &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;
  42. REM ================================================================== EXCEPTIONS
  43. Const UNKNOWNFILEERROR = &quot;UNKNOWNFILEERROR&quot; &apos; Source file does not exist
  44. Const UNKNOWNFOLDERERROR = &quot;UNKNOWNFOLDERERROR&quot; &apos; Source folder or Destination folder does not exist
  45. Const NOTAFILEERROR = &quot;NOTAFILEERROR&quot; &apos; Destination is a folder, not a file
  46. Const NOTAFOLDERERROR = &quot;NOTAFOLDERERROR&quot; &apos; Destination is a file, not a folder
  47. Const OVERWRITEERROR = &quot;OVERWRITEERROR&quot; &apos; Destination can not be overwritten
  48. Const READONLYERROR = &quot;READONLYERROR&quot; &apos; Destination has its read-only attribute set
  49. Const NOFILEMATCHERROR = &quot;NOFILEMATCHFOUND&quot; &apos; No file matches Source containing wildcards
  50. Const FOLDERCREATIONERROR = &quot;FOLDERCREATIONERROR&quot; &apos; FolderName is an existing folder or file
  51. REM ============================================================ MODULE CONSTANTS
  52. &apos;&apos;&apos; TextStream open modes
  53. Const cstForReading = 1
  54. Const cstForWriting = 2
  55. Const cstForAppending = 8
  56. REM ===================================================== CONSTRUCTOR/DESTRUCTOR
  57. REM -----------------------------------------------------------------------------
  58. Public Function Dispose() As Variant
  59. Set Dispose = Nothing
  60. End Function &apos; ScriptForge.SF_FileSystem Explicit destructor
  61. REM ================================================================== PROPERTIES
  62. REM -----------------------------------------------------------------------------
  63. Property Get ConfigFolder() As String
  64. &apos;&apos;&apos; Return the configuration folder of LibreOffice
  65. Const cstThisSub = &quot;FileSystem.getConfigFolder&quot;
  66. SF_Utils._EnterFunction(cstThisSub)
  67. ConfigFolder = SF_FileSystem._GetConfigFolder(&quot;user&quot;)
  68. SF_Utils._ExitFunction(cstThisSub)
  69. End Property &apos; ScriptForge.SF_FileSystem.ConfigFolder
  70. REM -----------------------------------------------------------------------------
  71. Property Get ExtensionsFolder() As String
  72. &apos;&apos;&apos; Return the folder containing the installed extensions
  73. Dim oMacro As Object &apos; /singletons/com.sun.star.util.theMacroExpander
  74. Const cstThisSub = &quot;FileSystem.getExtensionsFolder&quot;
  75. SF_Utils._EnterFunction(cstThisSub)
  76. Set oMacro = SF_Utils._GetUNOService(&quot;MacroExpander&quot;)
  77. ExtensionsFolder = SF_FileSystem._ConvertFromUrl(oMacro.ExpandMacros(&quot;$UNO_USER_PACKAGES_CACHE&quot;) &amp; &quot;/&quot;)
  78. SF_Utils._ExitFunction(cstThisSub)
  79. End Property &apos; ScriptForge.SF_FileSystem.ExtensionsFolder
  80. REM -----------------------------------------------------------------------------
  81. Property Get FileNaming() As Variant
  82. &apos;&apos;&apos; Return the current files and folder notation, either &quot;ANY&quot;, &quot;URL&quot; or &quot;SYS&quot;
  83. &apos;&apos;&apos; &quot;ANY&quot;: methods receive either URL or native file names, but always return URL file names
  84. &apos;&apos;&apos; &quot;URL&quot;: methods expect URL arguments and return URL strings (when relevant)
  85. &apos;&apos;&apos; &quot;SYS&quot;: idem but operating system notation
  86. Const cstThisSub = &quot;FileSystem.getFileNaming&quot;
  87. SF_Utils._EnterFunction(cstThisSub)
  88. FileNaming = _SF_.FileSystemNaming
  89. SF_Utils._ExitFunction(cstThisSub)
  90. End Property &apos; ScriptForge.SF_FileSystem.FileNaming (get)
  91. REM -----------------------------------------------------------------------------
  92. Property Let FileNaming(ByVal pvNotation As Variant)
  93. &apos;&apos;&apos; Set the files and folders notation: &quot;ANY&quot;, &quot;URL&quot; or &quot;SYS&quot;
  94. Const cstThisSub = &quot;FileSystem.setFileNaming&quot;
  95. SF_Utils._EnterFunction(cstThisSub)
  96. If VarType(pvNotation) = V_STRING Then
  97. Select Case UCase(pvNotation)
  98. Case &quot;ANY&quot;, &quot;URL&quot;, &quot;SYS&quot; : _SF_.FileSystemNaming = UCase(pvNotation)
  99. Case Else &apos; Unchanged
  100. End Select
  101. End If
  102. SF_Utils._ExitFunction(cstThisSub)
  103. End Property &apos; ScriptForge.SF_FileSystem.FileNaming (let)
  104. REM -----------------------------------------------------------------------------
  105. Property Get ForAppending As Integer
  106. &apos;&apos;&apos; Convenient constant (see documentation)
  107. ForAppending = cstForAppending
  108. End Property &apos; ScriptForge.SF_FileSystem.ForAppending
  109. REM -----------------------------------------------------------------------------
  110. Property Get ForReading As Integer
  111. &apos;&apos;&apos; Convenient constant (see documentation)
  112. ForReading = cstForReading
  113. End Property &apos; ScriptForge.SF_FileSystem.ForReading
  114. REM -----------------------------------------------------------------------------
  115. Property Get ForWriting As Integer
  116. &apos;&apos;&apos; Convenient constant (see documentation)
  117. ForWriting = cstForWriting
  118. End Property &apos; ScriptForge.SF_FileSystem.ForWriting
  119. REM -----------------------------------------------------------------------------
  120. Property Get HomeFolder() As String
  121. &apos;&apos;&apos; Return the user home folder
  122. Const cstThisSub = &quot;FileSystem.getHomeFolder&quot;
  123. SF_Utils._EnterFunction(cstThisSub)
  124. HomeFolder = SF_FileSystem._GetConfigFolder(&quot;home&quot;)
  125. SF_Utils._ExitFunction(cstThisSub)
  126. End Property &apos; ScriptForge.SF_FileSystem.HomeFolder
  127. REM -----------------------------------------------------------------------------
  128. Property Get InstallFolder() As String
  129. &apos;&apos;&apos; Return the installation folder of LibreOffice
  130. Const cstThisSub = &quot;FileSystem.getInstallFolder&quot;
  131. SF_Utils._EnterFunction(cstThisSub)
  132. InstallFolder = SF_FileSystem._GetConfigFolder(&quot;inst&quot;)
  133. SF_Utils._ExitFunction(cstThisSub)
  134. End Property &apos; ScriptForge.SF_FileSystem.InstallFolder
  135. REM -----------------------------------------------------------------------------
  136. Property Get ObjectType As String
  137. &apos;&apos;&apos; Only to enable object representation
  138. ObjectType = &quot;SF_FileSystem&quot;
  139. End Property &apos; ScriptForge.SF_FileSystem.ObjectType
  140. REM -----------------------------------------------------------------------------
  141. Property Get ServiceName As String
  142. &apos;&apos;&apos; Internal use
  143. ServiceName = &quot;ScriptForge.FileSystem&quot;
  144. End Property &apos; ScriptForge.SF_FileSystem.ServiceName
  145. REM -----------------------------------------------------------------------------
  146. Property Get TemplatesFolder() As String
  147. &apos;&apos;&apos; Return the folder defined in the LibreOffice paths options as intended for templates files
  148. Dim sPath As String &apos; Template property of com.sun.star.util.PathSettings
  149. Const cstThisSub = &quot;FileSystem.getTemplatesFolder&quot;
  150. SF_Utils._EnterFunction(cstThisSub)
  151. sPath = SF_Utils._GetUNOService(&quot;PathSettings&quot;).Template
  152. TemplatesFolder = SF_FileSystem._ConvertFromUrl(Split(sPath, &quot;;&quot;)(0))
  153. SF_Utils._ExitFunction(cstThisSub)
  154. End Property &apos; ScriptForge.SF_FileSystem.TemplatesFolder
  155. REM -----------------------------------------------------------------------------
  156. Property Get TemporaryFolder() As String
  157. &apos;&apos;&apos; Return the folder defined in the LibreOffice paths options as intended for temporary files
  158. Const cstThisSub = &quot;FileSystem.getTemporaryFolder&quot;
  159. SF_Utils._EnterFunction(cstThisSub)
  160. TemporaryFolder = SF_FileSystem._GetConfigFolder(&quot;temp&quot;)
  161. SF_Utils._ExitFunction(cstThisSub)
  162. End Property &apos; ScriptForge.SF_FileSystem.TemporaryFolder
  163. REM -----------------------------------------------------------------------------
  164. Property Get UserTemplatesFolder() As String
  165. &apos;&apos;&apos; Return the folder defined in the LibreOffice paths options as intended for User templates files
  166. Dim sPath As String &apos; Template_writable property of com.sun.star.util.PathSettings
  167. Const cstThisSub = &quot;FileSystem.getUserTemplatesFolder&quot;
  168. SF_Utils._EnterFunction(cstThisSub)
  169. sPath = SF_Utils._GetUNOService(&quot;PathSettings&quot;).Template_writable
  170. UserTemplatesFolder = SF_FileSystem._ConvertFromUrl(sPath)
  171. SF_Utils._ExitFunction(cstThisSub)
  172. End Property &apos; ScriptForge.SF_FileSystem.UserTemplatesFolder
  173. REM ===================================================================== METHODS
  174. REM -----------------------------------------------------------------------------
  175. Public Function BuildPath(Optional ByVal FolderName As Variant _
  176. , Optional ByVal Name As Variant _
  177. ) As String
  178. &apos;&apos;&apos; Combines a folder path and the name of a file and returns the combination with a valid path separator
  179. &apos;&apos;&apos; Inserts an additional path separator between the foldername and the name, only if necessary
  180. &apos;&apos;&apos; Args:
  181. &apos;&apos;&apos; FolderName: Path with which Name is combined. Path need not specify an existing folder
  182. &apos;&apos;&apos; Name: To be appended to the existing path.
  183. &apos;&apos;&apos; Returns:
  184. &apos;&apos;&apos; The path concatenated with the file name after insertion of a path separator, if necessary
  185. &apos;&apos;&apos; Example:
  186. &apos;&apos;&apos; Dim a As String
  187. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  188. &apos;&apos;&apos; a = FSO.BuildPath(&quot;C:\Windows&quot;, &quot;Notepad.exe&quot;) returns C:\Windows\Notepad.exe
  189. Dim sBuild As String &apos; Return value
  190. Dim sFile As String &apos; Alias for Name
  191. Const cstFileProtocol = &quot;file:///&quot;
  192. Const cstThisSub = &quot;FileSystem.BuildPath&quot;
  193. Const cstSubArgs = &quot;FolderName, Name&quot;
  194. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  195. sBuild = &quot;&quot;
  196. Check:
  197. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  198. If Not SF_Utils._ValidateFile(FolderName, &quot;FolderName&quot;) Then GoTo Finally
  199. If Not SF_Utils._Validate(Name, &quot;Name&quot;, V_STRING) Then GoTo Finally
  200. End If
  201. FolderName = SF_FileSystem._ConvertToUrl(FolderName)
  202. Try:
  203. &apos; Add separator if necessary. FolderName is now in URL notation
  204. If Len(FolderName) &gt; 0 Then
  205. If Right(FolderName, 1) &lt;&gt; &quot;/&quot; Then sBuild = FolderName &amp; &quot;/&quot; Else sBuild = FolderName
  206. Else
  207. sBuild = cstFileProtocol
  208. End If
  209. &apos; Encode the file name
  210. sFile = ConvertToUrl(Name)
  211. &apos; Some file names produce http://file.name.suffix/
  212. If Left(sFile, 7) = &quot;http://&quot; Then sFile = cstFileProtocol &amp; Mid(sFile, 8, Len(sFile) - 8)
  213. &apos; Combine both parts
  214. If Left(sFile, Len(cstFileProtocol)) = cstFileProtocol Then sBuild = sBuild &amp; Mid(sFile, Len(cstFileProtocol) + 1) Else sBuild = sBuild &amp; sFile
  215. Finally:
  216. BuildPath = SF_FileSystem._ConvertFromUrl(sBuild)
  217. SF_Utils._ExitFunction(cstThisSub)
  218. Exit Function
  219. Catch:
  220. GoTo Finally
  221. End Function &apos; ScriptForge.SF_FileSystem.BuildPath
  222. REM -----------------------------------------------------------------------------
  223. Public Function CompareFiles(Optional ByVal FileName1 As Variant _
  224. , Optional ByVal FileName2 As Variant _
  225. , Optional ByVal CompareContents As Variant _
  226. )
  227. &apos;&apos;&apos; Compare 2 files and return True if they seem identical
  228. &apos;&apos;&apos; The comparison may be based on the file attributes, like modification time,
  229. &apos;&apos;&apos; or on their contents.
  230. &apos;&apos;&apos; Args:
  231. &apos;&apos;&apos; FileName1: The 1st file to compare
  232. &apos;&apos;&apos; FileName2: The 2nd file to compare
  233. &apos;&apos;&apos; CompareContents: When True, the contents of the files are compared. Default = False
  234. &apos;&apos;&apos; Returns:
  235. &apos;&apos;&apos; True when the files seem identical
  236. &apos;&apos;&apos; Exceptions:
  237. &apos;&apos;&apos; UNKNOWNFILEERROR One of the files does not exist
  238. &apos;&apos;&apos; Example:
  239. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  240. &apos;&apos;&apos; MsgBox FSO.CompareFiles(&quot;C:\myFile1.txt&quot;, &quot;C:\myFile2.txt&quot;, CompareContents := True)
  241. Dim bCompare As Boolean &apos; Return value
  242. Dim sFile As String &apos; Alias of FileName1 and 2
  243. Dim iFile As Integer &apos; 1 or 2
  244. Const cstPyHelper = &quot;$&quot; &amp; &quot;_SF_FileSystem__CompareFiles&quot;
  245. Const cstThisSub = &quot;FileSystem.CompareFiles&quot;
  246. Const cstSubArgs = &quot;FileName1, FileName2, [CompareContents=False]&quot;
  247. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  248. bCompare = False
  249. Check:
  250. If IsMissing(CompareContents) Or IsEmpty(CompareContents) Then CompareContents = False
  251. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  252. If Not SF_Utils._ValidateFile(FileName1, &quot;FileName1&quot;, False) Then GoTo Finally
  253. If Not SF_Utils._ValidateFile(FileName2, &quot;FileName2&quot;, False) Then GoTo Finally
  254. If Not SF_Utils._Validate(CompareContents, &quot;CompareContents&quot;, V_BOOLEAN) Then GoTo Finally
  255. End If
  256. &apos; Do the files exist ? Otherwise raise error
  257. sFile = FileName1 : iFile = 1
  258. If Not SF_FileSystem.FileExists(sFile) Then GoTo CatchNotExists
  259. sFile = FileName2 : iFile = 2
  260. If Not SF_FileSystem.FileExists(sFile) Then GoTo CatchNotExists
  261. Try:
  262. With ScriptForge.SF_Session
  263. bCompare = .ExecutePythonScript(.SCRIPTISSHARED, _SF_.PythonHelper &amp; cstPyHelper _
  264. , _ConvertFromUrl(FileName1) _
  265. , _ConvertFromUrl(FileName2) _
  266. , CompareContents)
  267. End With
  268. Finally:
  269. CompareFiles = bCompare
  270. SF_Utils._ExitFunction(cstThisSub)
  271. Exit Function
  272. Catch:
  273. GoTo Finally
  274. CatchNotExists:
  275. SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot; &amp; iFile, sFile)
  276. GoTo Finally
  277. End Function &apos; ScriptForge.SF_FileSystem.CompareFiles
  278. REM -----------------------------------------------------------------------------
  279. Public Function CopyFile(Optional ByVal Source As Variant _
  280. , Optional ByVal Destination As Variant _
  281. , Optional ByVal Overwrite As Variant _
  282. ) As Boolean
  283. &apos;&apos;&apos; Copies one or more files from one location to another
  284. &apos;&apos;&apos; Args:
  285. &apos;&apos;&apos; Source: FileName or NamePattern which can include wildcard characters, for one or more files to be copied
  286. &apos;&apos;&apos; Destination: FileName where the single Source file is to be copied
  287. &apos;&apos;&apos; or FolderName where the multiple files from Source are to be copied
  288. &apos;&apos;&apos; If FolderName does not exist, it is created
  289. &apos;&apos;&apos; Anyway, wildcard characters are not allowed in Destination
  290. &apos;&apos;&apos; Overwrite: If True (default), files may be overwritten
  291. &apos;&apos;&apos; CopyFile will fail if Destination has the read-only attribute set, regardless of the value of Overwrite.
  292. &apos;&apos;&apos; Returns:
  293. &apos;&apos;&apos; True if at least one file has been copied
  294. &apos;&apos;&apos; False if an error occurred
  295. &apos;&apos;&apos; An error also occurs if a source using wildcard characters doesn&apos;t match any files.
  296. &apos;&apos;&apos; The method stops on the first error it encounters
  297. &apos;&apos;&apos; No attempt is made to roll back or undo any changes made before an error occurs
  298. &apos;&apos;&apos; Exceptions:
  299. &apos;&apos;&apos; UNKNOWNFILEERROR Source does not exist
  300. &apos;&apos;&apos; UNKNOWNFOLDERERROR Source folder or Destination folder does not exist
  301. &apos;&apos;&apos; NOFILEMATCHERROR No file matches Source containing wildcards
  302. &apos;&apos;&apos; NOTAFOLDERERROR Destination is a file, not a folder
  303. &apos;&apos;&apos; NOTAFILEERROR Destination is a folder, not a file
  304. &apos;&apos;&apos; OVERWRITEERROR Destination can not be overwritten
  305. &apos;&apos;&apos; READONLYERROR Destination has its read-only attribute set
  306. &apos;&apos;&apos; Example:
  307. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  308. &apos;&apos;&apos; FSO.CopyFile(&quot;C:\Windows\*.*&quot;, &quot;C:\Temp\&quot;, Overwrite := False) &apos; Only files are copied, subfolders are not
  309. Dim bCopy As Boolean &apos; Return value
  310. Const cstThisSub = &quot;FileSystem.CopyFile&quot;
  311. Const cstSubArgs = &quot;Source, Destination, [Overwrite=True]&quot;
  312. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  313. bCopy = False
  314. Check:
  315. If IsMissing(Overwrite) Or IsEmpty(Overwrite) Then Overwrite = True
  316. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  317. If Not SF_Utils._ValidateFile(Source, &quot;Source&quot;, True) Then GoTo Finally
  318. If Not SF_Utils._ValidateFile(Destination, &quot;Destination&quot;, False) Then GoTo Finally
  319. If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, V_BOOLEAN) Then GoTo Finally
  320. End If
  321. Try:
  322. bCopy = SF_FileSystem._CopyMove(&quot;CopyFile&quot;, Source, Destination, Overwrite)
  323. Finally:
  324. CopyFile = bCopy
  325. SF_Utils._ExitFunction(cstThisSub)
  326. Exit Function
  327. Catch:
  328. GoTo Finally
  329. End Function &apos; ScriptForge.SF_FileSystem.CopyFile
  330. REM -----------------------------------------------------------------------------
  331. Public Function CopyFolder(Optional ByVal Source As Variant _
  332. , Optional ByVal Destination As Variant _
  333. , Optional ByVal Overwrite As Variant _
  334. ) As Boolean
  335. &apos;&apos;&apos; Copies one or more folders from one location to another
  336. &apos;&apos;&apos; Args:
  337. &apos;&apos;&apos; Source: FolderName or NamePattern which can include wildcard characters, for one or more folders to be copied
  338. &apos;&apos;&apos; Destination: FolderName where the single Source folder is to be copied
  339. &apos;&apos;&apos; or FolderName where the multiple folders from Source are to be copied
  340. &apos;&apos;&apos; If FolderName does not exist, it is created
  341. &apos;&apos;&apos; Anyway, wildcard characters are not allowed in Destination
  342. &apos;&apos;&apos; Overwrite: If True (default), folders and their content may be overwritten
  343. &apos;&apos;&apos; CopyFile will fail if Destination has the read-only attribute set, regardless of the value of Overwrite.
  344. &apos;&apos;&apos; Returns:
  345. &apos;&apos;&apos; True if at least one folder has been copied
  346. &apos;&apos;&apos; False if an error occurred
  347. &apos;&apos;&apos; An error also occurs if a source using wildcard characters doesn&apos;t match any folders.
  348. &apos;&apos;&apos; The method stops on the first error it encounters
  349. &apos;&apos;&apos; No attempt is made to roll back or undo any changes made before an error occurs
  350. &apos;&apos;&apos; Exceptions:
  351. &apos;&apos;&apos; UNKNOWNFILEERROR Source does not exist
  352. &apos;&apos;&apos; UNKNOWNFOLDERERROR Source folder or Destination folder does not exist
  353. &apos;&apos;&apos; NOFILEMATCHERROR No file matches Source containing wildcards
  354. &apos;&apos;&apos; NOTAFOLDERERROR Destination is a file, not a folder
  355. &apos;&apos;&apos; OVERWRITEERROR Destination can not be overwritten
  356. &apos;&apos;&apos; READONLYERROR Destination has its read-only attribute set
  357. &apos;&apos;&apos; Example:
  358. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  359. &apos;&apos;&apos; FSO.CopyFolder(&quot;C:\Windows\*&quot;, &quot;C:\Temp\&quot;, Overwrite := False)
  360. Dim bCopy As Boolean &apos; Return value
  361. Const cstThisSub = &quot;FileSystem.CopyFolder&quot;
  362. Const cstSubArgs = &quot;Source, Destination, [Overwrite=True]&quot;
  363. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  364. bCopy = False
  365. Check:
  366. If IsMissing(Overwrite) Or IsEmpty(Overwrite) Then Overwrite = True
  367. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  368. If Not SF_Utils._ValidateFile(Source, &quot;Source&quot;, True) Then GoTo Finally
  369. If Not SF_Utils._ValidateFile(Destination, &quot;Destination&quot;, False) Then GoTo Finally
  370. If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, V_BOOLEAN) Then GoTo Finally
  371. End If
  372. Try:
  373. bCopy = SF_FileSystem._CopyMove(&quot;CopyFolder&quot;, Source, Destination, Overwrite)
  374. Finally:
  375. CopyFolder = bCopy
  376. SF_Utils._ExitFunction(cstThisSub)
  377. Exit Function
  378. Catch:
  379. GoTo Finally
  380. End Function &apos; ScriptForge.SF_FileSystem.CopyFolder
  381. REM -----------------------------------------------------------------------------
  382. Public Function CreateFolder(Optional ByVal FolderName As Variant) As Boolean
  383. &apos;&apos;&apos; Return True if the given folder name could be created successfully
  384. &apos;&apos;&apos; The parent folder does not need to exist beforehand
  385. &apos;&apos;&apos; Args:
  386. &apos;&apos;&apos; FolderName: a string representing the folder to create. It must not exist
  387. &apos;&apos;&apos; Returns:
  388. &apos;&apos;&apos; True if FolderName is a valid folder name, does not exist and creation was successful
  389. &apos;&apos;&apos; False otherwise including when FolderName is a file
  390. &apos;&apos;&apos; Exceptions:
  391. &apos;&apos;&apos; FOLDERCREATIONERROR FolderName is an existing folder or file
  392. &apos;&apos;&apos; Example:
  393. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  394. &apos;&apos;&apos; FSO.CreateFolder(&quot;C:\NewFolder\&quot;)
  395. Dim bCreate As Boolean &apos; Return value
  396. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  397. Const cstThisSub = &quot;FileSystem.CreateFolder&quot;
  398. Const cstSubArgs = &quot;FolderName&quot;
  399. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  400. bCreate = False
  401. Check:
  402. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  403. If Not SF_Utils._ValidateFile(FolderName, &quot;FolderName&quot;) Then GoTo Finally
  404. End If
  405. Try:
  406. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  407. If SF_FileSystem.FolderExists(FolderName) Then GoTo CatchExists
  408. If SF_FileSystem.FileExists(FolderName) Then GoTo CatchExists
  409. oSfa.createFolder(SF_FileSystem._ConvertToUrl(FolderName))
  410. bCreate = True
  411. Finally:
  412. CreateFolder = bCreate
  413. SF_Utils._ExitFunction(cstThisSub)
  414. Exit Function
  415. Catch:
  416. GoTo Finally
  417. CatchExists:
  418. SF_Exception.RaiseFatal(FOLDERCREATIONERROR, &quot;FolderName&quot;, FolderName)
  419. GoTo Finally
  420. End Function &apos; ScriptForge.SF_FileSystem.CreateFolder
  421. REM -----------------------------------------------------------------------------
  422. Public Function CreateTextFile(Optional ByVal FileName As Variant _
  423. , Optional ByVal Overwrite As Variant _
  424. , Optional ByVal Encoding As Variant _
  425. ) As Object
  426. &apos;&apos;&apos; Creates a specified file and returns a TextStream object that can be used to write to the file
  427. &apos;&apos;&apos; Args:
  428. &apos;&apos;&apos; FileName: Identifies the file to create
  429. &apos;&apos;&apos; Overwrite: Boolean value that indicates if an existing file can be overwritten (default = True)
  430. &apos;&apos;&apos; Encoding: The character set that should be used
  431. &apos;&apos;&apos; Use one of the Names listed in https://www.iana.org/assignments/character-sets/character-sets.xhtml
  432. &apos;&apos;&apos; Note that LibreOffice does not implement all existing sets
  433. &apos;&apos;&apos; Default = UTF-8
  434. &apos;&apos;&apos; Returns:
  435. &apos;&apos;&apos; An instance of the SF_TextStream class representing the opened file or a Null object if an error occurred
  436. &apos;&apos;&apos; It doesn&apos;t check either if the given encoding is implemented in LibreOffice
  437. &apos;&apos;&apos; Exceptions:
  438. &apos;&apos;&apos; OVERWRITEERROR File exists, creation impossible
  439. &apos;&apos;&apos; Example:
  440. &apos;&apos;&apos; Dim myFile As Object
  441. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  442. &apos;&apos;&apos; Set myFile = FSO.CreateTextFile(&quot;C:\Temp\ThisFile.txt&quot;, Overwrite := True)
  443. Dim oTextStream As Object &apos; Return value
  444. Const cstThisSub = &quot;FileSystem.CreateTextFile&quot;
  445. Const cstSubArgs = &quot;FileName, [Overwrite=True], [Encoding=&quot;&quot;UTF-8&quot;&quot;]&quot;
  446. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  447. Set oTextStream = Nothing
  448. Check:
  449. If IsMissing(Overwrite) Or IsEmpty(Overwrite) Then Overwrite = True
  450. If IsMissing(Encoding) Or IsEmpty(Encoding) Then Encoding = &quot;UTF-8&quot;
  451. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  452. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  453. If Not SF_Utils._Validate(Overwrite, &quot;Overwrite&quot;, V_BOOLEAN) Then GoTo Finally
  454. If Not SF_Utils._Validate(Encoding, &quot;Encoding&quot;, V_STRING) Then GoTo Finally
  455. End If
  456. With SF_FileSystem
  457. If .FileExists(FileName) Then
  458. If Overwrite Then .DeleteFile(FileName) Else GoTo CatchOverWrite
  459. End If
  460. Try:
  461. Set oTextStream = .OpenTextFile(FileName, .ForWriting, Create := True, Encoding := Encoding)
  462. End With
  463. Finally:
  464. Set CreateTextFile = oTextStream
  465. SF_Utils._ExitFunction(cstThisSub)
  466. Exit Function
  467. Catch:
  468. GoTo Finally
  469. CatchOverWrite:
  470. SF_Exception.RaiseFatal(OVERWRITEERROR, &quot;FileName&quot;, FileName)
  471. GoTo Finally
  472. End Function &apos; ScriptForge.SF_FileSystem.CreateTextFile
  473. REM -----------------------------------------------------------------------------
  474. Public Function DeleteFile(Optional ByVal FileName As Variant) As Boolean
  475. &apos;&apos;&apos; Deletes one or more files
  476. &apos;&apos;&apos; Args:
  477. &apos;&apos;&apos; FileName: FileName or NamePattern which can include wildcard characters, for one or more files to be deleted
  478. &apos;&apos;&apos; Returns:
  479. &apos;&apos;&apos; True if at least one file has been deleted
  480. &apos;&apos;&apos; False if an error occurred
  481. &apos;&apos;&apos; An error also occurs if a FileName using wildcard characters doesn&apos;t match any files.
  482. &apos;&apos;&apos; The method stops on the first error it encounters
  483. &apos;&apos;&apos; No attempt is made to roll back or undo any changes made before an error occurs
  484. &apos;&apos;&apos; Exceptions:
  485. &apos;&apos;&apos; UNKNOWNFILEERROR FileName does not exist
  486. &apos;&apos;&apos; NOFILEMATCHERROR No file matches FileName containing wildcards
  487. &apos;&apos;&apos; NOTAFILEERROR Argument is a folder, not a file
  488. &apos;&apos;&apos; Example:
  489. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  490. &apos;&apos;&apos; FSO.DeleteFile(&quot;C:\Temp\*.*&quot;) &apos; Only files are deleted, subfolders are not
  491. Dim bDelete As Boolean &apos; Return value
  492. Const cstThisSub = &quot;FileSystem.DeleteFile&quot;
  493. Const cstSubArgs = &quot;FileName&quot;
  494. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  495. bDelete = False
  496. Check:
  497. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  498. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;, True) Then GoTo Finally
  499. End If
  500. Try:
  501. bDelete = SF_FileSystem._Delete(&quot;DeleteFile&quot;, FileName)
  502. Finally:
  503. DeleteFile = bDelete
  504. SF_Utils._ExitFunction(cstThisSub)
  505. Exit Function
  506. Catch:
  507. GoTo Finally
  508. End Function &apos; ScriptForge.SF_FileSystem.DeleteFile
  509. REM -----------------------------------------------------------------------------
  510. Public Function DeleteFolder(Optional ByVal FolderName As Variant) As Boolean
  511. &apos;&apos;&apos; Deletes one or more Folders
  512. &apos;&apos;&apos; Args:
  513. &apos;&apos;&apos; FolderName: FolderName or NamePattern which can include wildcard characters, for one or more Folders to be deleted
  514. &apos;&apos;&apos; Returns:
  515. &apos;&apos;&apos; True if at least one folder has been deleted
  516. &apos;&apos;&apos; False if an error occurred
  517. &apos;&apos;&apos; An error also occurs if a FolderName using wildcard characters doesn&apos;t match any folders.
  518. &apos;&apos;&apos; The method stops on the first error it encounters
  519. &apos;&apos;&apos; No attempt is made to roll back or undo any changes made before an error occurs
  520. &apos;&apos;&apos; Exceptions:
  521. &apos;&apos;&apos; UNKNOWNFOLDERERROR FolderName does not exist
  522. &apos;&apos;&apos; NOFILEMATCHERROR No folder matches FolderName containing wildcards
  523. &apos;&apos;&apos; NOTAFOLDERERROR Argument is a file, not a folder
  524. &apos;&apos;&apos; Example:
  525. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  526. &apos;&apos;&apos; FSO.DeleteFolder(&quot;C:\Temp\*&quot;) &apos; Only folders are deleted, files in the parent folder are not
  527. Dim bDelete As Boolean &apos; Return value
  528. Const cstThisSub = &quot;FileSystem.DeleteFolder&quot;
  529. Const cstSubArgs = &quot;FolderName&quot;
  530. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  531. bDelete = False
  532. Check:
  533. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  534. If Not SF_Utils._ValidateFile(FolderName, &quot;FolderName&quot;, True) Then GoTo Finally
  535. End If
  536. Try:
  537. bDelete = SF_FileSystem._Delete(&quot;DeleteFolder&quot;, FolderName)
  538. Finally:
  539. DeleteFolder = bDelete
  540. SF_Utils._ExitFunction(cstThisSub)
  541. Exit Function
  542. Catch:
  543. GoTo Finally
  544. End Function &apos; ScriptForge.SF_FileSystem.DeleteFolder
  545. REM -----------------------------------------------------------------------------
  546. Public Function FileExists(Optional ByVal FileName As Variant) As Boolean
  547. &apos;&apos;&apos; Return True if the given file exists
  548. &apos;&apos;&apos; Args:
  549. &apos;&apos;&apos; FileName: a string representing a file
  550. &apos;&apos;&apos; Returns:
  551. &apos;&apos;&apos; True if FileName is a valid File name and it exists
  552. &apos;&apos;&apos; False otherwise including when FileName is a folder
  553. &apos;&apos;&apos; Example:
  554. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  555. &apos;&apos;&apos; If FSO.FileExists(&quot;C:\Notepad.exe&quot;) Then ...
  556. Dim bExists As Boolean &apos; Return value
  557. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  558. Const cstThisSub = &quot;FileSystem.FileExists&quot;
  559. Const cstSubArgs = &quot;FileName&quot;
  560. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  561. bExists = False
  562. Check:
  563. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  564. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  565. End If
  566. FileName = SF_FileSystem._ConvertToUrl(FileName)
  567. Try:
  568. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  569. bExists = oSfa.exists(FileName) And Not oSfa.isFolder(FileName)
  570. Finally:
  571. FileExists = bExists
  572. SF_Utils._ExitFunction(cstThisSub)
  573. Exit Function
  574. Catch:
  575. GoTo Finally
  576. End Function &apos; ScriptForge.SF_FileSystem.FileExists
  577. REM -----------------------------------------------------------------------------
  578. Public Function Files(Optional ByVal FolderName As Variant _
  579. , Optional ByVal Filter As Variant _
  580. ) As Variant
  581. &apos;&apos;&apos; Return an array of the FileNames stored in the given folder. The folder must exist
  582. &apos;&apos;&apos; Args:
  583. &apos;&apos;&apos; FolderName: the folder to explore
  584. &apos;&apos;&apos; Filter: contains wildcards (&quot;?&quot; and &quot;*&quot;) to limit the list to the relevant files (default = &quot;&quot;)
  585. &apos;&apos;&apos; Returns:
  586. &apos;&apos;&apos; An array of strings, each entry is the FileName of an existing file
  587. &apos;&apos;&apos; Exceptions:
  588. &apos;&apos;&apos; UNKNOWNFOLDERERROR Folder does not exist
  589. &apos;&apos;&apos; NOTAFOLDERERROR FolderName is a file, not a folder
  590. &apos;&apos;&apos; Example:
  591. &apos;&apos;&apos; Dim a As Variant
  592. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  593. &apos;&apos;&apos; a = FSO.Files(&quot;C:\Windows\&quot;)
  594. Dim vFiles As Variant &apos; Return value
  595. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  596. Dim sFolderName As String &apos; URL lias for FolderName
  597. Dim sFile As String &apos; Single file
  598. Dim i As Long
  599. Const cstThisSub = &quot;FileSystem.Files&quot;
  600. Const cstSubArgs = &quot;FolderName, [Filter=&quot;&quot;&quot;&quot;]&quot;
  601. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  602. vFiles = Array()
  603. Check:
  604. If IsMissing(Filter) Or IsEmpty(Filter) Then Filter = &quot;&quot;
  605. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  606. If Not SF_Utils._ValidateFile(FolderName, &quot;FolderName&quot;) Then GoTo Finally
  607. If Not SF_Utils._Validate(Filter, &quot;Filter&quot;, V_STRING) Then GoTo Finally
  608. End If
  609. sFolderName = SF_FileSystem._ConvertToUrl(FolderName)
  610. If SF_FileSystem.FileExists(FolderName) Then GoTo CatchFile &apos; Must not be a file
  611. If Not SF_FileSystem.FolderExists(FolderName) Then GoTo CatchFolder &apos; Folder must exist
  612. Try:
  613. &apos; Get files
  614. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  615. vFiles = oSfa.getFolderContents(sFolderName, False)
  616. &apos; Adjust notations
  617. For i = 0 To UBound(vFiles)
  618. sFile = SF_FileSystem._ConvertFromUrl(vFiles(i))
  619. vFiles(i) = sFile
  620. Next i
  621. &apos; Reduce list to those passing the filter
  622. If Len(Filter) &gt; 0 Then
  623. For i = 0 To UBound(vFiles)
  624. sFile = SF_FileSystem.GetName(vFiles(i))
  625. If Not SF_String.IsLike(sFile, Filter) Then vFiles(i) = &quot;&quot;
  626. Next i
  627. vFiles = Sf_Array.TrimArray(vFiles)
  628. End If
  629. Finally:
  630. Files = vFiles
  631. SF_Utils._ExitFunction(cstThisSub)
  632. Exit Function
  633. Catch:
  634. GoTo Finally
  635. CatchFile:
  636. SF_Exception.RaiseFatal(NOTAFOLDERERROR, &quot;FolderName&quot;, FolderName)
  637. GoTo Finally
  638. CatchFolder:
  639. SF_Exception.RaiseFatal(UNKNOWNFOLDERERROR, &quot;FolderName&quot;, FolderName)
  640. GoTo Finally
  641. End Function &apos; ScriptForge.SF_FileSystem.Files
  642. REM -----------------------------------------------------------------------------
  643. Public Function FolderExists(Optional ByVal FolderName As Variant) As Boolean
  644. &apos;&apos;&apos; Return True if the given folder name exists
  645. &apos;&apos;&apos; Args:
  646. &apos;&apos;&apos; FolderName: a string representing a folder
  647. &apos;&apos;&apos; Returns:
  648. &apos;&apos;&apos; True if FolderName is a valid folder name and it exists
  649. &apos;&apos;&apos; False otherwise including when FolderName is a file
  650. &apos;&apos;&apos; Example:
  651. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  652. &apos;&apos;&apos; If FSO.FolderExists(&quot;C:\&quot;) Then ...
  653. Dim bExists As Boolean &apos; Return value
  654. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  655. Const cstThisSub = &quot;FileSystem.FolderExists&quot;
  656. Const cstSubArgs = &quot;FolderName&quot;
  657. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  658. bExists = False
  659. Check:
  660. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  661. If Not SF_Utils._ValidateFile(FolderName, &quot;FolderName&quot;) Then GoTo Finally
  662. End If
  663. FolderName = SF_FileSystem._ConvertToUrl(FolderName)
  664. Try:
  665. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  666. bExists = oSfa.isFolder(FolderName)
  667. Finally:
  668. FolderExists = bExists
  669. SF_Utils._ExitFunction(cstThisSub)
  670. Exit Function
  671. Catch:
  672. GoTo Finally
  673. End Function &apos; ScriptForge.SF_FileSystem.FolderExists
  674. REM -----------------------------------------------------------------------------
  675. Public Function GetBaseName(Optional ByVal FileName As Variant) As String
  676. &apos;&apos;&apos; Returns the BaseName part of the last component of a File- or FolderName, without its extension
  677. &apos;&apos;&apos; The method does not check for the existence of the specified file or folder
  678. &apos;&apos;&apos; Args:
  679. &apos;&apos;&apos; FileName: Path and file name
  680. &apos;&apos;&apos; Returns:
  681. &apos;&apos;&apos; The BaseName of the given argument in native operating system format. May be empty
  682. &apos;&apos;&apos; Example:
  683. &apos;&apos;&apos; Dim a As String
  684. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  685. &apos;&apos;&apos; a = FSO.GetBaseName(&quot;C:\Windows\Notepad.exe&quot;) returns Notepad
  686. Dim sBase As String &apos; Return value
  687. Dim sExt As String &apos; Extension
  688. Dim sName As String &apos; Last component of FileName
  689. Dim vName As Variant &apos; Array of trunks of sName
  690. Const cstThisSub = &quot;FileSystem.GetBaseName&quot;
  691. Const cstSubArgs = &quot;FileName&quot;
  692. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  693. sBase = &quot;&quot;
  694. Check:
  695. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  696. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  697. End If
  698. Try:
  699. sName = SF_FileSystem.GetName(FileName)
  700. If Len(sName) &gt; 0 Then
  701. If InStr(sName, &quot;.&quot;) &gt; 0 Then
  702. vName = Split(sName, &quot;.&quot;)
  703. sExt = vName(UBound(vName))
  704. sBase = Left(sName, Len(sName) - Len(sExt) - 1)
  705. Else
  706. sBase = sName
  707. End If
  708. End If
  709. Finally:
  710. GetBaseName = sBase
  711. SF_Utils._ExitFunction(cstThisSub)
  712. Exit Function
  713. Catch:
  714. GoTo Finally
  715. End Function &apos; ScriptForge.SF_FileSystem.GetBaseName
  716. REM -----------------------------------------------------------------------------
  717. Public Function GetExtension(Optional ByVal FileName As Variant) As String
  718. &apos;&apos;&apos; Returns the extension part of a File- or FolderName, without the dot (.).
  719. &apos;&apos;&apos; The method does not check for the existence of the specified file or folder
  720. &apos;&apos;&apos; Args:
  721. &apos;&apos;&apos; FileName: Path and file name
  722. &apos;&apos;&apos; Returns:
  723. &apos;&apos;&apos; The extension without a leading dot. May be empty
  724. &apos;&apos;&apos; Example:
  725. &apos;&apos;&apos; Dim a As String
  726. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  727. &apos;&apos;&apos; a = FSO.GetExtension(&quot;C:\Windows\Notepad.exe&quot;) returns exe
  728. Dim sExt As String &apos; Return value
  729. Dim sName As String &apos; Last component of FileName
  730. Dim vName As Variant &apos; Array of trunks of sName
  731. Const cstThisSub = &quot;FileSystem.GetExtension&quot;
  732. Const cstSubArgs = &quot;FileName&quot;
  733. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  734. sExt = &quot;&quot;
  735. Check:
  736. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  737. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  738. End If
  739. Try:
  740. sName = SF_FileSystem.GetName(FileName)
  741. If Len(sName) &gt; 0 And InStr(sName, &quot;.&quot;) &gt; 0 Then
  742. vName = Split(sName, &quot;.&quot;)
  743. sExt = vName(UBound(vName))
  744. End If
  745. Finally:
  746. GetExtension = sExt
  747. SF_Utils._ExitFunction(cstThisSub)
  748. Exit Function
  749. Catch:
  750. GoTo Finally
  751. End Function &apos; ScriptForge.SF_FileSystem.GetExtension
  752. REM -----------------------------------------------------------------------------
  753. Public Function GetFileLen(Optional ByVal FileName As Variant) As Currency
  754. &apos;&apos;&apos; Return file size in bytes with four decimals &apos;&apos;&apos;
  755. &apos;&apos;&apos; Args:
  756. &apos;&apos;&apos; FileName: a string representing a file
  757. &apos;&apos;&apos; Returns:
  758. &apos;&apos;&apos; File size if FileName exists
  759. &apos;&apos;&apos; Exceptions:
  760. &apos;&apos;&apos; UNKNOWNFILEERROR The file does not exist of is a folder
  761. &apos;&apos;&apos; Example:
  762. &apos;&apos;&apos; Print SF_FileSystem.GetFileLen(&quot;C:\pagefile.sys&quot;)
  763. Dim curSize As Currency &apos; Return value
  764. Const cstPyHelper = &quot;$&quot; &amp; &quot;_SF_FileSystem__GetFilelen&quot;
  765. Const cstThisSub = &quot;FileSystem.GetFileLen&quot;
  766. Const cstSubArgs = &quot;FileName&quot;
  767. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  768. curSize = 0
  769. Check:
  770. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  771. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  772. End If
  773. Try:
  774. If SF_FileSystem.FileExists(FileName) Then
  775. With ScriptForge.SF_Session
  776. curSize = .ExecutePythonScript(.SCRIPTISSHARED, _SF_.PythonHelper &amp; cstPyHelper _
  777. , _ConvertFromUrl(FileName))
  778. End With
  779. Else
  780. GoTo CatchNotExists
  781. End If
  782. Finally:
  783. GetFileLen = curSize
  784. SF_Utils._ExitFunction(cstThisSub)
  785. Exit Function
  786. Catch:
  787. GoTo Finally
  788. CatchNotExists:
  789. SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, FileName)
  790. GoTo Finally
  791. End Function &apos; ScriptForge.SF_FileSystem.GetFileLen
  792. REM -----------------------------------------------------------------------------
  793. Public Function GetFileModified(Optional ByVal FileName As Variant) As Date
  794. &apos;&apos;&apos; Returns the last modified date for the given file
  795. &apos;&apos;&apos; Args:
  796. &apos;&apos;&apos; FileName: a string representing an existing file
  797. &apos;&apos;&apos; Returns:
  798. &apos;&apos;&apos; The modification date and time as a Basic Date
  799. &apos;&apos;&apos; Exceptions:
  800. &apos;&apos;&apos; UNKNOWNFILEERROR The file does not exist of is a folder
  801. &apos;&apos;&apos; Example:
  802. &apos;&apos;&apos; Dim a As Date
  803. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  804. &apos;&apos;&apos; a = FSO.GetFileModified(&quot;C:\Temp\myDoc.odt&quot;)
  805. Dim dModified As Date &apos; Return value
  806. Dim oModified As New com.sun.star.util.DateTime
  807. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  808. Const cstThisSub = &quot;FileSystem.GetFileModified&quot;
  809. Const cstSubArgs = &quot;FileName&quot;
  810. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  811. dModified = 0
  812. Check:
  813. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  814. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  815. End If
  816. Try:
  817. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  818. If SF_FileSystem.FileExists(FileName) Then
  819. FileName = SF_FileSystem._ConvertToUrl(FileName)
  820. Set oModified = oSfa.getDateTimeModified(FileName)
  821. dModified = CDateFromUnoDateTime(oModified)
  822. Else
  823. GoTo CatchNotExists
  824. End If
  825. Finally:
  826. GetFileModified = dModified
  827. SF_Utils._ExitFunction(cstThisSub)
  828. Exit Function
  829. Catch:
  830. GoTo Finally
  831. CatchNotExists:
  832. SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, FileName)
  833. GoTo Finally
  834. End Function &apos; ScriptForge.SF_FileSystem.GetFileModified
  835. REM -----------------------------------------------------------------------------
  836. Public Function GetName(Optional ByVal FileName As Variant) As String
  837. &apos;&apos;&apos; Returns the last component of a File- or FolderName
  838. &apos;&apos;&apos; The method does not check for the existence of the specified file or folder
  839. &apos;&apos;&apos; Args:
  840. &apos;&apos;&apos; FileName: Path and file name
  841. &apos;&apos;&apos; Returns:
  842. &apos;&apos;&apos; The last component of the full file name in native operating system format
  843. &apos;&apos;&apos; Example:
  844. &apos;&apos;&apos; Dim a As String
  845. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  846. &apos;&apos;&apos; a = FSO.GetName(&quot;C:\Windows\Notepad.exe&quot;) returns Notepad.exe
  847. Dim sName As String &apos; Return value
  848. Dim vFile As Variant &apos; Array of components
  849. Const cstThisSub = &quot;FileSystem.GetName&quot;
  850. Const cstSubArgs = &quot;FileName&quot;
  851. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  852. sName = &quot;&quot;
  853. Check:
  854. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  855. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  856. End If
  857. FileName = SF_FileSystem._ConvertToUrl(FileName)
  858. Try:
  859. If Len(FileName) &gt; 0 Then
  860. If Right(FileName, 1) = &quot;/&quot; Then FileName = Left(FileName, Len(FileName) - 1)
  861. vFile = Split(FileName, &quot;/&quot;)
  862. sName = ConvertFromUrl(vFile(UBound(vFile))) &apos; Always in SYS format
  863. End If
  864. Finally:
  865. GetName = sName
  866. SF_Utils._ExitFunction(cstThisSub)
  867. Exit Function
  868. Catch:
  869. GoTo Finally
  870. End Function &apos; ScriptForge.SF_FileSystem.GetName
  871. REM -----------------------------------------------------------------------------
  872. Public Function GetParentFolderName(Optional ByVal FileName As Variant) As String
  873. &apos;&apos;&apos; Returns a string containing the name of the parent folder of the last component in a specified File- or FolderName
  874. &apos;&apos;&apos; The method does not check for the existence of the specified file or folder
  875. &apos;&apos;&apos; Args:
  876. &apos;&apos;&apos; FileName: Path and file name
  877. &apos;&apos;&apos; Returns:
  878. &apos;&apos;&apos; A FolderName including its final path separator
  879. &apos;&apos;&apos; Example:
  880. &apos;&apos;&apos; Dim a As String
  881. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  882. &apos;&apos;&apos; a = FSO.GetParentFolderName(&quot;C:\Windows\Notepad.exe&quot;) returns C:\Windows\
  883. Dim sFolder As String &apos; Return value
  884. Dim sName As String &apos; Last component of FileName
  885. Dim vFile As Variant &apos; Array of file components
  886. Const cstThisSub = &quot;FileSystem.GetParentFolderName&quot;
  887. Const cstSubArgs = &quot;FileName&quot;
  888. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  889. sFolder = &quot;&quot;
  890. Check:
  891. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  892. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  893. End If
  894. FileName = SF_FileSystem._ConvertToUrl(FileName)
  895. Try:
  896. If Right(FileName, 1) = &quot;/&quot; Then FileName = Left(FileName, Len(FileName) - 1)
  897. vFile = Split(FileName, &quot;/&quot;)
  898. If UBound(vFile) &gt;= 0 Then vFile(UBound(vFile)) = &quot;&quot;
  899. sFolder = Join(vFile, &quot;/&quot;)
  900. If sFolder = &quot;&quot; Or Right(sFolder, 1) &lt;&gt; &quot;/&quot; Then sFolder = sFolder &amp; &quot;/&quot;
  901. Finally:
  902. GetParentFolderName = SF_FileSystem._ConvertFromUrl(sFolder)
  903. SF_Utils._ExitFunction(cstThisSub)
  904. Exit Function
  905. Catch:
  906. GoTo Finally
  907. End Function &apos; ScriptForge.SF_FileSystem.GetParentFolderName
  908. REM -----------------------------------------------------------------------------
  909. Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
  910. &apos;&apos;&apos; Return the actual value of the given property
  911. &apos;&apos;&apos; Args:
  912. &apos;&apos;&apos; PropertyName: the name of the property as a string
  913. &apos;&apos;&apos; Returns:
  914. &apos;&apos;&apos; The actual value of the property
  915. &apos;&apos;&apos; Exceptions
  916. &apos;&apos;&apos; ARGUMENTERROR The property does not exist
  917. Const cstThisSub = &quot;FileSystem.GetProperty&quot;
  918. Const cstSubArgs = &quot;PropertyName&quot;
  919. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  920. GetProperty = Null
  921. Check:
  922. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  923. If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
  924. End If
  925. Try:
  926. Select Case UCase(PropertyName)
  927. Case &quot;ConfigFolder&quot; : GetProperty = ConfigFolder
  928. Case &quot;ExtensionsFolder&quot; : GetProperty = ExtensionsFolder
  929. Case &quot;FileNaming&quot; : GetProperty = FileNaming
  930. Case &quot;HomeFolder&quot; : GetProperty = HomeFolder
  931. Case &quot;InstallFolder&quot; : GetProperty = InstallFolder
  932. Case &quot;TemplatesFolder&quot; : GetProperty = TemplatesFolder
  933. Case &quot;TemporaryFolder&quot; : GetProperty = TemporaryFolder
  934. Case &quot;UserTemplatesFolder&quot; : GetProperty = UserTemplatesFolder
  935. Case Else
  936. End Select
  937. Finally:
  938. SF_Utils._ExitFunction(cstThisSub)
  939. Exit Function
  940. Catch:
  941. GoTo Finally
  942. End Function &apos; ScriptForge.SF_FileSystem.GetProperty
  943. REM -----------------------------------------------------------------------------
  944. Public Function GetTempName() As String
  945. &apos;&apos;&apos; Returns a randomly generated temporary file name that is useful for performing
  946. &apos;&apos;&apos; operations that require a temporary file : the method does not create any file
  947. &apos;&apos;&apos; Args:
  948. &apos;&apos;&apos; Returns:
  949. &apos;&apos;&apos; A FileName as a String that can be used f.i. with CreateTextFile()
  950. &apos;&apos;&apos; The FileName does not have any suffix
  951. &apos;&apos;&apos; Example:
  952. &apos;&apos;&apos; Dim a As String
  953. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  954. &apos;&apos;&apos; a = FSO.GetTempName() &amp; &quot;.txt&quot;
  955. Dim sFile As String &apos; Return value
  956. Dim sTempDir As String &apos; The path to a temporary folder
  957. Dim lRandom As Long &apos; Random integer
  958. Const cstThisSub = &quot;FileSystem.GetTempName&quot;
  959. Const cstSubArgs = &quot;&quot;
  960. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  961. sFile = &quot;&quot;
  962. Check:
  963. SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
  964. Try:
  965. lRandom = SF_Session.ExecuteCalcFunction(&quot;RANDBETWEEN&quot;, 1, 999999)
  966. sFile = SF_FileSystem.TemporaryFolder &amp; &quot;SF_&quot; &amp; Right(&quot;000000&quot; &amp; lRandom, 6)
  967. Finally:
  968. GetTempName = SF_FileSystem._ConvertFromUrl(sFile)
  969. SF_Utils._ExitFunction(cstThisSub)
  970. Exit Function
  971. Catch:
  972. GoTo Finally
  973. End Function &apos; ScriptForge.SF_FileSystem.GetTempName
  974. REM -----------------------------------------------------------------------------
  975. Public Function HashFile(Optional ByVal FileName As Variant _
  976. , Optional ByVal Algorithm As Variant _
  977. ) As String
  978. &apos;&apos;&apos; Return an hexadecimal string representing a checksum of the given file
  979. &apos;&apos;&apos; Next algorithms are supported: MD5, SHA1, SHA224, SHA256, SHA384 and SHA512
  980. &apos;&apos;&apos; Args:
  981. &apos;&apos;&apos; FileName: a string representing a file
  982. &apos;&apos;&apos; Algorithm: The hashing algorithm to use
  983. &apos;&apos;&apos; Returns:
  984. &apos;&apos;&apos; The requested checksum as a string. Hexadecimal digits are lower-cased
  985. &apos;&apos;&apos; A zero-length string when an error occurred
  986. &apos;&apos;&apos; Exceptions:
  987. &apos;&apos;&apos; UNKNOWNFILEERROR The file does not exist of is a folder
  988. &apos;&apos;&apos; Example:
  989. &apos;&apos;&apos; Print SF_FileSystem.HashFile(&quot;C:\pagefile.sys&quot;, &quot;MD5&quot;)
  990. Dim sHash As String &apos; Return value
  991. Const cstPyHelper = &quot;$&quot; &amp; &quot;_SF_FileSystem__HashFile&quot;
  992. Const cstThisSub = &quot;FileSystem.HashFile&quot;
  993. Const cstSubArgs = &quot;FileName, Algorithm=&quot;&quot;MD5&quot;&quot;|&quot;&quot;SHA1&quot;&quot;|&quot;&quot;SHA224&quot;&quot;|&quot;&quot;SHA256&quot;&quot;|&quot;&quot;SHA384&quot;&quot;|&quot;&quot;SHA512&quot;&quot;&quot;
  994. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  995. sHash = &quot;&quot;
  996. Check:
  997. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  998. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  999. If Not SF_Utils._Validate(Algorithm, &quot;Algorithm&quot;, V_STRING _
  1000. , Array(&quot;MD5&quot;, &quot;SHA1&quot;, &quot;SHA224&quot;, &quot;SHA256&quot;, &quot;SHA384&quot;, &quot;SHA512&quot;)) Then GoTo Finally
  1001. End If
  1002. Try:
  1003. If SF_FileSystem.FileExists(FileName) Then
  1004. With ScriptForge.SF_Session
  1005. sHash = .ExecutePythonScript(.SCRIPTISSHARED, _SF_.PythonHelper &amp; cstPyHelper _
  1006. , _ConvertFromUrl(FileName), LCase(Algorithm))
  1007. End With
  1008. Else
  1009. GoTo CatchNotExists
  1010. End If
  1011. Finally:
  1012. HashFile = sHash
  1013. SF_Utils._ExitFunction(cstThisSub)
  1014. Exit Function
  1015. Catch:
  1016. GoTo Finally
  1017. CatchNotExists:
  1018. SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, FileName)
  1019. GoTo Finally
  1020. End Function &apos; ScriptForge.SF_FileSystem.HashFile
  1021. REM -----------------------------------------------------------------------------
  1022. Public Function Methods() As Variant
  1023. &apos;&apos;&apos; Return the list or methods of the FileSystem service as an array
  1024. Methods = Array(&quot;BuildPath&quot; _
  1025. , &quot;CompareFiles&quot; _
  1026. , &quot;CopyFile&quot; _
  1027. , &quot;CopyFolder&quot; _
  1028. , &quot;CreateFolder&quot; _
  1029. , &quot;CreateTextFile&quot; _
  1030. , &quot;DeleteFile&quot; _
  1031. , &quot;DeleteFolder&quot; _
  1032. , &quot;FileExists&quot; _
  1033. , &quot;Files&quot; _
  1034. , &quot;FolderExists&quot; _
  1035. , &quot;GetBaseName&quot; _
  1036. , &quot;GetExtension&quot; _
  1037. , &quot;GetFileLen&quot; _
  1038. , &quot;GetFileModified&quot; _
  1039. , &quot;GetName&quot; _
  1040. , &quot;GetParentFolderName&quot; _
  1041. , &quot;GetTempName&quot; _
  1042. , &quot;HashFile&quot; _
  1043. , &quot;MoveFile&quot; _
  1044. , &quot;MoveFolder&quot; _
  1045. , &quot;OpenTextFile&quot; _
  1046. , &quot;PickFile&quot; _
  1047. , &quot;PickFolder&quot; _
  1048. , &quot;SubFolders&quot; _
  1049. )
  1050. End Function &apos; ScriptForge.SF_FileSystem.Methods
  1051. REM -----------------------------------------------------------------------------
  1052. Public Function MoveFile(Optional ByVal Source As Variant _
  1053. , Optional ByVal Destination As Variant _
  1054. ) As Boolean
  1055. &apos;&apos;&apos; Moves one or more files from one location to another
  1056. &apos;&apos;&apos; Args:
  1057. &apos;&apos;&apos; Source: FileName or NamePattern which can include wildcard characters, for one or more files to be moved
  1058. &apos;&apos;&apos; Destination: FileName where the single Source file is to be moved
  1059. &apos;&apos;&apos; If Source and Destination have the same parent folder MoveFile amounts to renaming the Source
  1060. &apos;&apos;&apos; or FolderName where the multiple files from Source are to be moved
  1061. &apos;&apos;&apos; If FolderName does not exist, it is created
  1062. &apos;&apos;&apos; Anyway, wildcard characters are not allowed in Destination
  1063. &apos;&apos;&apos; Returns:
  1064. &apos;&apos;&apos; True if at least one file has been moved
  1065. &apos;&apos;&apos; False if an error occurred
  1066. &apos;&apos;&apos; An error also occurs if a source using wildcard characters doesn&apos;t match any files.
  1067. &apos;&apos;&apos; The method stops on the first error it encounters
  1068. &apos;&apos;&apos; No attempt is made to roll back or undo any changes made before an error occurs
  1069. &apos;&apos;&apos; Exceptions:
  1070. &apos;&apos;&apos; UNKNOWNFILEERROR Source does not exist
  1071. &apos;&apos;&apos; UNKNOWNFOLDERERROR Source folder or Destination folder does not exist
  1072. &apos;&apos;&apos; NOFILEMATCHERROR No file matches Source containing wildcards
  1073. &apos;&apos;&apos; NOTAFOLDERERROR Destination is a file, not a folder
  1074. &apos;&apos;&apos; NOTAFILEERROR Destination is a folder, not a file
  1075. &apos;&apos;&apos; OVERWRITEERROR Destination can not be overwritten
  1076. &apos;&apos;&apos; Example:
  1077. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  1078. &apos;&apos;&apos; FSO.MoveFile(&quot;C:\Temp1\*.*&quot;, &quot;C:\Temp2\&quot;) &apos; Only files are moved, subfolders are not
  1079. Dim bMove As Boolean &apos; Return value
  1080. Const cstThisSub = &quot;FileSystem.MoveFile&quot;
  1081. Const cstSubArgs = &quot;Source, Destination&quot;
  1082. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1083. bMove = False
  1084. Check:
  1085. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1086. If Not SF_Utils._ValidateFile(Source, &quot;Source&quot;, True) Then GoTo Finally
  1087. If Not SF_Utils._ValidateFile(Destination, &quot;Destination&quot;, False) Then GoTo Finally
  1088. End If
  1089. Try:
  1090. bMove = SF_FileSystem._CopyMove(&quot;MoveFile&quot;, Source, Destination, False)
  1091. Finally:
  1092. MoveFile = bMove
  1093. SF_Utils._ExitFunction(cstThisSub)
  1094. Exit Function
  1095. Catch:
  1096. GoTo Finally
  1097. End Function &apos; ScriptForge.SF_FileSystem.MoveFile
  1098. REM -----------------------------------------------------------------------------
  1099. Public Function MoveFolder(Optional ByVal Source As Variant _
  1100. , Optional ByVal Destination As Variant _
  1101. ) As Boolean
  1102. &apos;&apos;&apos; Moves one or more folders from one location to another
  1103. &apos;&apos;&apos; Args:
  1104. &apos;&apos;&apos; Source: FolderName or NamePattern which can include wildcard characters, for one or more folders to be moved
  1105. &apos;&apos;&apos; Destination: FolderName where the single Source folder is to be moved
  1106. &apos;&apos;&apos; FolderName must not exist
  1107. &apos;&apos;&apos; or FolderName where the multiple folders from Source are to be moved
  1108. &apos;&apos;&apos; If FolderName does not exist, it is created
  1109. &apos;&apos;&apos; Anyway, wildcard characters are not allowed in Destination
  1110. &apos;&apos;&apos; Returns:
  1111. &apos;&apos;&apos; True if at least one folder has been moved
  1112. &apos;&apos;&apos; False if an error occurred
  1113. &apos;&apos;&apos; An error also occurs if a source using wildcard characters doesn&apos;t match any folders.
  1114. &apos;&apos;&apos; The method stops on the first error it encounters
  1115. &apos;&apos;&apos; No attempt is made to roll back or undo any changes made before an error occurs
  1116. &apos;&apos;&apos; Exceptions:
  1117. &apos;&apos;&apos; UNKNOWNFILEERROR Source does not exist
  1118. &apos;&apos;&apos; UNKNOWNFOLDERERROR Source folder or Destination folder does not exist
  1119. &apos;&apos;&apos; NOFILEMATCHERROR No file matches Source containing wildcards
  1120. &apos;&apos;&apos; NOTAFOLDERERROR Destination is a file, not a folder
  1121. &apos;&apos;&apos; OVERWRITEERROR Destination can not be overwritten
  1122. &apos;&apos;&apos; Example:
  1123. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  1124. &apos;&apos;&apos; FSO.MoveFolder(&quot;C:\Temp1\*&quot;, &quot;C:\Temp2\&quot;)
  1125. Dim bMove As Boolean &apos; Return value
  1126. Const cstThisSub = &quot;FileSystem.MoveFolder&quot;
  1127. Const cstSubArgs = &quot;Source, Destination&quot;
  1128. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1129. bMove = False
  1130. Check:
  1131. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1132. If Not SF_Utils._ValidateFile(Source, &quot;Source&quot;, True) Then GoTo Finally
  1133. If Not SF_Utils._ValidateFile(Destination, &quot;Destination&quot;, False) Then GoTo Finally
  1134. End If
  1135. Try:
  1136. bMove = SF_FileSystem._CopyMove(&quot;MoveFolder&quot;, Source, Destination, False)
  1137. Finally:
  1138. MoveFolder = bMove
  1139. SF_Utils._ExitFunction(cstThisSub)
  1140. Exit Function
  1141. Catch:
  1142. GoTo Finally
  1143. End Function &apos; ScriptForge.SF_FileSystem.MoveFolder
  1144. REM -----------------------------------------------------------------------------
  1145. Public Function OpenTextFile(Optional ByVal FileName As Variant _
  1146. , Optional ByVal IOMode As Variant _
  1147. , Optional ByVal Create As Variant _
  1148. , Optional ByVal Encoding As Variant _
  1149. ) As Object
  1150. &apos;&apos;&apos; Opens a specified file and returns a TextStream object that can be used to read from, write to, or append to the file
  1151. &apos;&apos;&apos; Args:
  1152. &apos;&apos;&apos; FileName: Identifies the file to open
  1153. &apos;&apos;&apos; IOMode: Indicates input/output mode. Can be one of three constants: ForReading, ForWriting, or ForAppending
  1154. &apos;&apos;&apos; Create: Boolean value that indicates whether a new file can be created if the specified filename doesn&apos;t exist.
  1155. &apos;&apos;&apos; The value is True if a new file and its parent folders may be created; False if they aren&apos;t created (default)
  1156. &apos;&apos;&apos; Encoding: The character set that should be used
  1157. &apos;&apos;&apos; Use one of the Names listed in https://www.iana.org/assignments/character-sets/character-sets.xhtml
  1158. &apos;&apos;&apos; Note that LibreOffice does not implement all existing sets
  1159. &apos;&apos;&apos; Default = UTF-8
  1160. &apos;&apos;&apos; Returns:
  1161. &apos;&apos;&apos; An instance of the SF_TextStream class representing the opened file or a Null object if an error occurred
  1162. &apos;&apos;&apos; The method does not check if the file is really a text file
  1163. &apos;&apos;&apos; It doesn&apos;t check either if the given encoding is implemented in LibreOffice nor if it is the right one
  1164. &apos;&apos;&apos; Exceptions:
  1165. &apos;&apos;&apos; UNKNOWNFILEERROR File does not exist
  1166. &apos;&apos;&apos; Example:
  1167. &apos;&apos;&apos; Dim myFile As Object
  1168. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  1169. &apos;&apos;&apos; Set myFile = FSO.OpenTextFile(&quot;C:\Temp\ThisFile.txt&quot;, FSO.ForReading)
  1170. &apos;&apos;&apos; If Not IsNull(myFile) Then &apos; ... Go ahead with reading text lines
  1171. Dim oTextStream As Object &apos; Return value
  1172. Dim bExists As Boolean &apos; File to open does exist
  1173. Const cstThisSub = &quot;FileSystem.OpenTextFile&quot;
  1174. Const cstSubArgs = &quot;FileName, [IOMode=1], [Create=False], [Encoding=&quot;&quot;UTF-8&quot;&quot;]&quot;
  1175. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1176. Set oTextStream = Nothing
  1177. Check:
  1178. With SF_FileSystem
  1179. If IsMissing(IOMode) Or IsEmpty(IOMode) Then IOMode = ForReading
  1180. If IsMissing(Create) Or IsEmpty(Create) Then Create = False
  1181. If IsMissing(Encoding) Or IsEmpty(Encoding) Then Encoding = &quot;UTF-8&quot;
  1182. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1183. If Not SF_Utils._ValidateFile(FileName, &quot;FileName&quot;) Then GoTo Finally
  1184. If Not SF_Utils._Validate(IOMode, &quot;IOMode&quot;, V_NUMERIC _
  1185. , Array(ForReading, ForWriting, ForAppending)) _
  1186. Then GoTo Finally
  1187. If Not SF_Utils._Validate(Create, &quot;Create&quot;, V_BOOLEAN) Then GoTo Finally
  1188. If Not SF_Utils._Validate(Encoding, &quot;Encoding&quot;, V_STRING) Then GoTo Finally
  1189. End If
  1190. bExists = .FileExists(FileName)
  1191. Select Case IOMode
  1192. Case ForReading : If Not bExists Then GoTo CatchNotExists
  1193. Case Else : If Not bExists And Not Create Then GoTo CatchNotExists
  1194. End Select
  1195. If IOMode = ForAppending And Not bExists Then IOMode = ForWriting
  1196. End With
  1197. Try:
  1198. &apos; Create and initialize TextStream class instance
  1199. Set oTextStream = New SF_TextStream
  1200. With oTextStream
  1201. .[Me] = oTextStream
  1202. .[_Parent] = SF_FileSystem
  1203. ._FileName = SF_FileSystem._ConvertToUrl(FileName)
  1204. ._IOMode = IOMode
  1205. ._Encoding = Encoding
  1206. ._FileExists = bExists
  1207. ._Initialize()
  1208. End With
  1209. Finally:
  1210. Set OpenTextFile = oTextStream
  1211. SF_Utils._ExitFunction(cstThisSub)
  1212. Exit Function
  1213. Catch:
  1214. GoTo Finally
  1215. CatchNotExists:
  1216. SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, FileName)
  1217. GoTo Finally
  1218. End Function &apos; ScriptForge.SF_FileSystem.OpenTextFile
  1219. REM -----------------------------------------------------------------------------
  1220. Public Function PickFile(Optional ByVal DefaultFile As Variant _
  1221. , Optional ByVal Mode As Variant _
  1222. , Optional ByVal Filter As Variant _
  1223. ) As String
  1224. &apos;&apos;&apos; Returns the file selected with a FilePicker dialog box
  1225. &apos;&apos;&apos; The mode, OPEN or SAVE, and the filter may be preset
  1226. &apos;&apos;&apos; If mode = SAVE and the picked file exists, a warning message will be displayed
  1227. &apos;&apos;&apos; Modified from Andrew Pitonyak&apos;s Base Macro Programming §10.4
  1228. &apos;&apos;&apos; Args:
  1229. &apos;&apos;&apos; DefaultFile: Folder part: the FolderName from which to start. Default = the last selected folder
  1230. &apos;&apos;&apos; File part: the default file to open or save
  1231. &apos;&apos;&apos; Mode: &quot;OPEN&quot; (input file) or &quot;SAVE&quot; (output file)
  1232. &apos;&apos;&apos; Filter: by default only files having the given suffix will be displayed. Default = all suffixes
  1233. &apos;&apos;&apos; The filter combo box will contain the given SuffixFilter (if not &quot;*&quot;) and &quot;*.*&quot;
  1234. &apos;&apos;&apos; Returns:
  1235. &apos;&apos;&apos; The selected FileName in URL format or &quot;&quot; if the dialog was cancelled
  1236. &apos;&apos;&apos; Example:
  1237. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  1238. &apos;&apos;&apos; FSO.PickFile(&quot;C:\&quot;, &quot;OPEN&quot;, &quot;txt&quot;) &apos; Only *.txt files are displayed
  1239. Dim oFileDialog As Object &apos; com.sun.star.ui.dialogs.FilePicker
  1240. Dim oFileAccess As object &apos; com.sun.star.ucb.SimpleFileAccess
  1241. Dim oPath As Object &apos; com.sun.star.util.PathSettings
  1242. Dim iAccept As Integer &apos; Result of dialog execution
  1243. Dim sInitPath As String &apos; Current working directory
  1244. Dim sBaseFile As String
  1245. Dim iMode As Integer &apos; Numeric alias for SelectMode
  1246. Dim sFile As String &apos; Return value
  1247. Const cstThisSub = &quot;FileSystem.PickFile&quot;
  1248. Const cstSubArgs = &quot;[DefaultFile=&quot;&quot;&quot;&quot;], [Mode=&quot;&quot;OPEN&quot;&quot;|&quot;&quot;SAVE&quot;&quot;],[Filter=&quot;&quot;&quot;&quot;]&quot;
  1249. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1250. sFile = &quot;&quot;
  1251. Check:
  1252. If IsMissing(DefaultFile) Or IsEmpty(DefaultFile) Then DefaultFile = &quot;&quot;
  1253. If IsMissing(Mode) Or IsEmpty(Mode) Then Mode = &quot;OPEN&quot;
  1254. If IsMissing(Filter) Or IsEmpty(Filter) Then Filter = &quot;&quot;
  1255. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1256. If Not SF_Utils._ValidateFile(DefaultFile, &quot;DefaultFile&quot;, , True) Then GoTo Finally
  1257. If Not SF_Utils._Validate(Mode, &quot;Mode&quot;, V_STRING, Array(&quot;OPEN&quot;, &quot;SAVE&quot;)) Then GoTo Finally
  1258. If Not SF_Utils._Validate(Filter, &quot;Filter&quot;, V_STRING) Then GoTo Finally
  1259. End If
  1260. DefaultFile = SF_FileSystem._ConvertToUrl(DefaultFile)
  1261. Try:
  1262. &apos; Derive numeric equivalent of the Mode argument: https://api.libreoffice.org/docs/idl/ref/TemplateDescription_8idl.html
  1263. With com.sun.star.ui.dialogs.TemplateDescription
  1264. If Mode = &quot;OPEN&quot; Then iMode = .FILEOPEN_SIMPLE Else iMode = .FILESAVE_AUTOEXTENSION
  1265. End With
  1266. &apos; Activate the filepicker dialog
  1267. Set oFileDialog = SF_Utils._GetUNOService(&quot;FilePicker&quot;)
  1268. With oFileDialog
  1269. .Initialize(Array(iMode))
  1270. &apos; Set filters
  1271. If Len(Filter) &gt; 0 Then .appendFilter(&quot;*.&quot; &amp; Filter, &quot;*.&quot; &amp; Filter) &apos; Twice: required by API
  1272. .appendFilter(&quot;*.*&quot;, &quot;*.*&quot;)
  1273. If Len(Filter) &gt; 0 Then .setCurrentFilter(&quot;*.&quot; &amp; Filter) Else .setCurrentFilter(&quot;*.*&quot;)
  1274. &apos; Set initial folder
  1275. If Len(DefaultFile) = 0 Then &apos; TODO: SF_Session.WorkingFolder
  1276. Set oPath = SF_Utils._GetUNOService(&quot;PathSettings&quot;)
  1277. sInitPath = oPath.Work &apos; Probably My Documents
  1278. Else
  1279. sInitPath = SF_FileSystem._ParseUrl(ConvertToUrl(DefaultFile)).Path
  1280. End If
  1281. &apos; Set default values
  1282. Set oFileAccess = SF_Utils._GetUNOService(&quot;FileAccess&quot;)
  1283. If oFileAccess.exists(sInitPath) Then .SetDisplayDirectory(sInitPath)
  1284. sBaseFile = SF_FileSystem.GetName(DefaultFile)
  1285. .setDefaultName(sBaseFile)
  1286. &apos; Get selected file
  1287. iAccept = .Execute()
  1288. If iAccept = com.sun.star.ui.dialogs.ExecutableDialogResults.OK Then sFile = .getSelectedFiles()(0)
  1289. End With
  1290. Finally:
  1291. PickFile = SF_FileSystem._ConvertFromUrl(sFile)
  1292. SF_Utils._ExitFunction(cstThisSub)
  1293. Exit Function
  1294. Catch:
  1295. GoTo Finally
  1296. End Function &apos; ScriptForge.SF_FileSystem.PickFile
  1297. REM -----------------------------------------------------------------------------
  1298. Public Function PickFolder(Optional ByVal DefaultFolder As variant _
  1299. , Optional ByVal FreeText As Variant _
  1300. ) As String
  1301. &apos;&apos;&apos; Display a FolderPicker dialog box
  1302. &apos;&apos;&apos; Args:
  1303. &apos;&apos;&apos; DefaultFolder: the FolderName from which to start. Default = the last selected folder
  1304. &apos;&apos;&apos; FreeText: text to display in the dialog. Default = &quot;&quot;
  1305. &apos;&apos;&apos; Returns:
  1306. &apos;&apos;&apos; The selected FolderName in URL or operating system format
  1307. &apos;&apos;&apos; The zero-length string if the dialog was cancelled
  1308. &apos;&apos;&apos; Example:
  1309. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  1310. &apos;&apos;&apos; FSO.PickFolder(&quot;C:\&quot;, &quot;Choose a folder or press Cancel&quot;)
  1311. Dim oFolderDialog As Object &apos; com.sun.star.ui.dialogs.FolderPicker
  1312. Dim iAccept As Integer &apos; Value returned by the dialog (OK, Cancel, ..)
  1313. Dim sFolder As String &apos; Return value &apos;
  1314. Const cstThisSub = &quot;FileSystem.PickFolder&quot;
  1315. Const cstSubArgs = &quot;[DefaultFolder=&quot;&quot;&quot;&quot;], [FreeText=&quot;&quot;&quot;&quot;]&quot;
  1316. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1317. sFolder = &quot;&quot;
  1318. Check:
  1319. If IsMissing(DefaultFolder) Or IsEmpty(DefaultFolder) Then DefaultFolder = &quot;&quot;
  1320. If IsMissing(FreeText) Or IsEmpty(FreeText) Then FreeText = &quot;&quot;
  1321. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1322. If Not SF_Utils._ValidateFile(DefaultFolder, &quot;DefaultFolder&quot;, , True) Then GoTo Finally
  1323. If Not SF_Utils._Validate(FreeText, &quot;FreeText&quot;, V_STRING) Then GoTo Finally
  1324. End If
  1325. DefaultFolder = SF_FileSystem._ConvertToUrl(DefaultFolder)
  1326. Try:
  1327. Set oFolderDialog = SF_Utils._GetUNOService(&quot;FolderPicker&quot;)
  1328. If Not IsNull(oFolderDialog) Then
  1329. With oFolderDialog
  1330. If Len(DefaultFolder) &gt; 0 Then .DisplayDirectory = ConvertToUrl(DefaultFolder)
  1331. .Description = FreeText
  1332. iAccept = .Execute()
  1333. &apos; https://api.libreoffice.org/docs/idl/ref/ExecutableDialogResults_8idl.html
  1334. If iAccept = com.sun.star.ui.dialogs.ExecutableDialogResults.OK Then
  1335. .DisplayDirectory = .Directory &apos; Set the next default initial folder to the selected one
  1336. sFolder = .Directory &amp; &quot;/&quot;
  1337. End If
  1338. End With
  1339. End If
  1340. Finally:
  1341. PickFolder = SF_FileSystem._ConvertFromUrl(sFolder)
  1342. SF_Utils._ExitFunction(cstThisSub)
  1343. Exit Function
  1344. Catch:
  1345. GoTo Finally
  1346. End Function &apos; ScriptForge.SF_FileSystem.PickFolder
  1347. REM -----------------------------------------------------------------------------
  1348. Public Function Properties() As Variant
  1349. &apos;&apos;&apos; Return the list or properties of the FileSystem module as an array
  1350. Properties = Array( _
  1351. &quot;ConfigFolder&quot; _
  1352. , &quot;ExtensionsFolder&quot; _
  1353. , &quot;FileNaming&quot; _
  1354. , &quot;HomeFolder&quot; _
  1355. , &quot;InstallFolder&quot; _
  1356. , &quot;TemplatesFolder&quot; _
  1357. , &quot;TemporaryFolder&quot; _
  1358. , &quot;UserTemplatesFolder&quot; _
  1359. )
  1360. End Function &apos; ScriptForge.SF_FileSystem.Properties
  1361. REM -----------------------------------------------------------------------------
  1362. Public Function SetProperty(Optional ByVal PropertyName As Variant _
  1363. , Optional ByRef Value As Variant _
  1364. ) As Boolean
  1365. &apos;&apos;&apos; Set a new value to the given property
  1366. &apos;&apos;&apos; Args:
  1367. &apos;&apos;&apos; PropertyName: the name of the property as a string
  1368. &apos;&apos;&apos; Value: its new value
  1369. &apos;&apos;&apos; Exceptions
  1370. &apos;&apos;&apos; ARGUMENTERROR The property does not exist
  1371. Const cstThisSub = &quot;FileSystem.SetProperty&quot;
  1372. Const cstSubArgs = &quot;PropertyName, Value&quot;
  1373. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1374. SetProperty = False
  1375. Check:
  1376. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1377. If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
  1378. End If
  1379. Try:
  1380. Select Case UCase(PropertyName)
  1381. Case Else
  1382. End Select
  1383. Finally:
  1384. SF_Utils._ExitFunction(cstThisSub)
  1385. Exit Function
  1386. Catch:
  1387. GoTo Finally
  1388. End Function &apos; ScriptForge.SF_FileSystem.SetProperty
  1389. REM -----------------------------------------------------------------------------
  1390. Public Function SubFolders(Optional ByVal FolderName As Variant _
  1391. , Optional ByVal Filter As Variant _
  1392. ) As Variant
  1393. &apos;&apos;&apos; Return an array of the FolderNames stored in the given folder. The folder must exist
  1394. &apos;&apos;&apos; Args:
  1395. &apos;&apos;&apos; FolderName: the folder to explore
  1396. &apos;&apos;&apos; Filter: contains wildcards (&quot;?&quot; and &quot;*&quot;) to limit the list to the relevant folders (default = &quot;&quot;)
  1397. &apos;&apos;&apos; Returns:
  1398. &apos;&apos;&apos; An array of strings, each entry is the FolderName of an existing folder
  1399. &apos;&apos;&apos; Exceptions:
  1400. &apos;&apos;&apos; UNKNOWNFOLDERERROR Folder does not exist
  1401. &apos;&apos;&apos; NOTAFOLDERERROR FolderName is a file, not a folder
  1402. &apos;&apos;&apos; Example:
  1403. &apos;&apos;&apos; Dim a As Variant
  1404. &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
  1405. &apos;&apos;&apos; a = FSO.SubFolders(&quot;C:\Windows\&quot;)
  1406. Dim vSubFolders As Variant &apos; Return value
  1407. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  1408. Dim sFolderName As String &apos; URL lias for FolderName
  1409. Dim sFolder As String &apos; Single folder
  1410. Dim i As Long
  1411. Const cstThisSub = &quot;FileSystem.SubFolders&quot;
  1412. Const cstSubArgs = &quot;FolderName, [Filter=&quot;&quot;&quot;&quot;]&quot;
  1413. If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
  1414. vSubFolders = Array()
  1415. Check:
  1416. If IsMissing(Filter) Or IsEmpty(Filter) Then Filter = &quot;&quot;
  1417. If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
  1418. If Not SF_Utils._ValidateFile(FolderName, &quot;FolderName&quot;) Then GoTo Finally
  1419. If Not SF_Utils._Validate(Filter, &quot;Filter&quot;, V_STRING) Then GoTo Finally
  1420. End If
  1421. sFolderName = SF_FileSystem._ConvertToUrl(FolderName)
  1422. If SF_FileSystem.FileExists(FolderName) Then GoTo CatchFile &apos; Must not be a file
  1423. If Not SF_FileSystem.FolderExists(FolderName) Then GoTo CatchFolder &apos; Folder must exist
  1424. Try:
  1425. &apos; Get SubFolders
  1426. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  1427. vSubFolders = oSfa.getFolderContents(sFolderName, True)
  1428. &apos; List includes files; remove them or adjust notations of folders
  1429. For i = 0 To UBound(vSubFolders)
  1430. sFolder = SF_FileSystem._ConvertFromUrl(vSubFolders(i) &amp; &quot;/&quot;)
  1431. If SF_FileSystem.FileExists(sFolder) Then vSubFolders(i) = &quot;&quot; Else vSubFolders(i) = sFolder
  1432. &apos; Reduce list to those passing the filter
  1433. If Len(Filter) &gt; 0 And Len(vSubFolders(i)) &gt; 0 Then
  1434. sFolder = SF_FileSystem.GetName(vSubFolders(i))
  1435. If Not SF_String.IsLike(sFolder, Filter) Then vSubFolders(i) = &quot;&quot;
  1436. End If
  1437. Next i
  1438. vSubFolders = SF_Array.TrimArray(vSubFolders)
  1439. Finally:
  1440. SubFolders = vSubFolders
  1441. SF_Utils._ExitFunction(cstThisSub)
  1442. Exit Function
  1443. Catch:
  1444. GoTo Finally
  1445. CatchFile:
  1446. SF_Exception.RaiseFatal(NOTAFOLDERERROR, &quot;FolderName&quot;, FolderName)
  1447. GoTo Finally
  1448. CatchFolder:
  1449. SF_Exception.RaiseFatal(UNKNOWNFOLDERERROR, &quot;FolderName&quot;, FolderName)
  1450. GoTo Finally
  1451. End Function &apos; ScriptForge.SF_FileSystem.SubFolders
  1452. REM =========================================================== PRIVATE FUNCTIONS
  1453. REM -----------------------------------------------------------------------------
  1454. Private Function _ConvertFromUrl(psFile) As String
  1455. &apos;&apos;&apos; Execute the builtin ConvertFromUrl function only when relevant
  1456. &apos;&apos;&apos; i.e. when FileNaming (how arguments and return values are provided) = &quot;SYS&quot;
  1457. &apos;&apos;&apos; Called at the bottom of methods returning file names
  1458. &apos;&apos;&apos; Remark: psFile might contain wildcards
  1459. Const cstQuestion = &quot;$QUESTION$&quot;, cstStar = &quot;$STAR$&quot; &apos; Special tokens to replace wildcards
  1460. If SF_FileSystem.FileNaming = &quot;SYS&quot; Then
  1461. _ConvertFromUrl = Replace(Replace( _
  1462. ConvertFromUrl(Replace(Replace(psFile, &quot;?&quot;, cstQuestion), &quot;*&quot;, cstStar)) _
  1463. , cstQuestion, &quot;?&quot;), cstStar, &quot;*&quot;)
  1464. Else
  1465. _ConvertFromUrl = psFile
  1466. End If
  1467. End Function &apos; ScriptForge.FileSystem._ConvertFromUrl
  1468. REM -----------------------------------------------------------------------------
  1469. Private Function _ConvertToUrl(psFile) As String
  1470. &apos;&apos;&apos; Execute the builtin ConvertToUrl function only when relevant
  1471. &apos;&apos;&apos; i.e. when FileNaming (how arguments and return values are provided) = &quot;SYS&quot;
  1472. &apos;&apos;&apos; Called at the top of methods receiving file names as arguments
  1473. &apos;&apos;&apos; Remark: psFile might contain wildcards
  1474. If SF_FileSystem.FileNaming = &quot;URL&quot; Then
  1475. _ConvertToUrl = psFile
  1476. Else
  1477. &apos; ConvertToUrl encodes &quot;?&quot;
  1478. _ConvertToUrl = Replace(ConvertToUrl(psFile), &quot;%3F&quot;, &quot;?&quot;)
  1479. End If
  1480. End Function &apos; ScriptForge.FileSystem._ConvertToUrl
  1481. REM -----------------------------------------------------------------------------
  1482. Private Function _CopyMove(psMethod As String _
  1483. , psSource As String _
  1484. , psDestination As String _
  1485. , pbOverWrite As Boolean _
  1486. ) As Boolean
  1487. &apos;&apos;&apos; Checks the arguments and executes the given method
  1488. &apos;&apos;&apos; Args:
  1489. &apos;&apos;&apos; psMethod: CopyFile/CopyFolder or MoveFile/MoveFolder
  1490. &apos;&apos;&apos; psSource: Either File/FolderName
  1491. &apos;&apos;&apos; or NamePattern which can include wildcard characters, for one or more files/folders to be copied
  1492. &apos;&apos;&apos; psDestination: FileName or FolderName for copy/move of a single file/folder
  1493. &apos;&apos;&apos; Otherwise a destination FolderName. If it does not exist, it is created
  1494. &apos;&apos;&apos; pbOverWrite: If True, files/folders may be overwritten
  1495. &apos;&apos;&apos; Must be False for Move operations
  1496. &apos;&apos;&apos; Next checks are done:
  1497. &apos;&apos;&apos; With wildcards (multiple files/folders):
  1498. &apos;&apos;&apos; - Parent folder of source must exist
  1499. &apos;&apos;&apos; - Destination must not be a file
  1500. &apos;&apos;&apos; - Parent folder of Destination must exist
  1501. &apos;&apos;&apos; - If the Destination folder does not exist a new folder is created,
  1502. &apos;&apos;&apos; - At least one file matches the wildcards expression
  1503. &apos;&apos;&apos; - Destination files/folder must not exist if pbOverWrite = False
  1504. &apos;&apos;&apos; - Destination files/folders must not have the read-only attribute set
  1505. &apos;&apos;&apos; - Destination files must not be folders, destination folders must not be files
  1506. &apos;&apos;&apos; Without wildcards (single file/folder):
  1507. &apos;&apos;&apos; - Source file/folder must exist and be a file/folder
  1508. &apos;&apos;&apos; - Parent folder of Destination must exist
  1509. &apos;&apos;&apos; - Destination must not be an existing folder/file
  1510. &apos;&apos;&apos; - Destination file/folder must not exist if pbOverWrite = False
  1511. &apos;&apos;&apos; - Destination file must not have the read-only attribute set
  1512. Dim bCopyMove As Boolean &apos; Return value
  1513. Dim bCopy As Boolean &apos; True if Copy, False if Move
  1514. Dim bFile As Boolean &apos; True if File, False if Folder
  1515. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  1516. Dim bWildCards As Boolean &apos; True if wildcards found in Source
  1517. Dim bCreateFolder As Boolean &apos; True when the destination folder should be created
  1518. Dim bDestExists As Boolean &apos; True if destination exists
  1519. Dim sSourceUrl As String &apos; Alias for Source
  1520. Dim sDestinationUrl As String &apos; Alias for Destination
  1521. Dim sDestinationFile As String &apos; Destination FileName
  1522. Dim sParentFolder As String &apos; Parent folder of Source
  1523. Dim vFiles As Variant &apos; Array of candidates for copy/move
  1524. Dim sFile As String &apos; Single file/folder
  1525. Dim sName As String &apos; Name (last component) of file
  1526. Dim i As Long
  1527. &apos; Error handling left to calling routine
  1528. bCopyMove = False
  1529. bCopy = ( Left(psMethod, 4) = &quot;Copy&quot; )
  1530. bFile = ( Right(psMethod, 4) = &quot;File&quot; )
  1531. bWildCards = ( InStr(psSource, &quot;*&quot;) + InStr(psSource, &quot;?&quot;) + InStr(psSource, &quot;%3F&quot;) &gt; 0 ) &apos;ConvertToUrl() converts sometimes &quot;?&quot; to &quot;%3F&quot;
  1532. bDestExists = False
  1533. With SF_FileSystem
  1534. Check:
  1535. If bWildCards Then
  1536. sParentFolder = .GetParentFolderName(psSource)
  1537. If Not .FolderExists(sParentFolder) Then GoTo CatchNoMatch
  1538. If .FileExists(psDestination) Then GoTo CatchFileNotFolder
  1539. If Not .FolderExists(.GetParentFolderName(psDestination)) Then GoTo CatchDestFolderNotExists
  1540. bCreateFolder = Not .FolderExists(psDestination)
  1541. Else
  1542. Select Case bFile
  1543. Case True &apos; File
  1544. If Not .FileExists(psSource) Then GoTo CatchFileNotExists
  1545. If Not .FolderExists(.GetParentFolderName(psDestination)) Then GoTo CatchSourceFolderNotExists
  1546. If .FolderExists(psDestination) Then GoTo CatchFolderNotFile
  1547. bDestExists = .FileExists(psDestination)
  1548. If pbOverWrite = False And bDestExists = True Then GoTo CatchDestinationExists
  1549. bCreateFolder = False
  1550. Case False &apos; Folder
  1551. If Not .FolderExists(psSource) Then GoTo CatchSourceFolderNotExists
  1552. If Not .FolderExists(.GetParentFolderName(psDestination)) Then GoTo CatchDestFolderNotExists
  1553. If .FileExists(psDestination) Then GoTo CatchFileNotFolder
  1554. bDestExists = .FolderExists(psDestination)
  1555. If pbOverWrite = False And bDestExists Then GoTo CatchDestinationExists
  1556. bCreateFolder = Not bDestExists
  1557. End Select
  1558. End If
  1559. Try:
  1560. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  1561. If bWildCards Then
  1562. If bFile Then vFiles = .Files(sParentFolder, .GetName(psSource)) Else vFiles = .SubFolders(sParentFolder, .GetName(psSource))
  1563. If UBound(vFiles) &lt; 0 Then GoTo CatchNoMatch
  1564. &apos; Go through the candidates
  1565. If bCreateFolder Then .CreateFolder(psDestination)
  1566. For i = 0 To UBound(vFiles)
  1567. sFile = vFiles(i)
  1568. sDestinationFile = .BuildPath(psDestination, .GetName(sFile))
  1569. If bFile Then bDestExists = .FileExists(sDestinationFile) Else bDestExists = .FolderExists(sDestinationFile)
  1570. If pbOverWrite = False Then
  1571. If bDestExists Then GoTo CatchDestinationExists
  1572. If .FolderExists(sDestinationFile) Then GoTo CatchDestinationExists
  1573. End If
  1574. sSourceUrl = ._ConvertToUrl(sFile)
  1575. sDestinationUrl = ._ConvertToUrl(sDestinationFile)
  1576. If bDestExists Then
  1577. If oSfa.isReadOnly(sDestinationUrl) Then GoTo CatchDestinationReadOnly
  1578. End If
  1579. Select Case bCopy
  1580. Case True : oSfa.copy(sSourceUrl, sDestinationUrl)
  1581. Case False : oSfa.move(sSourceUrl, sDestinationUrl)
  1582. End Select
  1583. Next i
  1584. Else
  1585. sSourceUrl = ._ConvertToUrl(psSource)
  1586. sDestinationUrl = ._ConvertToUrl(psDestination)
  1587. If bDestExists Then
  1588. If oSfa.isReadOnly(sDestinationUrl) Then GoTo CatchDestinationReadOnly
  1589. End If
  1590. If bCreateFolder Then .CreateFolder(psDestination)
  1591. Select Case bCopy
  1592. Case True : oSfa.copy(sSourceUrl, sDestinationUrl)
  1593. Case False : oSfa.move(sSourceUrl, sDestinationUrl)
  1594. End Select
  1595. End If
  1596. End With
  1597. bCopyMove = True
  1598. Finally:
  1599. _CopyMove = bCopyMove
  1600. Exit Function
  1601. CatchFileNotExists:
  1602. SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;Source&quot;, psSource)
  1603. GoTo Finally
  1604. CatchSourceFolderNotExists:
  1605. SF_Exception.RaiseFatal(UNKNOWNFOLDERERROR, &quot;Source&quot;, psSource)
  1606. GoTo Finally
  1607. CatchDestFolderNotExists:
  1608. SF_Exception.RaiseFatal(UNKNOWNFOLDERERROR, &quot;Destination&quot;, psDestination)
  1609. GoTo Finally
  1610. CatchFolderNotFile:
  1611. SF_Exception.RaiseFatal(NOTAFILEERROR, &quot;Destination&quot;, psDestination)
  1612. GoTo Finally
  1613. CatchDestinationExists:
  1614. SF_Exception.RaiseFatal(OVERWRITEERROR, &quot;Destination&quot;, psDestination)
  1615. GoTo Finally
  1616. CatchNoMatch:
  1617. SF_Exception.RaiseFatal(NOFILEMATCHERROR, &quot;Source&quot;, psSource)
  1618. GoTo Finally
  1619. CatchFileNotFolder:
  1620. SF_Exception.RaiseFatal(NOTAFOLDERERROR, &quot;Destination&quot;, psDestination)
  1621. GoTo Finally
  1622. CatchDestinationReadOnly:
  1623. SF_Exception.RaiseFatal(READONLYERROR, &quot;Destination&quot;, Iif(bWildCards, sDestinationFile, psDestination))
  1624. GoTo Finally
  1625. End Function &apos; ScriptForge.SF_FileSystem._CopyMove
  1626. REM -----------------------------------------------------------------------------
  1627. Public Function _CountTextLines(ByVal psFileName As String _
  1628. , Optional ByVal pbIncludeBlanks As Boolean _
  1629. ) As Long
  1630. &apos;&apos;&apos; Convenient function to count the number of lines in a textfile
  1631. &apos;&apos;&apos; Args:
  1632. &apos;&apos;&apos; psFileName: the file in FileNaming notation
  1633. &apos;&apos;&apos; pbIncludeBlanks: if True (default), zero-length lines are included
  1634. &apos;&apos;&apos; Returns:
  1635. &apos;&apos;&apos; The number of lines, f.i. to ease array sizing. -1 if file reading error
  1636. Dim lLines As Long &apos; Return value
  1637. Dim oFile As Object &apos; File handler
  1638. Dim sLine As String &apos; The last line read
  1639. Try:
  1640. lLines = 0
  1641. If IsMissing(pbIncludeBlanks) Then pbIncludeBlanks = True
  1642. Set oFile = SF_FileSystem.OpenTextFile(psFileName, ForReading)
  1643. With oFile
  1644. If Not IsNull(oFile) Then
  1645. Do While Not .AtEndOfStream
  1646. sLine = .ReadLine()
  1647. lLines = lLines + Iif(Len(sLine) &gt; 0 Or pbIncludeBlanks, 1, 0)
  1648. Loop
  1649. End If
  1650. .CloseFile()
  1651. Set oFile = .Dispose()
  1652. End With
  1653. Finally:
  1654. _CountTextLines = lLines
  1655. Exit Function
  1656. End Function &apos; ScriptForge.SF_FileSystem._CountTextLines
  1657. REM -----------------------------------------------------------------------------
  1658. Private Function _Delete(psMethod As String _
  1659. , psFile As String _
  1660. ) As Boolean
  1661. &apos;&apos;&apos; Checks the argument and executes the given psMethod
  1662. &apos;&apos;&apos; Args:
  1663. &apos;&apos;&apos; psMethod: CopyFile/CopyFolder or MoveFile/MoveFolder
  1664. &apos;&apos;&apos; psFile: Either File/FolderName
  1665. &apos;&apos;&apos; or NamePattern which can include wildcard characters, for one or more files/folders to be deleted
  1666. &apos;&apos;&apos; Next checks are done:
  1667. &apos;&apos;&apos; With wildcards (multiple files/folders):
  1668. &apos;&apos;&apos; - Parent folder of File must exist
  1669. &apos;&apos;&apos; - At least one file matches the wildcards expression
  1670. &apos;&apos;&apos; - Files or folders to delete must not have the read-only attribute set
  1671. &apos;&apos;&apos; Without wildcards (single file/folder):
  1672. &apos;&apos;&apos; - File/folder must exist and be a file/folder
  1673. &apos;&apos;&apos; - A file or folder to delete must not have the read-only attribute set
  1674. Dim bDelete As Boolean &apos; Return value
  1675. Dim bFile As Boolean &apos; True if File, False if Folder
  1676. Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
  1677. Dim bWildCards As Boolean &apos; True if wildcards found in File
  1678. Dim sFileUrl As String &apos; Alias for File
  1679. Dim sParentFolder As String &apos; Parent folder of File
  1680. Dim vFiles As Variant &apos; Array of candidates for deletion
  1681. Dim sFile As String &apos; Single file/folder
  1682. Dim sName As String &apos; Name (last component) of file
  1683. Dim i As Long
  1684. &apos; Error handling left to calling routine
  1685. bDelete = False
  1686. bFile = ( Right(psMethod, 4) = &quot;File&quot; )
  1687. bWildCards = ( InStr(psFile, &quot;*&quot;) + InStr(psFile, &quot;?&quot;) + InStr(psFile, &quot;%3F&quot;) &gt; 0 ) &apos;ConvertToUrl() converts sometimes &quot;?&quot; to &quot;%3F&quot;
  1688. With SF_FileSystem
  1689. Check:
  1690. If bWildCards Then
  1691. sParentFolder = .GetParentFolderName(psFile)
  1692. If Not .FolderExists(sParentFolder) Then GoTo CatchNoMatch
  1693. Else
  1694. Select Case bFile
  1695. Case True &apos; File
  1696. If .FolderExists(psFile) Then GoTo CatchFolderNotFile
  1697. If Not .FileExists(psFile) Then GoTo CatchFileNotExists
  1698. Case False &apos; Folder
  1699. If .FileExists(psFile) Then GoTo CatchFileNotFolder
  1700. If Not .FolderExists(psFile) Then GoTo CatchFolderNotExists
  1701. End Select
  1702. End If
  1703. Try:
  1704. Set oSfa = SF_Utils._GetUnoService(&quot;FileAccess&quot;)
  1705. If bWildCards Then
  1706. If bFile Then vFiles = .Files(sParentFolder) Else vFiles = .SubFolders(sParentFolder)
  1707. &apos; Select candidates
  1708. For i = 0 To UBound(vFiles)
  1709. If Not SF_String.IsLike(.GetName(vFiles(i)), .GetName(psFile)) Then vFiles(i) = &quot;&quot;
  1710. Next i
  1711. vFiles = SF_Array.TrimArray(vFiles)
  1712. If UBound(vFiles) &lt; 0 Then GoTo CatchNoMatch
  1713. &apos; Go through the candidates
  1714. For i = 0 To UBound(vFiles)
  1715. sFile = vFiles(i)
  1716. sFileUrl = ._ConvertToUrl(sFile)
  1717. If oSfa.isReadOnly(sFileUrl) Then GoTo CatchReadOnly
  1718. oSfa.kill(sFileUrl)
  1719. Next i
  1720. Else
  1721. sFileUrl = ._ConvertToUrl(psFile)
  1722. If oSfa.isReadOnly(sFileUrl) Then GoTo CatchReadOnly
  1723. oSfa.kill(sFileUrl)
  1724. End If
  1725. End With
  1726. bDelete = True
  1727. Finally:
  1728. _Delete = bDelete
  1729. Exit Function
  1730. CatchFolderNotExists:
  1731. SF_Exception.RaiseFatal(UNKNOWNFOLDERERROR, &quot;FolderName&quot;, psFile)
  1732. GoTo Finally
  1733. CatchFileNotExists:
  1734. SF_Exception.RaiseFatal(UNKNOWNFILEERROR, &quot;FileName&quot;, psFile)
  1735. GoTo Finally
  1736. CatchFolderNotFile:
  1737. SF_Exception.RaiseFatal(NOTAFILEERROR, &quot;FileName&quot;, psFile)
  1738. GoTo Finally
  1739. CatchNoMatch:
  1740. SF_Exception.RaiseFatal(NOFILEMATCHERROR, Iif(bFile, &quot;FileName&quot;, &quot;FolderName&quot;), psFile)
  1741. GoTo Finally
  1742. CatchFileNotFolder:
  1743. SF_Exception.RaiseFatal(NOTAFOLDERERROR, &quot;FolderName&quot;, psFile)
  1744. GoTo Finally
  1745. CatchReadOnly:
  1746. SF_Exception.RaiseFatal(READONLYERROR, Iif(bFile, &quot;FileName&quot;, &quot;FolderName&quot;), Iif(bWildCards, sFile, psFile))
  1747. GoTo Finally
  1748. End Function &apos; ScriptForge.SF_FileSystem._Delete
  1749. REM -----------------------------------------------------------------------------
  1750. Private Function _GetConfigFolder(ByVal psFolder As String) As String
  1751. &apos;&apos;&apos; Returns one of next configuration folders: see https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1util_1_1PathSubstitution.html
  1752. &apos;&apos;&apos; inst =&gt; Installation path of LibreOffice
  1753. &apos;&apos;&apos; prog =&gt; Program path of LibreOffice
  1754. &apos;&apos;&apos; user =&gt; The user installation/config directory
  1755. &apos;&apos;&apos; work =&gt; The work directory of the user. Under Windows this would be the &quot;MyDocuments&quot; subdirectory. Under Unix this would be the home-directory
  1756. &apos;&apos;&apos; home =&gt; The home directory of the user. Under Unix this would be the home- directory.
  1757. &apos;&apos;&apos; Under Windows this would be the CSIDL_PERSONAL directory, for example &quot;Documents and Settings\&lt;username&gt;\Documents&quot;
  1758. &apos;&apos;&apos; temp =&gt; The current temporary directory
  1759. Dim oSubst As Object &apos; com.sun.star.util.PathSubstitution
  1760. Dim sConfig As String &apos; Return value
  1761. sConfig = &quot;&quot;
  1762. Set oSubst = SF_Utils._GetUNOService(&quot;PathSubstitution&quot;)
  1763. If Not IsNull(oSubst) Then sConfig = oSubst.getSubstituteVariableValue(&quot;$(&quot; &amp; psFolder &amp; &quot;)&quot;) &amp; &quot;/&quot;
  1764. _GetConfigFolder = SF_FileSystem._ConvertFromUrl(sConfig)
  1765. End Function &apos; ScriptForge.FileSystem._GetConfigFolder
  1766. REM -----------------------------------------------------------------------------
  1767. Public Function _ParseUrl(psUrl As String) As Object
  1768. &apos;&apos;&apos; Returns a com.sun.star.util.URL structure based on the argument
  1769. Dim oParse As Object &apos; com.sun.star.util.URLTransformer
  1770. Dim bParsed As Boolean &apos; True if parsing is successful
  1771. Dim oUrl As New com.sun.star.util.URL &apos; Return value
  1772. oUrl.Complete = psUrl
  1773. Set oParse = SF_Utils._GetUNOService(&quot;URLTransformer&quot;)
  1774. bParsed = oParse.parseStrict(oUrl, &quot;&quot;)
  1775. If bParsed Then oUrl.Path = ConvertToUrl(oUrl.Path)
  1776. Set _ParseUrl = oUrl
  1777. End Function &apos; ScriptForge.SF_FileSystem._ParseUrl
  1778. REM -----------------------------------------------------------------------------
  1779. Public Function _SFInstallFolder() As String
  1780. &apos;&apos;&apos; Returns the installation folder of the ScriptForge library
  1781. &apos;&apos;&apos; Either:
  1782. &apos;&apos;&apos; - The library is present in [My Macros &amp; Dialogs]
  1783. &apos;&apos;&apos; ($config)/basic/ScriptForge
  1784. &apos;&apos;&apos; - The library is present in [LibreOffice Macros &amp; Dialogs]
  1785. &apos;&apos;&apos; ($install)/share/basic/ScriptForge
  1786. Dim sFolder As String &apos; Folder
  1787. _SFInstallFolder = &quot;&quot;
  1788. sFolder = BuildPath(ConfigFolder, &quot;basic/ScriptForge&quot;)
  1789. If Not FolderExists(sFolder) Then
  1790. sFolder = BuildPath(InstallFolder, &quot;share/basic/ScriptForge&quot;)
  1791. If Not FolderExists(sFolder) Then Exit Function
  1792. End If
  1793. _SFInstallFolder = _ConvertFromUrl(sFolder)
  1794. End Function &apos; ScriptForge.SF_FileSystem._SFInstallFolder
  1795. REM ============================================ END OF SCRIPTFORGE.SF_FileSystem
  1796. </script:module>