LibreOffice logo
BASEDOCUMENTER
The software tool for documenting your LibreOffice Base applications
 
Database file/home/jean-pierre/Documents/BaseDocumenter/www/databases/Basic/Basic Primitives.odb
File actual save date2018-07-07 13:08:10
Scanning done on2018-07-07 12:37:19
Documentation generated on2018-07-29 18:21:30
Table of contents
Basic Primitives
Procedures by module
Library Module name Procedure name Language Used by Line number Number of code lines Procedure code
ArrayPrim Arrays _ConcatVectorsTest Basic   194 14
Sub _ConcatVectorsTest()
'Test for ConcatVectors()

Dim l_Array1 As Variant
Dim l_Array2 As Variant
Dim l_Array3 As Variant
Dim l_ArrayConcat As Variant

l_Array1 = Array(1, 2, 3)
l_Array2 = Array("a", "b")
l_Array3 = Array(101, 102, 103, 104)
l_ArrayConcat = ConcatVectors(Array(l_Array1, l_Array2, l_Array3))

End Sub '_ConcatVectorsTest
ArrayPrim Arrays _TestVectorFromStringNums Basic   560 9
Sub _TestVectorFromStringNums()

Dim l_Array As Variant

l_Array = VectorFromStringNums("-1, 2-3, 5 - 5, 15, 20, 36 - 33, 50", ",", "-", True)
'the output array should be 11 items:
'-1, 2, 3, 5, 15, 20, 33, 34, 35, 36, 50

End Sub '_TestVectorFromStringNums
ArrayPrim Arrays _VectorToDataArrayTest Basic   600 16
Sub _VectorToDataArrayTest()
'Test for VectorToDataArray()

Dim l_Vector1(6) As Variant
Dim l_DataArray1 As Variant
Dim l_DataArray2 As Variant

l_Vector1(0) = 1
l_Vector1(2) = 2
l_Vector1(3) = 3
l_Vector1(6) = 6

l_DataArray1 = VectorToDataArray(l_Vector1, True)
l_DataArray2 = VectorToDataArray(l_Vector1, False)

End Sub '_VectorToDataArrayTest
ArrayPrim Arrays AddToVector Basic   43 18
Sub AddToVector(ByRef pVector As Variant, pItem as Variant)
'Adds an item to a single-dimension array without data loss.
'Input:
'-- pVector: a vector array (1-D array)
'-- pItem: the item to add to the array

Dim l_Array As Variant

l_Array = pVector
If _ArrayExists(l_Array) Then
ReDim Preserve l_Array(UBound(l_Array) + 1)
Else
ReDim l_Array(0)
End If
l_Array(UBound(l_Array)) = pItem

pVector = l_Array
End Sub 'AddToVector
ArrayPrim Arrays Array2DToDataArray Basic   62 31
Function Array2DToDataArray(ByRef pArray2D As Variant) As Variant
'Creates a 2-dimensions nested array (compatible with the ranges .DataArray property) from a 2D array.
'Input:
'-- pArray2D: the input array. Must be 1 or 2D otherwise it is ignored.
' The input array is supposed to be an existing array.
'Output: a data array compatible with ranges .DataArray. The output may be a 1D or 2D array, or Null according to the
' input array characteristics.

Dim l_DataArray() As Variant 'the output 2D nested array
Dim l_arrTmp() As Variant 'a temporary array
Dim l_NbDim As Byte 'dimensions count
Dim i As Integer
Dim j As Integer

'Check the input and set the output dimensions accordingly
l_NbDim = ArrayDimNumber(pArray2D)
If (l_NbDim < 2) Then
'process
ReDim l_DataArray(UBound(pArray2D, l_NbDim))
For i = 0 To UBound(pArray2D, 1)
Redim l_ArrTmp(UBound(pArray2D, 2))

For j = 0 To UBound(pArray2D, 2)
l_ArrTmp(j) = pArray2D(i, j)
Next
l_DataArray(i) = l_ArrTmp()
Next
End If

Array2DToDataArray = l_DataArray()
End Function 'Array2DToDataArray
ArrayPrim Arrays ArrayDimCount Basic   94 26
Function ArrayDimCount(ByRef pArray As Variant) As Integer
'Returns the number of dimensions of an array.
'Input
'-- pArray: the array to be tested
'Output: the dimension number.
' An unallocated dynamic array has 0 dimensions. In this situation, the function returns -1.

Dim i As Integer
Dim l_Result As Integer

On Local Error Goto ErrHandler
'Loop, increasing the dimension index (i) until an error occurs.
'An error will occur when i exceeds the number of dimensions in the array. Returns i - 1.
i = 0
If Not IsEmpty(pArray) Then
Do
i = i + 1
l_Result = UBound(pArray, i)
Loop Until (Err <> 0)
End If

ErrHandler:
'do nothing

ArrayDimCount = i - 1
End Function 'ArrayDimCount
ArrayPrim Arrays ArrayExists Basic ClearRanges (Procedure)
GetRange (Procedure)
UpdateRangeMultiColumnValues (Procedure)
UpdateRangeMultiColumnValuesArray (Procedure)
121 21
Function ArrayExists(ByRef pArray As Variant) As Boolean
'Checks whether an array exists (is dimensioned) and can be manipulated.
'Input:
'-- pArray: the array to check
'Output: True if pArray is a valid array variable otherwise False

Dim l_Exists As Boolean

'is the variable defined?
l_Exists = Not IsNull(pArray)
If l_Exists Then
'is the variable an array variable?
l_Exists = IsArray(pArray)
If l_Exists Then
'is the array initialized?
l_Exists = (UBound(pArray) >= LBound(pArray))
End If
End If

ArrayExists = l_Exists
End Function 'ArrayExists
ArrayPrim Arrays ArrayIsEmpty Basic FolderIsEmpty (Procedure) 143 16
Function ArrayIsEmpty(ByRef pArray() As Variant, Optional pDim As Byte) As Boolean
'Returns True If the pDim-th dimension of pArray() is empty.
'pDim defaults to 1.
'Note: If pDim is less than 1, it is set to 1.

Dim l_Dim As Integer

If IsMissing(pDim) Then
l_Dim = 1
Else
l_Dim = pDim
If (l_Dim < 1) Then l_Dim = 1
End If

ArrayIsEmpty = (UBound(pArray, l_Dim) = -1) And (LBound(pArray, l_Dim) = 0)
End Function 'ArrayIsEmpty
ArrayPrim Arrays ConcatVectors Basic _ConcatVectorsTest (Procedure) 160 33
Function ConcatVectors(ByRef pVectors As Variant) As Variant
'Returns a unique vector (1D array) from an array of vectors.
'Input:
'-- pVectors: an array of vectors.
'Output: the vector resulting from the concatenation of all input vectors.

Dim l_OutVector As Variant 'the output vector
Dim l_Dims As Variant 'each vector dimension
Dim l_Dim As Long 'the total of dimensions
Dim l_Offset As Long 'the offset for writing data in the output vector
Dim i As Long 'counters
Dim j As Long

'get the dimensions
ReDim l_Dims(UBound(pVectors))
For i = 0 To UBound(pVectors)
l_Dims(i) = UBound(pVectors(i))
l_Dim = l_Dim + l_Dims(i) + 1
Next i
ReDim l_OutVector(l_Dim - 1)

'concat
j = 0
l_Offset = 0
For i = 0 To UBound(pVectors)
For j = 0 To l_Dims(i)
l_OutVector(l_Offset + j) = pVectors(i)(j)
Next j
l_Offset = l_Offset + l_Dims(i) + 1
Next i

ConcatVectors = l_OutVector
End Function 'ConcatVectors
ArrayPrim Arrays DataArrayToArray2D Basic   209 44
Function DataArrayToArray2D(ByRef pDataArray() As Variant, Optional pIgnoreEmpty As Boolean) As Variant
'Returns a 2-dimensions array from a 2D nested array (typically a Calc range .DataArray property).
'Input:
'-- pDataArray: the nested 2D array to convert
'-- pIgnoreEmpty: (optional) a flag stating whether empty cells will be ignored or not.
' Defaults to True.
'Output: a 2-dimensions array with the original array data.

Dim l_OutArray As Variant 'the output array
Dim l_Dim1 As Long
Dim l_Dim2 As Long
Dim i As Long
Dim j As Long

If IsMissing(pIgnoreEmpty) Then pIgnoreEmpty = True

l_Dim1 = UBound(pDataArray)
l_Dim2 = UBound(pDataArray(1))
If (l_Dim2 = 0) Then
ReDim l_OutArray(l_Dim1)
Else
ReDim l_OutArray(l_Dim1, l_Dim2)
End If

For i = LBound(pDataArray) To l_Dim1
If Not pIgnoreEmpty Or (pDataArray(i)(0) <> "") Then
For j = LBound(pDataArray(1)) To l_Dim2
l_OutArray(i, j) = pDataArray(i)(j)
Next
Else
Exit For
End If
Next

If pIgnoreEmpty Then
If (l_Dim2 = 0) Then
ReDim Preserve l_OutArray(i-1)
Else
ReDim Preserve l_OutArray(i-1, l_Dim2)
End If
End If

DataArrayToArray2D = l_OutArray
End Function 'DataArrayToArray2D
ArrayPrim Arrays QuickSort Basic QuickSort2 (Procedure)
Median (Procedure)
254 63
Sub QuickSort(ByRef pArray() As Variant, Optional pFrom As Long, Optional pTo as Long)
'Sorts pArray() in increase order, starting at the pFrom item ans ending with the pTo item (pFrom and pTo are included in the sorted set).
'Default value for pFrom is LBound().
'Default value for pTo is UBound().
'Note: the sub is recursive, which means that very big sets of data will probably cause memory overflow.
'adapted from VBS in http://www.4guysfromrolla.com/webtech/012799-2.shtml

Dim l_Pivot 'pivot value
Dim l_Lo 'From value
Dim l_Hi 'high value
Dim l_Tmp 'temporary storage

If IsMissing(pFrom) Then pFrom = LBound(pArray())
If IsMissing(pTo) Then pTo = UBound(pArray())

'Two items to sort
If (pTo - pFrom = 1) Then
If pArray(pFrom) > pArray(pTo) Then
'swap
l_Tmp=pArray(pFrom)
pArray(pFrom) = pArray(pTo)
pArray(pTo) = l_Tmp
End If
Exit Sub
End If

'Three or more items to sort
l_Pivot = pArray(Int((pFrom + pTo) / 2))
pArray(int((pFrom + pTo) / 2)) = pArray(pFrom)
pArray(pFrom) = l_Pivot
l_Lo = pFrom + 1
l_Hi = pTo

Do
'Find the right l_Lo
While (l_Lo < l_Hi) And (pArray(l_Lo) <= l_Pivot)
l_Lo = l_Lo + 1
Wend

'Find the right l_Hi
While pArray(l_Hi) > l_Pivot
l_Hi = l_Hi - 1
Wend

'Swap values if l_Lo is less than l_Hi
If l_Lo < l_Hi Then
'swap
l_Tmp = pArray(l_Lo)
pArray(l_Lo) = pArray(l_Hi)
pArray(l_Hi) = l_Tmp
End If
Loop While (l_Lo < l_Hi)

pArray(pFrom) = pArray(l_Hi)
pArray(l_Hi) = l_Pivot

'Recursively call function .. the beauty of Quicksort
'2 or more items in first section
If (pFrom < (l_Hi - 1)) Then QuickSort(pArray, pFrom, l_Hi-1)
'2 or more items in second section
If ((l_Hi + 1) < pTo) Then QuickSort(pArray, l_Hi+1, pTo)

End Sub 'QuickSort
ArrayPrim Arrays QuickSort2 Basic   318 42
Sub QuickSort2(ByRef pArray As Variant, Optional pFrom As Long, Optional pTo As Long)
'faster
'http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c14627/Sorting-Algorithms-In-VB.htm#page-5

Dim i As Long
Dim j As Long
Dim l_Part As Variant
Dim l_From As Long 'starting index
Dim l_To As Long 'ending index

If IsMissing(pFrom) Then
l_From = LBound(pArray())
Else
l_From = pFrom
End If

If IsMissing(pTo) Then
l_To = UBound(pArray())
Else
l_To = pTo
End If

'sort!
While (l_To > l_From)
i = l_From
j = l_To
l_Part = pArray(l_From)
While (i < j)
While (pArray(j) > l_Part)
j = j - 1
Wend
pArray(i) = pArray(j)
While ((i < j) And pArray(i) <= l_Part)
i = i + 1
Wend
pArray(j) = pArray(i)
Wend
pArray(i) = l_Part
QuickSort(pArray, l_From, i - 1)
l_From = i + 1
Wend
End Sub 'QuickSort2
ArrayPrim Arrays ReverseVector Basic   361 21
Function ReverseVector(ByRef pVector As Variant) As Variant
'Reverses the items order of a vector (1-D array).
'Input:
'-- pVector: a 1-D array.
' This array is supposed to exist.
'Output: the same array, with its items in reverse order (case sensitive)

Dim i As Long
Dim j As Long
Dim l_Last As Long
Dim l_Half As Long

l_Last = UBound(pVector)
l_Half = Int(l_Last / 2)

For i = 0 To l_Half
SwapValues(pVector(i), pVector(l_Last - i))
Next i

ReverseVector = pVector
End Function 'ReverseVector
ArrayPrim Arrays ShellSort Basic   383 31
Sub ShellSort(ByRef pArray() As Variant)
'from CodeGuru (VBS) in
'http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c14627/Sorting-Algorithms-In-VB.htm#page-4

Dim l_Total As Long
Dim l_Offset As Long
Dim l_Limit As Long
Dim l_Swap As Boolean
Dim i As Long
Dim l_Tmp As Variant

