Если оперировать поячеечно, то несложно выполнить любую операцию с множествами ячеек. Но в функциях Intersect и Union были задействованы штатные возможности.
В коде ниже при вычитании (Difference) использована функция GetCellCollection.
В качестве ключа элемента коллекции ячеек задано имя ячейки AbsoluteName. По ключу и удаляем (вычитаем) ненужные ячейки.
В примере от @sokol92 использован словарь (Map) с ключом в виде отформатированной комбинации свойств (индексы листа, столбца, строки...). Сделано это для решения проблемы сортировки ячеек при их помещении (put) в словарь. Таким образом, если использовать этот подход, то и ключ будет соответствующим при удалении ячейки из словаря.
Работать с VBA Collection проще, но возникла проблема с сортировкой ячеек перед их добавлении в коллекцию. В ответе #21 приведен пример сортировки, если бы это был не Basic, а Python. В ответе #22 показан способ сортировки через выделение на листе, но он имеет баг при выделении диапазонов, расположенных на нескольких листах (возможный, но менее вероятный случай).
Впрочем, несложно реализовать функцию AddToSortedCollection
Function
AddToSortedCollection(col As Collection, vNewItem, Optional sKey$) As Boolean
которая добавит новый элемент на правильное место (метод Add имеет параметр, определяющий место вставки i: col.Add vNewItem, sKey,
i)
Тогда для правильной сортировки придется изменить ключ (подход от @sokol92), отформатировав строку исходя из:
Each spreadsheet can have up to 10 000 sheets, and each sheet can have a maximum of 1 048 576 rows and a maximum of 1 024 columns.
Difference()
Function Difference(RangeAddress As com.sun.star.table.CellRangeAddress _
, RangeAddresses() As com.sun.star.table.CellRangeAddress) As Object
''' Subtract other cell ranges (or a range) from the specified cell range.
''' Argument:
''' RangeAddress: The specified cell range (its address).
''' RangeAddresses():
''' A sequence of other cell ranges (their addresses)
''' to be subtracted (excluded) from the specified range.
''' Return a new range with elements in the range that are not in the others.
''' range - other - … '(S = A \ B)
On Local Error GoTo HandleErrors
Dim oRanges As Object, oCell As Object
Dim A As New Collection, B As New Collection
A = GetCellCollection(Array(RangeAddress))
B = GetCellCollection(RangeAddresses())
On Local Error Resume Next
For Each oCell In B
A.Remove oCell.AbsoluteName
Next
On Local Error GoTo HandleErrors
oRanges = ThisComponent.createInstance("com.sun.star.sheet.SheetCellRanges")
For Each oCell In A
oRanges.addRangeAddress(oCell.RangeAddress, True)
Next
Difference = IIf(oRanges.Count, oRanges, Nothing)
Exit Function
HandleErrors:
Msgbox "Error " & Err & " at line " & Erl & ": " & Error _
, MB_ICONSTOP, "macro:Difference()"
End Function
Sub Test_Difference()
Dim oRanges As Object, oRange1 As Object, oRange2 As Object
With ThisComponent.CurrentController.ActiveSheet
oRange1 = .getCellRangeByName("B3:F25")
oRange2 = .getCellRangeByName("B4:G4")
End With
oRanges = Difference(oRange1.RangeAddress, Array(oRange2.RangeAddress))
MsgBox oRanges.AbsoluteName
End Sub