calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / wizards / source / scriptforge / SF_TextStream.xba
blob35f1b6fb2b492e43919631427a91cd43c084a7f7
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_TextStream" 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 =======================================================================================================================
8 Option Compatible
9 Option ClassModule
11 Option Explicit
13 &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;
14 &apos;&apos;&apos; SF_TextStream
15 &apos;&apos;&apos; =============
16 &apos;&apos;&apos; Class instantiated by the
17 &apos;&apos;&apos; SF_FileSystem.CreateTextFile
18 &apos;&apos;&apos; SF_FileSystem.OpenTextFile
19 &apos;&apos;&apos; methods to facilitate the sequential processing of text files
20 &apos;&apos;&apos; All open/read/write/close operations are presumed to happen during the same macro run
21 &apos;&apos;&apos; The encoding to be used may be chosen by the user
22 &apos;&apos;&apos; The list is in the Name column of https://www.iana.org/assignments/character-sets/character-sets.xhtml
23 &apos;&apos;&apos; Note that probably not all values are available
24 &apos;&apos;&apos; Line delimiters may be chosen by the user
25 &apos;&apos;&apos; In input, CR, LF or CR+LF are supported
26 &apos;&apos;&apos; In output, the default value is the usual newline on the actual operating system (see SF_FileSystem.sfNEWLINE)
27 &apos;&apos;&apos;
28 &apos;&apos;&apos; The design choices are largely inspired by
29 &apos;&apos;&apos; https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/textstream-object
30 &apos;&apos;&apos; The implementation is mainly based on the XTextInputStream and XTextOutputStream UNO interfaces
31 &apos;&apos;&apos; https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1io_1_1XTextInputStream.html
32 &apos;&apos;&apos; https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1io_1_1XTextOutputStream.html
33 &apos;&apos;&apos;
34 &apos;&apos;&apos; Instantiation example:
35 &apos;&apos;&apos; Dim FSO As Object, myFile As Object
36 &apos;&apos;&apos; Set FSO = CreateScriptService(&quot;FileSystem&quot;)
37 &apos;&apos;&apos; Set myFile = FSO.OpenTextFile(&quot;C:\Temp\ThisFile.txt&quot;, FSO.ForReading) &apos; Once per file
38 &apos;&apos;&apos;
39 &apos;&apos;&apos; Detailed user documentation:
40 &apos;&apos;&apos; https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03/sf_textstream.html?DbPAR=BASIC
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;
43 REM ================================================================== EXCEPTIONS
45 Const FILENOTOPENERROR = &quot;FILENOTOPENERROR&quot; &apos; The file is already closed
46 Const FILEOPENMODEERROR = &quot;FILEOPENMODEERROR&quot; &apos; The file is open in incompatible mode
47 Const ENDOFFILEERROR = &quot;ENDOFFILEERROR&quot; &apos; When file was read, an end-of-file was encountered
49 REM ============================================================= PRIVATE MEMBERS
51 Private [Me] As Object
52 Private [_Parent] As Object
53 Private ObjectType As String &apos; Must be TEXTSTREAM
54 Private ServiceName As String
55 Private _FileName As String &apos; File where it is about
56 Private _IOMode As Integer &apos; ForReading, ForWriting or ForAppending
57 Private _Encoding As String &apos; https://www.iana.org/assignments/character-sets/character-sets.xhtml
58 Private _NewLine As String &apos; Line break in write mode
59 Private _FileExists As Boolean &apos; True if file exists before open
60 Private _LineNumber As Long &apos; Number of lines read or written
61 Private _FileHandler As Object &apos; com.sun.star.io.XInputStream or
62 &apos; com.sun.star.io.XOutputStream or
63 &apos; com.sun.star.io.XStream
64 Private _InputStream As Object &apos; com.sun.star.io.TextInputStream
65 Private _OutputStream As Object &apos; com.sun.star.io.TextOutputStream
66 Private _ForceBlankLine As Boolean &apos; Workaround: XTextInputStream misses last line if file ends with newline
68 REM ============================================================ MODULE CONSTANTS
70 REM ===================================================== CONSTRUCTOR/DESTRUCTOR
72 REM -----------------------------------------------------------------------------
73 Private Sub Class_Initialize()
74 Set [Me] = Nothing
75 Set [_Parent] = Nothing
76 ObjectType = &quot;TEXTSTREAM&quot;
77 ServiceName = &quot;ScriptForge.TextStream&quot;
78 _FileName = &quot;&quot;
79 _IOMode = -1
80 _Encoding = &quot;&quot;
81 _NewLine = &quot;&quot;
82 _FileExists = False
83 _LineNumber = 0
84 Set _FileHandler = Nothing
85 Set _InputStream = Nothing
86 Set _OutputStream = Nothing
87 _ForceBlankLine = False
88 End Sub &apos; ScriptForge.SF_TextStream Constructor
90 REM -----------------------------------------------------------------------------
91 Private Sub Class_Terminate()
92 Call Class_Initialize()
93 End Sub &apos; ScriptForge.SF_TextStream Destructor
95 REM -----------------------------------------------------------------------------
96 Public Function Dispose() As Variant
97 Call Class_Terminate()
98 Set Dispose = Nothing
99 End Function &apos; ScriptForge.SF_TextStream Explicit Destructor
101 REM ================================================================== PROPERTIES
103 REM -----------------------------------------------------------------------------
104 Property Get AtEndOfStream() As Boolean
105 &apos;&apos;&apos; In reading mode, True indicates that the end of the file has been reached
106 &apos;&apos;&apos; In write and append modes, or if the file is not ready =&gt; always True
107 &apos;&apos;&apos; The property should be invoked BEFORE each ReadLine() method:
108 &apos;&apos;&apos; A ReadLine() executed while AtEndOfStream is True will raise an error
109 &apos;&apos;&apos; Example:
110 &apos;&apos;&apos; Dim sLine As String
111 &apos;&apos;&apos; Do While Not myFile.AtEndOfStream
112 &apos;&apos;&apos; sLine = myFile.ReadLine()
113 &apos;&apos;&apos; &apos; ...
114 &apos;&apos;&apos; Loop
116 AtEndOfStream = _PropertyGet(&quot;AtEndOfStream&quot;)
118 End Property &apos; ScriptForge.SF_TextStream.AtEndOfStream
120 REM -----------------------------------------------------------------------------
121 Property Get Encoding() As String
122 &apos;&apos;&apos; Returns the name of the text file either in url or in native operating system format
123 &apos;&apos;&apos; Example:
124 &apos;&apos;&apos; Dim myFile As Object
125 &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
126 &apos;&apos;&apos; Set myFile = FSO.OpenTextFile(&quot;C:\Temp\myFile.txt&quot;)
127 &apos;&apos;&apos; MsgBox myFile.Encoding &apos; UTF-8
129 Encoding = _PropertyGet(&quot;Encoding&quot;)
131 End Property &apos; ScriptForge.SF_TextStream.Encoding
133 REM -----------------------------------------------------------------------------
134 Property Get FileName() As String
135 &apos;&apos;&apos; Returns the name of the text file either in url or in native operating system format
136 &apos;&apos;&apos; Example:
137 &apos;&apos;&apos; Dim myFile As Object
138 &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
139 &apos;&apos;&apos; Set myFile = FSO.OpenTextFile(&quot;C:\Temp\myFile.txt&quot;)
140 &apos;&apos;&apos; MsgBox myFile.FileName &apos; C:\Temp\myFile.txt
142 FileName = _PropertyGet(&quot;FileName&quot;)
144 End Property &apos; ScriptForge.SF_TextStream.FileName
146 REM -----------------------------------------------------------------------------
147 Property Get IOMode() As String
148 &apos;&apos;&apos; Returns either &quot;READ&quot;, &quot;WRITE&quot; or &quot;APPEND&quot;
149 &apos;&apos;&apos; Example:
150 &apos;&apos;&apos; Dim myFile As Object
151 &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
152 &apos;&apos;&apos; Set myFile = FSO.OpenTextFile(&quot;C:\Temp\myFile.txt&quot;)
153 &apos;&apos;&apos; MsgBox myFile.IOMode &apos; READ
155 IOMode = _PropertyGet(&quot;IOMode&quot;)
157 End Property &apos; ScriptForge.SF_TextStream.IOMode
159 REM -----------------------------------------------------------------------------
160 Property Get Line() As Long
161 &apos;&apos;&apos; Returns the number of lines read or written so far
162 &apos;&apos;&apos; Example:
163 &apos;&apos;&apos; Dim myFile As Object
164 &apos;&apos;&apos; FSO.FileNaming = &quot;SYS&quot;
165 &apos;&apos;&apos; Set myFile = FSO.OpenTextFile(&quot;C:\Temp\myFile.txt&quot;, FSO.ForAppending)
166 &apos;&apos;&apos; MsgBox myFile.Line &apos; The number of lines already present in myFile
168 Line = _PropertyGet(&quot;Line&quot;)
170 End Property &apos; ScriptForge.SF_TextStream.Line
172 REM -----------------------------------------------------------------------------
173 Property Get NewLine() As Variant
174 &apos;&apos;&apos; Returns the current character string to be inserted between 2 successive written lines
175 &apos;&apos;&apos; The default value is the native line separator in the current operating system
176 &apos;&apos;&apos; Example:
177 &apos;&apos;&apos; MsgBox myFile.NewLine
179 NewLine = _PropertyGet(&quot;NewLine&quot;)
181 End Property &apos; ScriptForge.SF_TextStream.NewLine (get)
183 REM -----------------------------------------------------------------------------
184 Property Let NewLine(ByVal pvLineBreak As Variant)
185 &apos;&apos;&apos; Sets the current character string to be inserted between 2 successive written lines
186 &apos;&apos;&apos; Example:
187 &apos;&apos;&apos; myFile.NewLine = Chr(13) &amp; Chr(10)
189 Const cstThisSub = &quot;TextStream.setNewLine&quot;
191 SF_Utils._EnterFunction(cstThisSub)
192 If VarType(pvLineBreak) = V_STRING Then _NewLine = pvLineBreak
193 SF_Utils._ExitFunction(cstThisSub)
195 End Property &apos; ScriptForge.SF_TextStream.NewLine (let)
197 REM ===================================================================== METHODS
199 REM -----------------------------------------------------------------------------
200 Public Function CloseFile() As Boolean
201 &apos;&apos;&apos; Empties the output buffer if relevant. Closes the actual input or output stream
202 &apos;&apos;&apos; Args:
203 &apos;&apos;&apos; Returns:
204 &apos;&apos;&apos; True if the closure was successful
205 &apos;&apos;&apos; Exceptions:
206 &apos;&apos;&apos; FILENOTOPENERROR Nothing found to close
207 &apos;&apos;&apos; Examples:
208 &apos;&apos;&apos; myFile.CloseFile()
210 Dim bClose As Boolean &apos; Return value
211 Const cstThisSub = &quot;TextStream.CloseFile&quot;
212 Const cstSubArgs = &quot;&quot;
214 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
215 bClose = False
217 Check:
218 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
219 If Not _IsFileOpen() Then GoTo Finally
221 Try:
222 If Not IsNull(_InputStream) Then _InputStream.closeInput()
223 If Not IsNull(_OutputStream) Then
224 _OutputStream.flush()
225 _OutputStream.closeOutput()
226 End If
227 Set _InputStream = Nothing
228 Set _OutputStream = Nothing
229 Set _FileHandler = Nothing
230 bClose = True
232 Finally:
233 CloseFile = bClose
234 SF_Utils._ExitFunction(cstThisSub)
235 Exit Function
236 Catch:
237 GoTo Finally
238 End Function &apos; ScriptForge.SF_TextStream.CloseFile
240 REM -----------------------------------------------------------------------------
241 Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
242 &apos;&apos;&apos; Return the actual value of the given property
243 &apos;&apos;&apos; Args:
244 &apos;&apos;&apos; PropertyName: the name of the property as a string
245 &apos;&apos;&apos; Returns:
246 &apos;&apos;&apos; The actual value of the property
247 &apos;&apos;&apos; If the property does not exist, returns Null
248 &apos;&apos;&apos; Exceptions:
249 &apos;&apos;&apos; see the exceptions of the individual properties
250 &apos;&apos;&apos; Examples:
251 &apos;&apos;&apos; myModel.GetProperty(&quot;MyProperty&quot;)
253 Const cstThisSub = &quot;TextStream.GetProperty&quot;
254 Const cstSubArgs = &quot;&quot;
256 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
257 GetProperty = Null
259 Check:
260 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
261 If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
262 End If
264 Try:
265 GetProperty = _PropertyGet(PropertyName)
267 Finally:
268 SF_Utils._ExitFunction(cstThisSub)
269 Exit Function
270 Catch:
271 GoTo Finally
272 End Function &apos; ScriptForge.SF_TextStream.GetProperty
274 REM -----------------------------------------------------------------------------
275 Public Function Methods() As Variant
276 &apos;&apos;&apos; Return the list of public methods of the Model service as an array
278 Methods = Array( _
279 &quot;CloseFile&quot; _
280 , &quot;ReadAll&quot; _
281 , &quot;readLine&quot; _
282 , &quot;SkipLine&quot; _
283 , &quot;WriteBlankLines&quot; _
284 , &quot;WriteLine&quot; _
287 End Function &apos; ScriptForge.SF_TextStream.Methods
289 REM -----------------------------------------------------------------------------
290 Public Function Properties() As Variant
291 &apos;&apos;&apos; Return the list or properties of the Timer class as an array
293 Properties = Array( _
294 &quot;AtEndOfStream&quot; _
295 , &quot;Encoding&quot; _
296 , &quot;FileName&quot; _
297 , &quot;IOMode&quot; _
298 , &quot;Line&quot; _
299 , &quot;NewLine&quot; _
302 End Function &apos; ScriptForge.SF_TextStream.Properties
304 REM -----------------------------------------------------------------------------
305 Public Function ReadAll() As String
306 &apos;&apos;&apos; Returns all the remaining lines in the text stream as one string. Line breaks are NOT removed
307 &apos;&apos;&apos; The resulting string can be split in lines
308 &apos;&apos;&apos; either by using the usual Split Basic builtin function if the line delimiter is known
309 &apos;&apos;&apos; or with the SF_String.SplitLines method
310 &apos;&apos;&apos; For large files, using the ReadAll method wastes memory resources.
311 &apos;&apos;&apos; Other techniques should be used to input a file, such as reading a file line-by-line
312 &apos;&apos;&apos; Args:
313 &apos;&apos;&apos; Returns:
314 &apos;&apos;&apos; The read lines. The string may be empty.
315 &apos;&apos;&apos; Note that the Line property in incremented only by 1
316 &apos;&apos;&apos; Exceptions:
317 &apos;&apos;&apos; FILENOTOPENERROR File not open or already closed
318 &apos;&apos;&apos; FILEOPENMODEERROR File opened in write or append modes
319 &apos;&apos;&apos; ENDOFFILEERROR Previous reads already reached the end of the file
320 &apos;&apos;&apos; Examples:
321 &apos;&apos;&apos; Dim a As String
322 &apos;&apos;&apos; a = myFile.ReadAll()
324 Dim sRead As String &apos; Return value
325 Const cstThisSub = &quot;TextStream.ReadAll&quot;
326 Const cstSubArgs = &quot;&quot;
328 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
329 sRead = &quot;&quot;
331 Check:
332 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
333 If Not _IsFileOpen(&quot;READ&quot;) Then GoTo Finally
334 If _InputStream.isEOF() Then GoTo CatchEOF
335 End If
337 Try:
338 sRead = _InputStream.readString(Array(), False)
339 _LineNumber = _LineNumber + 1
341 Finally:
342 ReadAll = sRead
343 SF_Utils._ExitFunction(cstThisSub)
344 Exit Function
345 Catch:
346 GoTo Finally
347 CatchEOF:
348 SF_Exception.RaiseFatal(ENDOFFILEERROR, FileName)
349 GoTo Finally
350 End Function &apos; ScriptForge.SF_TextStream.ReadAll
352 REM -----------------------------------------------------------------------------
353 Public Function ReadLine() As String
354 &apos;&apos;&apos; Returns the next line in the text stream as a string. Line breaks are removed.
355 &apos;&apos;&apos; Args:
356 &apos;&apos;&apos; Returns:
357 &apos;&apos;&apos; The read line. The string may be empty.
358 &apos;&apos;&apos; Exceptions:
359 &apos;&apos;&apos; FILENOTOPENERROR File not open or already closed
360 &apos;&apos;&apos; FILEOPENMODEERROR File opened in write or append modes
361 &apos;&apos;&apos; ENDOFFILEERROR Previous reads already reached the end of the file
362 &apos;&apos;&apos; Examples:
363 &apos;&apos;&apos; Dim a As String
364 &apos;&apos;&apos; a = myFile.ReadLine()
366 Dim sRead As String &apos; Return value
367 Dim iRead As Integer &apos; Length of line break
368 Const cstThisSub = &quot;TextStream.ReadLine&quot;
369 Const cstSubArgs = &quot;&quot;
371 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
372 sRead = &quot;&quot;
374 Check:
375 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
376 If Not _IsFileOpen(&quot;READ&quot;) Then GoTo Finally
377 If AtEndOfStream Then GoTo CatchEOF
378 End If
380 Try:
381 &apos; When the text file ends with a line break,
382 &apos; XTextInputStream.readLine() returns the line break together with the last line
383 &apos; Hence the workaround to force a blank line at the end
384 If _ForceBlankLine Then
385 sRead = &quot;&quot;
386 _ForceBlankLine = False
387 Else
388 sRead = _InputStream.readLine()
389 &apos; The isEOF() is set immediately after having read the last line
390 If _InputStream.isEOF() And Len(sRead) &gt; 0 Then
391 iRead = 0
392 If SF_String.EndsWith(sRead, SF_String.sfCRLF) Then
393 iRead = 2
394 ElseIf SF_String.EndsWith(sRead, SF_String.sfLF) Or SF_String.EndsWith(sRead, SF_String.sfCR) Then
395 iRead = 1
396 End If
397 If iRead &gt; 0 Then
398 sRead = Left(sRead, Len(sRead) - iRead)
399 _ForceBlankLine = True &apos; Provision for a last empty line at the next read loop
400 End If
401 End If
402 End If
403 _LineNumber = _LineNumber + 1
405 Finally:
406 ReadLine = sRead
407 SF_Utils._ExitFunction(cstThisSub)
408 Exit Function
409 Catch:
410 GoTo Finally
411 CatchEOF:
412 SF_Exception.RaiseFatal(ENDOFFILEERROR, FileName)
413 GoTo Finally
414 End Function &apos; ScriptForge.SF_TextStream.ReadLine
416 REM -----------------------------------------------------------------------------
417 Public Function SetProperty(Optional ByVal PropertyName As Variant _
418 , Optional ByRef Value As Variant _
419 ) As Boolean
420 &apos;&apos;&apos; Set a new value to the given property
421 &apos;&apos;&apos; Args:
422 &apos;&apos;&apos; PropertyName: the name of the property as a string
423 &apos;&apos;&apos; Value: its new value
424 &apos;&apos;&apos; Exceptions
425 &apos;&apos;&apos; ARGUMENTERROR The property does not exist
427 Dim bSet As Boolean &apos; Return value
428 Const cstThisSub = &quot;TextStream.SetProperty&quot;
429 Const cstSubArgs = &quot;PropertyName, Value&quot;
431 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
432 bSet = False
434 Check:
435 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
436 If Not SF_Utils._Validate(PropertyName, &quot;PropertyName&quot;, V_STRING, Properties()) Then GoTo Catch
437 End If
439 Try:
440 bSet = True
441 Select Case UCase(PropertyName)
442 Case &quot;NEWLINE&quot;
443 If Not SF_Utils._Validate(Value, &quot;Value&quot;, V_STRING) Then GoTo Catch
444 NewLine = Value
445 Case Else
446 bSet = False
447 End Select
449 Finally:
450 SetProperty = bSet
451 SF_Utils._ExitFunction(cstThisSub)
452 Exit Function
453 Catch:
454 GoTo Finally
455 End Function &apos; ScriptForge.SF_TextStream.SetProperty
457 REM -----------------------------------------------------------------------------
458 Public Sub SkipLine()
459 &apos;&apos;&apos; Skips the next line when reading a TextStream file.
460 &apos;&apos;&apos; Args:
461 &apos;&apos;&apos; Exceptions:
462 &apos;&apos;&apos; FILENOTOPENERROR File not open or already closed
463 &apos;&apos;&apos; FILEOPENMODEERROR File opened in write or append modes
464 &apos;&apos;&apos; ENDOFFILEERROR Previous reads already reached the end of the file
465 &apos;&apos;&apos; Examples:
466 &apos;&apos;&apos; myFile.SkipLine()
468 Dim sRead As String &apos; Read buffer
469 Const cstThisSub = &quot;TextStream.SkipLine&quot;
470 Const cstSubArgs = &quot;&quot;
472 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
474 Check:
475 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
476 If Not _IsFileOpen(&quot;READ&quot;) Then GoTo Finally
477 If Not _ForceBlankLine Then &apos; The file ends with a newline =&gt; return one empty line more
478 If _InputStream.isEOF() Then GoTo CatchEOF
479 End If
480 End If
482 Try:
483 sRead = ReadLine()
485 Finally:
486 SF_Utils._ExitFunction(cstThisSub)
487 Exit Sub
488 Catch:
489 GoTo Finally
490 CatchEOF:
491 SF_Exception.RaiseFatal(ENDOFFILEERROR, FileName)
492 GoTo Finally
493 End Sub &apos; ScriptForge.SF_TextStream.SkipLine
495 REM -----------------------------------------------------------------------------
496 Public Sub WriteBlankLines(Optional ByVal Lines As Variant)
497 &apos;&apos;&apos; Writes a number of empty lines in the output stream
498 &apos;&apos;&apos; Args:
499 &apos;&apos;&apos; Lines: the number of lines to write
500 &apos;&apos;&apos; Returns:
501 &apos;&apos;&apos; Exceptions:
502 &apos;&apos;&apos; FILENOTOPENERROR File not open or already closed
503 &apos;&apos;&apos; FILEOPENMODEERROR File opened in read mode
504 &apos;&apos;&apos; Examples:
505 &apos;&apos;&apos; myFile.WriteBlankLines(10)
506 Dim i As Long
507 Const cstThisSub = &quot;TextStream.WriteBlankLines&quot;
508 Const cstSubArgs = &quot;Lines&quot;
510 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
512 Check:
513 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
514 If Not _IsFileOpen(&quot;WRITE&quot;) Then GoTo Finally
515 If Not SF_Utils._Validate(Lines, &quot;Lines&quot;, V_NUMERIC) Then GoTo Finally
516 End If
518 Try:
519 For i = 1 To Lines
520 _OutputStream.writeString(_NewLine)
521 Next i
522 _LineNumber = _LineNumber + Lines
524 Finally:
525 SF_Utils._ExitFunction(cstThisSub)
526 Exit Sub
527 Catch:
528 GoTo Finally
529 End Sub &apos; ScriptForge.SF_TextStream.WriteBlankLines
531 REM -----------------------------------------------------------------------------
532 Public Sub WriteLine(Optional ByVal Line As Variant)
533 &apos;&apos;&apos; Writes the given line to the output stream. A newline is inserted if relevant
534 &apos;&apos;&apos; Args:
535 &apos;&apos;&apos; Line: the line to write, may be empty
536 &apos;&apos;&apos; Returns:
537 &apos;&apos;&apos; Exceptions:
538 &apos;&apos;&apos; FILENOTOPENERROR File not open or already closed
539 &apos;&apos;&apos; FILEOPENMODEERROR File opened in in read mode
540 &apos;&apos;&apos; Examples:
541 &apos;&apos;&apos; myFile.WriteLine(&quot;Next line&quot;)
542 Dim i As Long
543 Const cstThisSub = &quot;TextStream.WriteLine&quot;
544 Const cstSubArgs = &quot;Line&quot;
546 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
548 Check:
549 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
550 If Not _IsFileOpen(&quot;WRITE&quot;) Then GoTo Finally
551 If Not SF_Utils._Validate(Line, &quot;Line&quot;, V_STRING) Then GoTo Finally
552 End If
554 Try:
555 _OutputStream.writeString(Iif(_LineNumber &gt; 0, _NewLine, &quot;&quot;) &amp; Line)
556 _LineNumber = _LineNumber + 1
558 Finally:
559 SF_Utils._ExitFunction(cstThisSub)
560 Exit Sub
561 Catch:
562 GoTo Finally
563 End Sub &apos; ScriptForge.SF_TextStream.WriteLine
565 REM =========================================================== PRIVATE FUNCTIONS
567 REM -----------------------------------------------------------------------------
568 Public Sub _Initialize()
569 &apos;&apos;&apos; Opens file and setup input and/or output streams (ForAppending requires both)
571 Dim oSfa As Object &apos; com.sun.star.ucb.SimpleFileAccess
573 &apos; Default newline related to current operating system
574 _NewLine = SF_String.sfNEWLINE
576 Set oSfa = SF_Utils._GetUNOService(&quot;FileAccess&quot;)
578 &apos; Setup input and/or output streams based on READ/WRITE/APPEND IO modes
579 Select Case _IOMode
580 Case SF_FileSystem.ForReading
581 Set _FileHandler = oSfa.openFileRead(_FileName)
582 Set _InputStream = CreateUnoService(&quot;com.sun.star.io.TextInputStream&quot;)
583 _InputStream.setInputStream(_FileHandler)
584 Case SF_FileSystem.ForWriting
585 &apos; Output file is deleted beforehand
586 If _FileExists Then oSfa.kill(_FileName)
587 Set _FileHandler = oSfa.openFileWrite(_FileName)
588 Set _OutputStream = CreateUnoService(&quot;com.sun.star.io.TextOutputStream&quot;)
589 _OutputStream.setOutputStream(_FileHandler)
590 Case SF_FileSystem.ForAppending
591 Set _FileHandler = oSfa.openFileReadWrite(_FileName)
592 Set _InputStream = CreateUnoService(&quot;com.sun.star.io.TextInputStream&quot;)
593 Set _OutputStream = CreateUnoService(&quot;com.sun.star.io.TextOutputStream&quot;)
594 _InputStream.setInputStream(_FileHandler)
595 &apos; Position at end of file: Skip and count existing lines
596 _LineNumber = 0
597 Do While Not _InputStream.isEOF()
598 _InputStream.readLine()
599 _LineNumber = _LineNumber + 1
600 Loop
601 _OutputStream.setOutputStream(_FileHandler)
602 End Select
604 If _Encoding = &quot;&quot; Then _Encoding = &quot;UTF-8&quot;
605 If Not IsNull(_InputStream) Then _InputStream.setEncoding(_Encoding)
606 If Not IsNull(_OutputStream) Then _OutputStream.setEncoding(_Encoding)
608 End Sub &apos; ScriptForge.SF_TextStream._Initialize
610 REM -----------------------------------------------------------------------------
611 Private Function _IsFileOpen(Optional ByVal psMode As String) As Boolean
612 &apos;&apos;&apos; Checks if file is open with the right mode (READ or WRITE)
613 &apos;&apos;&apos; Raises an exception if the file is not open at all or not in the right mode
614 &apos;&apos;&apos; Args:
615 &apos;&apos;&apos; psMode: READ or WRITE or zero-length string
616 &apos;&apos;&apos; Exceptions:
617 &apos;&apos;&apos; FILENOTOPENERROR File not open or already closed
618 &apos;&apos;&apos; FILEOPENMODEERROR File opened in incompatible mode
620 _IsFileOpen = False
621 If IsMissing(psMode) Then psMode = &quot;&quot;
622 If IsNull(_InputStream) And IsNull(_OutputStream) Then GoTo CatchNotOpen
623 Select Case psMode
624 Case &quot;READ&quot;
625 If IsNull(_InputStream) Then GoTo CatchOpenMode
626 If _IOMode &lt;&gt; SF_FileSystem.ForReading Then GoTo CatchOpenMode
627 Case &quot;WRITE&quot;
628 If IsNull(_OutputStream) Then GoTo CatchOpenMode
629 If _IOMode = SF_FileSystem.ForReading Then GoTo CatchOpenMode
630 Case Else
631 End Select
632 _IsFileOpen = True
634 Finally:
635 Exit Function
636 CatchNotOpen:
637 SF_Exception.RaiseFatal(FILENOTOPENERROR, FileName)
638 GoTo Finally
639 CatchOpenMode:
640 SF_Exception.RaiseFatal(FILEOPENMODEERROR, FileName, IOMode)
641 GoTo Finally
642 End Function &apos; ScriptForge.SF_TextStream._IsFileOpen
644 REM -----------------------------------------------------------------------------
645 Private Function _PropertyGet(Optional ByVal psProperty As String)
646 &apos;&apos;&apos; Return the value of the named property
647 &apos;&apos;&apos; Args:
648 &apos;&apos;&apos; psProperty: the name of the property
650 Dim cstThisSub As String
651 Dim cstSubArgs As String
653 cstThisSub = &quot;TextStream.get&quot; &amp; psProperty
654 cstSubArgs = &quot;&quot;
655 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
657 Select Case UCase(psProperty)
658 Case UCase(&quot;AtEndOfStream&quot;)
659 Select Case _IOMode
660 Case SF_FileSystem.ForReading
661 If IsNull(_InputStream) Then _PropertyGet = True Else _PropertyGet = CBool(_InputStream.isEOF() And Not _ForceBlankLine)
662 Case Else : _PropertyGet = True
663 End Select
664 Case UCase(&quot;Encoding&quot;)
665 _PropertyGet = _Encoding
666 Case UCase(&quot;FileName&quot;)
667 _PropertyGet = SF_FileSystem._ConvertFromUrl(_FileName) &apos; Depends on FileNaming
668 Case UCase(&quot;IOMode&quot;)
669 With SF_FileSystem
670 Select Case _IOMode
671 Case .ForReading : _PropertyGet = &quot;READ&quot;
672 Case .ForWriting : _PropertyGet = &quot;WRITE&quot;
673 Case .ForAppending : _PropertyGet = &quot;APPEND&quot;
674 Case Else : _PropertyGet = &quot;&quot;
675 End Select
676 End With
677 Case UCase(&quot;Line&quot;)
678 _PropertyGet = _LineNumber
679 Case UCase(&quot;NewLine&quot;)
680 _PropertyGet = _NewLine
681 Case Else
682 _PropertyGet = Null
683 End Select
685 Finally:
686 SF_Utils._ExitFunction(cstThisSub)
687 Exit Function
688 End Function &apos; ScriptForge.SF_TextStream._PropertyGet
690 REM -----------------------------------------------------------------------------
691 Private Function _Repr() As String
692 &apos;&apos;&apos; Convert the TextStream instance to a readable string, typically for debugging purposes (DebugPrint ...)
693 &apos;&apos;&apos; Args:
694 &apos;&apos;&apos; Return:
695 &apos;&apos;&apos; &quot;[TextStream]: File name, IOMode, LineNumber&quot;
697 _Repr = &quot;[TextStream]: &quot; &amp; FileName &amp; &quot;,&quot; &amp; IOMode &amp; &quot;,&quot; &amp; CStr(Line)
699 End Function &apos; ScriptForge.SF_TextStream._Repr
701 REM ============================================ END OF SCRIPTFORGE.SF_TextStream
702 </script:module>