lobasic-macros

LibreOffice macros I use often
Log | Files | Refs

commit dfeca12b63083958b3bdc493c1430aa7e6a83d6e
parent c63614bb3b8dfbc55a3997ffd4fb2342aff163c0
Author: Bharatvaj Hemanth <bharatvaj@yahoo.com>
Date:   Tue, 25 Jun 2024 11:22:47 +0530

Fix UserFriendlyNames, HighlightOnline

Make the code more procedural

Diffstat:
A.gitignore | 1+
AStandard/Bharatgas.xba | 371+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DStandard/Module1.xba | 123-------------------------------------------------------------------------------
MStandard/script.xlb | 2+-
4 files changed, 373 insertions(+), 124 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +tags diff --git a/Standard/Bharatgas.xba b/Standard/Bharatgas.xba @@ -0,0 +1,370 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd"> +<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Bharatgas" script:language="StarBasic">REM ***** BASIC ***** +&apos;Option VBASupport 1 +Option Explicit + +Global Const exportFolder = &quot;C:\Users\bhara\export&quot; +Global Const rowsToSkip = 1 +Global Const insertNewRowFor = False +Global Const printOnlySummary = True +Global Const highlightBasedOn = &quot;Payment Option&quot; +Global Const roughHeaderMatch = True +Global Const highlightSearchString = &quot;Online Payment&quot; + +Function UsedRangeCursor(Optional ByRef oSheet as Object) as Object + &apos;FIXME Check if the split has already happen + Dim cursor as Object + if IsNull(oSheet) Or IsMissing(oSheet) Then + oSheet = ThisComponent.getCurrentController().getActiveSheet() + End If + cursor = oSheet.createCursor() + cursor.gotoStartOfUsedArea(False) + cursor.gotoEndOfUsedArea(True) + UsedRangeCursor = cursor +End Function + +Function UserFriendlyName(str as String) as String + Dim l as Long + Dim c as String + Dim i as Long + Dim prevChar as String + str = Trim(str) + &apos; Check if Len(str) is really called multiple times + l = Len(str) + For i = 0 To l + c = Mid(str, i + 1, 1) + If i &gt; 1 And (c &gt; &quot;A&quot; And c &lt; &quot;Z&quot;) Then + &apos; Only prepend space if &apos;c&apos; is not the first character... + &apos; or previous char doesn&apos;t have space + UserFriendlyName = UserFriendlyName &amp; IIf(prevChar = &quot; &quot;, &quot;&quot;, &quot; &quot;) &amp; c + Else + UserFriendlyName = UserFriendlyName &amp; c + End If + prevChar = c + Next +End Function + +Sub TestFn() + MsgBox UserFriendlyName(&quot;Area Name&quot;) + MsgBox UserFriendlyName(&quot;AreaName&quot;) + MsgBox UserFriendlyName(&quot; AreaName&quot;) +End Sub + +Sub SortAreaName(Optional oSheet As Variant, Optional cursor as Variant) + Dim oRange as Object + Dim oSortFields(0) as new com.sun.star.util.SortField + Dim oSortDesc(0) as new com.sun.star.beans.PropertyValue + Dim endRow as Integer + Dim endColumn as Integer + + If IsMissing(oSheet) Then + oSheet = ThisComponent.Sheets(0) + cursor = UsedRangeCursor(oSheet) + End If + + endRow = cursor.RangeAddress.EndRow + endColumn = cursor.RangeAddress.EndColumn + + oRange = oSheet.getCellRangeByPosition(0, 1, endColumn, endRow) + ThisComponent.getCurrentController.select(oRange) + + &apos; Area + oSortFields(0).Field = 0 + oSortFields(0).SortAscending = True + + &apos; FIXME This is not working + &apos; Date + &apos;oSortFields(1).Field = 4 + &apos;oSortFields(1).SortAscending = True + + oSortDesc(0).Name = &quot;SortFields&quot; + oSortDesc(0).Value = oSortFields + + oRange.Sort(oSortDesc) +End Sub + +Sub NewSheet(sheetName as String) + Dim sheets as Object + sheets = ThisComponent.Sheets() + If Not sheets.hasByName(sheetName) Then + sheets.insertNewByName(sheetName, sheets.getCount()) + End If + +End Sub + +Sub CleanColumnHeaders(oSheet as Object, endColumn as Integer) + Dim cell as Object + Dim neatName as String + Dim i as Integer + For i = 0 To endColumn + cell = oSheet.getCellByPosition(i, 0) + neatName = cell.getString() + neatName = UserFriendlyName(neatName) + cell.setString(neatName) + Next +End Sub + +Sub RemoveExtraMergeCells(oSheet as Object, oRangeAddress as Variant) + Dim oRange as Object + Dim oSortFields(0) as new com.sun.star.util.SortField + Dim oSortDesc(0) as new com.sun.star.beans.PropertyValue + Dim endRow as Integer + + endRow = oRangeAddress.EndRow + lastColumn = oRangeAddress.EndColumn + + rem set the range on which to sort&apos; + + &apos;oRange = oSheet.getCellRangeByName(&quot;A2:F20&quot;) + oRange = oSheet.getCellRangeByPosition(0, 0, lastColumn, 0) + ThisComponent.getCurrentController.select(oRange) + initialColumnCount = oRange.Columns.getCount() - 1 + deletedColumns = 0 + For j = 0 To (initialColumnCount - deletedColumns) + oCell = oRange.getCellByPosition(j, 0) + con = oCell.String + If con = &quot;&quot; Then + oRange.Columns.removeByIndex(j, 1) + deletedColumns = deletedColumns - 1 + Else + Print con + End If + Next +End Sub + + +Sub UnFreezeSelection + Dim document as Object + Dim dispatcher as Object + document = ThisComponent.CurrentController.Frame + dispatcher = createUnoService(&quot;com.sun.star.frame.DispatchHelper&quot;) + dispatcher.executeDispatch(document, &quot;.uno:FreezePanes&quot;, &quot;&quot;, 0, Array()) +End Sub + +Function GetHeaderPosition(ByRef oSheet as Object, searchString as String, endColumn as Long) as Integer + Dim iColumn as Integer + Dim oCell as Object + Dim cellString as String + If roughHeaderMatch Then + searchString = UserFriendlyName(searchString) + End If + For iColumn = 0 To endColumn - 1 + oCell = oSheet.getCellByPosition(iColumn, 0) + cellString = oCell.String + If roughHeaderMatch Then + cellString = UserFriendlyName(cellString) + End If + If cellString = searchString Then + GetHeaderPosition = iColumn + Exit For + End If + Next iColumn +End Function + +Sub HighlightOnline(ByRef oSheet as Object, endColumn as Long, endRow as Long) + &apos; Fix false positives when having ONLINE and the content has &quot;Online Payment&quot; + Dim currentStr as String + Dim oCell as Object + Dim oCellRange as Object + Dim str as String + Dim iSearchColumn as Long + Dim i as Integer + + &apos; Search for column position that has highlightBasedOn + iSearchColumn = GetHeaderPosition(oSheet, highlightBasedOn, endRow) + + For i = 0 To endRow - 1 + oCell = oSheet.getCellByPosition(iSearchColumn, i) + If InStr(oCell.getString(), highlightSearchString) &gt; 0 Then + oCellRange = oSheet.getCellRangeByPosition(0, i, endColumn, i) + oCellRange.CellBackColor = RGB(255, 255, 0) &apos; Yellow + End If + Next i +End Sub + + +Sub MainNew + Dim oRange as Object + Dim oSheet as Object + Dim oCellStyle as Object + oSheet = ThisComponent.Sheets.getByIndex(0) + oRange = oSheet.getCellRangeByPosition(1, 1, 4, 1) + &apos;oCellStyle = ThisComponent.StyleFamilies.getByName(&quot;CellStyles&quot;).getByName(&quot;InterHeader&quot;) + oRange.CellStyle = &quot;InterHeader&quot; +End Sub + +Sub Main + Dim s as Object + Dim cursor as Object + Dim c as Integer + Dim destSheet as Variant + Dim sheetName as String + Dim iArea as Long + Dim d as String + Dim a as String + Dim startRow as Long + Dim areaNames as New Collection + Dim dColumns as Object + Dim endRow as Long + Dim endColumn as Long + Dim areaColumn as Object + Dim areaRange, idRange, bookRange + Dim headerRange as Object + Dim cellRangeToCopy as Object + + s = ThisComponent.Sheets(0) + cursor = UsedRangeCursor(s) + + &apos; Skip Header + startRow = rowsToSkip + endRow = cursor.RangeAddress.EndRow + endColumn = cursor.RangeAddress.EndColumn + + &apos; TODO pass the column name/index as an argument + &apos; Transformations to be applied to the Main sheet before splitting the sheet by Area Name + &apos;Call UnFreezeSelection + cursor = UsedRangeCursor(s) + Call HighlightOnline(s, endColumn, endRow) + Call SortAreaName(s, cursor) + Call CleanColumnHeaders(s, endColumn) + + &apos; Justify Leftmost cells to left and Rightmost cells to right + &apos; TODO Maybe use more descriptive code? Like (&quot;AreaName&quot;)? + idRange = s.getCellRangeByPosition(1,startRow, 1, endRow) + idRange.setPropertyValue(&quot;HoriJustify&quot;, com.sun.star.table.CellHoriJustify.LEFT) + + bookRange = s.getCellRangeByPosition(endColumn, startRow, endColumn, endRow) + bookRange.setPropertyValue(&quot;HoriJustify&quot;, com.sun.star.table.CellHoriJustify.RIGHT) + + areaColumn = s.getCellRangeByPosition(0,startRow, 0, endRow) + headerRange = s.getCellRangeByPosition(0, 0, endColumn, 0) + + headerRange.CellStyle = &quot;Heading 1&quot; + &apos;On Error Goto ErrorHandler + For iArea = rowsToSkip To endRow - 1 + d = areaColumn.getCellByPosition(0, iArea).String + If d = &quot;&quot; Then + Exit For + End If + + If a &lt;&gt; d Or iArea = (endRow - 1) Then + &apos; FIXME Get the columns automatically from the sheet + &apos; FIXME Covert the end column from endColumn above + + If insertNewRowFor Then + &apos; FIXME This is a stub, not correct + s.Rows.insertByIndex(startRow, 1) + startRow = startRow + 1 + endRow = endRow + 1 + End If + + areaRange = s.getCellRangeByPosition(0, startRow, endColumn, iArea) + If printOnlySummary Then + GoTo Continue + End If + + &apos; TODO subtotals might solve this + &apos;s.group(areaRange.RangeAddress, 1) + + sheetName = a &amp; &quot; - PENDING&quot; + + &apos; Copy the Headers from the Main Document + &apos; FIXME This DOES NOT work when using with filtered data + &apos; TODO Get the number of columns to copy dynamically from the Sheet. + cellRangeToCopy = areaRange.RangeAddress + + If (cellRangeToCopy.EndRow - cellRangeToCopy.StartRow) = 0 Then + Goto Continue + End If + + &apos; Prepare Destination sheet + NewSheet(sheetName) + + destSheet = ThisComponent.Sheets().getByName(sheetName) + + &apos; Customize the Destination Sheet&apos;s Columns + &apos; TODO Make snuggly calculation. There should be a minimum width and AutoFit + destSheet.getColumns().getByName(&quot;B&quot;).Width = 2500 + destSheet.getColumns().getByName(&quot;C&quot;).Width = 4500 + &apos;destSheet.getColumns().getByName(&quot;F&quot;).Width = 8000 + + &apos; Copy Header + &apos; TODO Check if it&apos;s possible to use UsedRange instead of endColumn + s.copyRange(destSheet.getCellRangeByName(&quot;A1&quot;).CellAddress, _ + headerRange.RangeAddress) + + &apos; Copy all the contents uptil + s.copyRange(destSheet.getCellRangeByName(&quot;A2&quot;).CellAddress, _ + cellRangeToCopy) + + &apos;TODO Remove Columns that should be deleted in leaveColumns + &apos; Better leave it when copying above + destSheet.getColumns().removeByIndex(0, 1) + destSheet.getColumns().removeByIndex(4, 1) + + &apos;TODO Maybe use Dispatcher? + ExportPDF(destSheet) + Continue: + startRow = (iArea + 1) + a = d + End If + Next iArea + + ErrorHandler: + MsgBox &quot;Error#: &quot; &amp; Erl &amp; Error + &apos;MsgBox &quot;arrCount: &quot; &amp; areaNames.Count + MsgBox &quot;a: &quot; &amp; a &amp; &quot;, d: &quot; &amp; d + Reset +End Sub + +Sub ValidateFileName(fileName as String) + Dim invalidChars as String : invalidChars = &quot;\/:*?&quot;&quot;&lt;&gt;|&quot; + + For i = 1 To Len(fileName) + c = Mid(fileName, i, 1) + If InStr(invalidChars, c) &gt; 0 Then + Print &quot;invalid&quot; &amp; c + End If + Next +End Sub + +Sub ExportPDF(Optional ByVal oSheet as Object) + &apos;Exit Sub + Dim cursor as Object + Dim args(2) as New com.sun.star.beans.PropertyValue + Dim fd(2) as New com.sun.star.beans.PropertyValue + + Dim fileName as String + Dim fileUrl As String + + cursor = UsedRangeCursor(oSheet) + + &apos;ThisComponent.CurrentController.select(cursor) + fileName = exportFolder &amp; &quot;\&quot; &amp; oSheet.Name &amp; &quot;.pdf&quot; + fileUrl = ConvertToUrl(fileName) + + args(0).Name = &quot;FilterName&quot; + args(0).Value = &quot;calc_pdf_Export&quot; + + fd(0).Name = &quot;Selection&quot; + fd(0).Value = cursor + + &apos; conflicts with the Selection + fd(1).Name = &quot;SinglePageSheets&quot; + fd(1).Value = False + + fd(2).Name = &quot;IsSkipEmptyPages&quot; + fd(2).Value = True + + args(1).Name = &quot;FilterData&quot; + args(1).Value = fd + + args(2).Name = &quot;Overwrite&quot; + args(2).Value = True + + ThisComponent.storeToURL(fileUrl, args) +End Sub + + +</script:module> +\ No newline at end of file diff --git a/Standard/Module1.xba b/Standard/Module1.xba @@ -1,122 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd"> -<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic">Sub RemoveFreezedCells - s = ThisComponent.Sheets(0) - a = s.freezeAtPosition(0,1) - &apos;iFreezeRow = s.getPropertyValue(&quot;SplitRow&quot;) - &apos;MsgBox iFreezeRow -End Sub - -Rem Copy this to do the Windows Macros - -Sub RemoveExtraMergeCells - Dim oSheet as Variant - Dim cursor as Object - Dim oRange as Object - Dim oSortFields(0) as new com.sun.star.util.SortField - Dim oSortDesc(0) as new com.sun.star.beans.PropertyValue - Dim lastRow as Integer - - oSheet = ThisComponent.Sheets(0) - - cursor = oSheet.createCursor() - cursor.gotoStartOfUsedArea(False) - cursor.gotoEndOfUsedArea(True) - lastRow = cursor.RangeAddress.EndRow - lastColumn = cursor.RangeAddress.EndColumn - - rem set the range on which to sort&apos; - - &apos;oRange = oSheet.getCellRangeByName(&quot;A2:F20&quot;) - oRange = oSheet.getCellRangeByPosition(0, 0, lastColumn, 0) - ThisComponent.getCurrentController.select(oRange) - initialColumnCount = oRange.Columns.getCount() - 1 - deletedColumns = 0 - For j = 0 To (initialColumnCount - deletedColumns) - oCell = oRange.getCellByPosition(j, 0) - con = oCell.String - If con = &quot;&quot; Then - oRange.Columns.removeByIndex(j, 1) - deletedColumns = deletedColumns - 1 - Else - Print con - End If - Next -End Sub - -Sub SortAreaName - Dim oSheet as Variant - Dim cursor as Object - Dim oRange as Object - Dim oSortFields(0) as new com.sun.star.util.SortField - Dim oSortDesc(0) as new com.sun.star.beans.PropertyValue - Dim lastRow as Integer - - oSheet = ThisComponent.Sheets(0) - - cursor = oSheet.createCursor() - cursor.gotoStartOfUsedArea(False) - cursor.gotoEndOfUsedArea(True) - lastRow = cursor.RangeAddress.EndRow - - rem set the range on which to sort&apos; - &apos;oRange = oSheet.getCellRangeByPosition(0, 0, oSheet.Columns.Count - 1, oSheet.Rows.Count - 1) - &apos;oRange = oSheet.getCellRangeByName(&quot;A2:F20&quot;) - oRange = oSheet.getCellRangeByPosition(0, 1, 5, lastRow) - &apos;ThisComponent.getCurrentController.select(oRange) - - oSortFields(0).Field = 0 - oSortFields(0).SortAscending = True - - oSortDesc(0).Name = &quot;SortFields&quot; - oSortDesc(0).Value = oSortFields - - oRange.Sort(oSortDesc) -End Sub - -Sub SortTest - oSheet = ThisComponent.Sheets(0) - oRange = oSheet.queryContentCells(com.sun.star.sheet.CellFlags.VALUE) - - MsgBox oRange.Rows.Count - Exit Sub - - for x = 1 to oRange.Rows.Count - for y = 1 to oRange.Columns.Count - oSheet.getCellByPosition(x, y).Value = 0 - - next y - next x - -End Sub - -Sub Main - AssignVars - SortTest - rem SortAreaName -End Sub - -sub UnFreezeSelection - dim document as object - dim dispatcher as object - document = ThisComponent.CurrentController.Frame - dispatcher = createUnoService(&quot;com.sun.star.frame.DispatchHelper&quot;) - dispatcher.executeDispatch(document, &quot;.uno:FreezePanes&quot;, &quot;&quot;, 0, Array()) -end sub - -sub SortAscendingRecorded -rem ---------------------------------------------------------------------- -rem define variables -dim document as object -dim dispatcher as object -rem ---------------------------------------------------------------------- -rem get access to the document -document = ThisComponent.CurrentController.Frame -dispatcher = createUnoService(&quot;com.sun.star.frame.DispatchHelper&quot;) - -rem ---------------------------------------------------------------------- -dispatcher.executeDispatch(document, &quot;.uno:SortAscending&quot;, &quot;&quot;, 0, Array()) - - -end sub -</script:module> -\ No newline at end of file diff --git a/Standard/script.xlb b/Standard/script.xlb @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd"> <library:library xmlns:library="http://openoffice.org/2000/library" library:name="Standard" library:readonly="false" library:passwordprotected="false"> - <library:element library:name="Module1"/> + <library:element library:name="Bharatgas"/> </library:library> \ No newline at end of file