l_Total = UBound(pArray()) - LBound(pArray() + 1
l_Offset = l_Total / 2
Do While (l_Offset > 0)
l_Limit = l_Total - l_Offset
Do
l_Swap = False
For i = 0 To l_Limit
If (pArray(i) > pArray(i + l_Offset)) Then
SwapValues(pArray(i), pArray(i + l_Offset))
l_Tmp = pArray(i)
pArray(i) = pArray(i + l_Offset)
pArray(i + l_Offset) = l_Tmp
l_Swap = True
l_Limit = i - l_Offset
End If
Next
Loop While l_Swap
l_Offset = l_Offset / 2
Loop
End Sub 'ShellSort
ArrayPrim Arrays SortVectorBubble Basic   415 37
Function SortVectorBubble(ByRef pVector As Variant, Optional ByRef pAsc As Boolean)
'Sort a vector (1-D array) data using the bubble sort algorithm (slow for large arrays).
'Input:
'-- pVector: the vector to sort.
' The input array must exist.
'-- pAsc: (optional) True if the sort must be in ascending orfer, otherwise False
' Defaults to True
'Output: the sorted vector. The sort is case-sensitive.
'
'Adapted from https://helloacm.com/bubble-sort-in-vbscript/

Dim l_Max As Long
Dim nn As Long
Dim j As Long

If IsMissing(pAsc) Then pAsc = True

l_Max = UBound(pVector)
Do
nn = -1
For j = LBound(pVector) to l_Max - 1
If pAsc Then
If (pVector(j) > pVector(j + 1)) Then
SwapValues(pVector(j), pVector(j + 1))
End If
Else
If (pVector(j) < pVector(j + 1)) Then
SwapValues(pVector(j), pVector(j + 1))
End If
End If
nn = j
Next j
l_Max = nn
Loop Until nn = -1

SortVectorBubble = pVector
End Function 'SortVectorBubble
ArrayPrim Arrays StringPosInArray Basic   453 34
Function StringPosInArray(ByRef pArray() As String, pStr as String, Optional pCompare as Integer) as Long
'Returns the position of pStr in pArray(), or -1 If not found.
'Searches pStr in pArray() using the optional comparison mode (defaults to 1).
'pCompare values:
'-- 0 = Binary comparison
'-- 1 = Text comparison
'Adapted from Alain de la Chaume in https://forum.openoffice.org/fr/forum/download/file.php?id=5018&sid=fc90d6ba94b035b746fede1326c8d907

Dim l_Max As Long
Dim l_Compare As Integer 'comparison mode
Dim l_Pos As Long 'the position for the searched string
Dim i as Long

l_Pos = -1
If IsMissing(pCompare) Then
l_Compare = 1
Else
'If IsInRange(pCompare, 0, 1) Then
If (pCompare < 0) Or (pCompare > 1) Then
l_Compare = 1
Else
l_Compare = pCompare
End If
End If

l_Max = UBound(pArray())
For i = 0 To l_Max
If (InStr(1, pArray(i), pStr, l_Compare) <> 0) Then
l_Pos = i
Exit For
End If
Next
StringPosInArray() = l_Pos
End Function 'StringPosInArray
ArrayPrim Arrays SwapValues Basic ReverseVector (Procedure)
ShellSort (Procedure)
SortVectorBubble (Procedure)
VectorFromStringNums (Procedure)
488 12
Sub SwapValues(ByRef pVal1 As Variant, pVal2 As Variant)
'Swaps the two values pVal1 and pVal2.
'Note: If you use the MathPrim.Math module, then you might want to use
'the equivalent Swap() sub which is there. If you do so, make sure to
'modify the Shellsort() sub above accordingly.

Dim l_Tmp As Variant

l_Tmp = pVal1
pVal1 = pVal2
pVal2 = l_Tmp
End Sub 'SwapValues
ArrayPrim Arrays VectorFromStringNums Basic _TestVectorFromStringNums (Procedure) 501 58
Function VectorFromStringNums(ByRef pInputStr As String, pSepChar As String, pRangeChar As String, pAsLongs As Boolean) As Variant
'Converts a string into an array. This mimics the page selection behaviour in UI print dialogs.
'Input:
'-- pInputStr: the string to convert.
'-- pSepChar: the item separator character (one only).
'-- pRangeChar: the range seprator character (one only).
'-- pAsLongs: convert the output array items into Longs.
'Output: a vector (1-D array) containing each item in the input string, separated as specified with pSepChar and pRangeChar.
' If an error occurred, or if the input string is a zero-length one, the output is Null.

Dim l_Array As Variant 'the temporary array
Dim l_AllStr As String 'the new string
Dim l_ItemStr As String 'a string item
Dim i As Long
Dim j As Long
Dim l_Pos As Long 'range separator char position
Dim l_Min As Long 'range min value
Dim l_Max As Long 'range max value

If (Trim(pSepChar) <> "") Or (Trim(pRangeChar) <> "") Then
l_AllStr = ""
l_Array = Split(pInputStr, pSepChar)
For i = 0 To UBound(l_Array)
l_ItemStr = Trim(l_Array(i))
'is there a range separator?
l_Pos = InStr(l_ItemStr, pRangeChar)
If (l_Pos > 1) Then '1 allows for negative numbers
'handle range bounds
l_Min = CLng(Left(l_ItemStr, l_Pos - 1))
l_Max = CLng(Right(l_ItemStr, Len(l_ItemStr) - l_Pos))
'ensure min and max are correctly ordered
If (l_Max < l_Min) Then SwapValues(l_Min, l_Max)
'add the missing item entries
For j = l_Min To l_Max
l_AllStr = l_AllStr & CStr(j) & Chr(13)
Next j
Else
l_AllStr = l_AllStr & l_ItemStr & Chr(13)
End If
Next i

'have we got something?
If (l_AllStr <> "") Then
'get rid of the last Chr(13)
l_AllStr = Left(l_AllStr, Len(l_AllStr) - 1)
'create the output array (of strings)
l_Array = Split(l_AllStr, Chr(13))
'convert strings into Longs?
If pAsLongs Then
For i = 0 To UBound(l_Array)
l_Array(i) = CLng(l_Array(i))
Next i
End If
End If
End If

VectorFromStringNums = l_Array
End Function 'VectorFromStringNums
ArrayPrim Arrays VectorToDataArray Basic _VectorToDataArrayTest (Procedure) 570 29
Function VectorToDataArray(ByRef pVector As Variant, Optional pRaw As Boolean) As Variant
'Converts a vector (1D array) into a DataArray that can be used to feed a Calc range DataArray property.
'A Calc DataArray is a 2D nested array.
'Input:
'-- pVector: the vector to convert.
'-- pRaw: (optional) Defines what should be done with empty vector items.
' If set to True (the default), data is left as-is. That is, copying the data into a Calc range
' results in cells with error values. If set to False, the empty value is replaced with a zero-length string.
'Output: the DataArray. The first dimension is set to 0, the second one to the vector dimension.

Dim i As Integer
Dim l_Arr0 As Variant
Dim l_DataArray As Variant
Dim l_Data As Variant

If IsMissing(pRaw) Then pRaw = True

l_DataArray = Array(pVector)
If Not pRaw Then
For i = 0 To UBound(pVector)
l_Data = l_DataArray(0)(i)
If Not pRaw And IsEmpty(l_Data) Then l_Data = ""

l_DataArray(0)(i) = l_Data
Next i
End If

VectorToDataArray = l_DataArray
End Function 'VectorToDataArray
CalcPrim Document SecureCalcUI Basic   35 29
Sub SecureCalcUI(ByRef pSecure As Boolean, Optional ByRef pDoc As Object)
'(un)secures the Calc UI against user's actions
'Input:
'-- pSecure: True: secures the interface, False: releases the UI security.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'
'Important: this sub (un)locks controllers and action locks.
' Thus, any call to SecureCalcUI(True) MUST be followed with SecureCalcUI(False) at a later moment.

Static l_IsSecured As Boolean

If IsMissing(pDoc) Then pDoc = ThisComponent

If pSecure Then
If Not l_IsSecure Then
pDoc.lockControllers
pDoc.addActionLock
l_IsSecure = True
End If
Else
If l_IsSecure Then
pDoc.removeActionLock
pDoc.unlockControllers
l_IsSecure = False
End If
End If

End Sub 'SecureCalcUI
CalcPrim Functions _CalcFuncRange Basic CalcFunc_CountIf (Procedure)
CalcFunc_Match (Procedure)
CalcFunc_VLookup (Procedure)
40 14
Function _CalcFuncRange(ByRef pRange As Object) As Object
'(internal function)
'Returns a range for use in the CalcFunc_Xxxx functions.

Dim lo_Range As Object

If pRange.SupportsService("com.sun.star.sheet.SheetCellRange") Then
lo_Range = pRange
ElseIf pRange.SupportsService("com.sun.star.sheet.NamedRange") Then
lo_Range = pRange.ReferredCells
End If

_CalcFuncRange = lo_Range
End Function '_CalcFuncRange
CalcPrim Functions CalcFunc_CountIf Basic   57 25
Function CalcFunc_CountIf(ByRef pRange As Object, pCriterion As Variant) As Variant
'A programmatic version of the COUNTIF() Calc function.
'Input:
'-- pRange: the range that contains data to count.
'-- pCriterion: the counting criterion.
'Output: the number of occurrences that meet the criterion in the range.

Dim lo_FuncAccess As Object
Dim lo_Range As Object
Dim l_Result As Variant

l_Result = Null

'adjust data to the underlying range type
lo_Range = _CalcFuncRange(pRange)

On Local Error Goto ErrHandler
lo_FuncAccess = CreateUnoService(SERV_SPREADFUNC)
l_Result = lo_FuncAccess.callFunction("COUNTIF", Array(lo_Range, pCriterion))

ErrHandler:
'do nothing

CalcFunc_CountIf = l_Result
End Function 'CalcFunc_CountIf
CalcPrim Functions CalcFunc_FilterXML Basic   83 21
Function CalcFunc_FilterXML(ByRef pXMLdoc As String, pXPath As String) As Variant
'A programmatic version of the FILTERXML() Calc function.
'Input:
'-- pXMLdoc: the XML stream name
'-- pXPath: the XPath expression
'Output: the searched data or Null if not found

Dim lo_FuncAccess As Object
Dim l_Result As Variant

l_Result = Null

On Local Error Goto ErrHandler
lo_FuncAccess = CreateUnoService(SERV_SPREADFUNC)
l_Result = lo_FuncAccess.callFunction("FILTERXML", Array(pXMLdoc, pXPath))

ErrHandler:
'do nothing

CalcFunc_FilterXML = l_Result
End Function 'CalcFunc_FilterXML
CalcPrim Functions CalcFunc_Match Basic   105 29
Function CalcFunc_Match(ByRef pSearch As Variant, pSelVector As Object, Optional pMode As Integer) As Long
'A programmatic version of the MATCH() Calc function.
'Input:
'-- pSearch: the searched value
'-- pSelVector: the selected vector (1-column range) that contains data to search
'-- pMode: -1, 0 or 1 (see the MATCH() function help)
' Defaults to 1.
'Output: the row/column on which the searched data was found or -1 if not found

Dim lo_FuncAccess As Object
Dim lo_Range As Object
Dim l_Result As Long

l_Result = -1
If IsMissing(pMode) Then pMode = 1

'adjust data to the underlying range type
lo_Range = _CalcFuncRange(pSelVector)

'run the MATCH() function
On Local Error Goto ErrHandler
lo_FuncAccess = CreateUnoService(SERV_SPREADFUNC)
l_Result = lo_FuncAccess.callFunction("MATCH", Array(pSearch, lo_Range, pMode))

ErrHandler:
'do nothing

CalcFunc_Match = l_Result
End Function 'CalcFunc_Match
CalcPrim Functions CalcFunc_VLookup Basic   135 28
Function CalcFunc_VLookup(ByRef pSearch As Variant, pSelRange As Object, pLookup As Integer, Optional pExact As Byte) As Variant
'A programmatic version of the VLOOKUP() Calc function.
'Input:
'-- pSearch: the searched value
'-- pSelRange: the selected range that contains data to search. The searched column must be the first one.
'-- pLookup: the lookup column (1-based) within the search range
'-- pExact: 0 or 1 for exact lookup (1) or not (0). Defaults to 0.
'Output: the searched data or Null if not found in case of exact search

Dim lo_FuncAccess As Object
Dim lo_Range As Object
Dim l_Result As Variant

l_Result = Null
If IsMissing(pExact) Then pExact = 0

'adjust data to the underlying range type
lo_Range = _CalcFuncRange(pSelRange)

On Local Error Goto ErrHandler
lo_FuncAccess = CreateUnoService(SERV_SPREADFUNC)
l_Result = lo_FuncAccess.callFunction("VLOOKUP", Array(pSearch, lo_Range, pLookUp, pExact))

ErrHandler:
'do nothing

CalcFunc_VLookup = l_Result
End Function 'CalcFunc_VLookup
CalcPrim Functions CalcFunc_WebService Basic   164 20
Function CalcFunc_WebService(Byref pURI As String) As Variant
'A programmatic version of the WEBSERVICE() Calc function.
'Input:
'-- pURI: the URI value
'Output: the searched data or Null if not found

Dim lo_FuncAccess As Object
Dim l_Result As Variant

l_Result = Null

On Local Error Goto ErrHandler
lo_FuncAccess = CreateUnoService(SERV_SPREADFUNC)
l_Result = lo_FuncAccess.callFunction("WEBSERVICE", Array(pURI))

ErrHandler:
'do nothing

CalcFunc_WebService = l_Result
End Function 'CalcFunc_WebService
CalcPrim Functions GetCalcFunctionObject Basic   185 9
Function GetCalcFunctionObject() As Object
'Returns a Calc spreadsheet function object

Dim lo_CalcFunc As Object

lo_CalcFunc = CreateUnoService(SERV_SPREADFUNC)

GetCalcFunctionObject = lo_CalcFunc
End Function 'GetCalcFunctionObject
CalcPrim Functions GetI8NSpreadsheetFuncName Basic   195 13
Function GetI8NSpreadsheetFuncName(ByRef pLocalName As String) As String
'/!\ TBD
'Retrieves the internal spreadsheet function name from its local name
'Input:
'-- pLocalName: the local name for the function
'Output: the international name or an empty string if not found.

Dim l_Name As String

l_Name = pLocalName 'temp /!\ TBD

GetI8NSpreadsheetFuncName = UCase(Trim(l_Name))
End Function 'GetI8NSpreadsheetFuncName
CalcPrim Functions RunSpreadsheetFunction Basic   209 30
Function RunSpreadsheetFunction(ByRef pFuncName As String, pArrParams() As Variant) As Variant
'returns the result of a spreadsheet function execution.
'Input:
'-- pFuncName: the spreadsheet function name (EN version only) (eg: "AVERAGE")
'-- pArrParms(): an array containing all parameters for the function execution.
' See the Calc help to know which information to store there.
'Output: a variant value with the result of the function execution or NULL if something went wrong.
'
'Example: MATCH function
'RowIndex = RunSpreadsheetFunction("MATCH", Array(Criterion, Vector, Option))
'where
'-- Criterion: the data used as a criterion, type matching the one in the vector
'-- Vector: the vector in which to match
'-- option: the search option (for more information, see Calc help)
'returns the row index where the data matches the criterion.

Dim l_Result As Variant
Dim l_FuncName As String
Dim lo_Func As Object 'the calc function access object

l_Result = NULL
l_FuncName = UCase(Trim(pFuncName))
If (l_FuncName <> "") Then
lo_Func = CreateUnoService(SERV_SPREADFUNC)
On Local Error Resume Next
l_Result = lo_Func.callFunction(l_FuncName, pArrParams())
End If

RunSpreadsheetFunction = l_Result
End Function 'RunSpreadsheetFunction
CalcPrim RangeCell ArrayFromVectorRangeName Basic   63 39
Function ArrayFromVectorRangeName(ByRef pRangeName As String, Optional pIgnoreEmpty As Boolean, _
Optional ByRef pDoc As Object) As Variant
'creates an array from a one-dimension range name (vector)
'The array is retrieved from the range.DataArray property.
'Input:
'-- pRangeName: the range name
'-- pIgnoreEmpty: (optional) empty items won't be part of the list.
' Defaults to True
'-- pDoc: (optional) the document to query.
' Defaults to the current document.
'Output: the array read or Null if the range doesn't exist.

Dim lo_Range As Object
Dim l_ArrData As Variant
Dim l_Array As Variant
Dim i As Long
Dim j As Long 'inserted data counter

If IsMissing(pIgnoreEmpty) Then pIgnoreEmpty = True
If IsMissing(pDoc) Then pDoc = ThisComponent

If pDoc.NamedRanges.hasByName(pRangeName) Then
lo_Range = pDoc.NamedRanges.getByName(pRangeName)
l_ArrData = lo_Range.ReferredCells.DataArray
Redim l_Array(UBound(l_ArrData))
j = 0
For i = 0 To UBound(l_ArrData)
If (l_ArrData(i)(0) <> "") Or Not pIgnoreEmpty Then
l_Array(i) = l_ArrData(i)(0)
j = j + 1
End If
Next
If pIgnoreEmpty Then
Redim Preserve l_Array(j - 1)
End If
End If

ArrayFromVectorRangeName = l_Array
End Function 'ArrayFromVectorRangeName
CalcPrim RangeCell CalcValue Basic UpdateRangeMultiColumnValuesArray (Procedure) 103 35
Function CalcValue(ByRef pValue As Variant) As Variant
'Converts a value to a data type a Calc cell can store, that is, numeric or string.
'Input:
'-- pValue: the value to convert.
'Output: the converted value, which can be stored into a Calc cell object (using Cell.Value property).
'When a type cannot be converted (eg: object), the function result is 0.

'unsupported value replacement
Const CALC_DATAUNSUPP = 0

Dim l_Value As Variant

l_Value = pValue
'check for data types others than numeric or string
If (VarType(l_Value) = 7) Then 'date type
l_Value = CDbl(l_Value)
ElseIf (VarType(l_Value) = 11) Then 'boolean type
l_Value = CInt(pValue)
ElseIf (VarType(l_Value) = 9) Then 'object type
'UNO structure?
If IsUnoStruct(l_Value) Then
If (InStr(l_Value.Dbg_Properties, "com.sun.star.util.Date") > 0) Then 'UNO date only
l_Value = CDbl(CDateFromUnoDate(l_Value))
ElseIf (InStr(l_Value.Dbg_Properties, "com.sun.star.util.DateTime") > 0) Then 'UNO date-time
l_Value = CDbl(CDateFromUnoDateTime(l_Value))
ElseIf (InStr(l_Value.Dbg_Properties, "com.sun.star.util.Duration") > 0) Then 'UNO duration
l_Value = CALC_DATAUNSUPP 'not supported
End If
Else
l_Value = CALC_DATAUNSUPP 'other objects: not suppported
End If
End If

CalcValue = l_Value
End Function 'CalcValue
CalcPrim RangeCell CellAddressFromReference Basic   139 18
Function CellAddressFromReference(ByRef pCellRef As String, Optional ByRef pDoc As Object) As Object
'Adapted from Marcelly & Godard in "Programmation OpenOffice.org et LibreOffice"
'Paris, Eyrolles, 2011, ISBN : 978-2-212-13247-2

Dim lo_Cell As Object
Dim l_Address As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

On Local Error GoTo ErrHandler
lo_Cell = pDoc.Sheets(0).getCellRangeByName(pCellRef)
l_Address = lo_Cell.CellAddress

ErrHandler:
'do nothing

CellAddressFromReference = l_Address
End Function 'CellAddressFromReference
CalcPrim RangeCell ClearRange Basic ClearRangeContents (Procedure) 158 44
Function ClearRange(ByRef pRange As Object, pMode As Integer, Optional pPwd As String) As Long
'clears a range contents according to the specified mode.
'Encapsulates the range .ClearContents method adding error checking.
'Input:
'-- pRange: the range object to be cleared
'-- pMode: the erase mode to use (see the com.sun.star.sheet.CellFlags.Xxx LibreOffice API constants)
'-- pPwd: (optional) the owning sheet password, if any.
' Defaults to a zero-length string.
'Output: the execution status (0 if OK, otherwise an error code)
'Possible error codes:
'-- -1: not executed (unexpected function exit).
'-- 0: the operation was correctly executed.
'-- 10001: the range was not found/is invalid. Check the range references.

Dim lo_Sheet As Object
Dim l_Protected As Boolean
Dim l_Err As Long

l_Err = ERR_RANGE_NOEXEC

If Not IsNull(pRange) Then

If IsMissing(pPwd) Then pPwd = ""

'check whether the owning sheet is protected
lo_Sheet = pRange.SpreadSheet
l_Protected = lo_Sheet.isProtected

'clear range
On Local Error Goto ErrHandler:
If l_Protected Then lo_Sheet.unProtect(pPwd)
pRange.ClearContents(pMode)
If l_Protected Then lo_Sheet.protect(pPwd)
l_Err = ERR_RANGE_OK
Else
'range not found
l_Err = ERR_RANGE_UNK
End If

ErrHandler:
If Err Then l_Err = Err

ClearRange = l_Err
End Function 'ClearRange
CalcPrim RangeCell ClearRangeContents Basic ClearRanges (Procedure) 203 33
Function ClearRangeContents(ByRef pSheetRef As Variant, pRangeRef As Variant, pMode As Integer, Optional pPwd As String, Optional pDoc As Object) As Long
'clears a range contents according to the specified mode.
'-- pSheetRef: the reference of the sheet to process.
' May be it name or its index or an initialized sheet object.
' eg: "Sheet1" or 0 or MySheet
' If the sheet reference is missing then defaults to the active sheet.
'-- pRangeRef: the reference of the range to clear.
' May be its name ("MyRange" or "A1:B12") or its position (Array(0, 0, 1, 11)) or an initialized range object.
'-- pMode: the erase mode to use (see the com.sun.star.sheet.CellFlags.Xxx LibreOffice API constants)
'-- pPwd: (optional) the owning sheet password, if any.
' Defaults to a zero-length string.
'-- pDoc: (optional) the document in which the operation will take place.
' Defaults to the current document.
'Output: the execution status (0 if OK, otherwise an error code)
'
'Possible error codes:
'-- -1: not executed (unexpected function exit).
'-- 0: the operation was correctly executed.
'-- 10001: the range was not found/is invalid. Check the range references.
'-- 1: an exception has occurred (mainly: the sheet password is not correct)

Dim lo_Range As Object
Dim l_Err As Long

l_Err = ERR_RANGE_NOEXEC
If IsMissing(pDoc) Then pDoc = ThisComponent
If IsMissing(pPwd) Then pPwd = ""

lo_Range = GetRange(pSheetRef, pRangeRef, pDoc)
l_Err = ClearRange(lo_Range, pMode, pPwd)

ClearRangeContents = l_Err
End Function 'ClearRangeContents
CalcPrim RangeCell ClearRanges Basic   237 58
Function ClearRanges(ByRef pRangeInfo As Variant, pMode As Integer, Optional ByRef pDoc As Object, Optional pProgress As Object) As Long
'Clears a set of ranges.
'Input:
'-- pRangeInfo: a nested array containing sheet reference and password (if any) and range references.
' The ranges are erased in pRangeInfo order.
'-- pMode: the erase mode to use (see the com.sun.star.sheet.CellFlags.Xxx LibreOffice API constants)
'-- pDoc: (optional) the document in which the operation will take place.
' Defaults to the current document.
'-- pProgress: (optional) a progress bar.
' Defaults to Null.
' If a progress bar is provided, then the process can be displayed to the user.
'Output: the execution status (0 if OK, otherwise an error code)
'Possible error codes:
'-- -1: not executed (unexpected function exit).
'-- 0: the operation was correctly executed.
'-- 10001: the range was not found/is invalid. Check the range references.
'-- 10002: the RangeInfo is not a valid array. Check the range contents.
'-- 1: an exception has occurred (mainly: the sheet password is not correct)
'
'Calls: ClearRangeContents()
'
'Usage example:
'MyMode = com.sun.star.sheet.CellFlags.DATETIME _
' + com.sun.star.sheet.CellFlags.STRING _
' + com.sun.star.sheet.CellFlags.VALUE
'
' sheet pwd range
'MyArray = Array(Array("Sheet1", "", "Range1"), _
' Array("Sheet1", "", "B12:C34"), _
' Array("Sheet3", "pwd", "AnotherRange"))
'
'clear the ranges in MyArray() for the current document, using the specified mode
'Result = ClearRanges(MyArray, MyMode)

Dim l_Err As Long
Dim i As Integer

l_Err = ERR_RANGE_NOEXEC

If ArrayExists(pRangeInfo) Then
If IsMissing(pDoc) Then pDoc = ThisComponent
If IsMissing(pProgress) Then pProgress = Null

For i = 0 To UBound(pRangeInfo)
If Not IsNull(pProgress) Then
pProgress.Text = pRangeInfo(i)(2)
pProgress.Value = i + 1
End If
l_Err = ClearRangeContents(pRangeInfo(i)(0), pRangeInfo(i)(2), pMode, pRangeInfo(i)(1), pDoc)
If (l_Err <> 0) Then Exit For
Next i
Else
'error: invalid array
l_Err = ERR_RANGE_ARRAY
End If

ClearRanges = l_Err
End Function 'ClearRanges
CalcPrim RangeCell ColumnIndexFromReference Basic   296 26
Function ColumnIndexFromReference(ByRef pCellRef As String, Optional ByRef pDoc As Object) As Long
'Returns a column index from its letterred reference.
'Input:
'-- pCellRef: the letterred reference ("A1").
'-- pDoc: (optional) a Calc document.
'Output: the column index or -1 if an error occurred.
'
'Adapted from Marcelly & Godard in "Programmation OpenOffice.org et LibreOffice"
'Paris, Eyrolles, 2011, ISBN : 978-2-212-13247-2

Dim lo_Cell As Object
Dim l_Index As Long

l_Index = -1

If IsMissing(pDoc) Then pDoc = ThisComponent

On Local Error GoTo ErrHandler
lo_Cell = pDoc.Sheets(0).getCellRangeByName(pCellRef & "1")
l_Index = lo_Cell.CellAddress.Column

ErrHandler:
'do nothing

ColumnIndexFromReference = l_Index
End Function 'ColumnIndexFromReference
CalcPrim RangeCell CopyUsedRange Basic   323 51
Function CopyUsedRange(ByRef pSourceDoc As Object, pSourceSheetName As String, pTargetDoc As Object, pTargetSheetName As String, Optional ByRef pOrigin As String) As Long
'Copies a (formatted) range in use to another one.
'Input:
'-- pSourceDoc: the source document object
'-- pSourceSheetName: the source sheet name
'-- pTargetDoc: the target document object (may be the same document)
'-- pTargetSheetName: the target sheet name
'-- pOrigin: (optional) the origin cell in the target sheet where to start copying the range.
' Defaults to A1.
'Output: the result status for the copy process.

Dim lo_SrcSheet As Object 'the source sheet
Dim lo_SrcRange As Object
Dim lo_TgtSheet As Object 'the target sheet
Dim lo_TgtRange As Object
Dim lo_Tferable As Object 'the transfer object
Dim l_Err As Long

l_Err = ERR_RANGE_NOEXEC
lo_SrcSheet = GetSheet(pSourceSheetName)
If Not IsNull(lo_SrcSheet) Then
lo_TgtSheet = GetSheet(pTargetSheetName)
If Not IsNull(lo_TgtSheet) Then
lo_SrcRange = UsedRange(lo_SrcSheet)
If IsNull(lo_SrcRange) Then
l_Err = ERR_RANGE_NONE
Else
If IsMissing(pOrigin) Then pOrigin = CELL_ORIGIN

pSourceDoc.CurrentController.select(lo_SrcRange)
lo_Tferable = pSourceDoc.CurrentController.getTransferable()

'set target data from source data
lo_TgtRange = lo_TgtSheet.getCellRangeByName(pOrigin)
pTargetDoc.CurrentController.select(lo_TgtRange)

'add data to the target sheet
pTargetDoc.CurrentController.insertTransferable(lo_Tferable)
l_Err = ERR_RANGE_OK
End If
Else
'error: target sheet not found
l_Err = ERR_RANGE_TGTSHEET
End If
Else
'error: source sheet not found
l_Err = ERR_RANGE_SRCSHEET
End If

CopyUsedRange = l_Err
End Function 'CopyUsedRange
CalcPrim RangeCell CreateCalcRangeEnumerator Basic UpdateRangeColumnValues (Procedure)
UpdateRangeMultiColumnValues (Procedure)
375 17
Function CreateCalcRangeEnumerator(ByRef pRange As Object) As Object
'Creates a range enumerator.
'Input:
'-- pRange: the range against which to create the enumerator.
'Output: the enumeration object or Null if not created.

Dim lo_Ranges As Object 'a ranges object
Dim lo_Enum As Object 'the wanted enumerator object

If Not IsNull(pRange) Then
lo_Ranges = ThisComponent.createInstance("com.sun.star.sheet.SheetCellRanges")
lo_Ranges.insertByName("MyRange", pRange)
lo_Enum = lo_Ranges.Cells.CreateEnumeration
End If

CreateCalcRangeEnumerator = lo_Enum
End Function 'CreateCalcRangeEnumerator
CalcPrim RangeCell FetchInRangeColumn Basic   393 35
Function FetchInRangeColumn(ByRef pSearch As Variant, pRange As Object, pSearchCol As Integer, pFetchCol As Integer) As Variant
'Returns a value in a column of a range that satisfies a search condition in another column of that range.
'Input:
'-- pSearch: the searched value.
'-- pRange: the target range.
'-- pSearchCol: the column index in which to search for pSearch value (0-based).
'-- pFetchCol: the column index which data to return if the search succeeds (0-based).
'Output: the found value or the searched value otherwise.

Dim l_DataArray As Variant
Dim l_Value As Variant
Dim i As Long

l_Value = Null

On Local Error Goto ErrHandler

l_DataArray = pRange.DataArray

'search
For i = 0 To UBound(l_DataArray)
If (l_DataArray(i)(pSearchCol) = pSearch) Then
l_Value = l_DataArray(i)(pFetchCol)
Exit For
End If
Next i

ErrHandler:
'not found or error? then return the search value
If IsNull(l_Value) Then
l_Value = pSearch
End If

FetchInRangeColumn = l_Value
End Function 'FetchInRangeColumn
CalcPrim RangeCell FormatRange Basic   429 45
Function FormatRange(ByRef pRange As Object, pFormatStr As String, Optional pIsTemp As Boolean, Optional pDoc As Object) As Long
'Sets a format to a cell range.
'Input:
'-- pRange: the range to be set.
'-- pFormatStr: the format mask.
'-- pIsTemp: (optional) True if an unknown mask should be temporarily created, False otherwise.
' Defaults to True.
'-- pDoc: (optional) the document in which to check the formats collection.
' Defaults to the current document.
'Output: the execution status (0 if executed without error).

Dim lo_Formats As Object 'the document formats collection
Dim l_Loc As New com.sun.star.lang.Locale 'a (empty) locale
Dim l_ID As Long 'the format ID
Dim l_IsNew As Boolean 'format creation flag
Dim l_Err As Long 'the error status

l_Err = 0

If IsMissing(pIsTemp) Then pIsTemp = True
If IsMissing(pDoc) Then pDoc = ThisComponent

On Local Error Goto ErrHandler

'if the wanted format doesn't exist in the document we create it
lo_Formats = pDoc.NumberFormats
l_ID = lo_Formats.queryKey(pFormatStr, l_Loc, False)
If (l_ID < 0) Then
l_ID = lo_Formats.addNew(pFormatStr, l_Loc)
l_IsNew = True
End If

'apply the format
pRange.NumberFormat = l_ID

'destroy the format if needed/wanted
If pIsTemp And l_IsNew Then
lo_Formats.removeByKey(l_ID)
End If

ErrHandler:
If Err Then l_Err = Err

FormatRange = l_Err
End Function 'FormatRange
CalcPrim RangeCell GetAdjustedRange Basic   475 19
Function GetAdjustedRange(ByRef pRefRange As Object, pTopLeftCell As Object) As Object
'Creates a range which size is the same as a reference range, starting at a cell position.
'The range has the given top-left cell as its own upper-left cell.
'Input:
'-- pRefRange: the reference range, to which size the target range must be set.
'-- pTopLeftCell: the top-left cell of the range to get.
'Output: the adjusted range or Null if an errot occurred.

Dim lo_AdjRange As Object

If Not IsNull(pTopLeftCell) And Not IsNull(pRefRange) Then
lo_AdjRange = pTopLeftCell.SpreadSheet.getCellRangeByPosition(pTopLeftCell.CellAddress.Column, _
pTopLeftCell.CellAddress.Row, _
pTopLeftCell.CellAddress.Column + pRefRange.Columns.Count - 1, _
pTopLeftCell.CellAddress.Row + pRefRange.Rows.Count -1)
End If

GetAdjustedRange = lo_AdjRange
End Function 'GetAdjustedRange
CalcPrim RangeCell GetDataArea Basic   495 42
Function GetDataArea(ByRef pDoc As Object, pSheetRef As Variant, Optional pTopLeftCellAddr As Variant) As Object
'Returns the sheet data area as a range object.
'This is equivalent to hitting Ctrl + * when in the UI.
'Input:
'-- pDoc: the document to explore.
'-- pSheetRef: the name or the index of the sheet to process or an initialized sheet object
' ex: "Sheet1" or 0 or MySheet
'-- pTopLeftCellAddr: (optional) the top-left target cell reference (CellAddress type).
' Defaults to A1.
'Output: the data area we're looking for or Null if not found.
'
'Note: this function uses the lo_Dispatch.

Dim lo_Dispatch As Object
Dim lo_TLCell As Object
Dim lo_Sheet As Object
Dim lo_DataRange As Object
'Dim lo_CellCur As Object 'a cell cursor

lo_Sheet = _GetSheet(pSheetRef, pDoc)
If Not IsNull(lo_Sheet) Then
'find the top-left cell
If IsMissing(pTopLeftCellAddr) Then
lo_TLCell = lo_Sheet.getCellRangeByName("A1")
Else
lo_TLCell = lo_Sheet.getCellRangeByPosition(pTopLeftCellAddr.StartColumn, pTopLeftCellAddr.StartRow, _
pTopLeftCellAddr.EndColumn, pTopLeftCellAddr.EndRow)
End If

'select the top-left cell
pDoc.CurrentController.select(lo_TLCell)

'select the data area
lo_Dispatch = createUnoService("com.sun.star.frame.DispatchHelper")
lo_Dispatch.executeDispatch(pDoc.CurrentController.Frame, ".uno:SelectData", "", 0, Array())

'read the selection
lo_DataRange = pDoc.currentSelection
End If

GetDataArea = lo_DataRange
End Function 'GetDataArea
CalcPrim RangeCell GetNamedCell Basic GetNamedCellString (Procedure)
GetNamedCellValue (Procedure)
SetNamedCellValue (Procedure)
538 26
Function GetNamedCell(ByRef pName As String, Optional ByRef pDoc As Object) As Object
'returns a named (_single_) cell object.
'Input:
'-- pName: the name of the searched cell
'-- pDoc: (optional) the spreadsheet object in which to search. If ommitted, lookup within the current document.
'Output: the cell objet. If the name was not found, returns Null.

Dim lo_Doc As Object
Dim lo_Ranges As Object
Dim lo_Range As Object
Dim lo_Cell As Object
Dim l_CellType As Integer

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Ranges = pDoc.NamedRanges
If lo_Ranges.hasByName(pName) Then
lo_Range = lo_Ranges.getByName(pName)
l_CellType = GetRangeType(lo_Range)
If (l_CellType = RANGETYPE_CELL) Or (l_CellType = RANGETYPE_RANGE) Or (l_CellType = RANGETYPE_NAMED) Then
lo_Cell = lo_Range(0)
End If
End If

GetNamedCell = lo_Cell
End Function 'GetNamedCell
CalcPrim RangeCell GetNamedCellString Basic   565 20
Function GetNamedCellString(ByRef pName As String, Optional ByRef pDoc As Object) As String
'returns the string contents of a named (single) cell.
'Input:
'-- pName: the name of the searched cell
'-- pDoc: (optional) the spreadsheet object in which to search. If ommitted, lookup within the current document.
'Output: the cell string contents. If the cell was not found, returns an empty string.

Dim lo_Cell As Object
Dim l_Str As String

l_Str = ""
If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Cell = GetNamedCell(pName, pDoc)
If Not IsNull(lo_Cell) Then
l_Str = lo_Cell.ReferredCells.String
End If

GetNamedCellString = l_Str
End Function 'GetNamedCellString
CalcPrim RangeCell GetNamedCellValue Basic   586 20
Function GetNamedCellValue(ByRef pName As String, Optional ByRef pDoc As Object) As Variant
'returns the value contents of a named (single) cell.
'Input:
'-- pName: the name of the searched cell
'-- pDoc: (optional) the spreadsheet object in which to search. If ommitted, lookup within the current document.
'Output: the cell contents value. If the cell was not found, returns Null.

Dim lo_Cell As Object
Dim l_Value As Variant

l_Value = Null
If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Cell = GetNamedCell(pName, pDoc)
If Not IsNull(lo_Cell) Then
l_Value = lo_Cell.ReferredCells.Value
End If

GetNamedCellValue = l_Value
End Function 'GetNamedCellValue
CalcPrim RangeCell GetNamedRange Basic ShowColumns (Procedure)
ShowRows (Procedure)
607 22
Function GetNamedRange(ByRef pSheetName As String, pRangeName As String, Optional ByRef pDoc As Object) As Object
'returns a range object from a sheet name and the range name.
'The range name applies to any range type: single cell, single range, multiple range or named range.
'Input:
'-- pSheetName: the sheet name
'-- pRangeName: the searched range name
'-- pDoc: (optional) the document object. If pDoc is not specified, then the current spreadsheet is searched.
'Output: the range object or Null if not found.

Dim lo_Sheet As Object
Dim lo_Range As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

If pDoc.Sheets.hasByName(pSheetName) Then
lo_Sheet = pDoc.Sheets.getByName(pSheetName)
On Local Error Resume Next
lo_Range = lo_Sheet.getCellRangeByName(pRangeName)
End If

GetNamedRange = lo_Range
End Function 'GetNamedRange
CalcPrim RangeCell GetRange Basic ClearRangeContents (Procedure) 630 64
Function GetRange(Optional pRangeRef As Variant, Optional ByRef pSheetRef As Variant, Optional pDoc As Object) As Object
'Returns a range object.
'Input:
'-- pRangeRef: (optional) the reference of a range.
' May be its name ("MyRange" or "A1:B12") or its position (Array(0, 0, 1, 11)),
' or a RangeAddress UNO struct or an initialized range object.
' Defaults to the current range.
'-- pSheetRef: (optional) the reference of the sheet to explore.
' May be its name or its index, or an initialized sheet object.
' eg: "Sheet1" or 0 or MySheet
' If the sheet reference is missing then defaults to the active sheet
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: the range object or Null if not found
'
'Usage examples:
'MyRange = GetRange()
'MyRange = GetRange("SomeRange", "Sheet3") 'named range
'MyRange = GetRange(1, Array(0, 0, 1, 11), SomeDoc) 'A1:B12 in first sheet of SomeDoc

Dim lo_Sheet As Object
Dim lo_Range As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

'get the sheet
If IsMissing(pSheetRef) Then
lo_Sheet = pDoc.CurrentController.ActiveSheet
Else
lo_Sheet = GetSheet(pSheetRef, pDoc)
End If

'get the range
If Not IsNull(lo_Sheet) Then
'initialize the range object
If IsMissing(pRangeRef) Then
'default to active range
lo_Range = GetActiveRange(pDoc)
ElseIf (VarType(pRangeRef) = 8) Then
'string: range name
On Local Error Resume Next
lo_Range = lo_Sheet.GetCellRangeByName(pRangeRef)
ElseIf IsArray(pRangeRef) Then
'array: range position
If ArrayExists(pRangeRef) Then
If (UBound(pRangeRef) = 3) Then
On Local Error Resume Next
lo_Range = lo_Sheet.getCellRangeByPosition(pRangeRef(0), pRangeRef(1), pRangeRef(2), pRangeRef(3))
End If
End If
ElseIf IsUnoStruct(pRangeRef) Then
'is it a range address object?
If (InStr(pRangeRef.Dbg_Properties, "com.sun.star.table.CellRangeAddress") > 0) Then
lo_Range = lo_Sheet.getCellRangeByPosition(pRangeRef.StartColumn, pRangeRef.StartRow, pRangeRef.EndColumn, pRangeRef.EndRow)
End If
ElseIf (VarType(pRangeRef) = 9) Then
'object: range object (stupid? but hey... just in case)
lo_Range = pRangeRef
End If

End If

GetRange = lo_Range
End Function 'GetRange
CalcPrim RangeCell GetRangeColumn Basic GetRangeRow (Procedure) 695 15
Function GetRangeColumn(ByRef pRange As Object, pColNum As Integer) As Object
'Returns a column range object from a range.
'Input:
'-- pRange: the range from which we want a column
'-- pColNum: the column number (1-based)
'Output: the column range object.
'
'Note: a range Columns property returns all 1,024,000 rows of the sheet. This function returns only the actual height of the range column.

Dim lo_Column As Object 'the column range we're looking for

lo_Column = pRange.getCellRangeByPosition(pColNum - 1, 0, pColNum - 1, pRange.Rows.Count - 1)

GetRangeColumn = lo_Column
End Function 'GetRangeColumn
CalcPrim RangeCell GetRangeFromColumns Basic   711 22
Function GetRangeFromColumns(ByRef pSheet As Object, pStartColumn As Integer, Optional pEndColumn As Integer) As Object
'Returns a cell range that includes whole columns.
'Input:
'-- pSheet: the sheet to examine.
'-- pStartColumn: the starting column (0-based).
'-- pEndColumn: (optional) the ending column (0-based).
' Defaults to pStartColumn.
'Output: a cell range encompassing all columns from pStartCol to pEndCol or Null if an error occurred.
'
'Adapted from Silas in http://ooo-forums.apache.org/en/forum/viewtopic.php?f=20&t=58763

Dim lo_Cursor As Object
Dim lo_Range As Object

If IsMissing(pEndColumn) Then pEndColumn = pStartColumn

lo_Range = pSheet.getCellRangeByPosition(pStartColumn, 0, pEndColumn, 0)
lo_Cursor = pSheet.createCursorByRange(lo_Range)
lo_Cursor.expandToEntireColumns()

GetRangeFromColumns = lo_Cursor
End Function 'GetRangeFromColumns
CalcPrim RangeCell GetRangeFromRows Basic   734 22
Function GetRangeFromRows(ByRef pSheet As Object, pStartRow As Integer, Optional pEndRow As Integer) As Object
'Returns a cell range that includes whole rows.
'Input:
'-- pSheet: the sheet to examine.
'-- pStartRow: the starting row (0-based).
'-- pEndRow: (optional) the ending row (0-based).
' Defaults to pStartRow.
'Output: a cell range encompassing all rows from pStartRow to pEndRow.
'
'Adapted from Silas in http://ooo-forums.apache.org/en/forum/viewtopic.php?f=20&t=58763

Dim lo_Cursor As Object
Dim lo_Range As Object

If IsMissing(pEndCol) Then pEndRow = pStartRow

lo_Range = pSheet.getCellRangeByPosition(0, pStartRow, 0, pEndRow)
lo_Cursor = pSheet.createCursorByRange(lo_Range)
lo_Cursor.expandToEntireRows()

GetRangeFromRows = lo_Cursor
End Function 'GetRangeFromRows
CalcPrim RangeCell GetRangeRow Basic   757 15
Function GetRangeRow(ByRef pRange As Object, pRowNum As Integer) As Object
'Returns a row range object from a range.
'Input:
'-- pRange: the range from which we want a column
'-- pRowNum: the row number (1-based)
'Output: the row range object.
'
'Note: a range Rows property returns all 1,000 columns of the sheet. This function returns only the actual width of the range row.

Dim lo_Row As Object 'the row range we're looking for

lo_Row = pRange.getCellRangeByPosition(0, pRowNum - 1, pRange.Columns.Count - 1, pRowNum - 1)

GetRangeColumn = lo_Row
End Function 'GetRangeColumn
CalcPrim RangeCell GetRangeType Basic GetNamedCell (Procedure) 773 27
Function GetRangeType(ByRef pRange As Object) As Integer
'returns a range type
'Input:
'-- pRange: the range to check
'Output: the range type (see RANGETYPE_* constants)

Dim l_Type As Integer

'beware: the test order is important!
If IsNull(pRange) Then
l_Type = RANGETYPE_NULL
ElseIf IsMultiRange(pRange) Then
l_Type = RANGETYPE_RANGES
ElseIf IsSingleCell(pRange) Then 'this test MUST be performed before IsSingleRange
'since a single cell is also a single range
l_Type = RANGETYPE_CELL
ElseIf IsSingleRange(pRange) Then
l_Type = RANGETYPE_RANGE
ElseIf IsNamedRange(pRange) Then
l_Type = RANGETYPE_NAMED
Else
'unknown
l_Type = RANGETYPE_UNK
End If

GetRangeType = l_Type
End Function 'GetRangeType
CalcPrim RangeCell GotoLastCell Basic   801 22
Sub GotoLastCell(ByRef pSheet As Object, pSearchColNum As Integer, pColNum As Integer, Optional ByRef  pDoc As Object)
'Searches the last data cell in a given column of a sheet,
'then moves the active cell on the same row to another column of the same sheet.
'Input:
'-- pSheet: the sheet object to process.
'-- pSearchColNum: the column number to search (0-based: 0 = A; 1 = B; etc.).
'-- pColNum: the column number to reach
'-- pDoc: (optional) the document to process.
' Defaults to the current document

Dim lo_Cell As Object
Dim l_RowNum As Long

If IsMissing(pDoc) Then pDoc = ThisComponent

l_RowNum = LastRowIndex(pSearchColNum, pSheet)
If (l_RowNum > -1) Then
lo_Cell = pSheet.getCellByPosition(pColNum, l_RowNum)
pDoc.CurrentController.select(lo_Cell)
End If

End Sub 'GotoLastCell
CalcPrim RangeCell IsMultiRange Basic GetRangeType (Procedure) 824 4
Function IsMultiRange(ByRef pRange As Object) As Boolean
'returns True if the range is a multiple range
IsMultiRange = pRange.supportsService(SERV_CELLRANGES)
End Function 'IsMultiRange
CalcPrim RangeCell IsNamedRange Basic GetRangeType (Procedure) 829 4
Function IsNamedRange(ByRef pRange As Object) As Boolean
'returns True if the range is a multiple range
IsNamedRange = pRange.supportsService(SERV_NAMEDRANGE)
End Function 'IsNamedRange
CalcPrim RangeCell IsRangeInRange Basic IsRangeInRanges (Procedure) 834 38
Function IsRangeInRange(ByRef pInnerRange As Object, pOuterRange As Object) As Boolean
'Tests whether a range is contained within another one.
'Input:
'-- pInnerRange: the inner cell range
'-- pOuterRange: the outer cell range
'Output: True if pInnerRange in included within pOuterRange, otherwise False.

Dim lo_InnerRange As Object
Dim lo_OuterRange As Object
Dim l_StartCol As Long
Dim l_EndCol As Long
Dim l_StartRow As Long
Dim l_EndRow As Long
Dim l_OK As Boolean

l_OK = False
If Not IsNull(pOuterRange) And Not IsNull(pInnerRange) Then
'adjust data to the underlying range type
lo_OuterRange = RangeAsSheetCellRange(pOuterRange)
lo_InnerRange = RangeAsSheetCellRange(pInnerRange)

'get outer range position
With lo_OuterRange.rangeAddress
l_StartCol = .startColumn
l_EndCol = .endColumn
l_StartRow = .startRow
l_EndRow = .endRow
End With

'check
With lo_InnerRange.rangeAddress
l_OK = (l_StartCol <= .startColumn) And (l_EndCol >= .endColumn) _
And (l_StartRow <= .startRow) And (l_EndRow >= .endRow)
End With
End If

IsRangeInRange = l_OK
End Function 'IsRangeInRange
CalcPrim RangeCell IsRangeInRanges Basic   873 24
Function IsRangeInRanges(ByRef pInnerRange As Object, pOuterRanges As Variant) As Integer
'Tests whether a range is contained within another from a range set.
'Input:
'-- pInnerRange: the inner cell range
'-- pOuterRanges: the outer cell ranges array
'Output: the outer range index in which the inner one is contained or -1 if it is not contained in any.

Dim l_OK As Boolean
Dim l_Index As Integer
Dim i As Integer

l_Index = -1
If Not IsNull(pOuterRanges) And Not IsNull(pInnerRange) Then
'adjust data to the underlying range type
For i = 0 To UBound(pOuterRanges)
If IsRangeInRange(pInnerRange, pOuterRanges(i)) Then
l_Index = i
Exit For
End If
Next i
End If

IsRangeInRanges = l_Index
End Function 'IsRangeInRanges
CalcPrim RangeCell IsSingleCell Basic GetRangeType (Procedure) 898 4
Function IsSingleCell(ByRef pRange As Object) As Boolean
'returns True if the range is a cell
IsSingleCell = pRange.supportsService(SERV_CELL)
End Function 'IsSingleCell
CalcPrim RangeCell IsSingleRange Basic GetRangeType (Procedure) 903 4
Function IsSingleRange(ByRef pRange As Object) As Boolean
'returns True if the range is a single range
IsSingleRange = pRange.supportsService(SERV_CELLRANGE)
End Function 'IsSingleRange
CalcPrim RangeCell PasteSpecial Basic   908 54
Sub PasteSpecial(ByRef pSrcDoc As Object, pSrcRange As Object, pTgtDoc As Object, pTgtRange As Object)
'Applies the Edition > Paste special command to a given source range towards a given target range.
'This only copies text, dates and numerical values (without formatting).
'Input:
'-- pSrcDoc: the source document object.
'-- pSrcRange: the range to be copied.
'-- pTgtDoc: the target document object.
'-- pTgtRange: the range in which the copy must be processed.
'
'Caution: this sub uses the dispatcher. This implies that it can only process visible documents.

Dim lo_Dispatch As Object

lo_Dispatch = createUnoService("com.sun.star.frame.DispatchHelper")

'sélectionner les données source
pSrcDoc.CurrentController.select(pSrcRange)
lo_Dispatch.executeDispatch(pSrcDoc.CurrentController.Frame, ".uno:Copy", "", 0, Array())

'sélectionner les données cible
pTgtDoc.CurrentController.select(pTgtRange)

dim args1(5) as new com.sun.star.beans.PropertyValue
args1(0).Name = "Flags"
args1(0).Value = "SVD" 'S: Strings; V: Numerical values; D: Date/time; T: Format;
args1(1).Name = "FormulaCommand"
args1(1).Value = 0
args1(2).Name = "SkipEmptyCells"
args1(2).Value = False
args1(3).Name = "Transpose"
args1(3).Value = False
args1(4).Name = "AsLink"
args1(4).Value = False
args1(5).Name = "MoveMode"
args1(5).Value = 4

'MoveMode values (see https://bugs.documentfoundation.org/show_bug.cgi?id=97193#c12):
'Before version 5.1:
'0: INS_CELLSDOWN
'1: INS_CELLSRIGHT,
'2: INS_INSROWS,
'3: INS_INSCOLS,
'4: INS_NONE
'From version 5.1:
'0: INS_CELLSDOWN,
'1: INS_CELLSRIGHT,
'2: INS_INSROWS_BEFORE,
'3: INS_INSROWS_AFTER,
'4: INS_INSCOLS_BEFORE,
'5: INS_INSCOLS_AFTER,
'6: INS_NONE

lo_Dispatch.executeDispatch(pTgtDoc.CurrentController.Frame, ".uno:InsertContents", "", 0, args1())
End Sub 'PasteSpecial
CalcPrim RangeCell PasteTransferable Basic   963 18
Sub PasteTransferable(ByRef pSrcDoc As Object, pSrcRange As Object, pTgtDoc As Object, pTgtRange As Object)
'Pastes a range into another one. The formatting is retained.
'Input:
'-- pSrcDoc: the source document object.
'-- pSrcRange: the range to be copied.
'-- pTgtDoc: the target document object.
'-- pTgtRange: the range in which the copy must be processed.
'
'Caution: this sub can only process visible documents.

Dim lo_Tfer As Object

pSrcDoc.CurrentController.select(pSrcRange)
lo_Tfer = pSrcDoc.CurrentController.getTransferable()

pTgtDoc.CurrentController.select(pTgtRange)
pTgtDoc.CurrentController.insertTransferable(lo_Tfer)
End Sub 'PasteTransferable
CalcPrim RangeCell RangeAddressFromReference Basic   982 24
Function RangeAddressFromReference(ByRef pRangeRef As String, Optional ByRef pDoc As Object) As Object
'Returns a range address from its lettered reference.
'Input:
'-- pRangeRef: the lettered range reference ("A1:B2").
'-- pDoc: (optional) a Calc document.
'Output: the range address object or Null if an error occurred.
'
'Adapted from Marcelly & Godard in "Programmation OpenOffice.org et LibreOffice"
'Paris, Eyrolles, 2011, ISBN : 978-2-212-13247-2

Dim lo_Range As Object
Dim l_Address As Variant

If IsMissing(pDoc) Then pDoc = ThisComponent

On Local Error GoTo ErrHandler
lo_Range = pDoc.Sheets(0).getCellRangeByName(pRangeRef)
l_Address = lo_Range.RangeAddress

ErrHandler:
'do nothing

RangeAddressFromReference = l_Address
End Function 'RangeAddressFromReference
CalcPrim RangeCell RangeAddrString Basic   1007 25
Function RangeAddrString(ByRef pDocument As Object, pRangeAddr As Object) As String
'Returns the string for a range address
'
'Input:
'-- pDocument : the document
'-- pRangeAddr: the range being queried
'
'Output: a string representing the range address. This string is empty if any error occurred.

Dim lo_Range As Object 'the range for pRangeAddr
Dim l_Str As String 'the wanted address string

On Local Error GoTo OffLimit
l_Str = ""
lo_Range = pDocument.Sheets(pRangeAddr.Sheet).getCellRangeByPosition(pRangeAddr.StartColumn, pRangeAddr.StartRow, pRangeAddr.EndColumn, pRangeAddr.EndRow)
l_Str = Join(Split(lo_Range.AbsoluteName, "$"), "")
GoTo Finally

OffLimit:
err = 14 'pRangeAddr holds an off limits value

Finally:
RangeAddrString = l_Str

End Function 'RangeAddrString
CalcPrim RangeCell RangeAsSheetCellRange Basic IsRangeInRange (Procedure) 1033 21
Function RangeAsSheetCellRange(ByRef pRange As Object) As Object
'returns a sheetCellRange from any compatible range type
'Input:
'-- pRange: the range object to be converted
'Output: a range that supports the SheetCellRange service ("com.sun.star.sheet.SheetCellRange")

Dim lo_Range As Object

If pRange.SupportsService("com.sun.star.sheet.SheetCellRange") Then
lo_Range = pRange
ElseIf pRange.SupportsService("com.sun.star.sheet.NamedRange") Then
lo_Range = pRange.ReferredCells
'ElseIf pRange.SupportsService("com.sun.star.table.CellRange")
'? to-do
Else
'it supports some other service
lo_Range = Nothing
End If

RangeAsSheetCellRange = lo_Range
End Function 'RangeAsSheetCellRange
CalcPrim RangeCell SetActiveCellByName Basic   1055 25
Function SetActiveCellByName(ByRef pCellName As String, ByRef pSheetName As String, Optional ByRef pDoc As Object) As Object
'sets a cell as active.
'Input:
'-- pCellName: the cell name to activate.
'-- pSheetName: the sheet name in which to activate a cell.
'-- pDoc: (optional) the document to process. If pDoc is not specified, processes the current spreadsheet.
'Output: the cell object that was activated or NULL if it doesn't exist.

Dim lo_Sheet As Object
Dim lo_Range As Object

lo_Range = Nothing

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Sheet = SetActiveSheetByName(pSheetName, pDoc)
If Not IsNull(lo_Sheet) Then
On Local Error Resume Next
lo_Range = lo_Sheet.getCellRangeByName(pCellName)
If Not Err Then
pDoc.CurrentController.select(lo_Range)
End If
End If
SetActiveCellByName = lo_Range
End Function 'SetActiveCellByName
CalcPrim RangeCell SetActiveSheetByName Basic SetActiveCellByName (Procedure) 1081 23
Function SetActiveSheetByName(ByRef pSheetName As String, Optional pDoc As Object) As Object
'sets a sheet as active.
'Input:
'-- pSheetName: the sheet name to activate.
'-- pDoc: (optional) the document to process. If pDoc is not specified, processes the current spreadsheet.
'Output: returns the corresponding Sheet object or NULL if it doesn't exist/wasn't activated.

Dim lo_Sheet As Object

lo_Sheet = Nothing

If IsMissing(pDoc) Then pDoc = ThisComponent

If pDoc.Sheets.hasByName(pSheetName) Then
lo_Sheet = pDoc.Sheets.getByName(pSheetName)
'if the wanted sheet is not active, activate it
If Not (pDoc.CurrentController.ActiveSheet.Name = pSheetName) Then
pDoc.CurrentController.ActiveSheet = lo_Sheet
End If
End If

SetActiveSheetByName = lo_Sheet
End Function 'SetActiveSheetByName
CalcPrim RangeCell SetNamedCellValue Basic   1105 18
Sub SetNamedCellValue(ByRef pName As String, pValue As Variant, Optional ByRef pDoc As Variant)
'Sets a single named cell value.
'If the named cell is not found, does nothing.
'Input:
'-- pName: the name of the searched cell.
'-- pValue: the value to set.
'-- pDoc: (optional) the spreadsheet object in which to search. If ommitted, lookup within the current document.

Dim lo_Cell As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Cell = GetNamedCell(pName, pDoc)
If Not IsNull(lo_Cell) Then
lo_Cell.ReferredCells.Value = pValue
End If

End Sub 'SetNamedCellValue
CalcPrim RangeCell ShiftRange Basic   1124 26
Function ShiftRange(ByRef pOldRange As Object, pNewTLCell As Object) As Object
'Returns a new range from a given range, shifted to a specified top-left cell.
'Both ranges are of the same size.
'Input:
'-- pOldRange: the template range.
'-- pNewTLCell: the new top-left cell for the wanted range.
'Output: the new range on the same sheet as the new top-left cell, or Null if an error occurred.

Dim lo_Sheet As Object
Dim lo_NewRange As Object
Dim l_RangeWidth As Long
Dim l_RangeHeight As Long

'find dimensions
l_RangeWidth = pOldRange.RangeAddress.EndColumn - pOldRange.RangeAddress.StartColumn
l_RangeHeight = pOldRange.RangeAddress.EndRow - pOldRange.RangeAddress.StartRow

'apply the dimensions to the new range coordinates
lo_Sheet = pNewTLCell.Spreadsheet

On Local Error Resume Next
lo_NewRange = lo_Sheet.getCellRangeByPosition(pNewTLCell.CellAddress.Column, pNewTLCell.CellAddress.Row, _
pNewTLCell.CellAddress.Column + l_RangeWidth, pNewTLCell.CellAddress.Row + l_RangeHeight)

ShiftRange = lo_NewRange
End Function 'ShiftRange
CalcPrim RangeCell UpdateRangeColumnValues Basic   1151 62
Function UpdateRangeColumnValues(ByRef pSearch As Variant, pRange As Object, pLookupIndex As Integer, pUpdateIndex As Integer, pValue As Variant) As Long
'Updates all cells in a range column that match a criterion in another column of that range.
'Input:
'-- pSearch: the searched value.
'-- pRange: the range in which to search.
'-- pLookupIndex: the lookup column (1-based) within the search range.
' This index must be within pRange bounds (1 to columns count).
'-- pUpdateIndex: the update column (1-based) within the search range.
' This index must be within pRange bounds (1 to columns count).
'-- pValue: the value to insert into the matching cells.
'Output: the result code.
'Possible return values:
'-- ERR_RANGE_OK: process completed without error.
'-- ERR_RANGE_OUTOFBOUNDS: the lookup or update index is out of range.
'-- ERR_RANGE_ENUMERATOR: the enumerator couldn't be created.
'-- (other): the Basic error code
'
'Note: according to the range height, the update process may be lenghty. It is recommended that
' Calc controllers be locked in the interval.

Dim lo_Column As Object 'the search column
Dim lo_CurCell As Object 'the current cell
Dim lo_TgtCell As Object 'the target cell
Dim lo_Enum As Object 'an enumerator
Dim l_Result As Long 'the found row index
Dim i As Long
Dim l_Err As Long 'error flag

If ((pLookupIndex > 0) And (pLookupIndex <= pRange.Columns.Count)) _
And ((pUpdateIndex > 0) And (pUpdateIndex <= pRange.Columns.Count)) Then
l_Err = ERR_RANGE_OK
On Local Error Goto ErrHandler
'get the search column range (1st column of the range, total range height)
lo_Column = pRange.getCellRangeByPosition(pLookupIndex - 1, 0, pLookupIndex - 1, pRange.Rows.Count - 1)
'search for the wanted value: we need an enumerator
lo_Enum = CreateCalcRangeEnumerator(lo_Column)
If Not IsNull(lo_Enum) Then
i = 0 'row index
Do While lo_Enum.hasMoreElements
lo_CurCell = lo_Enum.NextElement
'found?
If (lo_CurCell.Value = pSearch) Then
'update pLookup column
lo_TgtCell = pRange.getCellByPosition(pUpdateIndex - 1, i)
lo_TgtCell.Value = pValue
End If
i = i + 1
Loop
Else
'error: can't create enumerator
l_Err = ERR_RANGE_ENUMERATOR
End If
Else
'error: the lookup or update column index is out of range bounds
l_Err = ERR_RANGE_OUTOFBOUNDS
End If

ErrHandler:
If Err Then l_Err = Err

UpdateRangeColumnValues = l_Err
End Function 'UpdateRangeColumnValues
CalcPrim RangeCell UpdateRangeMultiColumnValues Basic   1214 116
Function UpdateRangeMultiColumnValues(ByRef pSearch As Variant, pRange As Object, pLookupIndex As Integer, pUpdateValues As Variant) As Long
'Updates all cells in a range columns that match a criterion in another column of that range.
'Note: Do not use this function if you want to update cell data. Prefer it to update other cell items (formulas or settings),
' otherwise use the UpdateRangeMultiColumnValuesArray() function.
' Note that, because it uses an enumerator object, UpdateRangeMultiColumnValues() is *much* slower
' than UpdateRangeMultiColumnValuesArray().
'Input:
'-- pSearch: the searched value in the range.
'-- pRange: the selected range that contains data to search.
'-- pLookupIndex: the lookup column (1-based) within the range.
' This index must be within pRange bounds (1 to columns count).
'-- pUpdateValues: the update columns array (indices are 1-based) within the range.
' This is nested array with (ColumnIndex, Value, Mode) array items (see Usage below).
' The column indices must all be within pRange bounds (1 to columns count).
'Mode: the calc cell update mode. This value is one of the com.sun.star.sheet.CellFlags.XXX constants.
' The currently supported constants are: FORMULA, VALUE, DATETIME, STRING.
'Output: the result code.
'Possible return values:
'-- ERR_RANGE_OK: process completed without error.
'-- ERR_RANGE_OUTOFBOUNDS: the lookup or update index is out of range.
'-- ERR_RANGE_ENUMERATOR: the enumerator couldn't be created.
'-- ERR_RANGE_BADSRCARRAY: the update array is not usable.
'-- (other): the Basic error code
'
'Note: depending on the range height, the update process may be lengthy. It is recommended that
' Calc controllers be locked in the interval.
'
'Usage:
'Mode1 = com.sun.star.sheet.CellFlags.VALUE
'Mode2 = com.sun.star.sheet.CellFlags.FORMULA
'Formula = "=SUM(A1:A5)"
'Result = UpdateRangeMultiColumnValues(10, MyRange, 1, Array(Array(27, 1, Mode1), Array(28, Formula, Mode2)))
'replaces column 27 items with value 1 and column 28 items with a formula into MyRange range where column 1 items equal 10.

Dim lo_Column As Object 'the search column
Dim lo_CurCell As Object 'the current cell
Dim lo_TgtCell As Object 'the target cell
Dim lo_Enum As Object 'an enumerator
Dim l_Result As Long 'the found row index
Dim i As Long
Dim j As Long
Dim l_Err As Long 'error flag
Dim l_Index As Integer
Dim l_Value As Variant
Dim l_Mode As Integer
Dim l_NOK As Boolean

l_Err = ERR_RANGE_OK

'Check input arrays
If Not ArrayExists(pUpdateValues) Then
'array is unusable
l_Err = ERR_RANGE_BADSRCARRAY
ElseIf (pLookupIndex < 1) And (pLookupIndex > pRange.Columns.Count) Then
l_Err = ERR_RANGE_OUTOFBOUNDS
Else
'check bounds
For i = 0 To UBound(pUpdateValues)
l_Index = pUpdateValues(i)(0)
l_NOK = (l_Index < 1) Or (l_Index > pRange.Columns.Count)
If l_NOK Then
l_Err = ERR_RANGE_OUTOFBOUNDS
Exit For
End If
Next i
End If

'process
If (l_Err = 0) Then
On Local Error Goto ErrHandler
'get the search column range
lo_Column = pRange.getCellRangeByPosition(pLookupIndex - 1, 0, pLookupIndex - 1, pRange.Rows.Count - 1)
'search for the wanted value using an enumerator
lo_Enum = CreateCalcRangeEnumerator(lo_Column)
If Not IsNull(lo_Enum) Then
i = 0 'row index
Do While lo_Enum.hasMoreElements
lo_CurCell = lo_Enum.NextElement
'found?
If (lo_CurCell.Value = pSearch) Then
'insert values
For j = 0 To UBound(pUpdateValues)
'read cell information
lo_TgtCell = pRange.getCellByPosition(pUpdateValues(j)(0) - 1, i)
l_Value = pUpdateValues(j)(1)
l_Mode = pUpdateValues(j)(2)
'cell setting
Select Case l_Mode

Case com.sun.star.sheet.CellFlags.FORMULA
lo_TgtCell.Formula = l_Value

Case com.sun.star.sheet.CellFlags.VALUE
lo_TgtCell.Value = l_Value

Case com.sun.star.sheet.CellFlags.DATETIME
lo_TgtCell.Value = CDbl(l_Value)

Case com.sun.star.sheet.CellFlags.STRING
lo_TgtCell.String = l_Value
End Select
Next j
End If
i = i + 1
Loop
Else
'error: can't create enumerator
l_Err = ERR_RANGE_ENUMERATOR
End If
End If

ErrHandler:
If Err Then l_Err = Err

UpdateRangeMultiColumnValues = l_Err
End Function 'UpdateRangeMultiColumnValues
CalcPrim RangeCell UpdateRangeMultiColumnValuesArray Basic   1331 88
Function UpdateRangeMultiColumnValuesArray(ByRef pSearch As Variant, pRange As Object, pLookupIndex As Integer, pUpdateValues As Variant) As Long
'Updates all cells in a set of range columns that match a criterion in another column of that range.
'Note: Use this function only if you want to update cell *data*.
' For other cell items (formulas or settings), use the UpdateRangeMultiColumnValues function above.
' Note that because UpdateRangeMultiColumnValuesArray uses the range DataArray property, UpdateRangeMultiColumnValues is much slower
' than UpdateRangeMultiColumnValuesArray.
'Input:
'-- pSearch: the searched value in the range.
'-- pRange: the selected range that contains data to search.
'-- pLookupIndex: the lookup column (1-based) within the range.
' This index must be within pRange bounds (1 to columns count).
'-- pUpdateValues: the update columns array (indices are 1-based) within the range.
' This is nested array with (ColumnIndex, Value) array items.
' The column indices must all be within pRange bounds (1 to columns count).
'Output: the result code.
'Possible return values:
'-- 0: process completed without error.
'-- -2: the lookup or update index is out of range.
'-- -3: the enumerator couldn't be created.
'-- -4: the update array is not usable.
'-- (other): the Basic error code
'
'Depends on: CalcValue() function.
'
'Note: depending on the range height, the update process may be lengthy. It is recommended that
' Calc controllers be locked in the interval.
'
'Usage: Result = UpdateRangeMultiColumnValuesArray(SomeValue, MyRange, 1, Array(Array(27, 1), Array(28, SomeDate)))
'This replaces column 27 items with value 1 and column 28 items with value SomeDate into MyRange range where column 1 items equal SomeValue.


Dim i As Long
Dim j As Long
Dim l_Err As Long 'error flag
Dim l_RangeArray As Variant 'array for manipulating the data array
Dim l_Value As Variant
Dim l_Value2 As Variant
Dim l_Lookup As Variant 'the searched value
Dim l_ColIndex As Long
Dim l_NOK As Boolean

l_Err = 0

'Check input arrays
If Not ArrayExists(pUpdateValues) Then
'array is unusable
l_Err = -4
Else
'check bounds
For i = 0 To UBound(pUpdateValues)
l_ColIndex = pUpdateValues(i)(0)
l_NOK = (l_ColIndex < 1) Or (l_ColIndex > pRange.Columns.Count)
If l_NOK Then
l_Err = -2
Exit For
End If
Next i
End If

'process
If (l_Err = 0) Then
'On Local Error Goto ErrHandler
'get the range data array
l_RangeArray = pRange.DataArray
'update the data array
For i = 0 To UBound(l_RangeArray) - 1
l_Lookup = l_RangeArray(i)(pLookupIndex - 1)
If (l_Lookup = pSearch) Then
For j = 0 To UBound(pUpdateValues)
'get the value to insert
l_Value = pUpdateValues(j)(1)
'convert into possible data value for storage within a Calc cell
'(numeric or string)
l_Value = CalcValue(l_Value)
'insert
l_RangeArray(i)(pUpdateValues(j)(0) - 1) = l_Value
Next j
End If
Next i
'update the data array
pRange.DataArray = l_RangeArray
End If

ErrHandler:
If Err Then l_Err = Err

UpdateRangeMultiColumnValuesArray = l_Err
End Function 'UpdateRangeMultiColumnValuesArray
CalcPrim RangeCell UsedRange Basic CopyUsedRange (Procedure) 1420 21
Function UsedRange(ByRef pSheet As Object, Optional ByRef pOrigin As String) As Object
'Returns the used cells range in a given sheet.
'Input:
'-- pSheet: the sheet object to explore.
'-- pOrigin: (optional) the top-left cell from which to get the range.
' Defaults to A1.
'Output: the used range object in the sheet.

Dim lo_UsedRange As Object
Dim lo_CellCur As Object 'a cell cursor

If IsMissing(pOrigin) Then pOrigin = CELL_ORIGIN

'create a cursor on the used range
lo_CellCur = pSheet.createCursorByRange(pSheet.getCellRangeByName(pOrigin))
lo_CellCur.gotoEndOfUsedArea(True)
'get the used range
lo_UsedRange = pSheet.getCellRangeByName(lo_CellCur.AbsoluteName)

UsedRange = lo_UsedRange
End Function 'UsedRange
CalcPrim RangeCell VLookupCell Basic   1442 34
Function VLookupCell(ByRef pSearch As Variant, pRange As Object, pLookupIndex As Integer, pMatchType As Integer) As Object
'Retrieves a cell in a range, à-la VLOOKUP.
'This function is much alike the VLOOKUP() Calc function, but it returns a cell object instead of a value.
'Input:
'-- pSearch: the searched value
'-- pRange: the selected range that contains data to search. The searched column must be the first one.
'-- pLookupIndex: the lookup column (1-based) within the search range
'-- pMatchType: -1, 0 or 1 (see the MATCH() function help)
'Output: the matching cell or Null is none was found.

Dim lo_FuncAccess As Object 'the function access object
Dim lo_Col As Object 'the search column
Dim lo_Cell As Object 'the target cell
Dim l_Result As Long 'the found row index

If ((pLookupIndex > 0) And (pLookupIndex <= pRange.Columns.Count)) Then
'get the search column range (1st column of the range, total height)
lo_Col = pRange.getCellRangeByPosition(0, 0, 0, pRange.Rows.Count - 1)
'search for the wanted value
On Local Error Goto ErrHandler
lo_FuncAccess = CreateUnoService(SERV_SPREADFUNC)
l_Result = lo_FuncAccess.callFunction("MATCH", Array(pSearch, lo_Col, pMatchType))
'found?
If (l_Result > -1) Then
'retrieve the wanted cell object
lo_Cell = pRange.getCellByPosition(pLookupIndex - 1, l_Result - 1)
End If
End If

ErrHandler:
'do nothing

VLookupCell = lo_Cell
End Function 'VLookupCell
CalcPrim Sheet CopyRangeAt Basic   50 21
Function CopyRangeAt(ByRef pSrcRange As Object, pTgtSheet As Object, pRefCell As Object) As Long
'/!\ under development
'copies a given range to a sheet from a reference row.
'Returns an error code.
'Input:
'-- pSrcRange: the source range object
'-- pTgtSheet: the target sheet
'-- pRefCell: the target reference cell (row number in the target)
'Output: the execution result code (0 if OK):
'--
'--

Dim l_Err As Long

l_Err = 0
On Local Error Resume Next
pTgtSheet.copyRange(pRefCell.CellAddress, pSrcRange.RangeAddress)
l_Err = Err

CopyRangeAt = l_Err
End Function 'CopyRangeAt
CalcPrim Sheet FixRowCols Basic   72 24
Sub FixRowCols(pSheetName As String, pColNum As Integer, pRowNum As Integer, Optional ByRef pDoc As Object)
'Fixes/freezes a given sheet columns and rows
'/!\ to be checked
'Input:
'-- pSheetName: the sheet name to be processed
'-- pColNum: the column number for freezing (0 to not freeze a column)
'-- pRowNum: the row number for freezing (0 to not freeze a row)
'-- pDoc: (optional) the document in which to process a sheet
' Defaults to ThisComponent
'Note: If pColNum and pRowNum are both 0, then this "unfreezes" a previously freezed sheet row/col.

Dim lo_Ctrlr As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

If pDoc.Sheets.hasByName(pSheetName) Then
lo_Ctrlr = pDoc.CurrentController
If Not (lo_Ctrlr.ActiveSheet.Name = pSheetName) Then
lo_Ctrlr.ActiveSheet = pDoc.Sheets.getByName(pSheetName)
End If
lo_Ctrlr.freezeAtPosition(pColNum, pRowNum)
End If

End Sub 'FixRowCols
CalcPrim Sheet GetColNameFromNumber Basic   97 29
Function GetColNameFromNumber(ByRef pNum As Long) As String
'convert a column number (range 0, 1,..COLMAX) into its letter counterpart (range 'A', 'B',..'AMJ').
'Input:
'-- pNum: the column number (allowed values in 0..MAXCOL400)
'Output: a string representation of the column name, in range 'A'..'AMJ'
'If pNum is not in the allowed range, returns '?'.
'
'Adapted from a Python function by sundar nataraj
'http://stackoverflow.com/questions/23861680/convert-spreadsheet-number-to-column-letter

Dim l_Str As String
Dim l_Div As Long
Dim l_Mod As Long

l_Str = ""
If (pNum < 0) Or (pNum > MAXCOL400) Then
l_Str = "?"
Else
l_Div = pNum + 1
l_Str = ""
Do While (l_Div > 0)
l_Mod = (l_Div - 1) Mod 26
l_Str = Chr(65 + l_Mod) + l_Str
l_Div = Int((l_Div - l_Mod)/26)
Loop
End If

GetColNameFromNumber = l_Str
End Function 'GetColNameFromNumber
CalcPrim Sheet GetSheet Basic CopyUsedRange (Procedure)
GetRange (Procedure)
LastRowIndex (Procedure)
127 42
Function GetSheet(Optional ByRef pSheetRef As Variant, Optional pDoc As Object) As Object
'returns a sheet object.
'Input:
'-- pSheetRef: (optional) the name or the index of the sheet to process or an initialized sheet object
' eg: "Sheet1" or 0 or MySheet
' If the sheet reference is missing then defaults to the active sheet.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: the sheet object or Null if not found
'
'Usage examples:
'MySheet = GetSheet() -> current sheet for current document
'MySheet = GetSheet("Sheet3") -> sheet named "Sheet3" in current document
'MySheet = GetSheet(1, SomeDoc) -> 2nd sheet in SomeDoc document object

Dim lo_Sheet As Object
Dim i As Long

If IsMissing(pDoc) Then pDoc = ThisComponent

'initialize the sheet object
If IsMissing(pSheetRef) Then
'active sheet
lo_Sheet = pDoc.CurrentController.ActiveSheet
ElseIf IsNumeric(pSheetRef) Then
'number: sheet index
i = Fix(pSheetRef)
If (i >= 0) And (i < pDoc.Sheets.Count) Then
lo_Sheet = pDoc.Sheets(i)
End If
ElseIf (VarType(pSheetRef) = 8) Then
'string: sheet name
If pDoc.Sheets.hasByName(pSheetRef) Then
lo_Sheet = pDoc.Sheets.GetByName(pSheetRef)
End If
ElseIf (VarType(pSheetRef) = 9) Then
'object: sheet object
lo_Sheet = pSheetRef
End If

GetSheet = lo_Sheet
End Function 'GetSheet
CalcPrim Sheet LastRowIndex Basic GotoLastCell (Procedure) 170 90
Function LastRowIndex(ByRef pColRef As Variant, Optional ByRef pSheetRef As Variant, Optional ByRef pDoc As Object) As Long
'Returns the index of the last row with data in a column of a sheet.
'Input:
'-- pColRef: the name or the index of the column to check
' eg: "A" or 0
'-- pSheetRef: (optional)the name or the index of the sheet to process or an initialized sheet object
' eg: "Sheet1" or 0 or MySheet
' Defaults to the active sheet.
'-- pDoc: (optional) the document object in which to check
' Defaults to the current document
'Output: the row index for the last used cell in the given column
'or a negative number as an error flag:
'-- ERR_ROWINDEX_EMPTY: the whole column is empty
'-- ERR_ROWINDEX_UNKSHEET: the sheet is unknown
'-- ERR_ROWINDEX_UNKCOLINDEX : the index of the column does not exist
'-- ERR_ROWINDEX_UNKCOLNAME : the name of the column does not exist
'
'Adapted and edited from Martius code in https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=10817
'
'Usage examples:
'x = LastRowIndex("a", "Sheet3")
'x = LastRowIndex(5, "Sheet3")
'x = LastRowIndex("b", 2)
'x = LastRowIndex("b", SheetObject)
'x = LastRowIndex("MySheetName")
'x = LastRowIndex(2000)
'x = LastRowIndex("f", "Sheet3")
'x = LastRowIndex("b", 3)
'x = LastRowIndex("b")
'x = LastRowIndex(5)

Dim lo_Sheet As Object
Dim lo_Cols As Object
Dim lo_Col As Object
Dim lo_SearchDesc As Object 'search descriptor
Dim lo_SearchRes As Object 'search result
Dim l_ResultName As String
Dim l_arrNameItems As Variant

If IsMissing(pDoc) Then pDoc = ThisComponent

'get the sheet
If IsMissing(pSheetRef) Then
lo_Sheet = pDoc.CurrentController.ActiveSheet
Else
lo_Sheet = GetSheet(pSheetRef, pDoc)
If IsNull(lo_Sheet) Then
'error: sheet was not found
LastRowIndex = ERR_ROWINDEX_UNKSHEET
Exit Function
End If
End If

'get the column
lo_Cols = lo_Sheet.getColumns()
If IsNumeric(pColRef) then
If (pColRef >= 0) AND (pColRef < lo_Cols.getCount()) Then
lo_Col = lo_Cols.getByIndex(pColRef)
Else
'column number doesn't exist
LastRowIndex = ERR_ROWINDEX_UNKCOLINDEX
Exit Function
EndIf
Else
If lo_Cols.hasByName(pColRef) Then
lo_Col = lo_Cols.getByName(pColRef)
Else
'column name doesn't exist
LastRowIndex = ERR_ROWINDEX_UNKCOLNAME
Exit Function
EndIf
EndIf

'search data
lo_SearchDesc = lo_Col.createSearchDescriptor
lo_SearchDesc.searchRegularExpression = True
lo_SearchDesc.SearchString = "."
lo_SearchRes = lo_Col.FindAll(lo_SearchDesc)

'calculate row index
If Not IsNull(lo_SearchRes) Then
l_ResultName = lo_SearchRes.AbsoluteName
l_arrNameItems = Split(l_ResultName, "$")
LastRowIndex = Val(l_arrNameItems(UBound(l_arrNameItems))) - 1
Else
'data not found: empty column
LastRowIndex = ERR_ROWINDEX_EMPTY
End If

End Function 'LastRowIndex
CalcPrim Sheet LastUsedCell Basic LastUsedColumn (Procedure)
LastUsedRow (Procedure)
261 19
Function LastUsedCell(ByRef pSheet As Object) As Object
'Returns the last cell used in a given sheet (lower-right corner).
'Input:
'-- pSheet: the sheet object to explore.
'Output: the last used cell object in the sheet.

Dim l_Origin As String 'origin cell address
Dim lo_UsedRange As Object
Dim lo_CellCur As Object 'a cell cursor

'create a cursor on the used range
l_Origin = "A1"
lo_CellCur = pSheet.createCursorByRange(pSheet.getCellRangeByName(l_Origin))
lo_CellCur.gotoEndOfUsedArea(False)
'get the used range
lo_UsedRange = pSheet.getCellRangeByName(lo_CellCur.AbsoluteName)

LastUsedCell = lo_UsedRange
End Function 'LastUsedCell
CalcPrim Sheet LastUsedColumn Basic   281 17
Function LastUsedColumn(ByRef pSheet As Object) As Long
'Returns the last column used in a given sheet.
'Input:
'-- pSheet: the sheet object to explore.
'Output: the last used column number in the sheet.

Dim lo_UsedRange As Object
Dim l_Col As Long

l_Col = -1 'error condition

'get the used range
lo_UsedRange = LastUsedCell(pSheet)
l_Col = lo_UsedRange.RangeAddress.EndColumn

LastUsedColumn = l_Col
End Function 'LastUsedColumn
CalcPrim Sheet LastUsedRow Basic   299 17
Function LastUsedRow(ByRef pSheet As Object) As Long
'Returns the last row used in a given sheet.
'Input:
'-- pSheet: the sheet object to explore.
'Output: the last used row number in the sheet.

Dim lo_UsedRange As Object
Dim l_Row As Long

l_Row = -1 'error condition

'get the used range
lo_UsedRange = LastUsedCell(pSheet)
l_Row = lo_UsedRange.RangeAddress.EndRow

LastUsedRow = l_Row
End Function 'LastUsedRow
CalcPrim Sheet ProtectSheet Basic ProtectSheetByName (Procedure) 317 30
Function ProtectSheet(ByRef pSheet As Object, pProtect As Boolean, Optional pPwd As String) As Integer
'Protects or unprotects a sheet.
'Input:
'-- pSheet: the sheet object to protect
'-- pProtect: True to protect, False to unprotect
'-- pPwd: (optional) the password to apply. pPwd may be a blank string.
' Defaults to a blank string.
'Output:
'-- -1 if pSheet is not set (Null),
'-- the Basic error code for the action (see LibO help, 'Basic programs debugging' topic),
'-- 0 if the execution was successful.

Dim l_Err As Integer

l_Err = -1
If Not IsNull(pSheet) Then

If IsMissing(pPwd) Then pPwd = ""

On Local Error Resume Next
If pProtect Then
pSheet.protect(pPwd)
Else
pSheet.unprotect(pPwd)
End If
l_Err = Err
End If

ProtectSheet = l_Err
End Function 'ProtectSheet
CalcPrim Sheet ProtectSheetByName Basic   348 25
Function ProtectSheetByName(ByRef pSheetName As String, pProtect As Boolean, pPwd As String, Optional ByRef pDoc As Object) As Integer
'Protects or unprotect a sheet from its name.
'Input:
'-- pSheetName: the sheet name to protect
'-- pPwd: the password to apply. pPwd may be a blank string.
'-- pProtect: True to protect, False to unprotect
'-- pDoc: (optional) the document to be processed. If not specified, processes the current spreadsheet.
'Output:
'-- -1 if pSheet is not set (Null),
'-- the Basic error code of the action (see LibO help, 'Basic programs debugging' topic),
'-- 0 if the execution was successful.

Dim oSheet As Object
Dim l_Err As Integer

If IsMissing(pDoc) Then pDoc = ThisComponent

l_Err = -1
If pDoc.Sheets.hasByName(pSheetName) Then
pSheet = pDoc.Sheets.getByName(pSheetName)
l_Err = ProtectSheet(oSheet, pProtect, pPwd)
End If

ProtectSheetByName = l_Err
End Function 'ProtectSheetByName
CalcPrim Sheet ShowSheetByName Basic   374 22
Sub ShowSheetByName(ByRef pSheetName As String, pVisible As Boolean, Optional ByRef pDoc As Object)
'Shows or hides a sheet from its name.
'Input:
'-- pSheetName: the name of the sheet to be hidden/displayed
'-- pVisible: True to show, False to hide
'-- pDoc: (optional) the document to be processed. If pDoc is not supplied, applies to the current spreadsheet.

Dim oDoc As Object
Dim oSheet As Object

If IsMissing(pDoc) Then
oDoc = ThisComponent
Else
oDoc = pDoc
End If

If oDoc.Sheets.hasByName(pSheetName) Then
oSheet = oDoc.Sheets.getByName(pSheetName)
oSheet.IsVisible = pVisible
End If

End Sub 'ShowSheetByName
CalcPrim Spreadsheet ShowColumns Basic   40 20
Sub ShowColumns(ByRef pSheetName As String, pRangeName As String, pVisible As Boolean, Optional ByRef pDoc As Object)
'Shows or hides columns of a sheet.
'Input:
'-- pSheetName: the sheet name to process.
'-- pRangeName: the range which columns to show or hide.
'-- pVisible: set to True to show or False to hide.
'-- pDoc: (optional) the document to process.
' When pDoc is not specified, ShowColumns applies to the current spreadsheet.

Dim lo_Range As Object
Dim lo_Cols As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Range = GetNamedRange(pSheetName, pRangeName, pDoc)
If Not IsNull(lo_Range) Then
lo_Cols = lo_Range.Columns
lo_Cols.IsVisible = pVisible
End If
End Sub 'ShowColumns
CalcPrim Spreadsheet ShowInputLine Basic   61 19
Sub ShowInputLine(ByRef pVisible As Boolean)
'displays or hides the Calc input line (formula bar).
'Uses the Dispatcher.
'Input:
'-- pVisible: True to set the formula bar visible, otherwise False

'Dim oFrame As Object
'Dim oDispatch As Object
Dim l_Args(0) As New com.sun.star.beans.PropertyValue

'oFrame = ThisComponent.CurrentController.Frame
'oDispatch = createUnoService(LOPRIM_SERV_DISPATCH)

l_Args(0).Name = "InputLineVisible"
l_Args(0).Value = pVisible

'oDispatch.executeDispatch(oFrame, ".uno:InputLineVisible", "", 0, l_Args())
LibOPrim.App._UNOCommand("InputLineVisible", l_Args())
End Sub 'ShowInputLine
CalcPrim Spreadsheet ShowRows Basic   81 20
Sub ShowRows(ByRef pSheetName As String, pRangeName As String, pVisible As Boolean, Optional ByRef pDoc As Object)
'Shows or hides rows of a sheet.
'Input:
'-- pSheetName: the sheet name to process.
'-- pRangeName: the range which rows to show or hide.
'-- pVisible: set to True to show or False to hide.
'-- pDoc: (optional) the document to process.
' When pDoc is not specified, ShowRows applies to the current spreadsheet.

Dim lo_Range As Object
Dim lo_Rows As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Range = GetNamedRange(pSheetName, pRangeName, pDoc)
If Not IsNull(lo_Range) Then
lo_Rows = lo_Range.Rows
lo_Rows.IsVisible = pVisible
End If
End Sub 'ShowRows
CalcPrim Spreadsheet ToggleGrid Basic   102 6
Sub ToggleGrid()
'Toggles the current sheet grid display.

LibOPrim.App._UNOCommand("ToggleSheetGrid", Array())

End Sub 'ToggleGrid
DataStructPrim Collections AddCollectionItem Basic   33 47
Function AddCollectionItem(ByRef pColl As Object, ByRef pItem As Variant, pKey As String, Optional ByRef pForce As Boolean) As Long
'Adds an item to a collection.
'The action doesn’t end with an internal error when the key already exists.
'If the key is already present, the existing item may be replaced with the new one.
'Input:
'-- pColl: the collection for storing the item.
'-- pItem: the item to add.
'-- pKey: the key for the item.
'-- pForce: (optional) the existing item is replaced if the key already exists
' Defaults to False.
'Output: the process result.
'Possible values:
'-- 0: processed ok.
'-- 1: the collection object is not initialized.
'-- 2: the key already exists and the pForce option is False.
'-- 3: the collection object is not a collection. (TBD)

Dim l_Err As Long

l_Err = 0

If IsMissing(pForce) Then pForce = False

On Local Error Goto ErrHandler:
'currently missing: check pColl is a collection object
If Not IsNull(pColl) Then
pColl.Add(pItem, pKey)
Else
'error: the object is not set
l_Err = 1
End If
Goto FuncEnd:

'If we are here, an error occurred: the key is already in the collection
ErrHandler:
If pForce Then
pColl.Remove(pKey)
pColl.Add(pItem, pKey)
l_Err = Err
Else
'error: the key already exists
l_Err = 2
End If

FuncEnd:
AddCollectionItem = l_Err
End Function 'AddCollectionItem
DialogPrim Dialogs BrowseForDir Basic   34 24
Function BrowseForDir(ByRef pDefDir As String, pTitle As String, pDescription As String) As String
'Browse for a directory and returns the user's choice.
'This is a simple FolderPicker encapsulation.
'Input:
'-- pDefDir: the default (starting) directory (in URL or OS form).
'-- pTitle: the dialog title.
'-- pDescription: the description string for display in the dialog.
'Output: the selected folder name or a zero-length string if the user canceled the operation.
'The output folder name is in URL form with a trailing "\".

Dim lo_FP As Object 'the folder picker object
Dim l_Dir As String 'the selected directory name

l_Dir = ""
lo_FP = CreateUnoService("com.sun.star.ui.dialogs.FolderPicker")
lo_FP.DisplayDirectory = ConvertToURL(pDefDir)
lo_FP.Description = pDescription
lo_FP.Title = pTitle
If (lo_FP.execute = com.sun.star.ui.dialogs.ExecutableDialogResults.OK) Then
l_Dir = lo_FP.Directory & "/"
End If

BrowseForDir = l_Dir
End Function 'BrowseForDir
DialogPrim Dialogs CreateDialog Basic   59 31
Function CreateDialog(ByRef pLibName As String, pModuleName As String, Optional ByRef pLibCtnr As Object) As Object
'Creates a Uno dialog.
'Input:
'-- pLibName: the dialog library name
'-- pModuleName: the dialog module name
'-- pLibCtnr: (optional) the library container. If not specified, looks into DialogLibraries.
'Output: the dialog object created or Null if the dialog couldn't be created.
'
'Note: this is an enhanced version of the LibreOffice Tools.ModuleControls.LoadDialog() function,
' adding error checking.

Dim lo_Lib As Object 'the library name
Dim lo_ModName As Object 'the dialog module name
Dim lo_UnoDlg As Object 'the dialog object to be returned

lo_UnoDlg = Nothing

If IsMissing(pLibCtnr) Then pLibCtnr = DialogLibraries

If pLibCtnr.hasByName(pLibName) Then
pLibCtnr.LoadLibrary(pLibName)
lo_Lib = pLibCtnr.getByName(pLibName)
If lo_Lib.hasByName(pModuleName) Then
lo_ModName = lo_Lib.getByName(pModuleName)
On Local Error Resume Next
lo_UnoDlg = CreateUnoDialog(lo_ModName)
End If
End If

CreateDialog = lo_UnoDlg
End Function 'CreateDialog
DialogPrim Dialogs YesNoDialog Basic   91 9
Function YesNoDialog(ByRef pTitle As String, pMsg As String) As Boolean
'Displays a "Yes/No" dialog and returns the user's choice.
'Input:
'-- pTitle: the dialog box title.
'-- pMsg: the message to display in the dialog box.
'Output: True if the user selected Yes, False otherwise.

YesNoDialog = (MsgBox(pMsg, 4 + 32, pTitle) = 6)
End Function 'YesNoDialog
FormPrim Widgets CheckBoxCount Basic   48 55
Function CheckBoxCount(ByRef pFormName As String, Optional ByRef pDoc As Object, Optional pChecked As Boolean, Optional pNonPrintable As Boolean) As Long
'counts the checked checkboxes. Non printable checkboxes are counted if pNonPrintable is set to True.
'Input:
'-- pFormName: the form where checkboxes are to be checked
'-- pDoc: (optional) The document where checkboxes are to be counted (defaults to the current document)
'-- pChecked: a flag for (un)checked boxes counting (defaults to True)
'-- pNonPrintable: a flag for non printable widgets count. If set to False (default), non printable widgets are not counted.
'Output:
' The count of (un)checked checkboxes or -1 if an error was encountered.
'Possible errors:
'-- ERR_FORMPRIM_NODOC: no document specified
'-- ERR_FORMPRIM_NOFORM: no form on the document
'-- ERR_FORMPRIM_NOCONTROL: no controls on the form
'-- ERR_FORMPRIM_NOWIDGET: no checkbox control

Dim lo_Form As Object 'the form to explore
Dim lo_Controls As Object 'the controls on the form
Dim lo_CurControl As Object 'the current control
Dim i As Long
Dim l_Checked As Long 'count l_Checked checkboxes (defaults to True, that is only checked boxes are counted)
Dim l_CheckCount As Long

If IsMissing(pDoc) Then pDoc = ThisComponent

If IsMissing(pChecked) Then
l_Checked = 1
Else
l_Checked = CBool(pChecked)
End If

If IsMissing(pNonPrintable) Then pNonPrintable = False

l_CheckCount = ERR_FORMPRIM_NODOC
If Not IsNull(pDoc) Then
If pDoc.DrawPage.Forms.hasByName(pFormName) Then
lo_Form = pDoc.DrawPage.Forms.getByName(pFormName)
lo_Controls = lo_Form.getControlModels
For i = 0 To UBound(lo_Controls) - 1
lo_CurControl = lo_Controls(i)
'is it a checkbox?
If (lo_CurControl.ClassID = WIDG_ID_CBX) Then
If (l_CheckCount = -1) Then l_CheckCount = 0 'now, we've got a checkbox
'checked (state = 1)?
If (lo_CurControl.State = l_Checked) And (pNonPrintable Or lo_CurControl.Printable) Then
l_CheckCount = l_CheckCount + 1
End If
End If
Next i
Else
l_CheckCount = ERR_FORMPRIM_NOFORM
End If
End If

CheckBoxCount = l_CheckCount
End Function '_CheckBoxCount
FormPrim Widgets GetFormControl Basic   104 53
Function GetFormControl(ByRef pFormName As String, ByRef pCtrlName As String, Optional ByRef pDoc As Object) As Object
'Returns the control object which name is pCtrlName on a given form.
'Input:
'-- pFormName: the form name on whinch the control is placed
'-- pCtrlName: the control name
'-- pDoc: (optional) the document owning the form.
' Defaults to the current document.
'Output: the control object of Null if not found or the form is not found.

Dim lo_Form As Object 'the form on the document
Dim lo_Ctrl As Object 'the wanted control
Dim l_DocType As Long 'the document type

lo_Ctrl = Nothing

If IsMissing(pDoc) Then pDoc = ThisComponent

If Not IsNull(pDoc) Then
l_DocType = GetLibODocumentType(pDoc)
Select Case l_DocType

Case LOPRIM_DOCTYPECALC

Case LOPRIM_DOCTYPEWRITER
If pDoc.DrawPage.Forms.hasByName(pFormName) Then
lo_Form = pDoc.DrawPage.Forms.getByName(pFormName)
If lo_Form.hasByName(pCtrlName) Then
lo_Ctrl = lo_Form.getByName(pCtrlName)
End If
End If

Case LOPRIM_DOCTYPEIMPRESS

Case LOPRIM_DOCTYPEDRAW

'Case LOPRIM_DOCTYPEMATH not handled

Case LOPRIM_DOCTYPEBASE

Case LOPRIM_DOCTYPEUNK, ERR_LOPRIM_DOCTYPE
'do nothing

End Select
End If

If (l_DocType > LOPRIM_DOCTYPEUNK) Then
If lo_Form.hasByName(pCtrlName) Then
lo_Ctrl = lo_Form.getByName(pCtrlName)
End If
End If

GetFormControl = lo_Ctrl
End Function 'GetFormControl
IOPrim Files ChangeFileExt Basic   43 28
Function ChangeFileExt(ByRef pFileName As String, pNewExt As String) As String
'Changes the extension part of a *file* name.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'-- pNewExt: the new extension, without leading dot.
'Output: The new file name with the changed extension. If any, the path part is stripped out.
'Note: This does NOT check for the file/path existence.
'
'Dependency: StringsPrim.Strings

Dim l_FileName As String
Dim l_Array As Variant

l_FileName = ExtractFileName(pFileName)
'suppress multiple IOPRIM_EXTSEPCHARs
l_FileName = SuppressMultipleChars(l_FileName, IOPRIM_EXTSEPCHAR)
'set the new extension
l_Array = Split(l_FileName, IOPRIM_EXTSEPCHAR)
If (UBound(l_Array) = 0) Then
'no extension
ReDim Preserve l_Array(1)
l_Array(1) = pNewExt
Else
l_Array(UBound(l_Array)) = pNewExt
End If

ChangeFileExt = Join(l_Array, IOPRIM_EXTSEPCHAR)
End Function 'ChangeFileExt
IOPrim Files ExtractFileExt Basic   72 20
Function ExtractFileExt(ByRef pFileName As String) As String
'Retrieves the extension part of a file name.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'Output: The file extension, without leading dot.
'Note: This does NOT check for the file/path existence.

Dim l_URLName As String
Dim l_Array() As String
Dim l_Ext As String

l_Ext = ""
l_URLName = ConvertToURL(pFileName)
l_Array = Split(l_URLName, IOPRIM_EXTSEPCHAR)
If (UBound(l_Array) > 0) Then
l_Ext = l_Array(UBound(l_Array))
End If

ExtractFileExt = l_Ext
End Function 'ExtractFileExt
IOPrim Files ExtractFileName Basic ChangeFileExt (Procedure)
JustFileName (Procedure)
CalcShareFileName (Procedure)
LockFileName (Procedure)
93 16
Function ExtractFileName(ByRef pFileName As String) As String
'Retrieves a filename without access path from a FQDN file name.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'Output: The file name without the path part.
'Note: this does not check for the file/path existence.
'See also JustFileName().

Dim l_URLName As String
Dim l_Array() As String

l_URLName = ConvertToURL(pFileName)
l_Array = Split(l_URLName, IOPRIM_PATHSEPCHAR)

ExtractFileName = l_Array(UBound(l_Array))
End Function 'ExtractFileName
IOPrim Files ExtractFilePath Basic GetParentFolder (Procedure)
CalcShareFileName (Procedure)
LockFileName (Procedure)
110 21
Function ExtractFilePath(ByRef pFileName As String) As String
'Extracts the path from a given FQDN file name.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'Output: The path part of pFileName, in URL form and terminated with a / (slash).
'Note: this does not check for the file/path existence.

Dim l_URLName As String
Dim l_Array() As String
Dim l_Path As String

l_Path = ""
l_URLName = ConvertToURL(pFileName)
l_Array = Split(l_URLName, IOPRIM_PATHSEPCHAR)
If (UBound(l_Array) > 0) Then
l_Array(UBound(l_Array)) = ""
l_Path = Join(l_Array, IOPRIM_PATHSEPCHAR)
End If

ExtractFilePath = l_Path
End Function 'ExtractFilePath
IOPrim Files GetFileContents Basic   132 19
Function GetFileContents(ByRef pFileName As String) As String
'From Tools.GetRealFileContent
'Returns the content type of a document by extracting the content
'from the header of the document or an empty string if the content couldn't be determined.
'Returns a string describing the contents (see document appendix for values)

Dim l_URLName As String
Dim lo_Type As Object
Dim l_Content As String

l_Content = ""
l_URLName = ConvertToURL(pFileName)
If FileExists(l_URLName) Then
lo_Type = createUnoService("com.sun.star.document.TypeDetection")
l_Content = lo_Type.queryTypeByURL(l_URLName)
End If

GetFileContents = l_Content
End Function 'GetFileContents
IOPrim Files GetFileDateTimeModified Basic   152 23
Function GetFileDateTimeModified(ByRef pFileName As String) As Date
'Returns the date of the last modification for pFileName.
'Returns the date, or 0 if the operation couldn’t be executed.

Dim lo_Date As new com.sun.star.util.DateTime
Dim l_Date As Date
Dim l_URLName As String 'file name in URL form
Dim lo_SFA As Object 'the simple file access object

l_Date = 0
On Local Error GoTo ErrHandler:
l_URLName = ConvertToURL(pFileName)
If FileExists(l_URLName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
lo_Date = lo_SFA.getDateTimeModified(l_URLName)
l_Date = CDateFromUnoDateTime(lo_Date)
End If

ErrHandler:
'do nothing

GetFileDateTimeModified = l_Date
End Function 'GetFileDateTimeModified
IOPrim Files GetFileSize Basic   176 23
Function GetFileSize(ByRef pFileName As String) As Long
'Returns a file name size in bytes.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'Output: Returns the file size in bytes or -1 if an error was encountered.

Dim l_Size As Long
Dim l_URLName As String 'file name in URL form
Dim lo_SFA As Object 'the simple file access object

l_Size = -1
On Local Error Goto ErrHandler:
l_URLName = ConvertToURL(pFileName)
If FileExists(l_URLName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
l_Size = lo_SFA.getSize(l_URLName)
End If

ErrHandler:
'do nothing

GetFileSize = l_Size
End Function 'GetFileSize
IOPrim Files GetSafeDateTimeStr Basic   200 24
Function GetSafeDateTimeStr(ByRef pDate As Date, Optional pWithTime As Boolean) As String
'Returns a string representation of a date for use as part of a valid filename.
'Input:
'-- pDate: the date to be used.
'-- pWithTime: (optional) specifies if the result string has a time part or not. Defaults to True.
'Output: The string representation of the date/time, following the ISO masks:
'-- YYYYMMDD_HHmmSS (date and time),
'-- YYYYMMDD (date only; pWithTime is False).

Dim l_DateStr As String 'date part
Dim l_TimeStr As String 'time part

l_TimeStr = ""
If IsMissing(pWithTime) Then pWithTime = True

l_DateStr = CDateToISO(pDate) 'YYYYMMDD

If pWithTime Then
l_TimeStr = Format(pDate, "hhmmss")
l_TimeStr = IOPRIM_DATETIMESEPCHAR & l_TimeStr
End If

GetSafeDateTimeStr = l_DateStr & l_TimeStr
End Function 'GetSafeDateTimeStr
IOPrim Files IsHidden Basic   225 24
Function IsHidden(ByRef pFileName As String) As Boolean
'Checks whether a file is hidden or not.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'Output: Returns True if pFilename is hidden, otherwise False.
' If the file doesn’t exist, returns True.

Dim l_Hidden As Boolean
Dim l_URLName As String 'file name in URL form
Dim lo_SFA As Object 'the simple file access object

l_Hidden = True
On Local Error Goto ErrHandler:
l_URLName = ConvertToURL(pFileName)
If FileExists(l_URLName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
l_Hidden = lo_SFA.isHidden(l_URLName)
End If

ErrHandler:
'do nothing

IsHidden = l_Hidden
End Function 'IsHidden
IOPrim Files IsReadOnly Basic   250 24
Function IsReadOnly(ByRef pFileName As String) As Boolean
'Checks whether a file is read-only or not.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'Output: Returns True if pFilename is read-only, otherwise False.
' If the file doesn’t exist, returns True.

Dim l_RO As Boolean
Dim l_URLName As String 'file name in URL form
Dim lo_SFA As Object 'the simple file access object

l_RO = True
On Local Error Goto ErrHandler:
l_URLName = ConvertToURL(pFileName)
If FileExists(l_URLName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
l_RO = lo_SFA.isReadOnly(l_URLName)
End If

ErrHandler:
'do nothing

IsReadOnly = l_RO
End Function 'IsReadOnly
IOPrim Files JustFileName Basic   275 16
Function JustFileName(ByRef pFileName As String) As String
'Retrieves a filename without its access path nor its extension from a FQDN file name.
'Input:
'-- pFileName: the file name to be processed (in URL or OS form).
'Output: The file name without the path and extension parts.
'Note: this does not check for the file/path existence.
'See also ExtractFileName().

Dim l_FileName As String
Dim l_Array() As String

l_FileName = ExtractFileName(pFileName)
l_Array = Split(l_FileName, IOPRIM_EXTSEPCHAR)

JustFileName = l_Array(0)
End Function 'JustFileName
IOPrim Files NTFSFileNameString Basic   292 59
Function NTFSFileNameString(ByRef pFileName As String, Optional ByRef pExtended As Boolean) As String
'https://en.wikipedia.org/wiki/Filename
'Returns a NTFS compliant file name by stripping out some potentially problematic characters
'or names and replacing others with more secure chars.
'Input:
'-- pFileName: the original file name.
' Caution: The file name must be passed *without* the path part.
'-- pExtended: (optional) causes a more extended char set to be stripped out of the file name
' and accented chars are replaced with their non-accented counterparts.
' Defaults to False.
'Output: the transformed file name, if necessary.
'
'Details about the file naming checks:
'-- non-printable chars (Ascii < 32 decimal) are stripped out,
'-- spaces are replaced with '_' (underscores),
'-- accented chars are replaced with their unaccented counterparts,
'-- some characters are stripped out (see the NTFS_CHARSTRIP const below),
'-- optionally some more stripping is done for the additional NTFS_CHARSTRIPEX characters.
'-- if the file name starts with a system-reserved one (see the NTFS_CONFLICT const),
' an '_' is prepended to the file name in order to avoid any system conflict

Const NTFS_CHARSTRIP = """*/:<>?\|" 'basic set of char to strip out
Const NTFS_CHARSTRIPEX = "()[]{};,.!-+$'&#%–" 'complementary list
Const NTFS_CONFLICT = "AUX,CLOCK$,COM,CON,LPT,NUL,PRN,.,.." 'prohibited DOS file names

Dim l_Name As String 'the file name to be returned
Dim l_Str As String 'filename buffer
Dim l_Char As String
Dim l_CharStrip As String
Dim l_arrConflicts As Variant
Dim i As Long
Dim j As Long

If IsMissing(pExtended) Then pExtended = False

l_arrConflicts = Split(NTFS_CONFLICT, ",")
l_CharStrip = NTFS_CHARSTRIP
If pExtended Then
l_CharStrip = l_CharStrip & NTFS_CHARSTRIPEX
End If

'process ----------
'process conflicting names
For i = 0 To UBound(l_arrConflicts)
If (Left(l_Name, Len(l_arrConflicts(i))) = l_arrConflicts(i)) Then
l_Name = "_" & l_Name
End If
Next
'suppress non-printable chars
l_Name = FilterNonPrintableStr(pFileName)
'suppress accents
If pExtended Then l_Name = NoAccentStr(l_Name)
'replace spaces
l_Name = ReplaceStr(l_Name, " ", "_")
'process stripping
l_Name = StripChars(l_Name, l_CharStrip)

NTFSFileNameString = l_Name
End Function 'NTFSFileNameString
IOPrim Files SetHidden Basic   352 29
Function SetHidden(ByRef pFileName As String, pHide As Boolean) As Long
'Sets a pFileName as hidden or not, according to pHide.
'Returns 0 if the operation was executed, or an error code:
'-- file not found (ERR_IOPRIM_NOSUCHFILE),
'-- can’t set hidden flag (ERR_IOPRIM_FILEHIDE).

Dim l_Err As Long
Dim l_URLName As String 'file name in URL form
Dim lo_SFA As Object 'the simple file access object

On Local Error Goto IOERROR
l_Err = ERR_IOPRIM_NOERR
l_URLName = ConvertToURL(pFileName)
If FileExists(l_URLName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
lo_SFA.SetReadOnly(l_URLName, pHide)
Else
l_Err = ERR_IOPRIM_NOSUCHFILE
End If

IOERROR:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_FILEHIDE
Resume FEXIT
End If

FEXIT:
SetHidden = l_Err
End Function 'SetHidden
IOPrim Files SetReadOnly Basic   382 29
Function SetReadOnly(ByRef pFileName As String, pRO As Boolean) As Long
'Sets a pFileName as read-only or not, according to pRO.
'Returns 0 if the operation was executed, or an error code:
'-- file not found (ERR_IOPRIM_NOSUCHFILE),
'-- can’t set read-only flag (ERR_IOPRIM_FILEREADONLY).

Dim l_Err As Long
Dim l_URLName As String 'file name in URL form
Dim lo_SFA As Object 'the simple file access object

On Local Error Goto IOERROR
l_Err = ERR_IOPRIM_NOERR
l_URLName = ConvertToURL(pFileName)
If FileExists(l_URLName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
lo_SFA.SetReadOnly(l_URLName, pRO)
Else
l_Err = ERR_IOPRIM_NOSUCHFILE
End If

IOERROR:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_FILEREADONLY
Resume FEXIT
End If

FEXIT:
SetReadOnly = l_Err
End Function 'SetReadOnly
IOPrim Folders CheckPathStr Basic GetParentFolder (Procedure) 45 11
Function CheckPathStr(ByRef pPath As String) As String
'Checks that a path string terminates with a / (slash).
'Input:
'-- pPath: the path string to be checked.
'Output: The validated path string, with a / (slash) as last character.

Dim l_Path As String

l_Path = ConvertToURL(pPath)
CheckPathStr = ConvertFromURL(l_Path)
End Function 'CheckPathStr
IOPrim Folders CopyFolder Basic   57 45
Function CopyFolder(ByRef pSourceFolder As String, pTargetFolder As String) As Long
'Copies a folder into another.
'Input:
'-- pSourceFolder: the source folder.
'-- pTargetFolder: the target folder.
'If the target folder exists, the source folder is copied within the existent; if it doesn't exist, it is created.
'
'Note: pSourcefolder and pTargetFolder may be either in URL or OS form.
'
'Output: Returns 0 if the folder was copied, or the copy error:
'-- ERR_IOPRIM_NOSUCHFOLDER: source folder not found.
'-- ERR_IOPRIM_NOSPACE: can’t create target folder.
'-- ERR_IOPRIM_COPYTOSELF: can’t copy to same folder.
'-- ERR_IOPRIM_FOLDERCOPY: can’t copy folder.

Dim l_Err As Long
Dim l_SrcURL As String 'source folder in URL form
Dim l_TgtURL As String 'target folder in URL form
Dim lo_SFA as Object 'the simple file access object

l_Err = ERR_IOPRIM_NOERR
On Local Error Goto ErrHandler
If FolderExists(pSourceFolder) Then
If Not FolderExists(pTargetFolder) Then l_Err = CreateFolder(pTargetFolder)
If (l_Err = ERR_IOPRIM_NOERR) Then
l_SrcURL = ConvertToURL(pSourceFolder)
l_TgtURL = ConvertToURL(pTargetFolder)
If (l_SrcURL = l_TgtURL) Then
l_Err = ERR_IOPRIM_FOLDERTOSELF
Else
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
lo_SFA.copy(l_SrcURL, l_TgtURL)
End If
End If
Else
l_Err = ERR_IOPRIM_NOSUCHFOLDER
End If

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_FOLDERCOPY
End If

CopyFolder = l_Err
End Function 'CopyFolder
IOPrim Folders CreateFolder Basic CopyFolder (Procedure) 103 29
Function CreateFolder(ByRef pFolderName As String) As Long
'Creates a folder.
'Input
'-- pFolderName: the FQDN name of the folder to create (URL or OS form).
'Output: Returns ERR_IOPRIM_NOERR (0) if the folder was created, or the creation error:
'-- folder already exists (ERR_IOPRIM_FOLDEREXISTS),
'-- no space left on drive (ERR_IOPRIM_NOSPACE).

Dim l_FolderName As String
Dim l_Err As Long 'error code
Dim lo_SFA as Object 'the simple file access object

l_Err = ERR_IOPRIM_NOERR
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
On Local Error Goto ErrHandler
l_FolderName = ConvertToURL(pFolderName)
If Not lo_SFA.Exists(l_FolderName) Then
lo_SFA.CreateFolder(l_FolderName)
Else
l_Err = ERR_IOPRIM_FOLDEREXISTS
End If

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_NOSPACE
End If

CreateFolder = l_Err
End Function 'CreateFolder
IOPrim Folders DeleteFolder Basic   133 29
Function DeleteFolder(ByRef pFolderName As String) As Long
'Deletes a folder.
'Input:
'-- pFolderName: the FQDN name of the folder to delete (in URL or OS form).
'Output: Returns 0 if the folder was deleted, or the deletion error:
'-- ERR_IOPRIM_NOSUCHFOLDER: folder not found.
'-- ERR_IOPRIM_FOLDERDELETE: can’t delete folder.

Dim l_FolderName As String
Dim l_Err As Long 'error code
Dim lo_SFA as Object 'the simple file access object

l_Err = ERR_IOPRIM_NOERR
On Local Error Goto ErrHandler
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
l_FolderName = ConvertToURL(pFolderName)
If lo_SFA.Exists(l_FolderName) Then
lo_SFA.Kill(l_FolderName)
Else
l_Err = ERR_IOPRIM_NOSUCHFOLDER
End If

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_FOLDERDELETE
End If

DeleteFolder = l_Err
End Function 'DeleteFolder
IOPrim Folders FolderExists Basic CopyFolder (Procedure)
FolderIsEmpty (Procedure)
GetFolderContents (Procedure)
163 16
Function FolderExists(ByRef pFolderName As String) As Boolean
'Checks if a folder exists.
'Input:
'-- pFolderName: the FQDN name of the folder to check (in URL or OS form).
'Output: Returns True if the folder exists, otherwise False.

Dim l_Exists As Boolean 'existence flag
Dim lo_SFA as Object 'the simple file access object

l_Exists = False
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
On Local Error Resume Next
l_Exists = lo_SFA.Exists(ConvertToURL(pFolderName))

FolderExists = l_Exists
End Function 'FolderExists
IOPrim Folders FolderIsEmpty Basic   180 21
Function FolderIsEmpty(ByRef pFolderName As String) As Boolean
'Checks if a folder is empty.
'Input:
'-- pFolderName: the FQDN name of the folder to check (in URL or OS form).
'Output: Returns True if the folder is empty, otherwise False.

Dim l_IsEmpty As Boolean 'emptyness flag
Dim l_Array() As String 'folder contents (one-dimension array of strings: each string is a full folder/file name)
Dim l_FolderName As String
Dim lo_SFA as Object 'the simple file access object

l_IsEmpty = False
l_FolderName = ConvertToURL(pFolderName)
If FolderExists(l_FolderName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
l_Array() = lo_SFA.getFolderContents(l_FolderName, True)
l_IsEmpty = ArrayIsEmpty(l_Array())
End If

FolderIsEmpty = l_IsEmpty
End Function 'FolderIsEmpty
IOPrim Folders GetFolderContents Basic   202 60
Function GetFolderContents(ByRef pFolderName As String, pFilter As Byte, pContents As Variant) As Long
'Returns a folder contents names as a one-dimension string array.
'Input:
'-- pFolderName: the FQDN name of the folder to be scanned (in URL or OS form),
'-- pFilter: the output filter (all/files only/folders only) (See the IOPRIM_FOLDERFILTER_XXX constants)
'-- pContents: the array to be filled with the file and folder names (strings).
' The file names are in URL form.
'Output:
'Returns 0 if the folder contents was listed, or the access error:
'-- folder not found (ERR_IOPRIM_NOSUCHFOLDER),
'-- can’t list folder contents (ERR_IOPRIM_FOLDERLIST).

Dim l_Err As Long
Dim l_FolderName As String
Dim lo_SFA as Object 'the simple file access object
Dim l_Array As Variant 'the result as an array
Dim l_Result As String 'the result as a string
Dim l_FileName As String 'the current file name
Dim l_IsFolder As Boolean 'folder flag

l_Err = ERR_IOPRIM_NOERR

On Local Error Goto ErrHandler
l_FolderName = ConvertToURL(pFolderName)
If FolderExists(l_FolderName) Then
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
l_Array = lo_SFA.getFolderContents(l_FolderName, True)

Select Case pFilter

Case IOPRIM_FOLDERFILTER_FOLDERSONLY, IOPRIM_FOLDERFILTER_FILESONLY
If (UBound(l_Array) > -1) Then
l_Result = ""
For i = 0 To UBound(l_Array)
l_FileName = l_Array(i)
l_IsFolder = lo_SFA.isFolder(l_FileName)
If (l_IsFolder And (pFilter = IOPRIM_FOLDERFILTER_FOLDERSONLY)) _
Or (Not l_IsFolder And (pFilter = IOPRIM_FOLDERFILTER_FILESONLY)) Then
l_Result = l_Result & l_FileName & Chr(13)
End If
Next i
pContents = Split(l_Result, Chr(13))
End If

Case IOPRIM_FOLDERFILTER_ALL
pContents = l_Array

End Select
Else
'error: folder doesn't exist
l_Err = ERR_IOPRIM_NOSUCHFOLDER
End If

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_FOLDERLIST
End If

GetFolderContents = l_Err
End Function 'GetFolderContents
IOPrim Folders GetParentFolder Basic   263 18
Function GetParentFolder(ByRef pFolderName As String) As String
'Returns the parent of a given folder.
'Input:
'-- pFolderName: the FQDN name of the folder to process.
' pFolderName may be either in URL or OS form.
'Output: The name of the parent of pFolderName or a zero-length string if an error occurred.
'
'Note: this does not check for the child path existence.

Dim l_Folder As String
Dim l_Array() As String

l_Folder = ExtractFilePath(CheckPathStr(pFolderName))
l_Array = Split(pFolder, IOPRIM_PATHSEPCHAR)
l_Array(UBound(l_Array)) = ""

GetParentFolder = Join(l_Array, IOPRIM_PATHSEPCHAR)
End Function 'GetParentFolder
IOPrim Folders IsFolder Basic   282 15
Function IsFolder(ByRef pName As String) As Boolean
'Returns True if pName is a folder name, otherwise False.

Dim l_IsFolder As Boolean
Dim l_Name As String
Dim lo_SFA as Object 'the simple file access object

l_IsFolder = False
On Local Error Resume Next
l_Name = ConvertToURL(pName)
lo_SFA = createUnoService(IOPRIM_SERV_SFA)
l_IsFolder = lo_SFA.isFolder(l_Name)

IsFolder = l_IsFolder
End Function 'IsFolder
IOPrim Folders IsSubFolder Basic   298 15
Function IsSubFolder(ByRef pParentName As String, pChildName As String) As Boolean
'Returns True is pChildName is a child of pParentName, otherwise False.
'This function does NOT check if either folder exists.

Dim l_IsChild As Boolean
Dim l_Parent As String
Dim l_Child As String

l_IsChild = False
l_Parent = ConvertToURL(pParentName)
l_Child = ConvertToURL(pChildName)
l_IsChild = (InStr(l_Child, l_Parent) > 0)

IsSubFolder = l_IsChild
End Function 'IsSubFolder
IOPrim Log _WriteToLog Basic LogIt (Procedure) 250 6
Sub _WriteToLog(ByRef pMsg As String)
'(internal)

Print #g_LogFileH, pMsg

End Sub '_WriteToLog
IOPrim Log CloseLog Basic   76 23
Function CloseLog() As Long
'Closes the log file.
'Returns 0 if successful, otherwise an error code:
'-- Can't close (ERR_IOPRIM_LOGCANTCLOSE)

Dim l_Err As Long 'error code

l_Err = ERR_IOPRIMLOGNONE

On Local Error GoTo ErrHandler
If g_LogOpen Then
Close #g_LogFileH
g_LogOpen = False
g_LogEnabled = False
End If

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_LOGCANTCLOSE
End If

CloseLog = l_Err
End Function 'CloseLog
IOPrim Log DisableLogging Basic   100 6
Sub DisableLogging()
'disables the logging without closing the log file.

LogIt("Logging disabled")
g_LogEnabled = False
End Sub 'DisableLogging
IOPrim Log EnableLogging Basic   107 6
Sub EnableLogging()
'Enables logging. No disabled logging will take place until this sub is called.

g_LogEnabled = True
LogIt("Logging enabled")
End Sub 'EnableLogging
IOPrim Log LogError Basic   114 6
Function LogError(ByRef pMsg As String) As Long
'logs an error message
'Acts as a facade to LogIt()

LogError = LogIt(pMsg, IOPRIM_LOGERROR)
End Function 'LogError
IOPrim Log LogInfo Basic   121 6
Function LogInfo(ByRef pMsg As String) As Long
'logs an information message
'Acts as a facade to LogIt()

LogInfo = LogIt(pMsg, IOPRIM_LOGINFO)
End Function 'LogInfo
IOPrim Log LogIt Basic DisableLogging (Procedure)
EnableLogging (Procedure)
LogError (Procedure)
LogInfo (Procedure)
128 69
Function LogIt(ByRef pMsg As String, Optional pType As Integer) As Long
'Writes pMsg to the log file, with an optional pType flag.
'The values for pType are integers in (see constants above):
'-- 0 : IOPRIM_LOGUNK (unknown message type)
'-- 1 : IOPRIM_LOGERROR (error message)
'-- 2 : IOPRIM_LOGINFO (information message)
'All output to the log file is timestamped.
'pType defaults to 0 (unknown message type).
'
'Output line structure:
'20160325 153412 [ERR ] File not found
'^^^^^^^^ ^^^^^^ ^^^^^^ ^^^
'date time type message...
'
'The log message is written only if the logging is not suspended.
'Returns 0 if successful, otherwise an error code:
'-- logging is suspended (ERR_IOPRIM_LOGSUSPENDED)
'-- log file is closed (ERR_IOPRIM_LOGFILECLOSED)
'-- can't write to log file (ERR_IOPRIM_LOGCANTWRITE)

Dim l_Err As Long 'error code
Dim l_Type As Integer
Dim l_Prefix As String 'log prefix, according to the line type
Dim l_Msg As String 'the message to be logged

On Local Error GoTo ErrHandler
l_Err = ERR_IOPRIMLOGNONE

l_Err = OpenLog()
If (l_Err <> ERR_IOPRIMLOGNONE) Then
LogIt = l_Err
Exit Function
End If

If g_LogEnabled Then
'set l_Type value
If IsMissing(pType) Then
l_Type = IOPRIM_LOGUNK
Else
l_Type = pType
End If

'create the log message
l_Msg = CStr(Now) & IOPRIM_LOGSEP
Select Case l_Type

Case IOPRIM_LOGUNK : l_Msg = l_Msg & pMsg

Case IOPRIM_LOGERROR : l_Msg = l_Msg & "[" & IOPRIM_LOGERRORSTR & "]" & IOPRIM_LOGSEP & pMsg

Case IOPRIM_LOGINFO : l_Msg = l_Msg & "[" & IOPRIM_LOGINFOSTR & "]" & IOPRIM_LOGSEP & pMsg

Case Else l_Msg = l_Msg & pMsg

End Select

'output the message to the log file
_WriteToLog(l_Msg)
Else
l_Err = ERR_IOPRIM_LOGSUSPENDED
End If

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_LOGCANTWRITE
End If

LogIt = l_Err
End Function 'LogIt
IOPrim Log OpenLog Basic LogIt (Procedure) 198 35
Function OpenLog() As Long
'Opens a log file (path and name in global vars).
'If g_LogOverwrite is True, the log file replaces any previous log file with the same name,
'otherwise the log is appended to the existing log file.
'Returns 0 if successfully opened, otherwise an error code:
'-- Undefined settings (ERR_IOPRIM_LOGSET)
'-- Can’t open the log file (ERR_IOPRIM_LOGCANTOPEN).

Dim l_Err As Long 'output error code

l_Err = ERR_IOPRIMLOGNONE
If g_LogOpen Then
OpenLog = l_Err
Exit Function
End If

If Not g_LogSet Then
l_Err = ERR_IOPRIM_LOGSET
Else
On Local Error GoTo ErrHandler
If g_LogOverwrite Then
Open g_LogFilename For Output As #g_LogFileH
Else
Open g_LogFilename For Append As #g_LogFileH
End If
g_LogOpen = True
End If

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_LOGCANTOPEN
End If

OpenLog = l_Err
End Function 'OpenLog
IOPrim Log SetLogging Basic   234 15
Sub SetLogging(ByRef pLogFileName As String, Optional pOvw As Boolean)
'Sets the logging context: file name and overwrite mode

If IsMissing(pOvw) Then
g_LogOverwrite = False
Else
g_LogOverwrite = pOvw
End If

g_LogFileName = ConvertToURL(pLogName)
g_LogFileH = FreeFile

g_LogSet = True

End Sub 'SetLogging
IOPrim Streams CloseTextStream Basic   45 27
Function CloseTextStream(ByRef pStream As Object) As Long
'Closes a text stream.
'Returns 0 if the operation was executed, or an error code:
'-- stream is NULL (),
'-- pStream doesn't support any stream service (),
'-- Can’t close the stream ().

Dim l_Err As Long

l_Err = ERR_IOPRIM_NOERR
If IsNull(pStream) Then
'l_Err = ERR_IO
Else
If pStream.supportsService("com.sun.star.io.TextInputStream") Then
pStream.closeInput
ElseIf pStream.supportsService("com.sun.star.io.TextOutputStream") Then
pStream.closeOutput
ElseIf pStream.supportsService("com.sun.star.io.Stream") Then
pStream.closeInput
pStream.closeOutput
Else
'l_Err =
End If
End If

CloseStream = l_Err
End Function 'CloseStream
IOPrim Streams LoadTextStreamAsString Basic   73 32
Function LoadTextStreamAsString(ByRef pFileName As String, pEncoding As String) As String
'Reads a text file and returns it as a string, using the API services.
'Input:
'-- pFileName: the file name (FQDN, in URL or OS mode)
'-- pEncoding: the text file contents encoding, as a string (defaults to UTF-8 when not specified).
'For a complete encodings list, see https://www.iana.org/assignments/character-sets/character-sets.xhtml ('name' column).
'Output: the text file as a string.
'
'note: line separators (Ascii 10 and/or Ascii 13) are part of the returned string.

Dim l_FileURL As String
Dim l_Str As String 'the stream to return
Dim lo_SFA As Object 'the simple file access object
Dim lo_TextStream As Object 'the stream reading object
Dim lo_Stream As Object 'the stream that connects the SFA and the text stream

l_FileURL = ConvertToURL(pFileName)
lo_SFA = createUnoService("com.sun.star.ucb.SimpleFileAccess")
If lo_SFA.exists(l_FileURL) Then
lo_Stream = lo_SFA.openFileRead(l_FileURL)
lo_TextStream = createUnoService("com.sun.star.io.TextInputStream")
lo_TextStream.InputStream = lo_Stream
If (Trim(pEncoding) <> "") Then
lo_TextStream.Encoding = pEncoding
End If
l_Str = lo_TextStream.readString(Array(), False)
lo_TextStream.closeInput
lo_Stream.closeInput
End If

LoadTextStreamAsString = l_Str
End Function 'LoadTextStreamAsString
IOPrim Streams LoadTextStreamAsVector Basic   106 44
Function LoadTextStreamAsVector(ByRef pFileName As String, pEncoding As String) As Variant
'Reads a text file and returns it as a 1D array (vector) of strings.
'Input:
'-- pFileName: the file name (FQDN, in URL or OS mode)
'-- pEncoding: the text file contents encoding, as a string (defaults to UTF-8 when not specified).
'For a complete encodings list, see https://www.iana.org/assignments/character-sets/character-sets.xhtml ('name' column).
'Output: the text file as a string vector.

Dim l_Array As Variant 'the output array
Dim l_FileURL As String
Dim l_Str As String 'the stream to return
Dim lo_SFA As Object 'the simple file access object
Dim lo_TextStream As Object 'the stream reading object
Dim lo_Stream As Object 'the stream that connects the SFA and the text stream

l_FileURL = ConvertToURL(pFileName)
lo_SFA = createUnoService("com.sun.star.ucb.SimpleFileAccess")
If lo_SFA.exists(l_FileURL) Then
'init stream
lo_Stream = lo_SFA.openFileRead(l_FileURL)
lo_TextStream = createUnoService("com.sun.star.io.TextInputStream")
lo_TextStream.InputStream = lo_Stream
If (Trim(pEncoding) <> "") Then
lo_TextStream.Encoding = pEncoding
End If
'read, adding a specific line separator
l_Str = ""
Do While not lo_TextStream.isEOF()
l_Line = lo_TextStream.readLine()
If (l_Str = "") Then
l_Str = l_Line
Else
l_Str = l_Str & Chr(10) & l_Line
End If
Loop
'get the array
l_Array = Split(l_Str, Chr(10))
'end
lo_TextStream.closeInput
lo_Stream.closeInput
End If

LoadTextStreamAsVector = l_Array
End Function 'LoadTextStreamAsVector
IOPrim Streams OpenStream Basic   151 51
Function OpenStream(ByRef pFileName As String, pMode As Long) As Object
'Opens a pFileName (text stream) using pMode.
'Returns the stream object if the operation was executed, or NULL if an error was encountered.
'pMode values are:
'-- 1: Read (IOPRIM_READMODE)
'-- 2: Write (IOPRIM_WRITEMODE)
'-- 8: Read/Write (IOPRIM_APPENDMODE)

Dim lo_Stream As Object
Dim lo_Text As Object 'the text stream
Dim lo_SFA As Object 'the simple file access object
Dim l_URLName As String 'file name in URL form

On Local Error Goto IOERROR
'lo_Stream = Null
l_URLName = ConvertToURL(pFileName)
lo_SFA = createUnoService(IOPRIM_SERV_SFA)

Select Case pMode

Case IOPRIM_READMODE
'If FileExists(l_URLName) Then
lo_Stream = lo_SFA.openFileRead(l_URLName)
lo_Text = createUNOService ("com.sun.star.io.TextInputStream")
lo_Text.setInputStream(lo_Stream)
'End If

Case IOPRIM_WRITEMODE
lo_Stream = lo_SFA.openFileWrite(l_URLName)
lo_Text = createUNOService ("com.sun.star.io.TextOutputStream")
lo_Text.setOutputStream(lo_Stream)

Case IOPRIM_APPENDMODE
'If FileExists(l_URLName) Then
lo_Stream = lo_SFA.openFileReadWrite(l_URLName)
lo_Text = createUNOService ("com.sun.star.io.Stream")
lo_Text.setOutputStream(lo_Stream)
lo_Text.setInputStream(lo_Stream)
'End If

End Select

IOERROR:
If (Err <> 0) Then
lo_Text = Null
Resume FEXIT
End If

FEXIT:
OpenStream = lo_Text
End Function 'OpenStream
IOPrim Streams ReadTextStreamAsString Basic   203 2
Function ReadTextStreamAsString(ByRef pStream As Object, pString As String) As String
End Function 'ReadTextStreamAsString
IOPrim Streams StoreToStream Basic   206 2
Function StoreToStream(ByRef pStream As Object, pStr As String) As Long
End Function 'StoreToStream
IOPrim Streams WriteTextToStream Basic   209 2
Function WriteTextToStream(ByRef pStream As Object, pString As String) As Long
End Function 'WriteTextToStream
IOPrim TextFiles CloseTextFile Basic LoadTextFileAsString (Procedure) 43 18
Function CloseTextFile(ByRef pHFile As Integer) As Long
'Closes a given handle to a text file.
'Returns 0 if the file handle was closed, otherwise an error value:
' -- Can't close (ERR_IOPRIM_CANTCLOSETEXT).

Dim l_Err As Long

On Local Error Goto ErrHandler
l_Err = ERR_IOPRIM_NOERR
Close #pHFile

ErrHandler:
If (Err <> 0) Then
l_Err = ERR_IOPRIM_CANTCLOSETEXT
End If

CloseTextFile = l_Err
End Function 'CloseTextFile
IOPrim TextFiles LoadTextFileAsString Basic LoadTextFileAsVector (Procedure) 62 33
Function LoadTextFileAsString(ByRef pFileName As String, pLineSep As String) As String
'Reads a text file and returns it as a string.
'Input:
'-- pFileName: the file name (FQDN, in URL or OS mode)
'-- pLineSep: the line separators to add after each line read (except the last one).
'Output: the text file as a string.
'
'note: line separators are part of the returned string.

Dim l_FileURL As String
Dim l_Str As String
Dim l_Line As String
Dim l_Handle As Integer

l_FileURL = ConvertToURL(pFileName)
If FileExists(l_FileURL) Then
l_Str = ""
l_Handle = OpenTextFile(l_FileURL)
If (l_Handle > 0) Then
Do While Not Eof(l_Handle)
Line Input #l_Handle, l_Line
If (l_Str = "") Then
l_Str = l_Line
Else
l_Str = l_Str & pLineSep & l_Line
End If
Loop
CloseTextFile(l_Handle)
End If
End If

LoadTextFileAsString = l_Str
End Function 'LoadTextFileAsString
IOPrim TextFiles LoadTextFileAsVector Basic   96 14
Function LoadTextFileAsVector(ByRef pFileName As String) As Variant
'Reads a text file and returns it as a 1D array (vector) of strings.
'Input:
'-- pFileName: the file name (FQDN, in URL or OS mode)
'Output: the text file as a string vector.

Dim l_Str As String
Dim l_Array As Variant

l_Str = LoadTextFileAsString(pFileName, Chr(10))
l_Array = Split(l_Str, Chr(10))

LoadTextFileAsVector = l_Array
End Function 'LoadTextFileAsVector
IOPrim TextFiles OpenTextFile Basic LoadTextFileAsString (Procedure) 111 39
Function OpenTextFile(ByRef pFileName As String, Optional pMode As Integer) As Integer
'Opens a text file named pFileName under a specified mode.
'Returns the file handle (integer value, > 0)
'If an error occurred, returns 0.
'pMode defaults to IOPRIM_READMODE (other values: see IOPrim.Globals).

Dim l_URLName As String
Dim l_FileH As Integer 'file handle

l_FileH = 0
If IsMissing(pMode) Then pMode = IOPRIM_READMODE

On Local Error Goto ErrHandler
l_URLName = ConvertToURL(pFileName)
Select Case pMode

Case IOPRIM_READMODE
If FileExists(l_URLName) Then
l_FileH = FreeFile
Open pFilename For Input As #l_FileH
End If

Case IOPRIM_WRITEMODE
l_FileH = FreeFile
Open pFilename For Output As #l_FileH

Case IOPRIM_APPENDMODE
If FileExists(l_URLName) Then
l_FileH = FreeFile
Open pFilename For Append As #l_FileH
End If

End Select

ErrHandler:
'do nothing

OpenTextFile = l_FileH
End Function 'OpenTextFile
IOPrim TextFiles ReadTextAsString Basic   151 25
Function ReadTextAsString(ByRef pHFile As Integer, pLineSep As String) As String
'Reads a text file and returns it as a string.
'Input:
'-- pHFile: the file handler
'-- pLineSep: the line separators to add after each line read (except the last one).
'Output: the text file as a string.
'
'Note: line separators are part of the returned string.

Dim l_Str As String
Dim l_Line As String

If (pHFile > 0) Then
Do While Not Eof(pHFile)
Line Input #pHFile, l_Line
If (l_Str = "") Then
l_Str = l_Line
Else
l_Str = l_Str & pLineSep & l_Line
End If
Loop
End If

ReadTextAsString = l_Str
End Function 'ReadTextAsString
IOPrim TextFiles ReadTextAsVector Basic   177 14
Function ReadTextAsVector(ByRef pHFile As Integer) As Variant
'Reads a text file and returns it as a 1D array (vector) of strings.
'Input:
'-- pHFile: the file handler
'Output: the text file as a string vector.

Dim l_Str As String
Dim l_Array As Variant

l_Str = ReadTextFileAsString(pFileName, Chr(10))
l_Array = Split(l_Str, Chr(10))

ReadTextAsVector = l_Array
End Function 'ReadTextAsVector
IOPrim TextFiles ReadTextLine Basic   192 3
Function ReadTextLine(ByRef pHFile As Integer) As String
'TBD
End Function 'ReadTextLine
IOPrim TextFiles StoreFromArray Basic   196 3
Function StoreFromArray() As Long
'TBD
End Function 'StoreFromArray
IOPrim TextFiles StoreFromString Basic   200 3
Function StoreFromString() As Long
'TBD
End Function 'StoreFromString
IOPrim TextFiles WriteText Basic   204 3
Function WriteText() As Long
'TBD
End Function 'WriteText
LibOPrim App _GetPropertyValueByName Basic   45 21
Function _GetPropertyValueByName(ByRef pItems, pName As String) As Variant
'returns a property value from the property name
'input:
'-- pItems: the properties array
'-- pName : the property name for which we want the value
'output:
'the property value found (variant) or Null if not found
'
'adapted from hanya in https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=56336

Dim l_Value As Variant
Dim i As Long

l_Value = Nothing
For i = 0 To UBound(pItems)
If (pItems(i).Name = pName) Then
l_Value = pItems(i).Value
End If
Next
_GetPropertyValueByName = l_Value
End Function '_GetPropertyValueByName
LibOPrim App _UNOCommand Basic SetFullScreen (Procedure)
ShowNavigator (Procedure)
ShowPrinterDialog (Procedure)
ShowPrintPreview (Procedure)
ShowDocumentProperties (Procedure)
ShowSidebar (Procedure)
67 20
Sub _UNOCommand(ByRef pUnoCmd As String, Optional pArgs() As Variant)
'runs any UNO menu command, in pUnoCmd.
'The optional pArgs() allows to add command arguments.
'There is no control on the command passed.
'
'The common menu commands are available in the menubar.xml file, available in
'LibreOffice install directory, subdir /share/config/soffice.cfg/modules/sglobal/menubar

Dim lo_Frame As Variant
Dim lo_Dispatch As Object
Dim l_Args() As Variant

If Not IsMissing(pArgs) Then l_Args() = pArgs()

lo_Frame = ThisComponent.CurrentController.Frame
lo_Dispatch = createUnoService(LOPRIM_SERV_DISPATCH)

lo_Dispatch.executeDispatch(lo_Frame, ".uno:" & pUnoCmd, "", 0, l_Args())

End Sub '_UNOCommand
LibOPrim App SetFullScreen Basic   88 17
Sub SetFullScreen(Optional ByRef pShowToolbar As Boolean)
'Sets the current window to full screen.
'The optional pShowToolbar allows to simultaneously hide the FullScreen toolbar that displays when in full screen mode.
'Defaults to True (the FullScreen toolbar is left on-screen).

Dim l_Show As Boolean

If IsMissing(pShowToolbar) Then
l_Show = True
Else
l_Show = pShowToolbar
End If

_UNOCommand("FullScreen")
If Not l_Show Then HideToolbar(LOPRIM_TB_FULLSCREEN)

End Sub 'SetFullScreen
LibOPrim App ShowDocumentProperties Basic   132 6
Sub ShowDocumentProperties()
'Calls the LibO document properties dialog

_UNOCommand("SetDocumentProperties")

End Sub 'ShowDocumentProperties
LibOPrim App ShowNavigator Basic   106 11
Sub ShowNavigator(ByRef pShow As Boolean)
'toggles the Navigator display

Dim l_Args(0) As New com.sun.star.beans.PropertyValue

l_Args(0).Name = "Navigator"
l_Args(0).Value = pShow

_UNOCommand("Navigator", l_Args())

End Sub 'ShowNavigator
LibOPrim App ShowPrinterDialog Basic   118 6
Sub ShowPrinterDialog()
'Calls the LibO document printer dialog

_UNOCommand("Print")

End Sub 'ShowPrinterDialog
LibOPrim App ShowPrintPreview Basic   125 6
Sub ShowPrintPreview()
'Calls the LibO print preview dialog

_UNOCommand("PrintPreview")

End Sub 'ShowPrintPreview
LibOPrim App ShowSidebar Basic   139 11
Sub ShowSidebar(ByRef pShow As Boolean)
'Toggles the LibO sidebar display

Dim l_Args(0) As New com.sun.star.beans.PropertyValue

l_Args(0).Name = "Sidebar"
l_Args(0).Value = pShow

_UNOCommand("Sidebar", l_Args())

End Sub 'ShowSideBar
LibOPrim CustomProperties _CreateCustomProperty_Test Basic   121 41
Sub _CreateCustomProperty_Test()

Dim l_Err As Long
Dim l_Props As Variant
Dim lo_UnoDate As New com.sun.star.util.Date
Dim lo_UnoDateTime As New com.sun.star.util.DateTime
Dim lo_UnoDuration As New com.sun.star.util.Duration

'string
l_Props = Array("TestString", "some text")
l_Err = CreateCustomProperty(l_Props)
Print l_Err

'number (float)
l_Err = CreateCustomProperty(Array("TestDouble", 1.25))
Print l_Err

'number (integer)
Print CreateCustomProperty(Array("TestInteger", 987))

'boolean
Print CreateCustomProperty(Array("TestBoolean", True))

'date
Print CreateCustomProperty(Array("TestDate", Date()))

'uno date
lo_UnoDate = CDateToUNODate(Date())
Print CreateCustomProperty(Array("TestUNODate", lo_UnoDate))

'uno datetime
lo_UnoDateTime = CDateToUNODateTime(Now())
Print CreateCustomProperty(Array("TestUNODateTime", lo_UnoDateTime))

'duration
With lo_UnoDuration
.Hours = 10
End With
Print CreateCustomProperty(Array("TestUNODuration", lo_UnoDuration))

End Sub '_CreateCustomProperty_Test
LibOPrim CustomProperties _CustomPropertiesToArray_Test Basic   221 7
Sub _CustomPropertiesToArray_Test()

Dim l_Array As Variant

l_Array = CustomPropertiesToArray()

End sub '_CustomPropertiesToArray_Test
LibOPrim CustomProperties _CustomPropertyExists_Test Basic   182 6
Sub _CustomPropertyExists_Test()

Print CustomPropertyExists("TestProperty")
Print CustomPropertyExists("Author")

End Sub '_CustomPropertyExists
LibOPrim CustomProperties _CustomPropertyType_Test Basic   269 3
Sub _CustomPropertyType_Test()
'TBD
End Sub '_CustomPropertyType_Test
LibOPrim CustomProperties _DeleteAllCustomProperties_Test Basic   290 3
Sub _DeleteAllCustomProperties_Test()
'TBD
End Sub '_DeleteAllCustomProperties_Test
LibOPrim CustomProperties _DeleteCustomProperty_Test Basic   330 3
Sub _DeleteCustomProperty_Test()

End Sub '_DeleteCustomProperty_Test
LibOPrim CustomProperties _GetCustomProperty_Test Basic   349 7
Sub _GetCustomProperty_Test()

Dim lo_Obj As Object

lo_Obj = GetCustomProperty("Author")

End Sub '_GetCustomProperty_Test
LibOPrim CustomProperties _GetCustomPropertyValue_Test Basic   378 8
Sub _GetCustomPropertyValue_Test()

Dim l_Value As Variant

l_Value = GetCustomPropertyValue("Author")
Print l_Value

End Sub '_GetCustomPropertyValue_Test
LibOPrim CustomProperties _SetCustomPropertyValue_Test Basic   422 5
Sub _SetCustomPropertyValue_Test()

Print SetCustomPropertyValue("TestProperty", "Test value")

End Sub '_SetCustomPropertyValue_Test
LibOPrim CustomProperties CreateCustomProperty Basic _CreateCustomProperty_Test (Procedure) 64 56
Function CreateCustomProperty(ByRef pArrProps As Variant, Optional ByRef pDoc As Object) As Long
'Adds a custom property to a document.
'Input:
'-- pArrProps: the property defines as an array of two items (0: property name ; 1: property value).
' The actual value type defines the property type.
'-- pDoc: (optional) the document in which the property should be added.
' Defaults to the current document.
'Output: An error code or ERR_CPROP_OK (0) if correctly executed.
'Possible error codes:
'-- ERR_CPROP_NORUN: the process did not run
'-- ERR_CPROP_NAME: illegal property name
'-- ERR_CPROP_EXISTS: the property name already exists
'-- ERR_CPROP_CREATE: the property could not be created.
'-- ERR_CPROP_TYPE: the provided type is not supported
'-- a system error code

Dim l_Result As Long 'error status
Dim l_Type As Integer
Dim lo_CProps As Object 'custom properties list

l_Result = ERR_CPROP_NORUN

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CProps = pDoc.DocumentProperties.UserDefinedProperties
If (Trim(pArrProps(0)) = "") Then
l_Result = ERR_CPROP_NAME
ElseIf lo_CProps.PropertySetInfo.hasPropertyByName(pArrProps(0)) Then
l_Result = ERR_CPROP_EXISTS
Else
'try to add the property according to its data type
l_Type = CustomPropertyType(pArrProps(1))
On Local Error GoTo ErrHandler:
Select Case l_Type
Case CPROP_TYPE_STRING, CPROP_TYPE_YESNO, CPROP_TYPE_UNODATE, CPROP_TYPE_UNODATETIME, CPROP_TYPE_UNODURATION
lo_CProps.addProperty(pArrProps(0), com.sun.star.beans.PropertyAttribute.REMOVEABLE, pArrProps(1))
l_Result = ERR_CPROP_OK

Case CPROP_TYPE_DATE
lo_CProps.addProperty(pArrProps(0), com.sun.star.beans.PropertyAttribute.REMOVEABLE, CDateToUnoDate(pArrProps(1)))
l_Result = ERR_CPROP_OK

Case CPROP_TYPE_NUMBER
lo_CProps.addProperty(pArrProps(0), com.sun.star.beans.PropertyAttribute.REMOVEABLE, CreateUnoValue("double", pArrProps(1)))
l_Result = ERR_CPROP_OK

Case Else
l_Result = ERR_CPROP_TYPE
End Select
End If

ErrHandler:
'do nothing

CreateCustomProperty = l_Result
End Function 'CreateCustomProperty
LibOPrim CustomProperties CustomPropertiesToArray Basic _CustomPropertiesToArray_Test (Procedure) 189 31
Function CustomPropertiesToArray(Optional ByRef pDoc As Object) As Variant
'Returns a document custom properties as an array.
'Input:
'-- pDoc: (optional) the document to analyze.
' Defaults to the current document.
'Output: a 2-D array containing the properties names (0), values (1) and types (2)
'The type references one of the CPROP_TYPE_Xxxx constants.

Dim l_Array As Variant 'output array result
Dim lo_arrProps As Variant 'custom properties values array
Dim lo_CProp As Object 'a custom property
Dim i As Long

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_arrProps = pDoc.DocumentProperties.UserDefinedProperties.PropertyValues

i = UBound(lo_arrProps)
ReDim l_Array(i, 2)

i = 0
For Each lo_CProp in lo_arrProps
l_Array(i, 0) = lo_CProp.Name
l_Array(i, 1) = lo_CProp.Value
l_Array(i, 2) = CustomPropertyType(lo_CProp.Value)

i = i + 1
Next

CustomPropertiesToArray = l_Array
End Function 'CustomPropertiesToArray
LibOPrim CustomProperties CustomPropertyExists Basic _CustomPropertyExists_Test (Procedure) 163 18
Function CustomPropertyExists(ByRef pName As String, Optional ByRef pDoc As Object) As Boolean
'Checks whether a given custom property exists.
'Input:
'-- pName: the property name
'-- pDoc: (optional) the document in which the property should be checked.
' Defaults to the current document.
'Output: True if the custom property pName exists, False otherwise.

Dim lo_CProps As Object 'custom properties list
Dim l_Exists As Boolean

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CProps = pDoc.DocumentProperties.UserDefinedProperties
l_Exists = lo_CProps.PropertySetInfo.hasPropertyByName(pName)

CustomPropertyExists = l_Exists
End Function 'CustomPropertyExists
LibOPrim CustomProperties CustomPropertyType Basic CreateCustomProperty (Procedure)
CustomPropertiesToArray (Procedure)
229 39
Function CustomPropertyType(ByRef pValue As Variant) As Integer
'Returns a custom property value type.
'Input:
'-- pValue: the value to check.
'Output: the type of pValue. The type values is one of the CPROP_TYPE_Xxx constants.
'If the type is none of the ones supported by custom properties, returns CPROP_TYPE_UNK.

Dim l_Type As Integer

l_Type = CPROP_TYPE_UNK

If (VarType(pValue) = V_STRING) Then
'string property
l_Type = CPROP_TYPE_STRING
ElseIf IsNumeric(pValue) Then
'numeric property
l_Type = CPROP_TYPE_NUMBER
ElseIf (VarType(pValue) = V_DATE) Then
'date property
l_Type = CPROP_TYPE_DATE
ElseIf (VarType(pValue) = 11) Then
'boolean property
l_Type = CPROP_TYPE_YESNO
ElseIf (VarType(pValue) = 9) Then
'object property
If ImplementsUNOstruct(pValue, "com.sun.star.util.Date") Then
'date property
l_Type = CPROP_TYPE_UNODATE
ElseIf ImplementsUNOstruct(pValue, "com.sun.star.util.DateTime") Then
'date-time property
l_Type = CPROP_TYPE_UNODATETIME
ElseIf ImplementsUNOstruct(pValue, "com.sun.star.util.Duration") Then
'duration property
l_Type = CPROP_TYPE_UNODURATION
End If
End If

CustomPropertyType = l_Type
End Function 'CustomPropertyType
LibOPrim CustomProperties DeleteAllCustomProperties Basic   273 16
Sub DeleteAllCustomProperties(Optional ByRef pDoc As Object)
'Removes all custom properties from a document.
'Input:
'-- pDoc: (optional) the document from which the properties must be deleted.
' Defaults to the current document.

Dim lo_CProps As Object 'custom properties list
Dim lo_CProp As Object 'a custom property

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CProps = pDoc.DocumentProperties.UserDefinedProperties
For Each lo_CProp In lo_CProps
lo_CProps.removeProperty(lo_CProp.Name)
Next
End Sub 'DeleteAllCustomProperties
LibOPrim CustomProperties DeleteCustomProperty Basic   294 35
Function DeleteCustomProperty(ByRef pName As String, Optional ByRef pDoc As Object) As Long
'Suppresses a custom property from a document.
'Input:
'-- pName: the property name to suppress.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: An error code or ERR_CPROP_OK (0) if executed
'Possible error codes
'-- ERR_CPROP_NORUN: the process did not run
'-- ERR_CPROP_NOTFOUND: the property was not found for this document
'-- other Basic runtime errors

Dim lo_CProps As Object 'custom properties
Dim l_Result As Long

l_Result = ERR_CPROP_NORUN

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CProps = pDoc.DocumentProperties.UserDefinedProperties
If lo_CProps.PropertySetInfo.hasPropertyByName(pName) Then
'try to delete the property
On Local Error GoTo ErrHandler:
lo_CProps.removeProperty(pName)
l_Result = ERR_CPROP_OK
Else
'error: property not found
l_Result = ERR_CPROP_NOTFOUND
End If

ErrHandler:
If Err Then l_Result = Err

DeleteCustomProperty = l_Result
End Function 'DeleteCustomProperty
LibOPrim CustomProperties GetCustomProperty Basic _GetCustomProperty_Test (Procedure) 334 14
Function GetCustomProperty(ByRef pName As String, Optional ByRef pDoc As Object) As Object

Dim lo_CProps As Object 'custom properties
Dim lo_CProp As Object 'a custom property

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CProps = pDoc.DocumentProperties.UserDefinedProperties
If lo_CProps.PropertySetInfo.hasPropertyByName(pName) Then
lo_CProp = lo_CProps.PropertySetInfo.getPropertyByName(pName)
End If

GetCustomProperty = lo_CProp
End Function 'GetCustomProperty
LibOPrim CustomProperties GetCustomPropertyValue Basic _GetCustomPropertyValue_Test (Procedure) 357 20
Function GetCustomPropertyValue(ByRef pName As String, Optional ByRef pDoc As Object) As Variant
'Retrieves a given property value.
'Input:
'-- pName: the property name to query.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: the property value or Null if not found.

Dim lo_CProps As Object 'custom properties
Dim l_Value As Variant

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CProps = pDoc.DocumentProperties.UserDefinedProperties
If lo_CProps.PropertySetInfo.hasPropertyByName(pName) Then
l_Value = lo_CProps.getPropertyValue(pName)
End If

GetCustomPropertyValue = l_Value
End Function 'GetCustomPropertyValue
LibOPrim CustomProperties SetCustomPropertyValue Basic _SetCustomPropertyValue_Test (Procedure) 387 34
Function SetCustomPropertyValue(ByRef pName As String, ByRef pValue As Variant, Optional ByRef pDoc As Object) As Long
'Sets a custom property value.
'Input:
'-- pName: the property name.
'-- pValue: the property value to set.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: An error code or ERR_CPROP_OK (0) if executed correctly.
'Possible error codes
'-- ERR_CPROP_NORUN: the process did not run
'-- ERR_CPROP_NOTFOUND: the property was not found for this document
'-- other Basic runtime errors

Dim lo_CProps As Object 'custom properties
Dim l_Result As Long

l_Result = ERR_CPROP_NORUN

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CProps = pDoc.DocumentProperties.UserDefinedProperties
If lo_CProps.PropertySetInfo.hasPropertyByName(pName) Then
On Local Error GoTo ErrHandler:
lo_CProps.setPropertyValue(pName, pValue)
l_Result = ERR_CPROP_OK
Else
l_Result = ERR_CPROP_NOTFOUND
End If

ErrHandler:
If Err Then l_Result = Err

SetCustomPropertyValue = l_Result
End Function 'SetCustomPropertyValue
LibOPrim Document CreateDocument Basic   52 45
Function CreateDocument(ByRef pType As Long, pHidden As Boolean, pReadOnly As Boolean) As Object
'Creates a new LibreOffice document and returns the corresponding object.
'This proposes the most common options when opening a LibreOffice document. For more advanced uses, call OpenDocumentEx(). [TBD]
'Input:
'-- pHidden: the document should be loaded as hidden.
'-- pReadOnly: the document should be loaded as read-only.
'Output: the document object or Null if the document couldn't be created.
'
'See also: OpenDocument() and OpenDocumentEx()

Dim l_TypeStr As String
Dim lo_Doc As Object 'the object document to be returned
Dim l_Props(1) As New com.sun.star.beans.PropertyValue

l_Props(0).Name = "Hidden"
l_Props(0).Value = pHidden
l_Props(1).Name = "ReadOnly"
l_Props(1).Value = pReadOnly

Select Case pType
Case LOPRIM_DOCTYPECALC
l_TypeStr = "private:factory/scalc"

Case LOPRIM_DOCTYPEWRITER
l_TypeStr = "private:factory/swriter"

Case LOPRIM_DOCTYPEIMPRESS
l_TypeStr = "private:factory/simpress"

Case LOPRIM_DOCTYPEDRAW
l_TypeStr = "private:factory/sdraw"

Case LOPRIM_DOCTYPEMATH
l_TypeStr = "private:factory/smath"

Case Else
'do nothing
End Select

If (l_TypeStr <> "") Then
lo_Doc = StarDesktop.loadComponentFromURL(l_TypeStr, "_blank", 0, l_Props())
End If

CreateDocument = lo_Doc
End Function 'CreateDocument
LibOPrim Document DocumentProtectionFlag Basic   98 47
Function DocumentProtectionFlag(ByRef pDoc As String) As Integer
'Checks whether a given LibreOffice document is protected and returns a value describing this status.
'This test is based upon the fact that a LibO protected document zip structure
'doesn't contain the usual 'Thumbnails' directory.
'
'Input:
'-- pDoc: the document name (FQDN) in URL or OS form.
' This document is supposed to exist.
'Output: 1 if the document is protected in any way, 0 if the document is not protected
' or -1 if an error occurred (eg: the document is not a LibO one/not in zip format)

Const ZIP_DIR_ROOT = ""
Const ZIP_DIR_THUMBNAILS = "Thumbnails"

Dim l_Flag As Integer
Dim lo_Package As Object 'the zip document container
Dim l_Arg As New com.sun.star.beans.NamedValue

l_Flag = -1 'default value: unknown/error

On Local Error Goto ErrHandler:
lo_Package = createUnoService("com.sun.star.packages.Package")

'open the document zip container
l_Arg.Name = "PackageFormat"
l_Arg.Value = False 'plain Zip format
lo_Package.initialize(Array(ConvertToURL(pDoc)), l_Arg)

'check for "Thumbnails" directory
'Checking for root first allows to ignore non-zip containers
If lo_Package.hasByHierarchicalName(ZIP_DIR_ROOT) Then
If lo_Package.hasByHierarchicalName(ZIP_DIR_THUMBNAILS) Then
l_Flag = 0 'not protected
Else
l_Flag = 1 'protected
End If
End If

'close zip container
lo_Package = Nothing

ErrHandler:
'do nothing
'We get here either because everything went OK or because the .initialize went wrong.

DocumentProtectionFlag = l_Flag
End Function 'DocumentProtectionFlag
LibOPrim Document GetCurrentDirectory Basic   146 22
Function GetCurrentDirectory(Optional pDoc As Object) As String
'Returns the current document directory name (URL notation).
'Input:
'-- pDoc: (optional) the document to look at. If omitted, looks at the current document.
'Output: The directory the document is in.
' The trailing "/" is part of the returned string.

Dim l_Dir As String 'the directory we're looking for
Dim l_Array() As String

l_Dir = ""
If IsMissing(pDoc) Then pDoc = ThisComponent
If pDoc.hasLocation Then
l_Array = Split(pDoc.Location, IOPRIM_PATHSEPCHAR)
If (UBound(l_Array) > 0) Then
l_Array(UBound(l_Array)) = ""
l_Dir = Join(l_Array, IOPRIM_PATHSEPCHAR)
End If
End If

GetCurrentDirectory = l_Dir
End Function 'GetCurrentDirectory
LibOPrim Document GetLibODocType Basic IsBaseDocument (Procedure)
IsCalcDocument (Procedure)
IsDrawDocument (Procedure)
IsImpressDocument (Procedure)
IsMathDocument (Procedure)
IsWriterDocument (Procedure)
169 41
Function GetLibODocType(Optional ByRef pDoc As Object) As Long
'Returns the LibreOffice document type.
'Input:
'-- pDoc: (optional) the document to look at. If omitted, looks at the current document.
'Output:
'The document type or an error value
'-- Type possible values: see the LOPRIM_DOCTYPE above.
'-- Error: the result may also be the ERR_LOPRIM_DOCTYPE error when the pDoc document is not set.

Dim lo_Doc As Object 'the document to examine
Dim l_Type As Long 'the type (or error) to be returned

l_Type = ERR_LOPRIM_DOCTYPE

If IsMissing(pDoc) Then
lo_Doc = ThisComponent
Else
lo_Doc = pDoc
End If

If Not IsNull(lo_Doc) Then
If lo_Doc.SupportsService("com.sun.star.sheet.SpreadsheetDocument") Then
l_Type = LOPRIM_DOCTYPECALC
ElseIf lo_Doc.SupportsService("com.sun.star.text.TextDocument") Then
l_Type = LOPRIM_DOCTYPEWRITER
ElseIf lo_Doc.SupportsService("com.sun.star.drawing.DrawingDocument") Then
l_Type = LOPRIM_DOCTYPEDRAW
ElseIf lo_Doc.SupportsService("com.sun.star.presentation.PresentationDocuments") Then
l_Type = LOPRIM_DOCTYPEIMPRESS
ElseIf lo_Doc.SupportsService("com.sun.star.formula.FormulaProperties") Then
l_Type = LOPRIM_DOCTYPEMATH
ElseIf lo_Doc.SupportsService("com.sun.star.sdb.OfficeDatabaseDocument") Then
l_Type = LOPRIM_DOCTYPEBASE
Else
'unknown type
l_Type = LOPRIM_DOCTYPEUNK
End If
End If

GetLibODocType = l_Type
End Function 'GetLibODocType
LibOPrim Document IsBaseDocument Basic   211 8
Function IsBaseDocument(Optional ByRef pDoc As Object) As Boolean
'Returns True if pDoc is a Base document, otherwise False. If omitted, looks at the current document.
'Note that if an error code is returned by GetLibODocType, it returns False as well.

If IsMissing(pDoc) Then pDoc = ThisComponent
IsBaseDocument = (GetLibODocType(pDoc) = LOPRIM_DOCTYPEBASE)

End Function 'IsBaseDocument
LibOPrim Document IsCalcDocument Basic   220 8
Function IsCalcDocument(Optional ByRef pDoc As Object) As Boolean
'Returns True if pDoc is a Calc document, otherwise False. If omitted, looks at the current document.
'Note that if an error code is returned by GetLibODocType, it returns False as well.

If IsMissing(pDoc) Then pDoc = ThisComponent
IsCalcDocument = (GetLibODocType(pDoc) = LOPRIM_DOCTYPECALC)

End Function 'IsCalcDocument
LibOPrim Document IsDrawDocument Basic   229 8
Function IsDrawDocument(Optional ByRef pDoc As Object) As Boolean
'Returns True if pDoc is a Draw document, otherwise False. If omitted, looks at the current document.
'Note that if an error code is returned by GetLibODocType, it returns False as well.

If IsMissing(pDoc) Then pDoc = ThisComponent
IsDrawDocument = (GetLibODocType(pDoc) = LOPRIM_DOCTYPEDRAW)

End Function 'IsDrawDocument
LibOPrim Document IsImpressDocument Basic   238 8
Function IsImpressDocument(Optional ByRef pDoc As Object) As Boolean
'Returns True if pDoc is an Impress document, otherwise False. If omitted, looks at the current document.
'Note that if an error code is returned by GetLibODocType, it returns False as well.

If IsMissing(pDoc) Then pDoc = ThisComponent
IsImpressDocument = (GetLibODocType(pDoc) = LOPRIM_DOCTYPEIMPRESS)

End Function 'IsImpressDocument
LibOPrim Document IsMathDocument Basic   247 8
Function IsMathDocument(Optional ByRef pDoc As Object) As Boolean
'Returns True if pDoc is a Math document, otherwise False. If omitted, looks at the current document.
'Note that if an error code is returned by GetLibODocType, it returns False as well.

If IsMissing(pDoc) Then pDoc = ThisComponent
IsMathDocument = (GetLibODocType(pDoc) = LOPRIM_DOCTYPEMATH)

End Function 'IsMathDocument
LibOPrim Document IsWriterDocument Basic   256 8
Function IsWriterDocument(Optional ByRef pDoc As Object) As Boolean
'Returns True if pDoc is a Writer document, otherwise False. If omitted, looks at the current document.
'Note that if an error code is returned by GetLibODocType, it returns False as well.

If IsMissing(pDoc) Then pDoc = ThisComponent
IsWriterDocument = (GetLibODocType(pDoc) = LOPRIM_DOCTYPEWRITER)

End Function 'IsWriterDocument
LibOPrim Document ModuleIdentifierStr Basic   265 18
Function ModuleIdentifierStr(Optional ByRef pDoc As Object) As String
'returns the libreoffice module identifier for a given document.
'Input:
'-- pDoc: (optional) the document which module to get.
' Defaults to the current document
'Output: the document module identifier.
'EG: for a text document (Writer module), returns "com.sun.star.text.TextDocument"

Dim l_Str As String
Dim lo_ModuleMgr As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_ModuleMgr = createUnoService("com.sun.star.frame.ModuleManager")
l_Str = lo_ModuleMgr.identify(pDoc)

ModuleIdentifierStr = l_Str
End Function 'ModuleIdentifierStr
LibOPrim Document OpenDocument Basic   284 28
Function OpenDocument(ByRef pFileName As String, pHidden As Boolean, pReadOnly As Boolean, pAsTemplate As Boolean) As Object
'Opens an existing LibreOffice document and returns the corresponding object.
'This proposes the most common options when opening a LibreOffice document. For more advanced uses, call OpenDocumentEx(). [TBD]
'Input:
'-- pFileName: The FQDN name of the document name (in URL or OS form).
' no check is accomplished against the document existence.
'-- pHidden: the document should be loaded as hidden.
'-- pReadOnly: the document should be loaded as read-only.
'-- pAsTemplate: a new document is created, using pFilename as a template.
'Output: the created document object or Null if the document couldn't be opened.
'
'See also: OpenDocumentEx() and CreateDocument()

Dim lo_Doc As Object 'the object document to be returned
Dim l_Props(2) As New com.sun.star.beans.PropertyValue

l_Props(0).Name = "Hidden"
l_Props(0).Value = pHidden
l_Props(1).Name = "ReadOnly"
l_Props(1).Value = pReadOnly
l_Props(2).Name = "AsTemplate"
l_Props(2).Value = pAsTemplate

On Local Error Resume Next
lo_Doc = StarDesktop.loadComponentFromURL(ConvertToURL(pFileName), "_blank", 0, l_Props())

OpenDocument = lo_Doc
End Function 'OpenDocument
LibOPrim Document OpenDocumentCopy Basic   313 34
Function OpenDocumentCopy(ByRef pTgtFileName As String, Optional pHidden As Boolean, Optional ByRef pSrcDoc) As Object
'Opens a copy of a document and returns the document object.
'Input:
'-- pTgtFileName: the document copy file name (in URL or OS form).
'-- pHidden: (optional) defines whether the copy should be made visible or not.
' Defaults to False.
'-- pSrcDoc: (optional) the source document.
' Defaults to the current document.
'Output: returns the document copy object or Null if it couldn't be copied/opened.
'
'Process: the source document is stored as a copy as defined by pTgtFileName then it is opened, hidden or not.

Dim l_FileName As String
Dim l_Props(0) As New com.sun.star.beans.PropertyValue
Dim lo_Doc As Object

If IsMissing(pHidden) Then pHidden = False
If IsMissing(pSrcDoc) Then pSrcDoc = ThisComponent

l_FileName = ConvertToURL(pTgtFileName)

On Local Error Goto ErrHandler
pSrcDoc.storeToURL(l_FileName, Array())

'open the copy (hidden or not)
l_Props(0).Name = "Hidden"
l_Props(0).Value = pHidden
lo_Doc = StarDesktop.loadComponentFromURL(l_TgtFileName, "_blank", 0, l_Props())

ErrHandler:
'do nothing

OpenDocumentCopy = lo_Doc
End Function 'OpenDocumentCopy
LibOPrim Document OpenDocumentEx Basic   348 17
Function OpenDocumentEx(ByRef pFileName As String, pOptions As Variant) As Object
'TBD
'*Hidden
'Password
'*ReadOnly
'Version
'MacroExecutionMode
'UpdateDocMode
'InteractionHandler
'*AsTemplate
'SuggestedSaveAsDir
'SuggestedSaveAsName
'FilterName
'FilterData

OpenDocumentEx = Null
End Function 'OpenDocumentEx
LibOPrim Extensions ExtensionDir Basic   43 20
Function ExtensionDir(ByRef pExtID As String) As String
'Get the extension directory for the extension unique id pExtID.
'eg: ExtensionDir("com.roland65.texmaths")
'input:
'-- pExtID: the unique ID for the extension
'output:
'-- the full directory name (in URL form) in which the extension has been installed
' or an empty string if pExtID is unknown

Dim l_Str As String
Dim lo_ExtInfo as Object

lo_ExtInfo = GetDefaultContext.getByName(LOPRIM_PACKAGEINFOSING)
If Not IsNull(lo_ExtInfo) Then
l_Str = lo_ExtInfo.getPackageLocation(pExtID)
End If
If (l_Str <> "") Then l_Str = l_Str & "/"

ExtensionDir = l_Str
End Function 'ExtensionDir
LibOPrim Graphics GetGraphicFromResource Basic   43 19
Function GetGraphicFromResource(ByRef pGraphicName As String, Optional ByRef pDoc As Object) As Object
'retrieves a graphic object from a document resources.
'Input:
'-- pDoc: the document with the resource
'-- pGraphicName: the name we had set to the resource.
'Output: the graphic object or Null if not found.

Dim lo_Bitmaps As Object
Dim lo_Graphic As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Bitmaps = pDoc.createInstance("com.sun.star.drawing.BitmapTable")
If lo_Bitmaps.hasByName(pGraphicName) Then
lo_Graphic = GetImage(lo_Bitmaps.getByName(pGraphicName))
End If

GetGraphicFromResource = lo_Graphic
End Function 'GetGraphicFromResource
LibOPrim Graphics GetImage Basic GetGraphicFromResource (Procedure) 63 19
Function GetImage(ByRef pFileName As String) As Variant
'retrieves an image object
'Input:
'-- pFileName: the image file name in URL or OS format.
'Output: the image object or Null if not found.

Dim lo_GP 'graphic provider
Dim lo_Graphic As Object
Dim l_aArg As New com.sun.star.beans.PropertyValue

lo_GP = createUnoService("com.sun.star.graphic.GraphicProvider")
l_aArg.Name = "URL"
l_aArg.Value = ConvertToURL(pFileName)

On Local Error Resume Next
lo_Graphic = lo_GP.queryGraphic(Array(l_aArg))

GetImage = lo_Graphic
End Function 'GetImage
LibOPrim Graphics GetImageManager Basic   83 22
Function GetImageManager(Optional ByRef pDoc As Object) As Object
'Returns the ImageManager for the current LibreOffice Module (Writer, Base, etc.).
'Input:
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'
'Adapted from librebel in https://ask.libreoffice.org/en/question/111748/how-to-change-toolbar-icon-back-to-text/

Dim lo_ModuleMgr As Object
Dim l_DocType As String
Dim lo_ModuleCfgMgrSupplier As Object
Dim lo_ModuleCfgMgr As Object

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_ModuleMgr = createUnoService("com.sun.star.frame.ModuleManager")
l_DocType = lo_ModuleMgr.identify(pDoc)
lo_ModuleCfgMgrSupplier = createUnoService("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")
lo_ModuleCfgMgr = lo_ModuleCfgMgrSupplier.getUIConfigurationManager(l_DocType)

GetImageManager = lo_ModuleCfgMgr.ImageManager
End Function 'GetImageManager
LibOPrim Graphics SetImageURL Basic   106 26
Function SetImageURL(ByRef strImageURL As String, ByRef strImageObjectName As String)
'This changes the graphic of a named image <strImageObjectName> to the specified <strImageURL>.
'For example if you inserted an Image called "Image 1" into your sheet, then you can set its graphic by calling:
' setImageURL("/home/user/Pictures/my_picture.jpg", "Image 1")
'Or as a Calc formula (if A1 contains the file path): =SETIMAGEURL(A1;"Image 1")
'
'adapted from code by Librebel in https://ask.libreoffice.org/en/question/144390/populate-a-output-sheet-txtimg/

Dim lo_DrawPage as Object
Dim lo_Obj As Object
Dim i As Integer

On Local Error Resume Next
lo_DrawPage = ThisComponent.getDrawPages().getByIndex(0)
'oDrawPage = ThisComponent.DrawPage REM for Base, Writer'
For i = 0 To lo_DrawPage.Count - 1
lo_Obj = lo_DrawPage.getByIndex(i)
If lo_Obj.Name = strImageObjectName Then REM Found.
If lo_Obj.getShapeType() = "com.sun.star.drawing.GraphicObjectShape" Then
lo_Obj.GraphicURL = ConvertToURL(strImageURL)
Exit For
End If
End If
Next i

End Function 'SetImageURL
LibOPrim SpecialFiles CalcShareFileName Basic IsCalcDocumentShared (Procedure) 54 28
Function CalcShareFileName(Optional ByRef pDoc As Object) As String
'Returns the Calc share file name for a given document
'Input:
'-- pDoc: (optional) the document which share file name to retrieve.
' Defaults to the current document.
'Output: the share file name or a zero-lenght string if the document object has not been saved yet.
'A Calc share file name form is: .~sharing.TheFileName.ods#
'
'Note: because of its URL form, the final '#' character must be returned as an Ascii hex value, prefixed with a '%', that is '%23'.
'Dependencies: IOPrim.Files, IOPrim.TextFiles, StringPrim.Strings

Const SHARE_MASK = ".~sharing.%FILENAME%%23" '# = Ascii 23 hex

Dim l_FullName As String 'the return name
Dim l_FileName As String 'the file name only
Dim l_PathName As String 'the path name only

If IsMissing(pDoc) Then pDoc = ThisComponent

If (Trim(pDoc.Location) <> "") Then
l_PathName = ExtractFilePath(pDoc.Location)
l_FileName = ExtractFileName(pDoc.Location)
l_FileName = ReplaceStr(SHARE_MASK, "%FILENAME%", l_FileName)
l_FullName = l_PathName & l_FileName
End If

CalcShareFileName = l_FullName
End Function 'CalcShareFileName
LibOPrim SpecialFiles GetLibreOfficeSpecialFileData Basic   83 35
Function GetLibreOfficeSpecialFileData(ByRef pSpecialFileName As String) As Variant
'Returns an array containing the LibreOffice special file's users information.
'The LibO special files are lock files and (Calc only) share files.
'Input:
'-- pSpecialFileName: the special file name which data to retrieve.
'Output: the data in a nested array or Null if the specified file name doesn't exist.
'
'Output array format
'One line per user, nesting a 5 column array:
'0: her/his user name (see LibreOffice identity settings)
'1: the OS user name (name & workstation name)
'2: the OS user name (only)
'3: the date/time the user opened the shared document.
'4: the LibreOffice user profile directory.
'
'Dependencies: IOPrim.Files, IOPrim.TextFiles, StringPrim.Strings

Const SEP = "," 'users' details separator

Dim l_Array As Variant 'the output array
Dim l_TmpArray As Variant 'a temporary array
Dim l_TmpSize As Integer
Dim i As Long

If FileExists(pSpecialFileName) Then
l_TmpArray = ReadTextFileAsVector(pSpecialFileName, "")
l_TmpSize = UBound(l_TmpArray)
ReDim l_Array(l_TmpSize)
For i = 0 To UBound(l_TmpSize)
l_Array(i) = Split(l_TmpArray(i), SEP)
Next i
End If

GetLibreOfficeSpecialFileData = l_Array
End Function 'GetLibreOfficeSpecialFileData
LibOPrim SpecialFiles IsCalcDocumentShared Basic   119 21
Function IsCalcDocumentShared(Optional ByRef pDoc As Object) As Boolean
'checks whether a calc document is used in share mode or not.
'Input:
'-- pDoc: (optional) the document to check.
' Defaults to the current document.
'Output: True if the document is in calc shared mode, False otherwise.

Dim l_FullName As String
Dim l_Shared As Boolean

l_Shared = False

If IsMissing(pDoc) Then pDoc = ThisComponent

l_FullName = CalcShareFileName(pDoc)
If (l_FullName <> "") Then
l_Shared = FileExists(l_FullName)
End If

IsCalcDocumentShared = l_Shared
End Function 'IsCalcDocumentShared
LibOPrim SpecialFiles LockFileName Basic   141 28
Function LockFileName(Optional ByRef pDoc As Object) As String
'Returns the lock file name for a given document
'Input:
'-- pDoc: (optional) the document which lock file name to retrieve.
' Defaults to the current document.
'Output: the lock file name or a zero-lenght string if the document object has not been saved yet.
'A lock file name form is: .~lock.TheFileName.ods#
'
'Note: because of its URL form, the final '#' character must be returned as an Ascii hex value, prefixed with a '%', that is '%23'.
'Dependencies: IOPrim.Files, IOPrim.TextFiles, StringPrim.Strings

Const LOCK_MASK = ".~lock.%FILENAME%%23" '# = Ascii 23 hex

Dim l_FullName As String 'the return name
Dim l_FileName As String 'the file name only
Dim l_PathName As String 'the path name only

If IsMissing(pDoc) Then pDoc = ThisComponent

If (Trim(pDoc.Location) <> "") Then
l_PathName = ExtractFilePath(pDoc.Location)
l_FileName = ExtractFileName(pDoc.Location)
l_FileName = ReplaceStr(LOCK_MASK, "%FILENAME%", l_FileName)
l_FullName = l_PathName & l_FileName
End If

LockFileName = l_FullName
End function 'LockFileName
LibOPrim System CreateProperty Basic   56 18
Function CreateProperty(ByRef Optional pName as String, ByRef Optional pValue as Variant) As com.sun.star.beans.PropertyValue
'creates a property value structure
'(from TexMath extension)
'input:
'-- pName : the name of the property
'-- pValue: the property value
'Either argument is optional.
'output:
'-- the name/value pair structure

Dim lo_PropertyValue As Variant 'the key/value structure

lo_PropertyValue = createUnoStruct(LOPRIM_PROPERTYVALUE)
If Not IsMissing(pName) Then lo_PropertyValue.Name = pName
If Not IsMissing(pValue) Then lo_PropertyValue.Value = pValue

CreateProperty = lo_PropertyValue
End Function 'CreateProperty
LibOPrim System ExpandMacro Basic   75 19
Function ExpandMacro(ByRef pMacro As String) As String
'Expands a macro. That is, replaces any macroprocessor string with its actual counterpart.
'EG (under Linux): "$UNO_USER_PACKAGES_CACHE" -> "file:///home/<user>/.config/libreoffice/4/user/uno_packages/cache"
' (where <user> is the actual session/username)
'input:
'-- pMacro: the macro-ified string to be expanded.
'output:
'-- Returns the string associated with the macro-ified string.
' The input string may contain any macro part.
' If pMacro doesn't contain any macro string, returns the input string.

Dim lo_Context as Object
Dim lo_MacroExpander as Object

lo_Context = getProcessServiceManager().DefaultContext
lo_MacroExpander = lo_Context.getValueByName(LOPRIM_THEEXPANDER)

ExpandMacro = lo_MacroExpander.ExpandMacros(pMacro)
End Function 'ExpandMacro
LibOPrim System GetRegKeyContent Basic   95 48
Function GetRegKeyContent(ByRef pKeyName As String, pMode As Long, Optional pLang As String) As Object
'Returns a configuration registry key contents.
'input
'-- pKeyName: the key name to read or write
'-- pMode: a combination of read (LOPRIM_CONFIGREAD) or write mode (LOPRIM_CONFIGWRITE)
' and-ed with user (LOPRIM_CONFIGUSER) or administrative access (LOPRIM_CONFIGADMIN)
'-- pLang: the language string (optional)
'output
'-- the configuration object or nil if not found.
'
'Use: myObject = GetRegKeyContent("MyKey", LOPRIM_CONFIGREAD + LOPRIM_CONFIGUSER, "FR")

Dim lo_ConfigProvider As Object 'the configuration provider that creates the output instance
Dim l_AccessMode As String 'the access mode string
Dim l_ProvName As String 'the provider name
Dim l_Args(2) As New com.sun.star.beans.PropertyValue

l_Args(0).Name = "nodepath"
l_Args(0).Value = keyName
l_Args(1).Name = "enableasync"
l_Args(1).Value = False

'get the provider name
l_ProvName = ""
If ((pMode And LOPRIM_CONFIGUSER) = LOPRIM_CONFIGUSER) Then
l_ProvName = LOPRIM_REGUSERPROV
ElseIf ((pMode And LOPRIM_CONFIGADMIN) = LOPRIM_CONFIGADMIN) Then
l_ProvName = LOPRIM_REGADMINPROV
End If

'get the access mode (defaults to 'read')
l_AccessMode = LOPRIM_REGREAD
If ((pMode And LOPRIM_CONFIGWRITE) = LOPRIM_CONFIGWRITE) Then
l_AccessMode = LOPRIM_REGWRITE
End If

'get the language (if any)
If Not IsMissing(pLang) Then
If (Len(pLang) > 0) Then
l_Args(2).Name = "Locale"
l_Args(2).Value = pLang
End If
End If

On Local Error Resume Next
lo_ConfigProvider = CreateUnoService(l_ProvName)
GetRegKeyContent = lo_ConfigProvider.createInstanceWithArguments(l_AccessMode, l_Args())
End Function 'GetRegKeyContent
LibOPrim Toolbars _GetPropertyValueByName Basic GetToolbarResName (Procedure) 68 21
Function _GetPropertyValueByName(ByRef pItems, pName As String) As Variant
'returns a property value from the property name
'input:
'-- pItems: the properties array
'-- pName : the property name for which we want the value
'output:
'the property value found (variant) or Null if not found
'
'adapted from hanya in https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=56336

Dim l_Value As Variant
Dim i As Long

l_Value = Nothing
For i = 0 To UBound(pItems)
If (pItems(i).Name = pName) Then
l_Value = pItems(i).Value
End If
Next
_GetPropertyValueByName = l_Value
End Function '_GetPropertyValueByName
LibOPrim Toolbars _ToolbarCommand Basic DeleteToolbar (Procedure)
DisplayToolbar (Procedure)
HideToolbar (Procedure)
ToolbarVisible (Procedure)
90 64
Function _ToolbarCommand(ByRef pToolbarName As String, pAction As String, pDoc As Object) As Long
'Runs a given action command against a given toolbar (see the LOPRIM_TBCMD_XXX constants)
'
'Note that the toolbar name can be either the UI name (document toolbars) or the internal ressource name (LibO own bars).
'
'Returns a status or error code:
'-- ERR_TBAR_NONE: no error.
'-- ERR_TBAR_UNKNOWN: the specified toolbar is unknown
'-- ERR_TBAR_DEL: the specified toolbar can't be deleted (applies to LibO toolbars)
'-- ERR_LOPRIM_CMDUNK: the action command is unknown
'-- ERR_TBAR_HIDDEN: (status) the specified toolbar is hidden
'-- ERR_TBAR_VISIBLE: (status) the specified toolbar is visible

Dim lo_Frame As Object 'the document frame
Dim lo_LOMgr As Object 'the document layout manager
Dim l_res As String 'the toolbar ressource name
Dim l_Err As Long 'the return error code

l_Err = ERR_TBAR_NONE

lo_Frame = pDoc.CurrentController.Frame
lo_LOMgr = lo_Frame.LayoutManager
If (InStr(pToolbarName, LOPRIM_TB_ROOT) > 0) Then
l_res = pToolbarName
Else
l_res = GetToolbarResName(pToolBarName, pDoc)
End If

If IsNull(lo_LOMgr.getElement(l_res)) Then
l_Err = ERR_TBAR_UNKNOWN
Else
Select Case pAction
'is visible?'
Case LOPRIM_TBCMD_VIS
If lo_LOMgr.isElementVisible(l_res) Then
l_Err = ERR_TBAR_VISIBLE
Else
l_Err = ERR_TBAR_HIDDEN
End If

'display/view
Case LOPRIM_TBCMD_VIEW
lo_LOMgr.showElement(l_res)

'hide
Case LOPRIM_TBCMD_HIDE
lo_LOMgr.hideElement(l_res)

'delete
Case LOPRIM_TBCMD_DEL
If (Instr(l_res, "custom_toolbar") > 0) Then
lo_LOMgr.destroyElement(l_res)
Else
l_Err = ERR_TBAR_DEL
End If

'unknown command
Case Else
l_Err = ERR_LOPRIM_CMDUNK
End Select
End If

_ToolbarCommand = l_Err
End Function '_ToolbarCommand
LibOPrim Toolbars CustomToolbarsToArray Basic   155 28
Function CustomToolbarsToArray(Optional ByRef pDoc As Object) As Variant
'Returns an array that holds data about all custom toolbars within a document.
'Input:
'-- pDoc: (optional) the document to explore.
' Defaults to the current document.
'Ouput: The returned array is a 2-dimension structure: array(toolbar count, 2)
'
'Adapted from Loopingss, in
'https://forum.openoffice.org/fr/forum/viewtopic.php?f=15&t=27370

Dim lo_CustomTB As Object 'toolbars data
Dim lo_aTB As Object 'a toolbar information
Dim l_arrTB() As Variant 'the array to be returned
Dim i As Long

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_CustomTB = pDoc.getUIConfigurationManager.getUIElementsInfo(com.sun.star.ui.UIElementType.TOOLBAR)
ReDim l_arrTB(UBound(lo_CustomTB), 2) As Variant
i = 0
For Each lo_aTB In lo_CustomTB
l_arrTB(i, 0) = lo_aTB(0).Value
l_arrTB(i, 1) = lo_aTB(1).Value
i = i + 1
Next

CustomToolbarsToArray = l_arrTB()
End Function 'CustomToolbarsToArray
LibOPrim Toolbars DeleteToolbar Basic   184 13
Function DeleteToolbar(ByRef pToolbarName As String, Optional ByRef pDoc As Object) As Long
'Deletes a given toolbar.
'input:
'-- pToolbarName: the toolbar name (specify either UI name or resource name)
'-- pDoc: the document (defaults to ThisComponent)
'output: an error code
'-- ERR_TBAR_NONE: no error.
'-- ERR_TBAR_UNKNOWN: the specified toolbar is unknown

If IsMissing(pDoc) Then pDoc = ThisComponent

DeleteToolbar = _ToolbarCommand(pToolbarName, LOPRIM_TBCMD_DEL, pDoc)
End Function 'DeleteToolbar
LibOPrim Toolbars DisplayToolbar Basic   198 14
Function DisplayToolbar(ByRef pToolbarName As String, Optional ByRef pDoc As Object) As Long
'Shows a given toolbar.
'input:
'-- pToolbarName: the toolbar name (specify either UI name or resource name)
'-- pDoc: the document (defaults to ThisComponent)
'output: an error code
'-- ERR_TBAR_NONE: no error.
'-- ERR_TBAR_UNKNOWN: the specified toolbar is unknown
'-- ERR_TBAR_DEL: the specified toolbar can't be deleted (LibO toolbars)

If IsMissing(pDoc) Then pDoc = ThisComponent

DisplayToolbar = _ToolbarCommand(pToolbarName, LOPRIM_TBCMD_VIEW, pDoc)
End Function 'DisplayToolbar
LibOPrim Toolbars GetToolbarResName Basic _ToolbarCommand (Procedure) 213 30
Function GetToolbarResName(ByRef pDoc As Object, pUIToolbarName As String) As String
'returns the resource name for pToolbarName (UI name) using pDoc layout manager.
'If pToolbarName is not found, returns an empty string
'
'adapted from hanya in https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=56336

Dim lo_Mgr As Object 'the configuration manager
Dim l_Items As Variant 'the toolbar resources property array
Dim l_Item As Variant 'an individual property
Dim i As Long
Dim l_Str As String 'the searched string value

l_Str = ""

If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Mgr = pDoc.getUIConfigurationManager()
l_Items = lo_Mgr.getUIElementsInfo(com.sun.star.ui.UIElementType.TOOLBAR)
For i = 0 To UBound(l_Items)
l_Item = l_Items(i)
If (_GetPropertyValueByName(l_Item, LOPRIM_TB_UINAME) = pUIToolbarName) Then
If Not IsNull(l_Item) Then
l_Str = _GetPropertyValueByName(l_Item, LOPRIM_TB_RESNAME)
End If
Exit For
End If
Next

GetToolbarResName = l_Str
End Function 'GetToolbarResName
LibOPrim Toolbars HideToolbar Basic SetFullScreen (Procedure) 244 13
Function HideToolbar(ByRef pToolbarName As String, Optional ByRef pDoc As Object) As Long
'Deletes a given toolbar.
'input:
'-- pToolbarName: the toolbar name (specify either UI name or resource name)
'-- pDoc: the document (defaults to ThisComponent)
'output: an error code
'-- ERR_TBAR_NONE: no error.
'-- ERR_TBAR_UNKNOWN: the specified toolbar is unknown

If IsMissing(pDoc) Then pDoc = ThisComponent

HideToolbar = _ToolbarCommand(pToolbarName, LOPRIM_TBCMD_HIDE, pDoc)
End Function 'HideToolbar
LibOPrim Toolbars ToolbarVisible Basic   258 15
Function ToolbarVisible(ByRef pToolbarName As String, Optional ByRef pDoc As Object) As Long
'Returns the status of a given toolbar: visible or not.
'input:
'-- pToolbarName: the UI toolbar name
'-- pDoc: the document (defaults to ThisComponent)
'output: a status code
'-- ERR_TBAR_NONE: no error.
'-- ERR_TBAR_UNKNOWN: the specified toolbar is unknown
'-- ERR_TBAR_HIDDEN: (pseudo-error) the toolbar is hidden
'-- ERR_TBAR_VISIBLE: (pseudo-error) the toolbar is visible

If IsMissing(pDoc) Then pDoc = ThisComponent

ToolbarVisible = _ToolbarCommand(pToolbarName, LOPRIM_TBCMD_VIS, pDoc)
End Function 'ToolbarVisible
LibOPrim UNO ImplementsUNOstruct Basic CustomPropertyType (Procedure) 43 18
Function ImplementsUNOstruct(ByRef pStruct As Object, ByRef pStructName As String) As Boolean
'Checks whether a UNO struct object implements a given UNO struct.
'Input:
'-- pStruct: the UNO structure object to check.
'-- pStructName: the UNO structure name to check against.
'Output: True if pStruct implements pStructName, False otherwise or if pStruct is not a UNO structure object.
'
'Note: one can't call the HasUnoInterfaces() function on UNO structs as this function only applies to UNO objects.

Dim l_OK As Boolean

l_OK = False
If IsUnoStruct(pStruct) Then
l_OK = (InStr(pStruct.Dbg_Properties, pStructName) > 0)
End If

ImplementsUNOstruct = l_OK
End Function 'ImplementsUNOstruct
MathPrim Math _AverageTest Basic   61 8
Sub _AverageTest()

Dim l_Array As Variant

l_Array = Array(1, 10, 100)
MsgBox Average(l_Array)

End Sub '_AverageTest
MathPrim Math Average Basic _AverageTest (Procedure) 46 14
Function Average(ByRef pArray() As Variant) As Double
'Returns the average value from pArray()
'The array is supposed to be populated

Dim l_Value As Double
Dim i As Long

l_Value = pArray(LBound(pArray))
For i = LBound(pArray) + 1 To UBound(pArray)
l_Value = l_Value + pArray(i)
Next

Average = l_Value / (LBound(pArray) + UBound(pArray) + 1)
End Function 'Average
MathPrim Math BankersRound Basic   70 25
Function BankersRound(ByRef pDecimals As Integer)
'Rounds pValue to pDecimals using the “bankers rounding”: rounding to the nearest even number.
'Rounds a value to a given number of decimals using the “bankers rounding”, that is rounding to the nearest even number.
'Input:
'-- pValue: the value to round.
'-- pDecimals: the number of decimals for the rounding.
'Output: The rounded number.
'Usage
'BankersRound(1,5, 0) -> 2
'BankersRound(2,5, 0) -> 2
'See also Round().

Dim l_Value As Double 'temporary value
Dim l_Mult As Long 'multiplicator

On Local Error Goto ErrHandler:
l_Mult = 10 ^ pDecimals
l_Value = (pValue * l_Mult) + .05
l_Value = l_Value / l_Mult

ErrHandler:
If Err Then l_Value = 0.0

BankersRound = l_Value
end Function 'BankersRound
MathPrim Math Init Basic   96 5
Sub Init()
'initializes the library

SetEpsilon(MATH_DELTA)
End Sub 'Init
MathPrim Math IsDifferent Basic   102 9
Function IsDifferent(ByRef pValue1 As Double, pValue2 As Double) As Boolean
'returns True if pValue1 and pValue2 differ from more than mEpsilon
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns True if pValue1 is different from pValue2, above the mEpsilon error margin.

IsDifferent = (Abs(pValue1 - pValue2) > mEpsilon)
End Function 'IsDifferent
MathPrim Math IsEqual Basic IsGreaterEqual (Procedure)
IsLowerEqual (Procedure)
112 9
Function IsEqual(ByRef pValue1 As Double, pValue2 As Double) As Boolean
'returns True if pValue1 and pValue2 differ from less than mEpsilon or mEpsilon
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns True if pValue1 is not different from pValue2, within the mEpsilon error margin.

IsEqual = (Abs(pValue1 - pValue2) <= mEpsilon)
End Function 'IsEqual
MathPrim Math IsGreater Basic IsGreaterEqual (Procedure)
IsInRange (Procedure)
Max (Procedure)
MaxInArray (Procedure)
122 10
Function IsGreater(ByRef pValue1 As Double, pValue2 As Double) As Boolean
'returns True if pValue1 is greater than pValue2, that is if the difference between
'both values is lower than mEpsilon
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns True if pValue1 is greater than pValue2, above the mEpsilon error margin.

IsGreater = ((pValue1 - pValue2) > mEpsilon)
End Function 'IsGreater
MathPrim Math IsGreaterEqual Basic IsInRange (Procedure) 133 10
Function IsGreaterEqual(ByRef pValue1 As Double, pValue2 As Double) As Boolean
'returns True if pValue1 is greater than or equal to pValue2, that is if the difference between
'both values is lower than mEpsilon or zero.
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns True if pValue1 is greater or equal to pValue2, above the mEpsilon error margin.

IsGreaterEqual = IsEqual(pValue1, pValue2) Or IsGreater(pValue1, pValue2)
End Function 'IsGreaterEqual
MathPrim Math IsInRange Basic   166 18
Function IsInRange(ByRef pValue As Double, pMin As Double, pMax As Double, Optional pExclusive As Boolean) As Boolean
'Checks whether a value is in a range bounds.
'Input
'-- pValue: the number to check.
'-- pMin: the range lower bound.
'-- pMax: the range upper bound.
'-- pExclusive: (optional) specifies if the check must exclude the bounds or not.
' Defaults to False.
'Output: Returns True if pValue is in the pMin..pMax range

If IsMissing(pExclusive) Then pExclusive = False

If pExclusive Then
IsInRange = IsGreater(pValue, pMin) And IsLower(pValue, pMax)
Else
IsInRange = IsGreaterEqual(pValue, pMin) And IsLowerEqual(pValue, pMax)
End If
End Function 'IsInRange
MathPrim Math IsLower Basic IsLowerEqual (Procedure)
IsInRange (Procedure)
Min (Procedure)
MinInArray (Procedure)
144 10
Function IsLower(ByRef pValue1 As Double, pValue2 As Double) As Boolean
'returns True if pValue1 is lower than pValue2, that is if the difference between
'both values is lower than -mEpsilon
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns True if pValue1 is lower than pValue2, above the mEpsilon error margin.

IsLower = ((pValue1 - pValue2) < -mEpsilon)
End Function 'IsLower
MathPrim Math IsLowerEqual Basic IsInRange (Procedure) 155 10
Function IsLowerEqual(ByRef pValue1 As Double, pValue2 As Double) As Boolean
'returns True if pValue1 is lower than or equal to pValue2, that is if the difference between
'both values is lower than mEpsilon or zero.
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns True if pValue1 is lower or equal to pValue2, above the mEpsilon error margin.

IsLowerEqual = IsEqual(pValue1, pValue2) Or IsLower(pValue1, pValue2)
End Function 'IsLowerEqual
MathPrim Math Max Basic   185 17
Function Max(ByRef pValue1 As Double, pValue2 As Double) As Double
'Returns the larger value of two doubles
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns the larger of two decimal numbers, within the mEpsilon error margin.

Dim l_Value As Double

If IsGreater(pValue1, pValue2) Then
l_Value = pValue1
Else
l_Value = pValue2
End If

Max = l_Value
End Function 'Max
MathPrim Math MaxInArray Basic   203 18
Function MaxInArray(ByRef pArray() As Variant) As Double
'Returns the greatest of the values in an array.
'Input
'-- pArray: The array to process. The array is supposed to be populated.
'Output: The largest value within the array within mEpsilon margin.

Dim l_Value As Double
Dim i As Long

l_Value = pArray(LBound(pArray))
For i = LBound(pArray) + 1 To UBound(pArray)
If IsGreater(pArray(i), l_Value) Then
l_Value = pArray(i)
End If
Next

MaxInArray = l_Value
End Function 'MaxInArray
MathPrim Math MaxLng Basic   222 14
Function MaxLng(ByRef pNum1 As Long, pNum2 As Long) As Long
'Returns the greatest of two integers.
'Input:
'-- pNum1: some integer
'-- pNum2: some integer
'Output: the greatest of both numbers.

If (pNum1 > pNum2) Then
MaxLng = pNum1
Else
MaxLng = pNum2
End If

End Function 'MaxLng
MathPrim Math Median Basic   237 33
Function Median(ByRef pArray() As Variant) As Double
'Returns the median value from the items in an array.
'Input:
'-- pArray: The array to process. The array is supposed to be populated.
'Output: The median value of the ones stored in the array.

Dim l_Array As Variant
Dim l_Item1 As Long
Dim l_Item2 As Long
Dim l_Sum As Double
Dim l_Count As Long
Dim l_Result As Double

'sort array
l_Array = QuickSort(pArray) 'QuickSort is in ArrayPrim.Arrays module
l_Count = (UBound(l_Array) - LBound(l_Array)) + 1

If (UBound(l_Array) Mod 2 = 0) Then
l_Item1 = (UBound(l_Array) / 2) + (LBound(l_Array) / 2)
Else
l_Item1 = Int(UBound(l_Array) / 2) + Int(LBound(l_Array) / 2) + 1
End If

If (l_Count Mod 2 <> 0) Then
l_Result = l_Array(l_Item1)
Else
l_Item2 = l_Item1 + 1
l_Sum = l_Array(l_Item1) + l_Array(l_Item2)
l_Result = l_Sum / 2
End If

Median = l_Result
End Function 'Median
MathPrim Math Min Basic   271 17
Function Min(ByRef pValue1 As Double, pValue2 As Double) As Double
'Returns the smaller value of two doubles
'Input:
'-- pValue1: the first number.
'-- pValue2: the second number.
'Output: Returns the smaller of two decimal numbers, within the mEpsilon error margin.

Dim l_Value As Double

If IsLower(pValue1, pValue2) Then
l_Value = pValue1
Else
l_Value = pValue2
End If

Min = l_Value
End Function 'Min
MathPrim Math MinInArray Basic   289 18
Function MinInArray(ByRef pArray() As Variant) As Double
'Returns the lowest of the values in an array.
'Input
'-- pArray: The array to process. The array is supposed to be populated.
'Output: The lowest value within the array within mEpsilon margin.

Dim l_Value As Double
Dim i As Long

l_Value = pArray(LBound(pArray))
For i = LBound(pArray) + 1 To UBound(pArray)
If IsLower(pArray(i), l_Value) Then
l_Value = pArray(i)
End If
Next

MinInArray = l_Value
End Function 'MinInArray
MathPrim Math Round Basic   308 25
Function Round(ByRef pValue As Double, pDecimals As Integer) As Double
'Rounds a value to a given number of decimals.
'Input:
'-- pValue: the value to round.
'-- pDecimals: the number of decimals for the rounding.
'Output: The rounded number.
'Usage
'Round(1,5, 0) -> 2
'Round(2,5, 0) -> 3

Dim l_Value As Double 'temporary value
Dim l_Mult As Long 'multiplicator

l_Value = 0.0

On Local Error Goto ErrHandler:
l_Mult = 10 ^ pDecimals
l_Value = (pValue * l_Mult) + .05
l_Value = l_Value / l_Mult

ErrHandler:
If Err Then l_Value = 0.0

Round = l_Value
End Function 'Round
MathPrim Math SetEpsilon Basic Init (Procedure) 334 3
Sub SetEpsilon(ByRef pNewValue As Double)
mEpsilon = pNewValue
End Sub 'SetEpsilon
MathPrim Math SwapValues Basic   338 9
Sub SwapValues(ByRef pValue1 As Variant, ByRef pValue2 As Variant)
'Swaps two values.

Dim l_Tmp As Variant

l_Tmp = pValue1
pValue1 = pValue2
pValue2 = l_Tmp
End Sub 'SwapValues
OSPrim OS GetOSName Basic IsLinux (Procedure)
IsOSX (Procedure)
IsWindows (Procedure)
47 21
Function GetOSName() As String
'Returns the OS name (see OSPRIM_OSxxx constants above).
'If the OS is not one of the three known ones, returns an empty string.
'Adapted from Heertsch (https://forum.openoffice.org/en/forum/viewtopic.php?f=45&t=26280&p=176535&hilit=operating#p137780)

Dim l_Num As Long
Dim l_Name As String

l_Name = ""
l_Num = GetGUIType()
Select Case l_Num
Case 1
l_Name = OSPRIM_OSWIN
Case 3
l_Name = OSPRIM_OSMAC
Case 4
l_Name = IIf(InStr(Environ("PATH"),"/usr/local/bin") = 0, OSPRIM_OSOSX, OSPRIM_OSLINUX)
End Select

GetOSName = l_Name
End Function 'GetOSName
OSPrim OS IsLinux Basic   69 8
Function IsLinux() As Boolean
'Returns True if the underlying operating system is Linux, otherwise False.

Dim l_Name As String

l_Name = GetOSName()
IsLinux = (l_Name = OSPRIM_OSLINUX)
End Function 'IsLinux
OSPrim OS IsOSX Basic   78 8
Function IsOSX() As Boolean
'Returns True if the underlying operating system is OS X, otherwise False.

Dim l_Name As String

l_Name = GetOSName()
IsOSX = (l_Name = OSPRIM_OSOSX)
End Function 'IsOSX
OSPrim OS IsWindows Basic   87 8
Function IsWindows() As Boolean
'Returns True if the underlying operating system is Windows, otherwise False.

Dim l_Name As String

l_Name = GetOSName()
IsWindows = (l_Name = OSPRIM_OSWIN)
End Function 'IsWindows
OSPrim OS RunCommand Basic   96 8
Function RunCommand() As Long
'TBD

Dim lo_ShellExec As Object

lo_ShellExec = createUnoService("com.sun.star.system.SystemShellExecute")
'lo_ShellExec.execute(Fichier.Files(0), "", 0)
End Function 'RunCommand
Standard Install _AddLibrary Basic AddBasicLibrary (Procedure) 28 30
Function _AddLibrary(ByRef pLib, pGlobalLib As Object, ByVal pSrcLib, pDestLib As String, pForce As Boolean)

Dim oSrcLib As Object
Dim oDestLib As Object
Dim i As Integer
Dim sSrcModules() As String

If Not pGlobalLib.hasByName(pDestLib) Then
pGlobalLib.createLibrary(pDestLib)
Else
'déjà installée
_AddLibrary = 1
Exit Function
End If

If pLib.hasByName(pSrcLib) Then
pLib.loadLibrary(pSrcLib)
oSrcLib = pLib.getByName(pSrcLib)
sSrcModules = oSrcLib.getElementNames()
i = LBound(sSrcModules())
While( i <= uBound(sSrcModules()))
oDestLib = pGlobalLib.getByName(pDestLib)
If Not oDestLib.hasByName(sSrcModules(i)) Then
oDestLib.insertByName(sSrcModules(i), oSrcLib.getByName(sSrcModules(i)))
End If
i = i + 1
Wend
End If
_AddLibrary = 0
End Function '_AddLibrary()
Standard Install _CheckLibrary Basic AddBasicLibrary (Procedure) 7 19
Function _CheckLibrary(ByRef pGlobalLib As Object, ByVal pDestLib As String)

Dim l_OK
Dim i As Integer

If pGlobalLib.hasByName(pDestLib) Then
'déjà installée
l_OK = (MsgBox("The " & pDestLib & " global library already exists." & Chr(13) & Chr(13) & "Do you want to replace it?", _
MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION, _
"Confirmation") = IDYES)
If l_OK Then
pGlobalLib.removeLibrary(pDestLib)
End If
Else
l_OK = True
End If

_CheckLibrary = l_OK
End Function '_CheckLibrary()
Standard Install AddBasicLibrary Basic   60 28
Sub AddBasicLibrary

Dim SrcLibraryName As String
Dim DestLibraryName As String
Dim oLib As Object
Dim oGlobalLib As Object
Dim l_Err As Integer

' set these 2 variables to your lib name
SrcLibraryName = "CSVlib" ' The name of the library that contains the modules (in this document)
DestLibraryName = "CSVlib" ' This library will be created and is the destination for the modules from the source document.
l_Err = -1

oLib = BasicLibraries ' For Basic libraries, c'est-à-dire dans les macros du document
oGlobalLib = GlobalScope.BasicLibraries
If _CheckLibrary(oGlobalLib, DestLibraryName) Then
l_Err = _AddLibrary(oLib, oGlobalLib, SrcLibraryName, DestLibraryName)
End If
'oLib = DialogLibraries ' The same for the Dialog libraries
'oGlobalLib = GlobalScope.DialogLibraries
'l_Err = _AddLibrary(oLib, oGlobalLib, SrcLibraryName, DestLibraryName)

If (l_Err = 0) Then
MsgBox("The " & DestLibraryName & " library was installed.")
Else
MsgBox("The " & DestLibraryName & " already exists!")
End If
End Sub
StringsPrim Strings DelChar Basic DelSpaces (Procedure) 44 9
Function DelChar(ByRef pStr As String, pChar As String) As String
'Strips a character out of a string and returns the result.
'Input
'-- pStr: the string to process.
'-- pChar: the character to be stripped out of pStr (1 char only)
'Output: The processed string, without the pChar character.

DelChar = Join(Split(pStr, pChar), "")
End Function 'DelChar
StringsPrim Strings DelSpaces Basic   54 22
Function DelSpaces(ByRef pStr As String, Optional pUnBreak As Boolean) As String
'Deletes all spacing characters in a string and returns the result.
'Input
'-- pStr: the string to process.
'-- pUnbreak: (optional) specifies if the unbreakable space must be processed or not. Defaults to False.
'Spaces can be:
'-- Chr(32): ordinary space
'-- Chr(160): unbreakable space
'Output: The processed string, without the spacing characters.
' If pUnBreak is set to True (defaults to False), unbreakable spaces (Chr(160)) are deleted as well as ordinary spaces (Chr(32)).

Dim l_Str As String

If IsMissing(pUnBreak) Then pUnBreak = False

'ordinary spaces
l_Str = DelChar(pStr, Chr(32))
'unbreakable spaces
If pUnBreak Then l_Str = DelChar(l_Str, Chr(160))

DelSpaces = l_Str
End Function 'DelSpaces
StringsPrim Strings FilterNonPrintableStr Basic NTFSFileNameString (Procedure) 77 21
Function FilterNonPrintableStr(ByRef pStr As String) As String
'Strips-out any non-printable char from the original string.
'Input:
'-- pStr: the string to process
'Output: the input string without non-printable chars

Dim l_Char As String
Dim l_Str As String
Dim i As Long
Dim j As Long

l_Str = ""
For i = 1 To Len(pStr)
l_Char = Mid(pStr, i, 1)
If (Asc(l_Char) > 31) Then
l_Str = l_Str & l_Char
End If
Next i

FilterNonPrintableStr = l_Str
End Function 'FilterNonPrintableStr
StringsPrim Strings LeftPad Basic   99 9
Function LeftPad(ByRef pStr As String, pPadChar As String, pLength As Long) As String
'Pads pStr on the left to pLength using pPadChar and returns the resulting string.
'If pLength is less than pStr actual length, the resulting string is shortened accordingly on the left.
'eg:
'LeftPad("1234", "x", 7) -> "xxx1234"
'LeftPad("1234", "x", 3) -> "234"

LeftPad = Right(String(pLength, pPadChar) & pStr, pLength)
End Function 'LeftPad
StringsPrim Strings NoAccentStr Basic NTFSFileNameString (Procedure) 109 28
Function NoAccentStr(ByRef pStr As String) As String
'Replaces accented chars with not accented ones
'Input:
'-- pStr: the string to process
'Output: the input string with accented chars replaced with their unaccented counterparts
' (see the two constants below)

Const CHAR_ACC = "ÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöùúûüýÿ"
Const CHAR_NOACC = "AAAAACEEEEIIIINOOOOOUUUUYaaaaaaceeeeiiiinooooouuuuyy"

Dim i As Long
Dim j As Long
Dim l_Char As String
Dim l_Str As String

l_Str = ""
For i = 1 To Len(pStr)
l_Char = Mid(pStr, i, 1)
j = InStr(CHAR_ACC, l_Char)
If (j > 0) Then
l_Str = l_Str & Mid(CHAR_NOACC, j, 1)
Else
l_Str = l_Str & l_Char
End If
Next i

NoAccentStr = l_Str
End Function 'NoAccentStr
StringsPrim Strings QuoteStr Basic   138 19
Function QuoteStr(ByRef pStr As String, pQuoteChar As String) As String
'Adds quotes to a string and returns the quoted string.
'Input
'-- pStr: the string to process.
'-- pQuoteChar: the quoting character.
'Output: Returns the quoted string using pQuoteChar to both ends of pStr.
' If pStr already has such quotation marks at both ends, pStr is left untouched.
'See UnQuoteStr().
'Usage
'QuoteStr("My Text", Chr(29)) --> "'My Text'"
'QuoteStr("'My Text", Chr(29)) --> "''My Text'"
'QuoteStr("'My Text'", Chr(29)) --> "'My Text'"

If (Left(pStr, 1) <> pQuoteChar) Or (Right(pStr, 1) <> pQuoteChar) Then
QuoteStr = pQuoteChar & pStr & pQuoteChar
Else
QuoteStr = pStr
End If
End Function 'QuoteStr
StringsPrim Strings ReplaceStr Basic NTFSFileNameString (Procedure)
CalcShareFileName (Procedure)
LockFileName (Procedure)
SuppressMultipleChars (Procedure)
158 7
Function ReplaceStr(ByRef pStr As String, pSearchStr As String, pReplStr As String) As String
'Replaces pSearchStr string into pStr with pReplStr and returns the modified string.
'eg:
'ReplaceStr("This is a test", " ", "_") -> This_is_a_test

ReplaceStr = Join(Split(pStr, pSearchStr), pReplStr)
End Function 'ReplaceStr
StringsPrim Strings RightPad Basic   166 15
Function RightPad(ByRef pStr As String, pPadChar As String, pLength As Long) As String
'Pads a string on the right to a given length using a padding character and returns the resulting string.
'Input:
'-- pStr: the string to process
'-- pPadChar: the character used for padding
'-- pLength: the output string length
'Output: The result string.
' If pLength is less than pStr actual length, the resulting string is shortened accordingly on the right.
'See LeftPad().
'Usage
'RightPad("1234", 7, "x") -> "1234xxx"
'RightPad("1234", 3, "x") -> "123"

RightPad = Left(pStr & String(pLength, pPadChar), pLength)
End Function 'RightPad
StringsPrim Strings StripChars Basic NTFSFileNameString (Procedure) 182 24
Function StripChars(ByRef pStr As String, pStripChars As String) As String
'Strips a given set of characters from a string.
'Input:
'-- pStr: the string to process
'-- pStripChars: the chars to strip from pStr.
'Output: the stripped string.
'
'Use: MyString = StripChars(MyString, "+-*/")
' strips out numeric operators from MyString

Dim l_Str As String 'output string buffer
Dim l_Char As String 'the character to strip out
Dim i As Long

l_Str = ""
For i = 1 To Len(pStr)
l_Char = Mid(pStr, i, 1)
If (InStr(pStripChars, l_Char) = 0) Then
l_Str = l_Str & l_Char
End If
Next i

StripChars = l_Str
End Function 'StripChars
StringsPrim Strings SuppressMultipleChars Basic ChangeFileExt (Procedure) 207 16
Function SuppressMultipleChars(ByRef pStr As String, pChar As String) As String
'Suppresses multiple occurrences of a given character in a string and returns the result.
'Input:
'-- pStr: the string to process.
'-- pChar: the char to filter.
'Output: the stripped-out extraneous characters. Multiple characters are suppressed, leaving one only.

Dim l_Search As String

l_Search = Left(pChar, 1) & Left(pChar, 1)
Do While InStr(1, pStr, l_Search)
pStr = ReplaceStr(pStr, l_Search, pChar)
Loop

SuppressMultipleChars = pStr
End Function 'SuppressMultipleChars
StringsPrim Strings TitleCase Basic   223 49
Function TitleCase(ByRef pStr As String) As String
'Converts a string into titlecase.
'eg: "test the o'connors and the mac-addamses" -> "Test The O'Connors And The Mac-Addamses"
'Input:
'-- pStr: the string to process
'Output: the processed string

Dim l_Str As String 'output buffer
Dim l_StrUC As String 'temporary version with uppercase chars
Dim l_SplitChars As String 'chars where to split the titles
Dim l_arrItems As Variant 'array of title items
Dim l_StrTmp As String 'temporary buffer
Dim l_CurSplit As String 'a splitting character
Dim j As Long
Dim i As Long

If (pStr = "") Then
l_Str = pStr
Else
'set the splitting chars set
l_SplitChars = " '’-" & Chr(160) 'Chr(160) = unbreakable space

'process the input string for each splitting character
l_Str = LCase(pStr)
l_Str = UCase(Left(l_Str, 1)) & Right(l_Str, Len(l_Str) - 1)
For i = 1 to Len(l_SplitChars)
l_CurSplit = Mid(l_SplitChars, i, 1)
l_arrItems = Split(l_Str, l_CurSplit)
If (UBound(l_arrItems) > 0) Then
l_StrTmp = ""
l_Str = ""
For j = 0 to UBound(l_arrItems)
'set 1st char uppercase
l_StrUC = UCase(Left(l_arrItems(j), 1)) & Right(l_arrItems(j), Len(l_arrItems(j)) - 1)
'add the split char if it is the first char
If (j > 0) Then
l_StrTmp = l_StrTmp & l_CurSplit & l_StrUC
Else
l_StrTmp = l_StrTmp & l_StrUC
End If
Next
'update the string to process
l_Str = l_Str & l_StrTmp
End If
Next
End If

TitleCase = l_Str
End Function 'TitleCase
StringsPrim Strings TrimEx Basic   273 49
Function TrimEx(ByRef pStr As String) As String
'Suppresses surrounding spaces from a given string.
'This function suppresses both standard spaces (Ascii 032) and unbreakable spaces (Ascii 160).
'Input:
'-- pStr: The string to process
'Output: the process result.

Dim l_Str As String
Dim l_Char As String
Dim i As Long
Dim l_Nb160 As Long

'suppress Chr(032)
l_Str = Trim(pStr)

'suppress Chr(160)
If (Len(l_Str) > 0) Then
'remove Chr(160)
l_Nb160 = 0
'first chars
For i = 1 To Len(l_Str)
l_Char = Mid(l_Str, i, 1)
If (Asc(l_Char) = Chr(160)) Then
l_Nb160 = l_Nb160 + 1
Else
Exit For
End If
Next
If (l_Nb160 > 0) Then
l_Str = Right(l_Str, Len(l_Str) - l_Nb160)
End If

'last chars
l_Nb160 = 0
For i = Len(l_Str) To 1 Step -1
l_Char = Mid(l_Str, i, 1)
If (Asc(l_Char) = Chr(160)) Then
l_Nb160 = l_Nb160 + 1
Else
Exit For
End If
Next
If (l_Nb160 > 0) Then
l_Str = Left(l_Str, Len(l_Str) - l_Nb160)
End If
End If

TrimEx = l_Str
End Function 'TrimEx
StringsPrim Strings UnQuoteStr Basic   323 10
Function UnQuoteStr(ByRef pStr As String, pQuoteChar As String) As String
'Removes quotes (using pQuoteChar) in pStr and returns the unquoted string.
'pQuoteChar is deleted only when it is present at both ends of pStr.

If (Left(pStr, 1) = pQuoteChar) And (Right(pStr, 1) = pQuoteChar) Then
UnQuoteStr = Mid(pStr, 2, Len(pStr) - 2)
Else
UnQuoteStr = pStr
End If
End Function 'UnQuoteStr
WriterPrim Autotexts _CreateHiddenDocument Basic AddAutoTexts (Procedure) 371 13
Function _CreateHiddenDocument() As Object
'(internal)
'Creates a hidden writer document in order to get a text cursor

Dim lo_Doc As Object
Dim l_Props(0) As New com.sun.star.beans.PropertyValue

l_Props(0).Name = "Hidden"
l_Props(0).Value = True
lo_Doc = StarDesktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, l_Props())

_CreateHiddenDocument = lo_Doc
End Function '_CreateHiddenDocument
WriterPrim Autotexts AddAutoText Basic   66 61
Function AddAutoText(ByRef pGroupName As String, pTitle As String, pShortcut As String, _
pText As Object, Optional pUpdate As Boolean) As Long
'Creates a new autotext and returns the creation status.
'Input:
'-- pGroupName: the owning autotext group name for the new autotext
'-- pTitle: the new autotext title (the full name)
'-- pShortcut: the name for the new autotext (the shortcut)
'-- pText: the autotext actual contents (text cursor)
'-- pUpdate: (Optional) set to True will cause the existing autotext with the same name to be updated.
' See UpdateAutoText() for more details.
'Output: the error status. Returns 0 if OK, otherwise see ERR_AUTOTEXT_XXX constants.
'-- ERR_AUTOTEXT_NONE: (0) creation completed.
'-- ERR_AUTOTEXT_SHORTCUT: the shortcut is not valid.
'-- ERR_AUTOTEXTGROUP_UNKNOWN: the group is unknown.
'-- ERR_AUTOTEXT_EXISTS: the shortcut already exists in this group.
'-- ERR_AUTOTEXT_CANTCREATE: creation problem. The AutoText wasn't created.
'
'Warning: This function attempts to create a new autotext within the specified group.
' If the target group is the LibO Basis container, some systems might refuse write access, thus cause
' a runtime error which is intercepted by the On Local Error statement below.
' Hence, in this situation, the returned object is Null.

Dim lo_AutotextGroup As Object 'the autotext group
Dim lo_AutoText As Object
Dim l_Shortcut As String
Dim l_Err As Long

l_Err = ERR_AUTOTEXT_NONE

'be conservative about updates
If IsMissing(pUpdate) Then pUpdate = False

l_Shortcut = Trim(pShortcut)
If (l_Shortcut <> "") Then
lo_AutotextGroup = GetAutoTextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
If lo_AutotextGroup.hasByName(l_Shortcut) And pUpdate Then
l_Err = UpdateAutoText(pGroupName, pTitle, l_Shortcut, pText)
Else
If Not lo_AutotextGroup.hasByName(l_Shortcut) Then
On Local Error Resume Next
lo_AutoText = lo_AutotextGroup.insertNewByName(l_Shortcut, pTitle, pText)
If Err Then
l_Err = ERR_AUTOTEXT_CANTCREATE
End If
Else
'error: autotext exists
l_Err = ERR_AUTOTEXT_EXISTS
End If
End If
Else
'error: unknown group name
l_Err = ERR_AUTOTEXTGROUP_UNKNOWN
End If
Else
'error: non valid shortcut
l_Err = ERR_AUTOTEXT_SHORTCUT
End If

AddAutoText = l_Err
End Function 'AddAutoText
WriterPrim Autotexts AddAutotextGroup Basic   128 50
Function AddAutotextGroup(ByRef pGroupName As String, Optional ByRef pLocal As Boolean, _
Optional ByRef pReplace As Boolean) As Long
'Creates an autotext group and returns the creation status.
'Input:
'-- pGroupName: the group name to create
'-- pLocal: if True, create it within the local profile tree
'-- pReplace: (Optional) if True, will replace any existing group with the same name.
' Defaults to False.
'Output: the creation status. Returns 0 if OK, otherwise see ERR_AUTOTEXT_XXX constants.
'-- ERR_AUTOTEXT_NONE: (0) creation completed.
'-- ERR_AUTOTEXTGROUP_EXISTS: the group already exists.
'-- ERR_AUTOTEXTGROUP_CANTCREATE: creation problem. The group wasn't created.
'
'Warning: when pLocal is set to False, the function attempts to create the group within the LibO Basis container
' on which some systems might refuse write access.

Dim lo_AutoTextContainer As Object 'the container
Dim lo_AutotextGroup As Object 'the autotext group
Dim l_Err As Long

l_Err = ERR_AUTOTEXT_NONE

If IsMissing(pLocal) Then pLocal = True
'be conservative about replacements
If IsMissing(pReplace) Then pReplace = False

lo_AutoTextContainer = CreateAutoTextContainer()

'delete the autotext group if required
If lo_AutoTextContainer.hasByName(pGroupName) And pReplace Then
lo_AutoTextContainer.removeByName(pGroupName)
End If

'if the group doesn't exist, create it, otherwise just return it
If Not lo_AutoTextContainer.hasByName(pGroupName) Then
On Local Error Resume Next
lo_AutotextGroup = lo_AutoTextContainer.insertNewByName(AutotextGroupID(pGroupName, pLocal))
If Err Then
'error: creation time error
l_Err = ERR_AUTOTEXTGROUP_CANTCREATE
Else
lo_AutotextGroup.Title = pGroupName
End If
Else
'error: group exists
l_Err = ERR_AUTOTEXTGROUP_EXISTS
End If

AddAutotextGroup = l_Err
End Function 'AddAutotextGroup
WriterPrim Autotexts AddAutoTexts Basic   179 40
Function AddAutoTexts(ByRef pGroupName As String, ByRef pAutoTextArray() As Variant) As Long
'Adds formatted autotexts to a group.
'Input:
'-- pGroupName: the target autotext group name
'-- pAutoTextArray(): an array containing the autotexts to be added.
' This is a 2-dimensions string array: dim1 = rows (as many as necessary); dim2 = 2 (3 columns)
' Col0: the shortcut for the autotext
' Col1: the name/title of the autotext
' Col2: the (formatted) text contents
'Output: the number of autotext entries added. Returns -1 if the group name doesn't exist.

Dim lo_Doc As Object 'dummy hidden writer document
Dim l_Props(0) As New com.sun.star.beans.PropertyValue
Dim lo_AutotextGroup As Object
Dim lo_AutoText As Object
Dim lo_TextCursor As Object 'a text cursor for autotext creation
Dim l_Count As Long
Dim i As Long

l_Count = -1
lo_AutotextGroup = GetAutoTextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
lo_Doc = _CreateHiddenDocument()
If Not IsNull(lo_Doc) Then
lo_TextCursor = lo_Doc.Text.CreateTextCursor
'add the autotexts
l_Count = 0
For i = 0 To UBound(pAutoTextArray())
If Trim(pAutoTextArray(i, 0) <> "") Then
lo_TextCursor.String = pAutoTextArray(i, 2)
lo_AutoText = NewAutoText(lo_AutotextGroup, pAutoTextArray(i, 1), pAutoTextArray(i, 0), lo_TextCursor)
If Not IsNull(lo_AutoText) Then l_Count = l_Count + 1
End If
Next
lo_Doc = Nothing
End If
End If

AddAutoTexts = l_Count
End Function 'AddAutoTexts
WriterPrim Autotexts AddRawAutoTexts Basic   220 34
Function AddRawAutoTexts(ByRef pGroupName As String, ByRef pAutoTextArray() As Variant) As Long
'Adds raw autotexts to a group.
'Input:
'-- pGroupName: the target autotext group name
'-- pAutoTextArray(): an array containing the autotexts to be added.
' This is a 2-dimensions string array: dim1 = rows (as many as necessary); dim2 = 2 (3 columns)
' Col0: the shortcut for the autotext
' Col1: the title of the autotext
' Col2: the raw text contents (no formatting)
'Output: the number of autotext entries added. Returns -1 if the group name doesn't exist.

Dim lo_AutotextGroup As Object
Dim lo_AutoText As Object
Dim lo_TextRange As Object 'a text cursor for autotext creation
Dim l_Count As Long
Dim i As Long

l_Count = -1
lo_AutotextGroup = GetAutoTextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
l_Count = 0
lo_TextRange = CreateUnoService(SVC_TEXTRANGE)
'add the autotexts
For i = 0 To UBound(pAutoTextArray())
If Trim(pAutoTextArray(i, 0) <> "") Then
lo_TextRange.String = pAutoTextArray(i, 2)
lo_AutoText = NewAutoText(lo_AutotextGroup, pAutoTextArray(i, 1), pAutoTextArray(i, 0), lo_TextRange)
If Not IsNull(lo_AutoText) Then l_Count = l_Count + 1
End If
Next
End If

AddRawAutoTexts = l_Count
End Function 'AddRawAutoTexts
WriterPrim Autotexts AutoTextExists Basic   318 18
Function AutoTextExists(ByRef pGroupName As String, pShortcut As String) As Boolean
'Returns True if an autotext shortcut exists within a given group name.
'Input:
'-- pGroupName: the name of the owning group.
'-- pShortcut: the autotext entry shortcut to check.
'Output: True if the shortcut exists within the group named pGroupName, otherwise False.

Dim lo_AutotextGroup As Object
Dim l_Exists As Boolean

l_Exists = False
lo_AutotextGroup = GetAutoTextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
l_Exists = lo_AutotextGroup.hasByName(pShortcut)
End If

AutotextGroupExists = l_Exists
End Function 'AutoTextExists
WriterPrim Autotexts AutotextGroupExists Basic AutoTextExists (Procedure) 255 12
Function AutotextGroupExists(ByRef pGroupName As String) As Boolean
'Returns True if a group name exists
'Input:
'-- pGroupName: the name to check.
'Output: True if the group named pGroupName exists, otherwise False.

Dim l_Exists As Boolean

l_Exists = (AutotextGroupNameIndex(pGroupName) > -1)

AutotextGroupExists = l_Exists
End Function 'AutotextGroupExists
WriterPrim Autotexts AutotextGroupID Basic AddAutotextGroup (Procedure)
NewAutotextGroup (Procedure)
268 19
Function AutotextGroupID(ByRef pGroupName As String, ByRef pLocal As Boolean) As String
'Returns the string ID for a group name.
'This is used as a group naming convention.
'Input:
'-- pGroupName: the name for the group.
'-- pLocal: True if the group is local to the user, otherwise False.
'Output: The string ID.
'
'Structure of the string ID: GroupName*{0|1} (GroupName<star><zero or one>)
'where 0 = global, 1 = local
'
'Example: if the local group name is MyGroup, returns MyGroup*1

Dim l_ID As String

l_ID = Trim(pGroupName) & "*" & CStr(Abs(CInt(pLocal))) '"0" (False) or "1" (True)

AutotextGroupID = l_ID
End Function 'AutotextGroupID
WriterPrim Autotexts AutotextGroupNameIndex Basic AutotextGroupExists (Procedure)
GetAutotextGroupByName (Procedure)
288 29
Function AutotextGroupNameIndex(ByRef pGroupName As String) As Long
'Returns the index of an autotext group within the container from its name.
'Input:
'-- pGroupName: the name of the group to check.
'Output: the index of the autotext group, or -1 if not found.

Dim lo_AutoTextContainer As Object
Dim l_Exists As Boolean
Dim i As Long

'we browse the groups within the container instead of calling .hasByName()
'because this is the only way to get global groups to be checked at once.
lo_AutoTextContainer = CreateAutoTextContainer()

i = 0
l_Exists = False
Do While (i < lo_AutoTextContainer.Count) And Not l_Exists
l_Exists = (lo_AutoTextContainer.ElementNames(i) = pGroupName)
i = i + 1
Loop

If l_Exists Then
i = i - 1
Else
i = -1
End If

AutotextGroupNameIndex = i
End Function 'AutotextGroupNameIndex
WriterPrim Autotexts AutoTextShortcutIndex Basic RenameAutoText (Procedure)
UpdateAutoText (Procedure)
UpdateAutoTextTitle (Procedure)
337 25
Function AutoTextShortcutIndex(ByRef pGroup As Object, pShortcut As String) As Long
'Returns the index of an autotext within the group from its name.
'Input:
'-- pGroup: the group owner object
'-- pShortcut: the name of the shortcut to check.
'Output: the index of the autotext, or -1 if not found.

Dim l_Exists As Boolean
Dim i As Long

i = 0
l_Exists = False
Do While (i < pGroup.Count) And Not l_Exists
l_Exists = (pGroup.ElementNames(i) = pShortcut)
i = i + 1
Loop

If l_Exists Then
i = i - 1
Else
i = -1
End If

AutoTextShortcutIndex = i
End Function 'AutoTextShortcutIndex
WriterPrim Autotexts CreateAutoTextContainer Basic AddAutotextGroup (Procedure)
AutotextGroupNameIndex (Procedure)
DeleteAutotextGroupByName (Procedure)
GetAutotextGroupByIndex (Procedure)
GetAutotextGroupNames (Procedure)
NewAutotextGroup (Procedure)
363 7
Function CreateAutoTextContainer() As Object
'Returns an autotext container object.
'Input: (none)
'Output: the container object.

CreateAutoTextContainer = CreateUnoService(SVC_AUTOCONTAINER)
End Function 'CreateAutoTextContainer
WriterPrim Autotexts DeleteAutoTextByShortcut Basic   415 40
Function DeleteAutoTextByShortcut(ByRef pGroupName As String, pShortcut As String) As Long
'Deletes an existing autotext from its shortcut, in a given group.
'Input:
'-- pGroupName: the name of the owning autotext group.
'-- pShortcut: the shortcut for the autotext to be deleted
'Output: a status code. No error is 0. See constants ERR_AUTOTEXT_XXX above.
'-- ERR_AUTOTEXT_NONE: (0) creation completed.
'-- ERR_AUTOTEXT_SHORTCUT: the shortcut is not valid.
'-- ERR_AUTOTEXT_CANTDELETE: the AutoText couldn't be deleted.
'-- ERR_AUTOTEXTGROUP_UNKNOWN: the group is unknown.
'-- ERR_AUTOTEXT_CANTDELETE: the AutoText couldn't be deleted.

Dim lo_AutotextGroup As Object
Dim l_Shortcut As String
Dim l_Err As Long

l_Err = ERR_AUTOTEXT_NONE

l_Shortcut = Trim(pShortcut)
If (l_Shortcut <> "") Then
lo_AutotextGroup = GetAutoTextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
If lo_AutotextGroup.hasByName(l_Shortcut) Then
On Local Error Resume Next
lo_AutotextGroup.removeByName(l_ShortCut)
If Err Then
l_Err = ERR_AUTOTEXT_CANTDELETE
End If
End If
Else
'error: group unknown
l_Err = ERR_AUTOTEXTGROUP_UNKNOWN
End If
Else
'error: non valid shortcut
l_Err = ERR_AUTOTEXT_SHORTCUT
End If

DeleteAutoTextByShortcut = l_Err
End Function 'DeleteAutoTextByShortcut
WriterPrim Autotexts DeleteAutotextGroupByName Basic   385 29
Function DeleteAutotextGroupByName(ByRef pGroupName As String) As Long
'Deletes an existing autotext group.
'Input:
'-- pGroupName: the name of the autotext group to be deleted.
'Output: a status code. No error is 0. See constants ERR_AUTOTEXT_XXX above.
'-- ERR_AUTOTEXT_NONE: (0) creation completed.
'-- ERR_AUTOTEXTGROUP_UNKNOWN: the group is unknown.
'-- ERR_AUTOTEXTGROUP_CANTDELETE: the group couldn't be deleted.
'
'Warning: the group is deleted, whether it is empty or not.

Dim lo_AutoTextContainer As Object
Dim l_Err As Long

l_Err = ERR_AUTOTEXT_NONE
lo_AutoTextContainer = CreateAutoTextContainer()

If lo_AutoTextContainer.hasByName(pGroupName) Then
On Local Error Resume Next
lo_AutoTextContainer.removeByName(pGroupName)
If Err Then
l_Err = ERR_AUTOTEXTGROUP_CANTDELETE
End If
Else
l_Err = ERR_AUTOTEXTGROUP_UNKNOWN
End If

DeleteAutotextGroupByName = l_Err
End Function 'DeleteAutoTextGroup
WriterPrim Autotexts GetAutoTextByShortcut Basic   515 19
Function GetAutoTextByShortcut(ByRef pGroupName As String, pShortcut As String) As Object
'Retrieves an autotext object from its shortcut.
'Input:
'-- pGroupName: the group owning the autotext.
'-- pShortcut: the shortcut to retrieve.
'Output: the autotext object or Null if the shortcut wasn't found.

Dim lo_AutotextGroup As Object
Dim lo_AutoText As Object

lo_AutotextGroup = GetAutoTextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
If lo_AutotextGroup.hasByName(pShortcut) Then
lo_AutoText = lo_AutotextGroup.getByName(pShortcut)
End If
End If

GetAutoTextByShortcut = lo_AutoText
End Function 'GetAutoTextByShortcut
WriterPrim Autotexts GetAutotextGroupByIndex Basic GetAutotextGroupByName (Procedure) 456 17
Function GetAutotextGroupByIndex(ByRef pIndex As Long) As Object
'Retrieves an autotext group object from its index in group.
'Input:
'-- pIndex: the index of the group to retrieve.
'Output: the group object or Null if it doesn't exist.

Dim lo_AutoTextContainer As Object
Dim lo_AutotextGroup As Object

If (pIndex > -1) Then
lo_AutoTextContainer = CreateAutoTextContainer()
On Local Error Resume Next
lo_AutotextGroup = lo_AutoTextContainer.getByIndex(pIndex)
End If

GetAutotextGroupByIndex = lo_AutotextGroup
End Function 'GetAutotextGroupByIndex
WriterPrim Autotexts GetAutotextGroupByName Basic AddAutoText (Procedure)
AddAutoTexts (Procedure)
AddRawAutoTexts (Procedure)
AutoTextExists (Procedure)
DeleteAutoTextByShortcut (Procedure)
GetAutoTextByShortcut (Procedure)
GetAutoTextShortcuts (Procedure)
GetAutoTextTitles (Procedure)
RenameAutoText (Procedure)
UpdateAutoText (Procedure)
UpdateAutoTextTitle (Procedure)
474 16
Function GetAutotextGroupByName(ByRef pGroupName As String) As Object
'Retrieves an autotext group object from its name.
'Input:
'-- pGroupName: the name of the group to retrieve.
'Output: the group object or Null if it doesn't exist.

Dim lo_AutotextGroup As Object
Dim i As Long

i = AutotextGroupNameIndex(pGroupName)
If (i > -1) Then
lo_AutotextGroup = GetAutotextGroupByIndex(i)
End If

GetAutotextGroupByName = lo_AutotextGroup
End Function 'GetAutotextGroupByName
WriterPrim Autotexts GetAutotextGroupNames Basic   491 23
Function GetAutotextGroupNames() As Variant
'Returns the autotext groups list.
'The list is an 1-dimension array of strings.
'Input: (none)
'Output: an array containing the names of all known autotext groups

Dim lo_AutoTextContainer As Object
Dim lo_AutotextGroup As Object
Dim l_Array() As Variant
Dim i As Long

lo_AutoTextContainer = CreateAutoTextContainer()

i = lo_AutoTextContainer.Count - 1
ReDim l_Array(i)
For i = 0 To lo_AutoTextContainer.Count - 1
' Insert the name and the title of all Autotexts
lo_AutotextGroup = lo_AutoTextContainer.getByIndex(i)
l_Array(i) = lo_AutotextGroup.Title
Next

GetAutotextGroupNames = l_Array()
End Function 'GetAutotextGroupNames
WriterPrim Autotexts GetAutoTextShortcuts Basic   535 16
Function GetAutoTextShortcuts(ByRef pGroupName As String) As Variant
'Returns the autotext shortcut list for a group
'The list is a 1-dimension array of strings (vector).
'Input
'-- pGroupName: the name of the group to explore
'Output: the resulting array of strings with the autotext shortcuts ('element names' in LibO Basic).
' The array is Null if the group doesn't exist or is empty.

Dim lo_AutotextGroup As Object
Dim l_Array() As Variant

lo_AutotextGroup = GetAutotextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then l_Array = lo_AutotextGroup.ElementNames

GetAutoTextShortcuts = l_Array()
End Function 'GetAutoTextShortcuts
WriterPrim Autotexts GetAutoTextTitles Basic   552 16
Function GetAutoTextTitles(ByRef pGroupName As String) As Variant
'Returns the autotext list of titles for a group name.
'The list is an 1-dimension array of strings (vector).
'Input
'-- pGroupName: the name of the group to explore
'Output: the resulting array of strings with the autotext titles.
' The array is Null if the group doesn't exist or is empty.

Dim lo_AutotextGroup As Object
Dim l_Array() As Variant

lo_AutotextGroup = GetAutotextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then l_Array = lo_AutotextGroup.Titles

GetAutoTextTitles = l_Array()
End Function 'GetAutoTextTitles
WriterPrim Autotexts NewAutoText Basic AddAutoTexts (Procedure)
AddRawAutoTexts (Procedure)
RenameAutoText (Procedure)
610 35
Function NewAutoText(ByRef pGroup As Object, pTitle As String, pShortcut As String, _
pText As Object, Optional pUpdate As Boolean) As Object
'Creates a new autotext and returns the corresponding object.
'Input:
'-- pGroup: the owning autotext group object for the new autotext
'-- pTitle: the new autotext title (the full name)
'-- pName: the name for the new autotext (the shortcut)
'-- pText: the autotext actual contents (text cursor)
'-- pUpdate: (Optional) set to True will cause the existing autotext with the same name to be updated
'Output: the autotext created or the existing object if it wasn't replaced
' or Null if the creation couldn't be achieved.
'
'Warning: This function attempts to create a new autotext within the specified group.
' If the target group is the LibO Basis container, some systems might refuse write access, thus cause
' a runtime error which is intercepted by the On Local Error statement below.
' Hence, in this situation, the returned object is Null.

Dim lo_AutoText As Object

'be conservative about updates
If IsMissing(pUpdate) Then pUpdate = False

If Not IsNull(pGroup) Then
If pGroup.hasByName(pShortcut) And pUpdate Then
UpdateAutoText(pGroup.Title, pTitle, pShortcut, pText)
Else
If Not pGroup.hasByName(pShortcut) Then
On Local Error Resume Next
lo_AutoText = pGroup.insertNewByName(pShortcut, pTitle, pText)
End If
End If
End If

NewAutoText = lo_AutoText
End Function 'NewAutoText
WriterPrim Autotexts NewAutotextGroup Basic   569 40
Function NewAutotextGroup(ByRef pGroupName As String, ByRef pLocal As Boolean, _
Optional ByRef pReplace As Boolean) As Object
'Creates an autotext group and returns the group object.
'Input:
'-- pGroupName: the group name to create
'-- pLocal: if True, create it within the local profile tree
'-- pReplace: (Optional) if True, will replace any existing group with the same name.
' Defaults to False.
'Output: the autotext group object created or the existing group object if it was not replaced or Null if an error occurred.
'
'Warning: when pLocal is set to False, the function attempts to create the group within the LibO Basis container
' on which some systems might refuse write access.

Dim lo_AutoTextContainer As Object 'the container
Dim lo_AutotextGroup As Object 'the autotext group

'be conservative about replacements
If IsMissing(pReplace) Then pReplace = False

lo_AutoTextContainer = CreateAutoTextContainer()

'delete the autotext group if required
If lo_AutoTextContainer.hasByName(pGroupName) And pReplace Then
On Local Error Resume Next
lo_AutoTextContainer.removeByName(pGroupName)
End If

'if the group doesn't exist, create it, otherwise just return it
If Not lo_AutoTextContainer.hasByName(pGroupName) Then
On Local Error Resume Next
lo_AutotextGroup = lo_AutoTextContainer.insertNewByName(AutotextGroupID(pGroupName, pLocal))
If Not IsNull(lo_AutotextGroup) Then
lo_AutotextGroup.Title = pGroupName
End If
Else
lo_AutotextGroup = lo_AutoTextContainer.getByName(pGroupName)
End If

NewAutotextGroup = lo_AutotextGroup
End Function 'NewAutotextGroup
WriterPrim Autotexts RenameAutoText Basic UpdateAutoText (Procedure) 646 60
Function RenameAutoText(ByRef pGroupName As String, ByRef pOldShortcut As String, ByRef pNewShortcut As String) As Long
'renames an entry shortcut. The other items of the entrey are left untouched.
'Input:
'-- pGroupName: the owning autotext group name for the autotext
'-- pOldShortcut: the current autotext shortcut
'-- pNewShortcut: the new autotext shortcut
'Output: the error status. Returns 0 if OK, otherwise see ERR_AUTOTEXT_XXX constants.
'-- ERR_AUTOTEXT_NONE: (0) creation completed.
'-- ERR_AUTOTEXT_SHORTCUT: a shortcut is not valid.
'-- ERR_AUTOTEXT_UNKNOWN: the shortcut doesn't exist for this group.
'-- ERR_AUTOTEXTGROUP_UNKNOWN: the group is unknown.
'-- ERR_AUTOTEXT_EXISTS: the shortcut already exists in this group.
'-- ERR_AUTOTEXT_CANTCREATE: creation problem. The AutoText wasn't created.

Dim lo_AutotextGroup As Object 'the autotext group
Dim l_OldShortcut As String 'the shortcut to change
Dim l_NewShortcut As String 'the new shortcut
Dim l_OldIndex As Long 'the index of the initial autotext entry
Dim lo_OldAutoText As Object 'the initial autotext object
Dim lo_NewAutoText As Object 'the new autotext object
Dim l_Err As Long

l_Err = ERR_AUTOTEXT_NONE
l_OldShortcut = Trim(pOldShortcut)
l_NewShortcut = Trim(pNewShortcut)
If (l_OldShortcut <> "") And (l_NewShortcut <> "") Then
lo_AutotextGroup = GetAutotextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
If lo_AutotextGroup.hasByName(l_OldShortcut) Then
'get current data
l_OldIndex = AutoTextShortcutIndex(lo_AutotextGroup, l_OldShortcut)
lo_OldAutoText = lo_AutotextGroup.getByIndex(l_OldIndex)
If Not lo_AutotextGroup.hasByName(l_NewShortcut) Then
'add new one
lo_NewAutoText = NewAutoText(lo_AutotextGroup, lo_AutotextGroup.Titles(l_OldIndex), l_NewShortCut, lo_OldAutoText.Text)
If Not IsNull(lo_NewAutoText) Then
lo_AutotextGroup.removeByName(l_OldShortcut)
Else
'error: couldn't create the new entry
l_Err = ERR_AUTOTEXT_CANTCREATE
End If
Else
'error: new shortcut exists already
l_Err = ERR_AUTOTEXT_EXISTS
End If
Else
'error: old shortcut doesn't exist
l_Err = ERR_AUTOTEXT_UNKNOWN
End If
Else
'error: group doesn't exist
l_Err = ERR_AUTOTEXTGROUP_UNKNOWN
End If
Else
'error: non valid shortcut
l_Err = ERR_AUTOTEXT_SHORTCUT
End If

RenameAutoText = l_Err
End Function 'RenameAutoText
WriterPrim Autotexts UpdateAutoText Basic AddAutoText (Procedure)
NewAutoText (Procedure)
707 73
Function UpdateAutoText(ByRef pGroupName As String, pTitle As String, pShortcut As String, pNewText As Object) As Long
'Updates an existing autotext contents and returns the result.
'Input:
'-- pGroupName: the owning autotext group name for the autotext
'-- pTitle: the new autotext title (the full name)
' If not provided (0-length string) then the current value is retained.
'-- pShortcut: the name of the autotext (the shortcut)
'-- pNewText: the autotext actual contents that will replace the existing one (text cursor)
'Output: the error status. Returns 0 if OK, otherwise see ERR_AUTOTEXT_XXX constants.
'-- ERR_AUTOTEXT_NONE: (0) creation completed.
'-- ERR_AUTOTEXT_SHORTCUT: the shortcut is not valid.
'-- ERR_AUTOTEXT_UNKNOWN: the shortcut doesn't exist for this group.
'-- ERR_AUTOTEXTGROUP_UNKNOWN: the group is unknown.
'-- ERR_AUTOTEXT_CANTCREATE: creation problem. The AutoText wasn't created.
'
'Warning: This function attempts to create a new autotext within the specified group.
' If the target group is the LibO Basis container, some systems might refuse write access, thus cause
' a runtime error which is intercepted by the On Local Error statement below.
' Hence, in this situation, the returned object is Null.

Dim lo_AutotextGroup As Object 'the autotext group
Dim lo_UpdAutoText As Object 'the updated autotext object
Dim l_Shortcut As String 'the current shortcut
Dim l_TempShortcut As String 'the temporary shortcut
Dim l_Title As String 'the title
Dim i As Long 'the autotext index in its owning group
Dim l_Err As Long

l_Err = ERR_AUTOTEXT_NONE
l_Shortcut = Trim(pShortcut)
If (l_Shortcut <> "") Then
lo_AutotextGroup = GetAutotextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
If lo_AutotextGroup.hasByName(l_Shortcut) Then
'set title if not changed
If (Trim(pTitle) = "") Then
i = AutoTextShortcutIndex(lo_AutotextGroup, l_Shortcut)
l_Title = lo_AutotextGroup.Titles(i)
Else
l_Title = pTitle
End If

'copy to a temporary shortcut
l_TempShortcut = l_Shortcut & "_TEMPUPD"
l_Err = RenameAutoText(pGroupName, l_ShortCut, l_TempShortcut)

'create the new entry and delete the temporary entry
If (l_Err = ERR_AUTOTEXT_NONE) Then
'create a new entry with the new shortcut
On Local Error Resume Next
lo_UpdAutoText = lo_AutotextGroup.insertNewByName(l_Shortcut, l_Title, pNewText)
If Err Then
l_Err = ERR_AUTOTEXT_CANTCREATE
Else
'remove temporary shortcut
lo_AutotextGroup.removeByName(l_TempShortcut)
End If
End If
Else
'error: the shortcut doesn't exist
l_Err = ERR_AUTOTEXT_UNKNOWN
End If
Else
'error: the group is unknown
l_Err = ERR_AUTOTEXTGROUP_UNKNOWN
End If
Else
'error: non valid shortcut
l_Err = ERR_AUTOTEXT_SHORTCUT
End If

UpdateAutoText = l_Err
End Function 'UpdateAutoText
WriterPrim Autotexts UpdateAutoTextTitle Basic   781 55
Function UpdateAutoTextTitle(ByRef pGroupName As String, pNewTitle As String, pShortcut As String) As Long
'Updates an existing autotext title and returns the result.
'Input:
'-- pGroupName: the owning autotext group name for the autotext
'-- pNewTitle: the new autotext title (the full name)
'-- pShortcut: the autotext shortcut
'Output: the error status. Returns 0 if OK, otherwise see ERR_AUTOTEXT_XXX constants.
'-- ERR_AUTOTEXT_NONE: (0) creation completed.
'-- ERR_AUTOTEXT_SHORTCUT: the shortcut is not valid.
'-- ERR_AUTOTEXT_TITLE: the title is not valid.
'-- ERR_AUTOTEXT_UNKNOWN: the shortcut doesn't exist for this group.
'-- ERR_AUTOTEXTGROUP_UNKNOWN: the group is unknown.
'
'Warning: This function attempts to create a new autotext within the specified group.
' If the target group is the LibO Basis container, some systems might refuse write access, thus cause
' a runtime error which is intercepted by the On Local Error statement below.
' Hence, in this situation, the returned object is Null.

Dim lo_AutotextGroup As Object 'the autotext group
Dim lo_TextRange As Object 'the AutoText text
Dim lo_CurAutoText As Object 'the current AutoText
Dim lo_UpdAutoText As Object 'the updated AutoText
Dim l_Shortcut As String 'the shortcut for the autotext entry
Dim l_TempShortcut As String 'a temporary shortcut
Dim i As Long
Dim l_Err As Long

l_Err = ERR_AUTOTEXT_NONE
l_Shortcut = Trim(pShortcut)
If (l_Shortcut <> "") Then
If (Trim(pNewTitle) <> "") Then
lo_AutotextGroup = GetAutotextGroupByName(pGroupName)
If Not IsNull(lo_AutotextGroup) Then
i = AutoTextShortcutIndex(lo_AutotextGroup, l_Shortcut)
If (i > -1) Then
lo_AutotextGroup.Titles(i) = pNewTitle
Else
'error: autotext entry not found
l_Err = ERR_AUTOTEXT_UNKNOWN
End If
Else
'error: the group is unknown
l_Err = ERR_AUTOTEXTGROUP_UNKNOWN
End If
Else
'error: no title set
l_Err = ERR_AUTOTEXT_TITLE
End If
Else
'error: non valid shortcut
l_Err = ERR_AUTOTEXT_SHORTCUT
End If

UpdateAutoTextTitle = l_Err
End Function 'UpdateAutoTextTitle
WriterPrim Bookmarks CreateBookmark Basic   42 30
Function CreateBookmark(ByRef pBookmarkName As String, ByRef pCursor As Object, Optional ByRef pDoc As Object) As Object
'Creates a bookmark in a document at a cursor place.
'Input:
'-- pBookmarkName: the name of the bookmark to be created.
'-- pCursor: the cursor where the bookmark should be created.
'-- pDoc: (optional) the document that will get the new bookmark.
' Defaults to the current document.
'Output: the created bookmark object or Null if the process failed.
'
'The possible process failures are:
'-- no bookmark name was provided
'-- the cursor is not set or not compatible
'-- the bookmarkname already exists

Dim lo_Anchor As Object 'the bookmark anchor

If IsMissing(pDoc) Then pDoc = ThisComponent

If Not IsNull(pCursor) And (Trim(pBookmarkName) <> "") Then
lo_Anchor = pDoc.createInstance("com.sun.star.text.Bookmark")
lo_Anchor.setName(pBookmarkName)
On Local Error GoTo ErrHandler:
pDoc.Text.insertTextContent(pCursor, lo_Anchor, False)
End If

ErrHandler:
'do nothing

CreateBookmark = lo_Anchor
End Function 'CreateBookmark
WriterPrim Bookmarks GotoBookmark Basic   73 37
Function GotoBookmark(ByRef pBookmarkName As String, Optional ByRef pSelect As Boolean, Optional ByRef pVisible As Boolean, Optional ByRef pDoc As Object) As Object
'Sets a cursor to a bookmark.
'Input:
'-- pBookmarkName: the name of the bookmark to be reached.
'-- pSelect: (optional) select the text between the current cursor position and the bookmark
' Defaults to False.
'-- pVisible: (optional) True to use the visible cursor otherwise use a (invisible) text cursor.
' Defaults to True.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: the bookmark object or Null in case of failure.
'
'The possible process failures (result False) are:
'-- no bookmark name was provided
'-- the bookmark name wasn't found.

Dim lo_Bookmark As Object 'the wanted bookmark
Dim lo_Cur As Object 'the cursor
Dim lo_Bookmarks As Object 'the bookmarks collection

If IsMissing(pSelect) Then pSelect = False
If IsMissing(pVisible) Then pVisible = True
If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Bookmarks = pDoc.Bookmarks
If lo_Bookmarks.hasByName(pBookmarkName) Then
lo_Bookmark = lo_Bookmarks.getByName(pBookmarkName)
If pVisible Then
lo_Cur = pDoc.CurrentController.ViewCursor
Else
lo_Cur = pDoc.Text.createTextCursor
End If
lo_Cur.gotoRange(lo_Bookmark.Anchor, pSelect)
End If

GotoBookmark = lo_Bookmark
End Function 'GotoBookmark
WriterPrim Bookmarks GotoBookmarkFromCursor Basic   111 30
Function GotoBookmarkFromCursor(ByRef pBookmarkName As String, ByRef pCursor As Object, Optional pSelect As Boolean, Optional ByRef pDoc As Object) As Object
'Sets a given cursor to a bookmark.
'Input:
'-- pBookmarkName: the name of the bookmark to be reached.
'-- pCursor: the cursor to use to go to the bookmark.
'-- pSelect: (optional) select the text between the current cursor position and the bookmark.
' Defaults to False.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: the bookmark object or Null in case of failure.
'
'The possible process failures (result False) are:
'-- no bookmark name was provided
'-- the bookmark name wasn't found.

Dim lo_Bookmark As Object 'the wanted bookmark
Dim lo_Cur As Object 'the cursor
Dim lo_Bookmarks As Object 'the bookmarks collection

If IsMissing(pSelect) Then pSelect = False
If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Bookmarks = pDoc.Bookmarks
If lo_Bookmarks.hasByName(pBookmarkName) Then
lo_Bookmark = lo_Bookmarks.getByName(pBookmarkName)
pCursor.gotoRange(lo_Bookmark.Anchor, pSelect)
End If

GotoBookmarkFromCursor = lo_Bookmark
End Function 'GotoBookmarkFromCursor
WriterPrim Bookmarks RemoveBookmark Basic   142 33
Function RemoveBookmark(ByRef pBookmarkName As String, Optional ByRef pDoc As Object) As Boolean
'Deletes a bookmark.
'Input:
'-- pBookmarkName: the name of the bookmark to be removed.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: True if the bookmark was removed otherwise False.
'
'The possible process failures (result False) are:
'-- no bookmark name was provided
'-- the bookmarkname wasn't found.

Dim lo_Bookmarks As Object
Dim lo_Bookmark As Object
Dim lo_Anchor As Object 'the bookmark anchor
Dim l_OK As Boolean

If IsMissing(pDoc) Then pDoc = ThisComponent

l_OK = False
lo_Bookmarks = pDoc.Bookmarks
If lo_Bookmarks.hasByName(pBookmarkName) Then
lo_Bookmark = lo_Bookmarks.getByName(pBookmarkName)
On Local Error GoTo ErrHandler:
pDoc.Text.removeTextContent(lo_Bookmark)
l_OK = True
End If

ErrHandler:
'do nothing

RemoveBookmark = l_OK
End Function 'RemoveBookmark
WriterPrim Fields CreateMasterField Basic ExportMasterFields (Procedure) 54 37
Function CreateMasterField(ByRef pFieldName As String, Optional pValue As Variant, Optional pDoc As Object) As Boolean
'Creates a user field (aka MasterField in a Writer document).
'Input:
'-- pFieldName: the master field name
'-- pValue: if provided, sets the initial value for the created master field.
'-- pDoc: the document in which the master field is to be created.
' If not specified, the current document is assumed.
'Output: True if the operation was successful otherwise False.

Dim lo_Masters As Object 'the masterfields in the target document
Dim lo_Master As Object 'a masterfield
Dim l_OK As Boolean 'the process flag

l_OK = False

'we don't process blank field names
If (Trim(pFieldName) <> "") Then
If IsMissing(pDoc) Then pDoc = ThisComponent

On Local Error Goto ErrHandler:
lo_Masters = pDoc.TextFieldMasters
If Not lo_Masters.hasByName(MFLD_USERSERVICE & pFieldName) Then
lo_Master = pDoc.createInstance(MFLD_USERINSTANCE)
lo_Master.Name = pFieldName
End If

If Not IsMissing(pValue) Then
lo_Master = lo_Masters.getByName(MFLD_USERSERVICE & pFieldName)
lo_Master.Content = pValue
End If
End If

ErrHandler:
If Err Then l_OK = False

CreateMasterField = l_OK
End Function 'CreateMasterField
WriterPrim Fields DeleteAllMasterFields Basic   92 34
Function DeleteAllMasterFields(Optional pDoc As Object) As Boolean
'Deletes all master fields in a document.
'Input:
'-- pDoc: (optional) the document in which the master fields are to be deleted.
' Defaults to the current document.
'Output: True if the operation was successful otherwise False.

Dim lo_Masters As Object 'the masterfields in the target document
Dim lo_Master As Object 'a masterfield
Dim l_MasterName As String 'a masterfield name
Dim l_OK As Boolean 'the process flag
Dim i As Long

l_OK = False
If IsMissing(pDoc) Then pDoc = ThisComponent

On Local Error Goto ErrHandler
lo_Masters = pDoc.TextFieldMasters
For i = UBound(lo_Masters.ElementNames()) To LBound(lo_Masters.ElementNames()) Step -1
l_MasterName = lo_MastersSrc.ElementNames(i)
If IsMasterFieldUser(l_MasterName) Then
If lo_Masters.hasByName(l_MasterName) Then
lo_Master = lo_Masters.getByName(l_MasterName)
lo_Master.dispose
l_OK = True
End If
End If
Next i

ErrHandler:
l_OK = Not Err

DeleteAllMasterFields = l_OK
End Function 'DeleteAllMasterFields
WriterPrim Fields DeleteMasterField Basic   127 28
Function DeleteMasterField(ByRef pFieldName As String, Optional pDoc As Object) As Boolean
'Deletes a master field.
'Input:
'-- pFieldName: the master field name
'-- pDoc: the document in which the master field is deleted.
' If not specified, the current document is assumed.
'Output: True if the operation was successful otherwise False.

Dim lo_Masters As Object
Dim lo_Master As Object
Dim l_OK As Boolean

l_OK = False
If IsMissing(pDoc) Then pDoc = ThisComponent

On Local Error Goto ErrHandler:
lo_Masters = pDoc.TextFieldMasters
If lo_Masters.hasByName(MFLD_USERSERVICE & pFieldName) Then
lo_Master = lo_Masters.getByName(MFLD_USERSERVICE & pFieldName)
lo_Master.dispose
l_OK = True
End If

ErrHandler:
l_OK = Not Err

DeleteMasterField = l_OK
End Function 'DeleteMasterField
WriterPrim Fields ExportMasterFields Basic   156 37
Function ExportMasterFields(ByRef pTargetDoc As Object, Optional pSourceDoc As Object) As Boolean
'Exports user fields to some other Writer document.
'Input:
'-- pTargetDoc: the target Writer document
'-- pSourceDoc: (optional) the source document.
' Defaults to the current document.
'Output: True if the process went well, otherwise False

Dim lo_MastersSrc As Object 'the masterfields in the source document
Dim l_FieldName As String 'the current masterfield name
Dim l_Value As Variant 'the current masterfield value
Dim l_OK As Boolean 'the process flag
Dim i As Long

l_OK = False
If IsMissing(pSourceDoc) Then pSourceDoc = ThisComponent

On Local Error Goto FuncEnd:

lo_MastersSrc = pSourceDoc.TextFieldMasters
For i = LBound(lo_MastersSrc.ElementNames()) To UBound(lo_MastersSrc.ElementNames())
l_FieldName = lo_MastersSrc.ElementNames(i)
'we just export users' masterfields (but not sequence fields)
If IsMasterFieldUser(l_FieldName) Then
'read the masterfield name in the source document
l_FieldName = GetMasterFieldNameOnly(l_FieldName)
'get its value
l_Value = GetMasterFieldValue(l_FieldName, pSourceDoc)
'create it within the target document
CreateMasterField(l_FieldName, l_Value, pTargetDoc)
End If
Next
l_OK = True

FuncEnd:
ExportMasterFields = l_OK
End Function 'ExportMasterFields
WriterPrim Fields GetMasterFieldNameOnly Basic ExportMasterFields (Procedure) 194 20
Function GetMasterFieldNameOnly(ByRef pFieldName As String) As String
'Returns the field name alone, as seen in the UI.
'Input:
'-- pMasterName: the full field name (incl. the MFLD_SERSERVICE part)
'Output: the name alone.

Dim l_Name As String
Dim l_arrParts() As String

l_Name = ""

'we don't process blank field names
If (Trim(pFieldName) <> "") Then
'we look for the last part of the passed name (separator is a dot)
l_arrParts = Split(pFieldName, ".")
l_Name = l_arrParts(UBound(l_arrParts))
End If

GetMasterFieldNameOnly = l_Name
End Function 'GetMasterFieldNameOnly
WriterPrim Fields GetMasterFieldType Basic   215 23
Function GetMasterFieldType(ByRef pFieldName As String) As Long
'Returns the masterfield type.
'Input:
'-- pFieldName: the full field name (incl. the MFLD_SERSERVICE part)
'Output: the masterfield type (see the MFLD_TYPE_XXX constants)

Dim l_IsUser As Boolean
Dim l_IsExpr As Boolean
Dim l_Type As Long

l_Type = MFLD_TYPE_UNK
l_IsUser = (InStr(pFieldName, UF_TYPEUSERID) > 0)
If l_IsUser Then
l_Type = MFLD_TYPE_USER
Else
l_IsExpr = (InStr(pFieldName, UF_TYPEEXPRID) > 0)
If l_IsExpr Then
l_Type = MFLD_TYPE_EXPR
End If
End If

GetMasterFieldType = l_Type
End Function 'GetMasterFieldType
WriterPrim Fields GetMasterFieldValue Basic ExportMasterFields (Procedure) 239 27
Function GetMasterFieldValue(ByRef pFieldName As String, Optional pDoc As Object) As Variant
'returns the value of a master field or Nothing if the field is not found.
'Input:
'-- pFieldName: the master field name
'-- pDoc: the document in which the master field is searched.
' If not specified, the current document is assumed.
'Output: the value of the field or Nothing if not found.

Dim lo_Masters As Object
Dim lo_Master As Object
Dim l_Result As Variant

l_Result = Nothing

'we don't process blank field names
If (Trim(pFieldName) <> "") Then
If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Masters = pDoc.TextFieldMasters
lo_Master = lo_Masters.getByName(MFLD_USERSERVICE & pFieldName)
IF Not IsNull(lo_Master) Then
l_Result = lo_Master.Content
End If
End If

GetUserFieldValue = l_Result
End Function 'GetMasterFieldValue
WriterPrim Fields IsMasterFieldUser Basic DeleteAllMasterFields (Procedure)
ExportMasterFields (Procedure)
267 17
Function IsMasterFieldUser(ByRef pFieldName As String) As Boolean
'Checks whether a masterfield is a user one or not.
'Input:
'-- pMasterFieldName: the masterfield name to check
'Output: True is its name contents a ".User." part, otherwise False

Dim l_IsUser As Boolean

l_IsUser = False

'we don't process blank field names
If (Trim(pFieldName) <> "") Then
l_IsUser = (InStr(pFieldName, MFLD_TYPEUSERID) > 0) 'other possibility is: "SetExpression"
End If

IsMasterFieldUser = l_IsUser
End Function 'IsMasterFieldUser
WriterPrim Fields SetMasterFieldValue Basic   285 24
Sub SetMasterFieldValue(ByRef pFieldName As String, pValue As Variant, Optional pDoc As Object)
'Inserts a value into a master field
'Input:
'-- pFieldName: the master field name to be set
'-- pValue: the value to set to the user field
'-- pDoc: the document in which the master field is searched.
' If not specified, the current document is assumed.
'Output: none

Dim lo_Masters As Object
Dim lo_Master As Object

'we don't process blank field names
If (Trim(pFieldName) <> "") Then
If IsMissing(pDoc) Then pDoc = ThisComponent

lo_Masters = pDoc.TextFieldMasters
lo_Master = lo_Masters.getByName(MFLD_USERSERVICE & pFieldName)
IF Not IsNull(lo_Master) Then
lo_Master.Content = pValue
End If
End If

End Sub 'SetMasterFieldValue
WriterPrim Styles GetStyleAtCursor Basic GetTableActualWidth (Procedure) 48 56
Function GetStyleAtCursor(ByRef pTextCursor As Object, pStyleFamily As String) As Object
'returns the style object for the text cursor.
'Input:
'-- pTextCursor: a text cursor object
'-- pStyleFamily: the style family to check
'Output: the style object for the family the text cursor is in,
' or Null if the style is not found or if the text cursor is not set.

Dim lo_Styles As Object 'the styles in a given family
Dim lo_Style As Object 'the wanted style object
Dim l_Name As String 'the style name

If Not IsNull(pTextCursor) Then
Select Case pStyleFamily
'page styles
Case STY_WFAMPAGES
l_Name = pTextCursor.PageStyleName

'paragraph styles
Case STY_WFAMPARAS
l_Name = pTextCursor.ParaStyleName

'character styles
Case STY_WFAMCHARS
If Not IsNull(pTextCursor.CharStyleNames) Then
l_Name = pTextCursor.CharStyleNames(0)
Else
l_Name = ""
End If

'frame/image styles
Case STY_WFAMFRAMES
l_Name = ""

'list styles
Case STY_WFAMNUMBER
l_Name = pTextCursor.NumberingStyleName

'table styles - Added in LibreOffice 5.3
Case STY_WFAMTABLES
l_Name = ""

Case Else
l_Name = ""
End Select

If (l_Name <> "") Then
lo_Styles = ThisComponent.StyleFamilies.getByName(pStyleFamily)
If lo_Styles.hasByName(l_Name) Then
lo_Style = lo_Styles.getByName(l_Name)
End If
End If
End If

GetStyleAtCursor = lo_Style
End Function 'GetStyleAtCursor
WriterPrim Tables GetColumnWidths Basic   43 71
Function GetColumnWidths(ByRef pTableName As String, pRowNum As Long, Optional pDoc As Object) As Variant
'Gets a table column widths and returns them into an array.
'Input:
'-- pTableName: the table name
'-- pRowNum: the row to browse (0-based) or -1 for a global process
'-- pDoc: (optional) the document container.
' If pDoc is missing the current document is assumed.
'Output: an array of all column widths for a given row, one item per column.
' If the row number passed is out of bounds, returns a non-initialised array.

Dim l_arrWidths As Long 'the writer table column widths to be returned
Dim l_Width As Long 'the table total width
Dim l_RelWidth As Long 'the table colmuns relative width
Dim l_ActualWidth As Long 'the actual width, in 100ths of mm
Dim l_ColWidth As Double 'the curent column width
Dim l_Total As Long 'the column widths accumulation
Dim lo_Table As Object 'the table
Dim l_ColCount As Long 'the column count
Dim l_Seps As Variant 'the table columns separators
Dim i As Long

If IsMissing(pDoc) Then pDoc = ThisComponent

If pDoc.TextTables.hasByName(pTableName) Then
lo_Table = ThisComponent.TextTables.getByName(pTableName)
l_RelWidth = lo_Table.TableColumnRelativeSum
l_ActualWidth = GetTableActualWidth(lo_Table)
If lo_Table.IsWidthRelative Then
l_Width = Int(lo_Table.RelativeWidth * l_ActualWidth / 100)
Else
l_Width = lo_Table.Width
End If

If (pRowNum = -1) Then
'get global table data
l_Seps = lo_Table.TableColumnSeparators
Else
'get the data for the specified row
'-> is the row out of bounds?
If (pRowNum > -1) And (pRowNum < lo_Table.Rows.Count) Then
l_Seps = lo_Table.Rows(pRowNum).TableColumnSeparators
Else
GetColumnWidths = l_arrWidths
Exit Function
End If
End If

'browse the columns and get the width information
l_ColCount = UBound(l_Seps) + 2
ReDim l_arrWidths(l_ColCount - 1)
l_Total = 0
For i = 0 To l_ColCount - 1
If (i = l_ColCount - 1) Then
'last column
'note: if the table has only 1 column, this will get its width
l_ColWidth = l_Width - l_Total
ElseIf (i = 0) Then
'first column
l_ColWidth = l_Seps(i).Position / l_RelWidth * l_Width
Else
'other columns
l_ColWidth = (l_Seps(i).Position - l_Seps(i-1).Position) / l_RelWidth * l_Width
End If
l_arrWidths(i) = Int(l_ColWidth / l_Width * l_ActualWidth)
'accumulate
l_Total = l_Total + l_ColWidth
Next
End If

GetColumnWidths = l_arrWidths()
End Function 'GetColumnWidths
WriterPrim Tables GetTableActualWidth Basic GetColumnWidths (Procedure) 115 18
Function GetTableActualWidth(ByRef pTable As Object) As Long
'Returns the actual width of a table, in 100ths of a millimetre
'Input:
'-- pTable: a valid table object to measure
'Output: the table overall width, in 100ths of a millimetre
'
'Note: Uses WriterPrim.Styles.GetStyleAtCursor()

Dim l_Width As Long '100ths of a millimetre
Dim lo_Style As Object

lo_Style = GetStyleAtCursor(pTable.getCellByPosition(0, 0).Text.createTextCursor, STY_WFAMPAGES)
If Not IsNull(lo_Style) Then
l_Width = lo_Style.Width - lo_Style.LeftMargin - lo_Style.RightMargin - pTable.LeftMargin - pTable.RightMargin
End If

GetTableActualWidth = l_Width
End Function 'GetTableActualWidth
WriterPrim Tables GetTableColCountByName Basic   134 26
Function GetTableColCountByName(ByRef pTableName As String, pRowNum As Long, Optional pDoc As Object) As Long
'Returns the column count for a given row in a table name.
'Input:
'-- pTableName: the table name
'-- pRowNum: the row number to count columns
'-- pDoc: (optional) the document container.
' If pDoc is missing the current document is assumed.
'Output: the number of columns or -1 if an error occurred (unknown table or row number out of bounds).

Dim lo_Table As Object 'the table
Dim l_Seps As Variant
Dim l_ColCount As Long 'the colmuns count

If IsMissing(pDoc) Then pDoc = ThisComponent

l_ColCount = -1
If pDoc.TextTables.hasByName(pTableName) Then
lo_Table = ThisComponent.TextTables.getByName(pTableName)
If (pRowNum > -1) And (pRowNum < lo_Table.Rows.Count) Then
l_Seps = lo_Table.Rows(pRowNum).TableColumnSeparators
l_ColCount = UBound(l_Seps) + 2
End If
End If

GetTableColCountByName = l_ColCount
End Function 'GetTableColCountByName
WriterPrim Tables GetTableRowCountByName Basic   161 22
Function GetTableRowCountByName(ByRef pTableName As String, Optional pDoc As Object) As Long
'Returns the row count for a given table name.
'Input:
'-- pTableName: the table name
'-- pDoc: (optional) the document container.
' If pDoc is missing the current document is assumed.
'Output: the number of rows or -1 if the table name is unknown.

Dim lo_Table As Object 'the table
Dim l_RowCount As Long 'the row count

If IsMissing(pDoc) Then pDoc = ThisComponent

If pDoc.TextTables.hasByName(pTableName) Then
lo_Table = ThisComponent.TextTables.getByName(pTableName)
l_RowCount = lo_Table.Rows.Count
Else
l_RowCount = -1
End If

GetTableRowCountByName = l_RowCount
End Function 'GetTableRowCountByName
WriterPrim Tables LockCell Basic   184 15
Sub LockCell(ByRef pTableName As String, pCellName As String, pLock As Boolean)
'(un)locks pCellName in pTableName according to pLock value.

Dim lo_Table As Object
Dim lo_Cell As Object

lo_Table = ThisComponent.TextTables.getByName(pTableName)
If Not IsNull(lo_Table) Then
lo_Cell = lo_Table.getCellByName(pCellName)
If Not IsNull(l_Cell) Then
lo_Cell.IsProtected = pLock
End If
End If

End Sub 'LockCell
WriterPrim Text GetSelection Basic   43 32
Function GetSelection(Optional pNearestWord As Boolean, Optional ByRef pDoc As Object) As Object
'Returns the current selection.
'Input:
'-- pNearestWord: (optional) if there's no current selection, causes
' the function to return the caret nearest word.
' Defaults to False.
'-- pDoc: (optional) the document to process.
' Defaults to the current document.
'Output: the current selection or the nearest word or Null if none.

Dim lo_VCur As Object 'view cursor
Dim lo_TCur As Object 'text cursor
Dim lo_Text As Object

If IsMissing(pDoc) Then pDoc = ThisComponent
If IsNull(pDoc) Then Exit Function

If IsMissing(pNearestWord) Then pNearestWord = False

'inits
lo_VCur = pDoc.CurrentController.ViewCursor
lo_Text = lo_VCur.Text
lo_TCur = lo_Text.CreateTextCursorByRange(lo_VCur)
'If Not HasSelection(pDoc) And pNearestWord Then
If (lo_TCur.String = "") And pNearestWord Then
'no current selection: search the nearest word
lo_TCur.gotoStartOfWord(False)
lo_TCur.gotoEndOfWord(True)
End If

GetSelection = lo_TCur
End Function 'GetSelection
WriterPrim Text HasSelection Basic   76 44
Function HasSelection(Optional ByRef pDoc As Object) As Boolean
'Returns True if some text is selected.
'Input:
'-- pDoc: (optional) the document to check.
' Defaults to the current document.
'Output: True if there's at least one selection, otherwise False.
'
'Adapted from Andrew in OOME 3
'

Dim lo_Sel As Object 'the current selections
Dim lo_ASel As Object 'a single selection
Dim lo_TCur As Object 'a text cursor
Dim l_Found As Boolean

l_Found = False

'check document
If IsMissing(pDoc) Then pDoc = ThisComponent
If IsNull(pDoc) Then Exit Function

'check selection
lo_Sel = pDoc.CurrentSelection
If Not IsNull(lo_Sel) Then
Select Case lo_Sel.Count
'no selection
Case 0
'do nothing

'1 selection, check IsCollapsed() on the associated cursor
Case 1
lo_ASel = lo_Sel.getByIndex(0)
lo_TCur = pDoc.Text.CreateTextCursorByRange(oSel)
l_Found = Not lo_TCur.IsCollapsed()

'more than 1 selection: there's a selection
Case Else
l_Found = True

End Select
End If

HasSelection = l_Found
End Function 'HasSelection