sc/source/ui/inc/tabvwsh.hxx   |    8 +-
 sc/source/ui/view/tabvwsh3.cxx |   14 ++-
 sc/source/ui/view/tabvwsh4.cxx |  150 +++++++++++++++++++++++++++++------------
 3 files changed, 124 insertions(+), 48 deletions(-)

New commits:
commit f9fcd884a37bc8adb3fab72b781985a652e1af12
Author:     Noel Grandin <[email protected]>
AuthorDate: Thu Jan 29 16:59:55 2026 +0200
Commit:     Noel Grandin <[email protected]>
CommitDate: Thu Jan 29 19:09:29 2026 +0100

    tdf#166121 split HandleDuplicateRecords method
    
    into two different methods for the different cases, so we
    can optimise the remove case more easily.
    
    Change-Id: Id57875f2b28b7ac5909b32c7df3dbfb817642e82
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198373
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <[email protected]>

diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index a7ba9ed4b659..5feca801d4e0 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -273,8 +273,12 @@ public:
     SC_DLLPUBLIC bool IsRefInputMode() const;
     void            ExecuteInputDirect();
 
-    void HandleDuplicateRecords(const rtl::Reference<ScTableSheetObj>& 
ActiveSheet,
-                                const css::table::CellRangeAddress& aRange, 
bool bRemove,
+    void HandleDuplicateRecordsHighlight(const 
rtl::Reference<ScTableSheetObj>& ActiveSheet,
+                                const css::table::CellRangeAddress& aRange,
+                                bool bIncludesHeaders, bool bDuplicateRows,
+                                const std::vector<int>& rSelectedEntries);
+    void HandleDuplicateRecordsRemove(const rtl::Reference<ScTableSheetObj>& 
ActiveSheet,
+                                const css::table::CellRangeAddress& aRange,
                                 bool bIncludesHeaders, bool bDuplicateRows,
                                 const std::vector<int>& rSelectedEntries);
     rtl::Reference<ScTableSheetObj> 
GetRangeWithSheet(css::table::CellRangeAddress& rRangeData, bool& bHasData, 
bool bHasUnoArguments);
diff --git a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx
index a4536393a88b..8fe42865d631 100644
--- a/sc/source/ui/view/tabvwsh3.cxx
+++ b/sc/source/ui/view/tabvwsh3.cxx
@@ -16,7 +16,6 @@
  *   except in compliance with the License. You may obtain a copy of
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
-
 #include <sfx2/bindings.hxx>
 #include <sfx2/dispatch.hxx>
 #include <sfx2/passwd.hxx>
@@ -938,9 +937,16 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
                 }
 
                 if (bHasData)
-                    GetViewData().GetViewShell()->HandleDuplicateRecords(
-                            xActiveSheet, aCellRange, aResponse.bRemove, 
aResponse.bIncludesHeaders,
-                            aResponse.bDuplicateRows, aResponse.vEntries);
+                {
+                    if (aResponse.bRemove)
+                        
GetViewData().GetViewShell()->HandleDuplicateRecordsRemove(
+                                xActiveSheet, aCellRange, 
aResponse.bIncludesHeaders,
+                                aResponse.bDuplicateRows, aResponse.vEntries);
+                    else
+                        
GetViewData().GetViewShell()->HandleDuplicateRecordsHighlight(
+                                xActiveSheet, aCellRange, 
aResponse.bIncludesHeaders,
+                                aResponse.bDuplicateRows, aResponse.vEntries);
+                }
 
                 rReq.Done();
             }
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index dc26f75673da..7e2cb7ebe91f 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -1924,9 +1924,8 @@ void 
ScTabViewShell::ExtendSingleSelection(css::table::CellRangeAddress& rRangeD
     rRangeData.EndColumn = aEndCol;
 }
 
