Hello, @karolus , @Lupp, and colleagues!
I suggest the SelectionStat macro with the same idea. Also works when multiple rectangular ranges are selected.
Considering that entire columns and rows can be selected, using the getUniqueCellFormatRanges
method seems useful.
In Python, the text will naturally be shorter. Python also has native dictionaries.
Option Explicit
' Counts the number of cells in a rectangular range, taking into account any merged cells.
Function CountUniqueCells(Byval oRange as Object) as Double
Dim oSheet as Object, oRanges as Object, oRg as Object, oRangeBig as Object
Dim oCur as Object, absoluteName as String, total as Double
Dim oMap as Object, adrRange, adrRg
oSheet = oRange.Spreadsheet
oMap = com.sun.star.container.EnumerableMap.create("string", "string")
adrRange = oRange.RangeAddress
total = GetCellCount(adrRange)
adrRange = oRange.RangeAddress
oRangeBig = oSheet.GetCellRangeByPosition(0, 0, adrRange.EndColumn, adrRange.EndRow)
For Each oRanges In oRangeBig.getUniqueCellFormatRanges()
For Each oRg In oRanges
If oRg.getIsMerged() Then
oCur = oSheet.createCursorByRange(oRg)
oCur.collapseToMergedArea()
absoluteName = oCur.AbsoluteName
If Not oMap.containsKey(absoluteName) Then
oMap.put absoluteName, ""
' Calculating the intersection of ranges oRange and oRg
adrRg = oCur.RangeAddress
With adrRg
If .StartRow < adrRange.StartRow Then .StartRow = adrRange.StartRow
If .StartColumn < adrRange.StartColumn Then .StartColumn = adrRange.StartColumn
If .EndRow > adrRange.EndRow Then .EndRow = adrRange.EndRow
If .EndColumn > adrRange.EndColumn Then .EndColumn = adrRange.EndColumn
If .EndColumn >= .StartColumn And .EndRow >= .StartRow Then
total = total + 1 - GetCellCount(adrRg)
End If
End With
End If
End If
Next oRg
Next oRanges
CountUniqueCells = total
End Function
' Returns the number of cells in a rectangular range.
Function GetCellCount(Byval adrRange as Object) as Double
With adrRange
GetCellCount = CDbl(.EndRow - .StartRow + 1) * CDbl(.EndColumn - .StartColumn + 1)
End With
End Function
' Shows statistics of selected cells
Sub SelectionStat()
Dim oSel as Object, aRanges, oRange as Object, adrRange
Dim nAreas as Double, nCells as Double, nUniqueCells as Double
oSel = ThisComponent.CurrentSelection
If HasUnoInterfaces(oSel, "com.sun.star.sheet.XSheetCellRange") Then
aRanges = Array(oSel)
ElseIf HasUnoInterfaces(oSel, "com.sun.star.sheet.XSheetCellRanges") Then
aRanges = oSel
Else
Msgbox "No cells selected"
Exit Sub
End If
For Each oRange In aRanges
nAreas = nAreas + 1
adrRange = oRange.RangeAddress
nCells = nCells + GetCellCount(adrRange)
nUniqueCells = nUniqueCells + CountUniqueCells(oRange)
Next
Msgbox "Areas: " & nAreas & Chr(10) & _
"Cells: " & nCells & Chr(10) & _
"UniqueCells: " & nUniqueCells
End Sub