https://bugs.documentfoundation.org/show_bug.cgi?id=172190

            Bug ID: 172190
           Summary: Calc: Multi-cell content clearing via Basic macro
                    removes inner cell borders in xlsx files (works
                    correctly with physical keyboard Delete) +
                    Enhancement: no programmatic way to dismiss "marching
                    ants" clipboard indicator
           Product: LibreOffice
           Version: 26.2.3.2 release
          Hardware: All
                OS: Windows (All)
            Status: UNCONFIRMED
          Severity: normal
          Priority: medium
         Component: Calc
          Assignee: [email protected]
          Reporter: [email protected]

Description:
SYMPTOM:
When running a Basic macro that clears content of a multi-cell range in an xlsx 
file (using any of the documented methods: oSel.clearContents(N), 
.uno:ClearContents dispatch, setString("") per cell, getDataArray/setDataArray, 
or external SendKeys via WScript.Shell), all inner cell borders within the 
selection are removed. Only the outer perimeter remains, as if the range had 
collapsed into a single cell.

The same operation performed via physical keyboard Delete key preserves all 
inner borders correctly.

STEPS TO REPRODUCE:
1. Open an xlsx file (originally created/edited in Excel or imported from 
   external source).
2. Apply both inner and outer borders to a multi-cell range (e.g., A1:C3 
   with Format > Cells > Borders > "Box and inner lines").
3. Add content to each cell.
4. Create a simple Basic macro in My Macros > Standard > Module1:

   Sub TestClear
       Dim oSel As Object
       oSel = ThisComponent.getCurrentSelection()
       oSel.clearContents(31)  ' value+date+string+annotation+formula
   End Sub

5. Select the bordered range.
6. Run the macro.

EXPECTED BEHAVIOR:
Content cleared from all cells. All inner and outer cell borders preserved 
(flag 31 excludes HARDATTR=32, so formatting including borders should not 
be touched).

ACTUAL BEHAVIOR:
Content cleared. Inner cell borders DISAPPEAR. Only the outer 4-line 
bounding box of the range remains. The range appears as one merged block, 
even though no actual merging occurred.

ENVIRONMENT:
- LibreOffice 26.2 (Windows 11 Pro x64)
- File format: .xlsx (originally from external source)
- Conditional formatting: none
- Merged cells: none
- Cell style: Default

WORKAROUND:
Physical keyboard Delete (selecting range and pressing Del) preserves all 
borders correctly. The bug is specific to programmatic/macro-triggered 
content clearing.

ADDITIONAL TESTING:
The following alternative approaches all exhibit the same bug:
- oSel.clearContents(31)  -- direct API
- .uno:ClearContents dispatch (with or without "Flags" property)
- For loop with oCell.setString("") per cell
- DataArray bypass (getDataArray + modify + setDataArray)
- com.sun.star.awt.Robot keyPress with Key.DELETE
- CreateObject("WScript.Shell").SendKeys "{DEL}"
- External wscript.exe process spawned via Shell, sending Ctrl+C and Delete 
  via SendKeys after 200-400ms delay (intended to bypass SolarMutex contention)

NONE of the programmatic approaches preserve inner borders. Only physical 
hardware-originated keyboard Delete works.

The bug appears to occur in the xlsx import filter's XF (Extended Format) 
border pool handling. When the LibreOffice cell topology is modified via 
any API/dispatch/synthetic input path, an "XF pool optimization" is 
triggered that collapses shared inner borders into a single outer frame.

In a brand new (blank) Calc spreadsheet without xlsx import, the same 
macro works correctly and preserves all borders. The bug is specific to 
files imported from xlsx format with the original border structure.

This makes Calc unusable for any automation/macro workflow on xlsx files 
that have user-applied multi-cell borders.


==============================================================
RELATED ENHANCEMENT REQUEST: Programmatic dismissal of clipboard
"marching ants" indicator
==============================================================

CURRENT BEHAVIOR:
After .uno:Copy or .uno:Cut (or any operation that fills the Calc 
clipboard), Calc displays an animated dashed border ("marching ants") 
around the source range to indicate the clipboard is active. This 
indicator only disappears when:
- Another Cut/Copy is performed, OR
- The user manually presses the physical Escape key

There is no documented programmatic way to dismiss this indicator from 
a Basic macro while preserving the Calc internal clipboard (ScTransferObj) 
state required for rich paste (formulas, formatting).