-/* bool bRemove == false ==> highlight duplicate rows */
-void ScTabViewShell::HandleDuplicateRecords(const 
rtl::Reference<ScTableSheetObj>& ActiveSheet,
-                                const css::table::CellRangeAddress& aRange, 
bool bRemove,
+void ScTabViewShell::HandleDuplicateRecordsHighlight(const 
rtl::Reference<ScTableSheetObj>& ActiveSheet,
+                                const css::table::CellRangeAddress& aRange,
                                 bool bIncludesHeaders, bool bDuplicateRows,
                                 const std::vector<int>& rSelectedEntries)
 {
@@ -1946,14 +1945,11 @@ void ScTabViewShell::HandleDuplicateRecords(const 
rtl::Reference<ScTableSheetObj
     uno::Reference<document::XActionLockable> xLockable(xModel, 
uno::UNO_QUERY);
 
     uno::Reference<sheet::XCalculatable> xCalculatable(xModel, uno::UNO_QUERY);
-    bool bAutoCalc = xCalculatable->isAutomaticCalculationEnabled();
     ScDocument& rDoc = GetViewData().GetDocShell()->GetDocument();
 
     comphelper::ScopeGuard aUndoContextGuard(
-        [&xUndoManager, &xLockable, &xModel, &xCalculatable, &bAutoCalc, 
&bRemove, &rDoc] {
+        [&xUndoManager, &xLockable, &xModel, &rDoc] {
         xUndoManager->getUndoManager()->leaveUndoContext();
-        if (bRemove)
-            xCalculatable->enableAutomaticCalculation(bAutoCalc);
         xLockable->removeActionLock();
         if (xModel->hasControllersLocked())
             xModel->unlockControllers();
@@ -1963,8 +1959,6 @@ void ScTabViewShell::HandleDuplicateRecords(const 
rtl::Reference<ScTableSheetObj
     rDoc.LockAdjustHeight();
     xModel->lockControllers();
     xLockable->addActionLock();
-    if (bRemove)
-        xCalculatable->enableAutomaticCalculation(true);
     xUndoManager->getUndoManager()->enterUndoContext("HandleDuplicateRecords");
 
     bool nModifier = false;         // modifier key pressed?
@@ -1975,28 +1969,17 @@ void ScTabViewShell::HandleDuplicateRecords(const 
rtl::Reference<ScTableSheetObj
         std::vector<uno::Sequence<uno::Any>> aUnionArray;
         sal_uInt32 nRow = bIncludesHeaders ? 1 : 0;
         sal_uInt32 lRows = aDataArray.getLength();
-        sal_uInt32 nDeleteCount = 0;
 
         while (nRow < lRows)
         {
             if (lcl_CheckInArray(aUnionArray, aDataArray[nRow], 
rSelectedEntries, true))
             {
-                if (bRemove)
-                {
-                    lcl_RemoveCells(ActiveSheet, aRange.Sheet, 
aRange.StartColumn,
-                                    aRange.StartRow + nRow - nDeleteCount, 
aRange.EndColumn,
-                                    aRange.StartRow + nRow - nDeleteCount, 
true);
-                    ++nDeleteCount;
-                }
-                else
+                for (int nCol = aRange.StartColumn; nCol <= aRange.EndColumn; 
++nCol)
                 {
-                    for (int nCol = aRange.StartColumn; nCol <= 
aRange.EndColumn; ++nCol)
-                    {
-                        bNoDuplicatesForSelection = false;
-                        DoneBlockMode( nModifier );
-                        nModifier = true;
-                        InitBlockMode( nCol, aRange.StartRow + nRow, 
aRange.Sheet, false, false);
-                    }
+                    bNoDuplicatesForSelection = false;
+                    DoneBlockMode( nModifier );
+                    nModifier = true;
+                    InitBlockMode( nCol, aRange.StartRow + nRow, aRange.Sheet, 
false, false);
                 }
             }
             else
@@ -2009,7 +1992,6 @@ void ScTabViewShell::HandleDuplicateRecords(const 
rtl::Reference<ScTableSheetObj
     else
     {
         std::vector<uno::Sequence<uno::Any>> aUnionArray;
-        sal_uInt32 nDeleteCount = 0;
         sal_uInt32 nColumn = bIncludesHeaders ? 1 : 0;
         sal_uInt32 lColumns = aDataArray[0].getLength();
 
@@ -2022,22 +2004,12 @@ void ScTabViewShell::HandleDuplicateRecords(const 
rtl::Reference<ScTableSheetObj
 
             if (lcl_CheckInArray(aUnionArray, aSeq, rSelectedEntries, false))
             {
-                if (bRemove)
-                {
-                    lcl_RemoveCells(ActiveSheet, aRange.Sheet,
-                                    aRange.StartColumn + nColumn - 
nDeleteCount, aRange.StartRow,
-                                    aRange.StartColumn + nColumn - 
nDeleteCount, aRange.EndRow, false);
-                    ++nDeleteCount;
-                }
-                else
+                for (int nRow = aRange.StartRow; nRow <= aRange.EndRow; ++nRow)
                 {
-                    for (int nRow = aRange.StartRow; nRow <= aRange.EndRow; 
++nRow)
-                    {
-                        bNoDuplicatesForSelection = false;
-                        DoneBlockMode( nModifier );
-                        nModifier = true;
-                        InitBlockMode( aRange.StartColumn + nColumn, nRow, 
aRange.Sheet, false, false);
-                    }
+                    bNoDuplicatesForSelection = false;
+                    DoneBlockMode( nModifier );
+                    nModifier = true;
+                    InitBlockMode( aRange.StartColumn + nColumn, nRow, 
aRange.Sheet, false, false);
                 }
             }
             else
@@ -2049,10 +2021,104 @@ void ScTabViewShell::HandleDuplicateRecords(const 
rtl::Reference<ScTableSheetObj
 
     }
 
-    if (bNoDuplicatesForSelection && !bRemove)
+    if (bNoDuplicatesForSelection)
         Unmark();
 }
 
+void ScTabViewShell::HandleDuplicateRecordsRemove(const 
rtl::Reference<ScTableSheetObj>& ActiveSheet,
+                                const css::table::CellRangeAddress& aRange,
+                                bool bIncludesHeaders, bool bDuplicateRows,
+                                const std::vector<int>& rSelectedEntries)
+{
+    if (rSelectedEntries.size() == 0)
+    {
+        Unmark();
+        return;
+    }
+
+    uno::Reference<frame::XModel> 
xModel(GetViewData().GetDocShell()->GetModel());
+    rtl::Reference<ScCellRangeObj> xSheetRange(
+            ActiveSheet->getScCellRangeByPosition(aRange.StartColumn, 
aRange.StartRow, aRange.EndColumn, aRange.EndRow));
+
+    uno::Sequence<uno::Sequence<uno::Any>> aDataArray = 
xSheetRange->getDataArray();
+
+    uno::Reference< document::XUndoManagerSupplier > xUndoManager( xModel, 
uno::UNO_QUERY );
+    uno::Reference<document::XActionLockable> xLockable(xModel, 
uno::UNO_QUERY);
+
+    uno::Reference<sheet::XCalculatable> xCalculatable(xModel, uno::UNO_QUERY);
+    bool bAutoCalc = xCalculatable->isAutomaticCalculationEnabled();
+    ScDocument& rDoc = GetViewData().GetDocShell()->GetDocument();
+
+    comphelper::ScopeGuard aUndoContextGuard(
+        [&xUndoManager, &xLockable, &xModel, &xCalculatable, &bAutoCalc, 
&rDoc] {
+        xUndoManager->getUndoManager()->leaveUndoContext();
+        xCalculatable->enableAutomaticCalculation(bAutoCalc);
+        xLockable->removeActionLock();
+        if (xModel->hasControllersLocked())
+            xModel->unlockControllers();
+        rDoc.UnlockAdjustHeight();
+    });
+
+    rDoc.LockAdjustHeight();
+    xModel->lockControllers();
+    xLockable->addActionLock();
+    xCalculatable->enableAutomaticCalculation(true);
+    xUndoManager->getUndoManager()->enterUndoContext("HandleDuplicateRecords");
+
+    if (bDuplicateRows)
+    {
+        std::vector<uno::Sequence<uno::Any>> aUnionArray;
+        sal_uInt32 nRow = bIncludesHeaders ? 1 : 0;
+        sal_uInt32 lRows = aDataArray.getLength();
+        sal_uInt32 nDeleteCount = 0;
+
+        while (nRow < lRows)
+        {
+            if (lcl_CheckInArray(aUnionArray, aDataArray[nRow], 
rSelectedEntries, true))
+            {
+                lcl_RemoveCells(ActiveSheet, aRange.Sheet, aRange.StartColumn,
+                                aRange.StartRow + nRow - nDeleteCount, 
aRange.EndColumn,
+                                aRange.StartRow + nRow - nDeleteCount, true);
+                ++nDeleteCount;
+            }
+            else
+            {
+                aUnionArray.push_back(aDataArray[nRow]);
+            }
+            ++nRow;
+        }
+    }
+    else
+    {
+        std::vector<uno::Sequence<uno::Any>> aUnionArray;
+        sal_uInt32 nDeleteCount = 0;
+        sal_uInt32 nColumn = bIncludesHeaders ? 1 : 0;
+        sal_uInt32 lColumns = aDataArray[0].getLength();
+
+        while (nColumn < lColumns)
+        {
+            uno::Sequence<uno::Any> aSeq;
+            aSeq.realloc(rSelectedEntries.size());
+            for (size_t i = 0; i < rSelectedEntries.size(); ++i)
+                aSeq.getArray()[i] = aDataArray[rSelectedEntries[i]][nColumn];
+
+            if (lcl_CheckInArray(aUnionArray, aSeq, rSelectedEntries, false))
+            {
+                lcl_RemoveCells(ActiveSheet, aRange.Sheet,
+                                aRange.StartColumn + nColumn - nDeleteCount, 
aRange.StartRow,
+                                aRange.StartColumn + nColumn - nDeleteCount, 
aRange.EndRow, false);
+                ++nDeleteCount;
+            }
+            else
+            {
+                aUnionArray.push_back(aSeq);
+            }
+            ++nColumn;
+        }
+
+    }
+}
+
 ScTabViewShell::ScTabViewShell( SfxViewFrame& rViewFrame,
                                 SfxViewShell* pOldSh ) :
     SfxViewShell(rViewFrame, SfxViewShellFlags::HAS_PRINTOPTIONS),

Reply via email to