lobasic-macros

LibreOffice macros I use often

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
4 files changed, 373 insertions(+), 124 deletions(-)
A
.gitignore
|
1
+
A
Standard/Bharatgas.xba
|
371
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
Standard/Module1.xba
|
123
-------------------------------------------------------------------------------
M
Standard/script.xlb
|
2
+-
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