summaryrefslogtreecommitdiff
path: root/wizards
diff options
context:
space:
mode:
authorJean-Pierre Ledure <jp@ledure.be>2022-04-10 17:05:33 +0200
committerJean-Pierre Ledure <jp@ledure.be>2022-04-10 18:06:05 +0200
commit43507de5764732300ae9a35cc570b7722a7e1a80 (patch)
treebaafc5ae05259e433b7d67c43839f6c2392a1917 /wizards
parent64046625553ecbfd9fe0661e5b6f48e283a909e0 (diff)
ScriptForge - (SF_Calc) new CompactUp() and CompactLeft() methods
The CompactUp(CompactLeft) method: Delete the rows(columns) of a specified range matching a filter expressed as a formula applied on each row(column). The deleted cells can span whole rows(columns) or be limited to the width(height) of the range. The execution of the method has no effect on the current selection. Args: Range: the range in which cells have to be erased, as a string WholeRow(WholeColumn): when True (default = False), erase whole rows(columns) FilterFormula: the formula to be applied on each row(column). The row(column) is erased when the formula results in True. The formula shall probably involve one or more cells of the first row(column) of the range.. By default, a row is erased when all the cells of the row(column) are empty, i.e. suppose the range is "A1:J200" (width = 10), the default value [for CompactUp] becomes "=(COUNTBLANK(A1:J1)=10)" Returns: A string representing the location of the initial range after compaction, or the zero-length string if the whole range has been deleted. Examples for CompactUp(): newrange = oDoc.CompactUp("SheetX.G1:L10") ' All empty rows of the range are suppressed newrange = oDoc.CompactUp("SheetX.G1:L10", WholeRow := True, _ FilterFormula := "=(G1=""X"")") ' The rows having a "X" in column G are completely suppressed Both methods are available for use from Basic and Python scripts. Change-Id: Ib1269b22bcd189ca86a1bd3bda2c67e895598cb0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132783 Tested-by: Jean-Pierre Ledure <jp@ledure.be> Tested-by: Jenkins Reviewed-by: Jean-Pierre Ledure <jp@ledure.be>
Diffstat (limited to 'wizards')
-rw-r--r--wizards/source/scriptforge/SF_Utils.xba2
-rw-r--r--wizards/source/scriptforge/python/scriptforge.py6
-rw-r--r--wizards/source/sfdocuments/SF_Calc.xba224
3 files changed, 228 insertions, 4 deletions
diff --git a/wizards/source/scriptforge/SF_Utils.xba b/wizards/source/scriptforge/SF_Utils.xba
index 5dbe667a52f0..e26cca66a776 100644
--- a/wizards/source/scriptforge/SF_Utils.xba
+++ b/wizards/source/scriptforge/SF_Utils.xba
@@ -1107,4 +1107,4 @@ Finally:
End Function &apos; ScriptForge.SF_Utils._VarTypeObj
REM ================================================= END OF SCRIPTFORGE.SF_UTILS
-</script:module>
+</script:module> \ No newline at end of file
diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py
index c1261a14fc40..600d8469e623 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -2086,6 +2086,12 @@ class SFDocuments:
def ClearValues(self, range):
return self.ExecMethod(self.vbMethod, 'ClearValues', range)
+ def CompactLeft(self, range, wholecolumn = False, filterformula = ''):
+ return self.ExecMethod(self.vbMethod, 'CompactLeft', range, wholecolumn, filterformula)
+
+ def CompactUp(self, range, wholerow = False, filterformula = ''):
+ return self.ExecMethod(self.vbMethod, 'CompactUp', range, wholerow, filterformula)
+
def CopySheet(self, sheetname, newname, beforesheet = 32768):
sheet = (sheetname.objectreference if isinstance(sheetname, SFDocuments.SF_CalcReference) else sheetname)
return self.ExecMethod(self.vbMethod + self.flgObject, 'CopySheet', sheet, newname, beforesheet)
diff --git a/wizards/source/sfdocuments/SF_Calc.xba b/wizards/source/sfdocuments/SF_Calc.xba
index bc5681992eec..33a523874f39 100644
--- a/wizards/source/sfdocuments/SF_Calc.xba
+++ b/wizards/source/sfdocuments/SF_Calc.xba
@@ -90,7 +90,6 @@ Private Const RANGEEXPORTERROR = &quot;RANGEEXPORTERROR&quot;
REM ============================================================= PRIVATE MEMBERS
Private [Me] As Object
-Private [_Parent] As Object
Private [_Super] As Object &apos; Document superclass, which the current instance is a subclass of
Private ObjectType As String &apos; Must be CALC
Private ServiceName As String
@@ -137,7 +136,6 @@ REM ====================================================== CONSTRUCTOR/DESTRUCTO
REM -----------------------------------------------------------------------------
Private Sub Class_Initialize()
Set [Me] = Nothing
- Set [_Parent] = Nothing
Set [_Super] = Nothing
ObjectType = &quot;CALC&quot;
ServiceName = &quot;SFDocuments.Calc&quot;
@@ -652,6 +650,224 @@ Catch:
End Sub &apos; SF_Documents.SF_Calc.ClearValues
REM -----------------------------------------------------------------------------
+Public Function CompactLeft(Optional ByVal Range As Variant _
+ , Optional ByVal WholeColumn As Variant _
+ , Optional ByVal FilterFormula As Variant _
+ ) As String
+&apos;&apos;&apos; Delete the columns of a specified range matching a filter expressed as a formula
+&apos;&apos;&apos; applied on each column.
+&apos;&apos;&apos; The deleted cells can span whole columns or be limited to the height of the range
+&apos;&apos;&apos; The execution of the method has no effect on the current selection
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Range: the range in which cells have to be erased, as a string
+&apos;&apos;&apos; WholeColumn: when True (default = False), erase whole columns
+&apos;&apos;&apos; FilterFormula: the formula to be applied on each column.
+&apos;&apos;&apos; The column is erased when the formula results in True,
+&apos;&apos;&apos; The formula shall probably involve one or more cells of the first column of the range..
+&apos;&apos;&apos; By default, a column is erased when all the cells of the column are empty,
+&apos;&apos;&apos; i.e. suppose the range is &quot;A1:J200&quot; (height = 0) the default value becomes
+&apos;&apos;&apos; &quot;=(COUNTBLANK(A1:A200)=200)&quot;
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; A string representing the location of the initial range after compaction,
+&apos;&apos;&apos; or the zero-length string if the whole range has been deleted
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; newrange = oDoc.CompactLeft(&quot;SheetX.G1:L10&quot;) &apos; All empty columns of the range are suppressed
+&apos;&apos;&apos; newrange = oDoc.CompactLeft(&quot;SheetX.G1:L10&quot;, WholeColumn := True, FilterFormula := &quot;=(G$7=&quot;&quot;X&quot;&quot;)&quot;)
+&apos;&apos;&apos; &apos; The columns having a &quot;X&quot; in row 7 are completely suppressed
+
+Dim sCompact As String &apos; Return value
+Dim oSourceAddress As Object &apos; Alias of Range as _Address
+Dim lLastRow As Long &apos; Last used row number in the sheet containing Range
+Dim sFormulaRange As String &apos; Range, as a string, where the FilterFormula must be stored
+Dim vCompact As Variant &apos; Array of Boolean values indicating which columns should be erased
+Dim lCountDeleted As Long &apos; Count the deleted columns
+Dim lCountToDelete As Long &apos; Count contiguous columns to be deleted at once
+Dim sPartialRange As String &apos; Contiguous columns to be deleted
+Dim i As Long
+
+Const cstThisSub = &quot;SFDocuments.Calc.CompactLeft&quot;
+Const cstSubArgs = &quot;Range, [WholeColumn=False], [FilterFormula=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ sCompact = &quot;&quot;
+
+Check:
+ If IsMissing(WholeColumn) Or IsEmpty(WholeColumn) Then WholeColumn = False
+ If IsMissing(FilterFormula) Or IsEmpty(FilterFormula) Then FilterFormula = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not _IsStillAlive(True) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(WholeColumn, &quot;WholeColumn&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(FilterFormula, &quot;FilterFormula&quot;, V_STRING) Then GoTo Finally
+ End If
+
+Try:
+ Set oSourceAddress = _ParseAddress(Range)
+
+ With oSourceAddress
+
+ &apos; Set the default formula =&gt; all cells are blank
+ If FilterFormula = &quot;&quot; Then FilterFormula = Printf(&quot;=(COUNTBLANK(%C1%R1:%C1%R2)-&quot; &amp; .Height &amp; &quot;=0)&quot;, Range)
+ &apos; Compute the range where to apply the formula
+ lLastRow = LastRow(.SheetName)
+ sFormulaRange = Offset(Range, lLastRow - .XCellRange.RangeAddress.StartColumn + 1, , 1)
+ SetFormula(sFormulaRange, FilterFormula)
+ &apos; Get the columns to compact: 0 = False, 1 = True
+ vCompact = GetValue(sFormulaRange)
+ ClearAll(sFormulaRange)
+
+ &apos; Iterates from the last to the first column of the range and remove the columns that match the filter
+ &apos; by groups of contiguous columns
+ lCountDeleted = 0
+ lCountToDelete = 0
+ For i = UBound(vCompact) To 0 Step -1
+ If vCompact(i) = 1 Then lCountToDelete = lCountToDelete + 1
+ If i &gt; 0 And vCompact(i) = 1 Then
+ &apos; Do nothing
+ ElseIf lCountToDelete &gt; 0 Then &apos; The current column must be kept but columns at the left must be removed
+ &apos; Do not forget when the 1st column must be removed
+ sPartialRange = Offset(Range, , Iif(i = 0 And vCompact(i) = 1, 0, i + 1), , lCountToDelete)
+ ShiftLeft(sPartialRange, WholeColumn)
+ lCountDeleted = lCountDeleted + lCountToDelete
+ lCountToDelete = 0
+ End If
+ Next i
+
+ &apos; Compute the final range position
+ If lCountDeleted &lt; .Width Then sCompact = Offset(Range, 0, 0, , .Width - lCountDeleted)
+
+ &apos; Push rightwards the cells that migrated leftwards irrelevantly
+ If Not WholeColumn Then
+ If Len(sCompact) &gt; 0 Then
+ sPartialRange = Offset(sCompact, 0, .Width - lCountDeleted, , lCountDeleted)
+ Else
+ sPartialRange = .RangeName
+ End If
+ ShiftRight(sPartialRange, WholeColumn := False)
+ End If
+
+ End With
+
+Finally:
+ CompactLeft = sCompact
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ &apos; When error, return the original range
+ If Not IsNull(oSourceAddress) Then sCompact = oSourceAddress.RangeName
+ GoTo Finally
+End Function &apos; SFDocuments.SF_Calc.CompactLeft
+
+REM -----------------------------------------------------------------------------
+Public Function CompactUp(Optional ByVal Range As Variant _
+ , Optional ByVal WholeRow As Variant _
+ , Optional ByVal FilterFormula As Variant _
+ ) As String
+&apos;&apos;&apos; Delete the rows of a specified range matching a filter expressed as a formula
+&apos;&apos;&apos; applied on each row.
+&apos;&apos;&apos; The deleted cells can span whole rows or be limited to the width of the range
+&apos;&apos;&apos; The execution of the method has no effect on the current selection
+&apos;&apos;&apos; Args:
+&apos;&apos;&apos; Range: the range in which cells have to be erased, as a string
+&apos;&apos;&apos; WholeRow: when True (default = False), erase whole rows
+&apos;&apos;&apos; FilterFormula: the formula to be applied on each row.
+&apos;&apos;&apos; The row is erased when the formula results in True,
+&apos;&apos;&apos; The formula shall probably involve one or more cells of the first row of the range..
+&apos;&apos;&apos; By default, a row is erased when all the cells of the row are empty,
+&apos;&apos;&apos; i.e. suppose the range is &quot;A1:J200&quot; (width = 10) the default value becomes
+&apos;&apos;&apos; &quot;=(COUNTBLANK(A1:J1)=10)&quot;
+&apos;&apos;&apos; Returns:
+&apos;&apos;&apos; A string representing the location of the initial range after compaction,
+&apos;&apos;&apos; or the zero-length string if the whole range has been deleted
+&apos;&apos;&apos; Examples:
+&apos;&apos;&apos; newrange = oDoc.CompactUp(&quot;SheetX.G1:L10&quot;) &apos; All empty rows of the range are suppressed
+&apos;&apos;&apos; newrange = oDoc.CompactUp(&quot;SheetX.G1:L10&quot;, WholeRow := True, FilterFormula := &quot;=(G1=&quot;&quot;X&quot;&quot;)&quot;)
+&apos;&apos;&apos; &apos; The rows having a &quot;X&quot; in column G are completely suppressed
+
+Dim sCompact As String &apos; Return value
+Dim oSourceAddress As Object &apos; Alias of Range as _Address
+Dim lLastCol As Long &apos; Last used column number in the sheet containing Range
+Dim sFormulaRange As String &apos; Range, as a string, where the FilterFormula must be stored
+Dim vCompact As Variant &apos; Array of Boolean values indicating which rows should be erased
+Dim lCountDeleted As Long &apos; Count the deleted rows
+Dim lCountToDelete As Long &apos; Count contiguous rows to be deleted at once
+Dim sPartialRange As String &apos; Contiguous rows to be deleted
+Dim i As Long
+
+Const cstThisSub = &quot;SFDocuments.Calc.CompactUp&quot;
+Const cstSubArgs = &quot;Range, [WholeRow=False], [FilterFormula=&quot;&quot;&quot;&quot;]&quot;
+
+ If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+ sCompact = &quot;&quot;
+
+Check:
+ If IsMissing(WholeRow) Or IsEmpty(WholeRow) Then WholeRow = False
+ If IsMissing(FilterFormula) Or IsEmpty(FilterFormula) Then FilterFormula = &quot;&quot;
+ If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+ If Not _IsStillAlive(True) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(Range, &quot;Range&quot;, V_STRING) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(WholeRow, &quot;WholeRow&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
+ If Not ScriptForge.SF_Utils._Validate(FilterFormula, &quot;FilterFormula&quot;, V_STRING) Then GoTo Finally
+ End If
+
+Try:
+ Set oSourceAddress = _ParseAddress(Range)
+
+ With oSourceAddress
+
+ &apos; Set the default formula =&gt; all cells are blank
+ If FilterFormula = &quot;&quot; Then FilterFormula = Printf(&quot;=(COUNTBLANK(%C1%R1:%C2%R1)-&quot; &amp; .Width &amp; &quot;=0)&quot;, Range)
+ &apos; Compute the range where to apply the formula
+ lLastCol = LastColumn(.SheetName)
+ sFormulaRange = Offset(Range, , lLastCol - .XCellRange.RangeAddress.StartRow + 1, , 1)
+ SetFormula(sFormulaRange, FilterFormula)
+ &apos; Get the rows to compact: 0 = False, 1 = True
+ vCompact = GetValue(sFormulaRange)
+ ClearAll(sFormulaRange)
+
+ &apos; Iterates from the last to the first row of the range and remove the rows that match the filter
+ &apos; by groups of contiguous rows
+ lCountDeleted = 0
+ lCountToDelete = 0
+ For i = UBound(vCompact) To 0 Step -1
+ If vCompact(i) = 1 Then lCountToDelete = lCountToDelete + 1
+ If i &gt; 0 And vCompact(i) = 1 Then
+ &apos; Do nothing
+ ElseIf lCountToDelete &gt; 0 Then &apos; The current row must be kept but rows below must be removed
+ &apos; Do not forget when the 1st row must be removed
+ sPartialRange = Offset(Range, Iif(i = 0 And vCompact(i) = 1, 0, i + 1), , lCountToDelete)
+ ShiftUp(sPartialRange, WholeRow)
+ lCountDeleted = lCountDeleted + lCountToDelete
+ lCountToDelete = 0
+ End If
+ Next i
+
+ &apos; Compute the final range position
+ If lCountDeleted &lt; .Height Then sCompact = Offset(Range, 0, 0, .Height - lCountDeleted)
+
+ &apos; Push downwards the cells that migrated upwards irrelevantly
+ If Not WholeRow Then
+ If Len(sCompact) &gt; 0 Then
+ sPartialRange = Offset(sCompact, .Height - lCountDeleted, 0, lCountDeleted)
+ Else
+ sPartialRange = .RangeName
+ End If
+ ShiftDown(sPartialRange, WholeRow := False)
+ End If
+
+ End With
+
+Finally:
+ CompactUp = sCompact
+ ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+ Exit Function
+Catch:
+ &apos; When error, return the original range
+ If Not IsNull(oSourceAddress) Then sCompact = oSourceAddress.RangeName
+ GoTo Finally
+End Function &apos; SFDocuments.SF_Calc.CompactUp
+
+REM -----------------------------------------------------------------------------
Public Function CopySheet(Optional ByVal SheetName As Variant _
, Optional ByVal NewName As Variant _
, Optional ByVal BeforeSheet As Variant _
@@ -1925,7 +2141,7 @@ Public Function Offset(Optional ByRef Range As Variant _
&apos;&apos;&apos; Exceptions:
&apos;&apos;&apos; OFFSETADDRESSERROR The computed range of cells falls beyond the sheet boundaries
&apos;&apos;&apos; Examples:
-&apos;&apos;&apos; oDoc.Offset(&quot;A1&quot;, 2, 2) &apos; &quot;&apos;SheetX&apos;.$C$3&quot; (A1 moved by two rows and two columns down)
+&apos;&apos;&apos; oDoc.Offset(&quot;A1&quot;, 2, 2) &apos; &quot;&apos;SheetX&apos;.$C$3&quot; (A1 moved by two rows and two columns down)
&apos;&apos;&apos; oDoc.Offset(&quot;A1&quot;, 2, 2, 5, 6) &apos; &quot;&apos;SheetX&apos;.$C$3:$H$7&quot;
Dim sOffset As String &apos; Return value
@@ -2727,6 +2943,7 @@ Check:
Try:
Set oSourceAddress = _ParseAddress(Range)
+ Set _LastParsedAddress = Nothing &apos; Range will be erased. Force re-parsing next time
With oSourceAddress
@@ -2889,6 +3106,7 @@ Check:
Try:
Set oSourceAddress = _ParseAddress(Range)
+ Set _LastParsedAddress = Nothing &apos; Range will be erased. Force re-parsing next time
With oSourceAddress