USE CASE:
A macro that implements custom Cut/Copy behavior (e.g., "cut content but 
preserve formatting" — see main bug above) leaves the marching ants 
animation persistently visible after the macro completes. This is 
visually distracting and creates an inconsistent user experience compared 
to the manual Ctrl+X behavior, where the indicator behaves predictably.

Microsoft Excel has Application.CutCopyMode = False which dismisses 
the equivalent indicator while preserving clipboard state. LibreOffice 
Calc has no equivalent.

ATTEMPTED PROGRAMMATIC DISMISSAL METHODS (none work reliably):
- oDispatcher.executeDispatch(oFrame, ".uno:Escape", "", 0, Array())
- oDispatcher.executeDispatch(oFrame, ".uno:Cancel", "", 0, Array())
- oDispatcher.executeDispatch(oFrame, ".uno:Deselect", "", 0, Array())
- Programmatic cell selection change via controller.select(...)
- .uno:SetInputMode (F2) immediately followed by .uno:Cancel 
  (only partially works, side-effects depend on cell content state)

The only thing that reliably dismisses marching ants is the physical 
Escape key press — but that also wipes the rich Calc clipboard, leaving 
only plain text. So even the "manual Escape" path is not a clean solution.

REQUEST:
Add one of:
(a) A new UNO command like .uno:ClearClipboardIndicator that dismisses 
    only the visual marching ants, preserving ScTransferObj for rich paste.
(b) An overload of existing dispatch (e.g., a parameter for .uno:Cancel) 
    that does the equivalent.
(c) A documented "magic incantation" of existing API calls if one already 
    exists in the codebase but is not user-discoverable.

This would make programmatic Cut workflows in Calc match the polish 
of equivalent Excel automation.

Steps to Reproduce:
1. Open an xlsx file imported from Excel or saved in xlsx format with 
   inner+outer cell borders applied to a multi-cell range (e.g., A1:C3 
   with Format > Cells > Borders > "Box and inner lines").
2. Add content to each cell.
3. Create a Basic macro in My Macros > Standard > Module1:

   Sub TestClear
       Dim oSel As Object
       oSel = ThisComponent.getCurrentSelection()
       oSel.clearContents(31)
   End Sub

4. Select the bordered multi-cell range.
5. Run the macro (Tools > Macros > Run Macro, or via assigned keyboard
shortcut).

Actual Results:
Content is cleared from all cells (expected). However, inner cell borders 
within the selection DISAPPEAR. Only the outer 4-line bounding box of 
the range remains. The range visually collapses as if it were a single 
merged cell — even though no actual cell merging occurred.

The same behavior is observed with every alternative programmatic approach 
tested:
- oSel.clearContents(31) direct API
- .uno:ClearContents dispatch (with/without "Flags" PropertyValue)
- per-cell oCell.setString("") loop
- DataArray bypass (getDataArray + modify in-memory + setDataArray)
- com.sun.star.awt.Robot keyPress with Key.DELETE
- CreateObject("WScript.Shell").SendKeys "{DEL}" from Basic
- External wscript.exe spawned via Shell, sending Ctrl+C and Delete via 
  SendKeys with 200-400ms delay (intended to escape SolarMutex contention)
- Pure-launcher pattern: macro contains NO UNO commands, only spawns VBS 
  that does both Ctrl+C and Delete via SendKeys

NONE of the programmatic methods preserve inner borders. The behavior 
appears to be a Calc xlsx-import XF border pool optimization that 
triggers on any macro/synthetic-input modification.

Expected Results:
Content should be cleared from all cells with all borders (inner AND outer) 
preserved intact. The flag value 31 explicitly excludes HARDATTR=32, so 
formatting/borders should not be affected per documented API behavior.

The expected behavior matches what happens when the user presses the 
physical Delete key on the same selection: content cleared, all borders 
(inner + outer) preserved.

Programmatic clearing should produce identical results to physical 
keyboard Delete. The current divergence makes Calc unsuitable for any 
macro-based workflow that touches xlsx files with multi-cell borders.


Reproducible: Always


User Profile Reset: No

Additional Info:
ENVIRONMENT:
- LibreOffice 26.2.3.2 (Windows 11 Pro x64)
- File format: .xlsx (originally imported from external source / Excel)
- Conditional formatting: none
- Merged cells: none
- Cell style: Default
- Reproducible on multiple xlsx files imported externally; NOT reproducible 
  in fresh blank Calc spreadsheets (the bug is xlsx-import-specific).

WORKAROUND:
Physical keyboard Delete (selecting range and pressing Del manually) 
preserves all borders correctly. The bug occurs only with programmatic 
content clearing.

LIKELY ROOT CAUSE (HYPOTHESIS):
The xlsx import filter creates a "shared XF border pool" where adjacent 
cells share border ownership. When the cell topology is modified via 
any API/dispatch/synthetic input path, an "XF pool optimization" is 
triggered that collapses inner shared borders into a single outer frame. 
Physical hardware keyboard events appear to bypass this optimization 
(likely going through ScTabView::CmdDelete or similar direct path 
without invoking the format re-evaluation engine).

==============================================================
RELATED ENHANCEMENT REQUEST: Programmatic dismissal of "marching ants"
==============================================================

After .uno:Copy or .uno:Cut, Calc displays an animated dashed border 
("marching ants") around the source range. There is no documented 
programmatic way to dismiss this indicator from Basic while preserving 
the Calc internal clipboard (ScTransferObj) state.

Excel's equivalent: Application.CutCopyMode = False (dismisses indicator, 
preserves clipboard). LibreOffice Calc has no equivalent.

Tested (all fail to dismiss while preserving rich clipboard):
- .uno:Escape, .uno:Cancel, .uno:Deselect dispatch
- Programmatic cell selection change via controller.select(...)
- .uno:SetInputMode (F2) immediately followed by .uno:Cancel

Only the physical Escape key dismisses marching ants — but it also wipes 
the rich Calc clipboard.

Request: Add a UNO command (e.g., .uno:ClearClipboardIndicator) that 
dismisses only the visual indicator while preserving ScTransferObj for 
rich paste.

==============================================================

ABOUT LIBREOFFICE (Help > About LibreOffice — Copy Version Info):
Version: 26.2.3.2 (X86_64)
Build ID: 70e089b17412e4cb7773e41413306b17a2328c34
CPU threads: 12; OS: Windows 11 X86_64 (build 26200); UI render: Skia/Raster;
VCL: win
Locale: tr-TR (tr_TR); UI: tr-TR
Calc: CL threaded

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to