1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <scitems.hxx>
22 #include <comphelper/lok.hxx>
23 #include <o3tl/safeint.hxx>
24 #include <o3tl/string_view.hxx>
25 #include <sfx2/app.hxx>
26 #include <editeng/editobj.hxx>
27 #include <editeng/justifyitem.hxx>
28 #include <sfx2/linkmgr.hxx>
29 #include <sfx2/bindings.hxx>
31 #include <vcl/weld.hxx>
32 #include <vcl/stdtext.hxx>
33 #include <vcl/svapp.hxx>
34 #include <svx/svdocapt.hxx>
35 #include <sal/log.hxx>
36 #include <unotools/charclass.hxx>
37 #include <osl/diagnose.h>
39 #include <com/sun/star/container/XNameContainer.hpp>
40 #include <com/sun/star/script/ModuleType.hpp>
41 #include <com/sun/star/script/XLibraryContainer.hpp>
42 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
44 #include <docfunc.hxx>
47 #include <strings.hrc>
49 #include <arealink.hxx>
51 #include <dociter.hxx>
52 #include <autoform.hxx>
53 #include <formulacell.hxx>
54 #include <cellmergeoption.hxx>
55 #include <detdata.hxx>
56 #include <detfunc.hxx>
57 #include <docpool.hxx>
59 #include <drwlayer.hxx>
60 #include <editutil.hxx>
61 #include <globstr.hrc>
62 #include <olinetab.hxx>
63 #include <patattr.hxx>
64 #include <rangenam.hxx>
65 #include <refundo.hxx>
66 #include <scresid.hxx>
67 #include <stlpool.hxx>
68 #include <stlsheet.hxx>
69 #include <tablink.hxx>
70 #include <tabvwsh.hxx>
71 #include <uiitems.hxx>
72 #include <undoblk.hxx>
73 #include <undocell.hxx>
74 #include <undodraw.hxx>
75 #include <undotab.hxx>
76 #include <sizedev.hxx>
78 #include <inputhdl.hxx>
79 #include <editable.hxx>
80 #include <compiler.hxx>
81 #include <scui_def.hxx>
82 #include <tabprotection.hxx>
83 #include <clipparam.hxx>
84 #include <externalrefmgr.hxx>
85 #include <undorangename.hxx>
86 #include <progress.hxx>
87 #include <dpobject.hxx>
88 #include <stringutil.hxx>
89 #include <cellvalue.hxx>
90 #include <tokenarray.hxx>
91 #include <rowheightcontext.hxx>
92 #include <cellvalues.hxx>
93 #include <undoconvert.hxx>
94 #include <docfuncutil.hxx>
95 #include <sheetevents.hxx>
96 #include <conditio.hxx>
97 #include <columnspanset.hxx>
98 #include <validat.hxx>
99 #include <SparklineGroup.hxx>
100 #include <SparklineAttributes.hxx>
101 #include <SparklineData.hxx>
102 #include <undo/UndoInsertSparkline.hxx>
103 #include <undo/UndoDeleteSparkline.hxx>
104 #include <undo/UndoDeleteSparklineGroup.hxx>
105 #include <undo/UndoEditSparklineGroup.hxx>
106 #include <undo/UndoUngroupSparklines.hxx>
107 #include <undo/UndoGroupSparklines.hxx>
108 #include <undo/UndoEditSparkline.hxx>
109 #include <config_features.h>
112 #include <basic/basmgr.hxx>
115 #include <sfx2/viewfrm.hxx>
117 using namespace com::sun::star
;
120 #define AUTOFORMAT_WARN_SIZE 0x10ffffUL
122 void ScDocFunc::NotifyDrawUndo( std::unique_ptr
<SdrUndoAction
> pUndoAction
)
124 // #i101118# if drawing layer collects the undo actions, add it there
125 ScDrawLayer
* pDrawLayer
= rDocShell
.GetDocument().GetDrawLayer();
126 if( pDrawLayer
&& pDrawLayer
->IsRecording() )
127 pDrawLayer
->AddCalcUndo( std::move(pUndoAction
) );
129 rDocShell
.GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoDraw
>( std::move(pUndoAction
), &rDocShell
) );
130 rDocShell
.SetDrawModified();
132 // the affected sheet isn't known, so all stream positions are invalidated
133 ScDocument
& rDoc
= rDocShell
.GetDocument();
134 SCTAB nTabCount
= rDoc
.GetTableCount();
135 for (SCTAB nTab
=0; nTab
<nTabCount
; nTab
++)
136 rDoc
.SetStreamValid(nTab
, false);
139 // paint row above the range (because of lines after AdjustRowHeight)
141 static void lcl_PaintAbove( ScDocShell
& rDocShell
, const ScRange
& rRange
)
143 SCROW nRow
= rRange
.aStart
.Row();
146 SCTAB nTab
= rRange
.aStart
.Tab(); //! all of them?
148 ScDocument
& rDoc
= rDocShell
.GetDocument();
149 rDocShell
.PostPaint( ScRange(0,nRow
,nTab
,rDoc
.MaxCol(),nRow
,nTab
), PaintPartFlags::Grid
);
153 bool ScDocFunc::AdjustRowHeight( const ScRange
& rRange
, bool bPaint
, bool bApi
)
155 ScDocument
& rDoc
= rDocShell
.GetDocument();
156 SfxViewShell
* pSomeViewForThisDoc
= rDocShell
.GetBestViewShell(false);
157 if ( rDoc
.IsImportingXML() )
159 // for XML import, all row heights are updated together after importing
162 if ( rDoc
.IsAdjustHeightLocked() )
167 SCTAB nTab
= rRange
.aStart
.Tab();
168 SCROW nStartRow
= rRange
.aStart
.Row();
169 SCROW nEndRow
= rRange
.aEnd
.Row();
171 ScSizeDeviceProvider
aProv( &rDocShell
);
174 sc::RowHeightContext
aCxt(rDoc
.MaxRow(), aProv
.GetPPTX(), aProv
.GetPPTY(), aOne
, aOne
, aProv
.GetDevice());
175 bool bChanged
= rDoc
.SetOptimalHeight(aCxt
, nStartRow
, nEndRow
, nTab
, bApi
);
176 // tdf#76183: recalculate objects' positions
179 if (comphelper::LibreOfficeKit::isActive())
181 SfxViewShell
* pViewShell
= SfxViewShell::GetFirst();
184 ScTabViewShell
* pTabViewShell
= dynamic_cast<ScTabViewShell
*>(pViewShell
);
185 if (pTabViewShell
&& pSomeViewForThisDoc
&& pTabViewShell
->GetDocId() == pSomeViewForThisDoc
->GetDocId())
187 if (ScPositionHelper
* pPosHelper
= pTabViewShell
->GetViewData().GetLOKHeightHelper(nTab
))
188 pPosHelper
->invalidateByIndex(nStartRow
);
190 pViewShell
= SfxViewShell::GetNext(*pViewShell
);
193 rDoc
.SetDrawPageSize(nTab
);
196 if ( bPaint
&& bChanged
)
197 rDocShell
.PostPaint(ScRange(0, nStartRow
, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
),
198 PaintPartFlags::Grid
| PaintPartFlags::Left
);
200 if (comphelper::LibreOfficeKit::isActive())
202 ScTabViewShell::notifyAllViewsHeaderInvalidation(pSomeViewForThisDoc
, ROW_HEADER
, nTab
);
203 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
204 pSomeViewForThisDoc
, false /* bColumns */, true /* bRows */, true /* bSizes*/,
205 false /* bHidden */, false /* bFiltered */, false /* bGroups */, nTab
);
211 bool ScDocFunc::DetectiveAddPred(const ScAddress
& rPos
)
213 ScDocShellModificator
aModificator( rDocShell
);
215 rDocShell
.MakeDrawLayer();
216 ScDocument
& rDoc
= rDocShell
.GetDocument();
217 bool bUndo (rDoc
.IsUndoEnabled());
218 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
219 SCCOL nCol
= rPos
.Col();
220 SCROW nRow
= rPos
.Row();
221 SCTAB nTab
= rPos
.Tab();
224 pModel
->BeginCalcUndo(false);
225 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).ShowPred( nCol
, nRow
);
226 std::unique_ptr
<SdrUndoGroup
> pUndo
;
228 pUndo
= pModel
->GetCalcUndo();
231 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_ADDPRED
);
232 rDoc
.AddDetectiveOperation( aOperation
);
235 rDocShell
.GetUndoManager()->AddUndoAction(
236 std::make_unique
<ScUndoDetective
>( &rDocShell
, std::move(pUndo
), &aOperation
) );
238 aModificator
.SetDocumentModified();
239 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
241 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
247 bool ScDocFunc::DetectiveDelPred(const ScAddress
& rPos
)
249 ScDocument
& rDoc
= rDocShell
.GetDocument();
251 bool bUndo(rDoc
.IsUndoEnabled());
252 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
256 ScDocShellModificator
aModificator( rDocShell
);
258 SCCOL nCol
= rPos
.Col();
259 SCROW nRow
= rPos
.Row();
260 SCTAB nTab
= rPos
.Tab();
263 pModel
->BeginCalcUndo(false);
264 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).DeletePred( nCol
, nRow
);
265 std::unique_ptr
<SdrUndoGroup
> pUndo
;
267 pUndo
= pModel
->GetCalcUndo();
270 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_DELPRED
);
271 rDoc
.AddDetectiveOperation( aOperation
);
274 rDocShell
.GetUndoManager()->AddUndoAction(
275 std::make_unique
<ScUndoDetective
>( &rDocShell
, std::move(pUndo
), &aOperation
) );
277 aModificator
.SetDocumentModified();
278 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
280 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
286 bool ScDocFunc::DetectiveAddSucc(const ScAddress
& rPos
)
288 ScDocShellModificator
aModificator( rDocShell
);
290 rDocShell
.MakeDrawLayer();
291 ScDocument
& rDoc
= rDocShell
.GetDocument();
293 bool bUndo(rDoc
.IsUndoEnabled());
294 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
295 SCCOL nCol
= rPos
.Col();
296 SCROW nRow
= rPos
.Row();
297 SCTAB nTab
= rPos
.Tab();
300 pModel
->BeginCalcUndo(false);
301 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).ShowSucc( nCol
, nRow
);
302 std::unique_ptr
<SdrUndoGroup
> pUndo
;
304 pUndo
= pModel
->GetCalcUndo();
307 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_ADDSUCC
);
308 rDoc
.AddDetectiveOperation( aOperation
);
311 rDocShell
.GetUndoManager()->AddUndoAction(
312 std::make_unique
<ScUndoDetective
>( &rDocShell
, std::move(pUndo
), &aOperation
) );
314 aModificator
.SetDocumentModified();
315 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
317 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
323 bool ScDocFunc::DetectiveDelSucc(const ScAddress
& rPos
)
325 ScDocument
& rDoc
= rDocShell
.GetDocument();
327 bool bUndo (rDoc
.IsUndoEnabled());
328 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
332 ScDocShellModificator
aModificator( rDocShell
);
334 SCCOL nCol
= rPos
.Col();
335 SCROW nRow
= rPos
.Row();
336 SCTAB nTab
= rPos
.Tab();
339 pModel
->BeginCalcUndo(false);
340 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).DeleteSucc( nCol
, nRow
);
341 std::unique_ptr
<SdrUndoGroup
> pUndo
;
343 pUndo
= pModel
->GetCalcUndo();
346 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_DELSUCC
);
347 rDoc
.AddDetectiveOperation( aOperation
);
350 rDocShell
.GetUndoManager()->AddUndoAction(
351 std::make_unique
<ScUndoDetective
>( &rDocShell
, std::move(pUndo
), &aOperation
) );
353 aModificator
.SetDocumentModified();
354 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
356 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
362 bool ScDocFunc::DetectiveAddError(const ScAddress
& rPos
)
364 ScDocShellModificator
aModificator( rDocShell
);
366 rDocShell
.MakeDrawLayer();
367 ScDocument
& rDoc
= rDocShell
.GetDocument();
369 bool bUndo (rDoc
.IsUndoEnabled());
370 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
371 SCCOL nCol
= rPos
.Col();
372 SCROW nRow
= rPos
.Row();
373 SCTAB nTab
= rPos
.Tab();
376 pModel
->BeginCalcUndo(false);
377 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).ShowError( nCol
, nRow
);
378 std::unique_ptr
<SdrUndoGroup
> pUndo
;
380 pUndo
= pModel
->GetCalcUndo();
383 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_ADDERROR
);
384 rDoc
.AddDetectiveOperation( aOperation
);
387 rDocShell
.GetUndoManager()->AddUndoAction(
388 std::make_unique
<ScUndoDetective
>( &rDocShell
, std::move(pUndo
), &aOperation
) );
390 aModificator
.SetDocumentModified();
391 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
393 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
399 bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab
)
401 ScDocShellModificator
aModificator( rDocShell
);
403 rDocShell
.MakeDrawLayer();
404 ScDocument
& rDoc
= rDocShell
.GetDocument();
406 bool bUndo (rDoc
.IsUndoEnabled());
407 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
409 std::unique_ptr
<weld::WaitObject
> xWaitWin(new weld::WaitObject(ScDocShell::GetActiveDialogParent()));
411 pModel
->BeginCalcUndo(false);
413 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).MarkInvalid( bOverflow
);
414 std::unique_ptr
<SdrUndoGroup
> pUndo
;
416 pUndo
= pModel
->GetCalcUndo();
422 pUndo
->SetComment( ScResId( STR_UNDO_DETINVALID
) );
423 rDocShell
.GetUndoManager()->AddUndoAction( std::move(pUndo
) );
425 aModificator
.SetDocumentModified();
428 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(nullptr,
429 VclMessageType::Info
, VclButtonsType::Ok
,
430 ScResId(STR_DETINVALID_OVERFLOW
)));
438 bool ScDocFunc::DetectiveDelAll(SCTAB nTab
)
440 ScDocument
& rDoc
= rDocShell
.GetDocument();
442 bool bUndo (rDoc
.IsUndoEnabled());
443 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
447 ScDocShellModificator
aModificator( rDocShell
);
450 pModel
->BeginCalcUndo(false);
451 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).DeleteAll( ScDetectiveDelete::Detective
);
452 std::unique_ptr
<SdrUndoGroup
> pUndo
;
454 pUndo
= pModel
->GetCalcUndo();
457 ScDetOpList
* pOldList
= rDoc
.GetDetOpList();
458 std::unique_ptr
<ScDetOpList
> pUndoList
;
459 if (bUndo
&& pOldList
)
460 pUndoList
.reset(new ScDetOpList(*pOldList
));
462 rDoc
.ClearDetectiveOperations();
466 rDocShell
.GetUndoManager()->AddUndoAction(
467 std::make_unique
<ScUndoDetective
>( &rDocShell
, std::move(pUndo
), nullptr, std::move(pUndoList
) ) );
469 aModificator
.SetDocumentModified();
470 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
472 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
478 bool ScDocFunc::DetectiveRefresh( bool bAutomatic
)
481 ScDocument
& rDoc
= rDocShell
.GetDocument();
483 ScDetOpList
* pList
= rDoc
.GetDetOpList();
484 if ( pList
&& pList
->Count() )
486 rDocShell
.MakeDrawLayer();
487 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
488 const bool bUndo (rDoc
.IsUndoEnabled());
490 pModel
->BeginCalcUndo(false);
492 // Delete in all sheets
494 SCTAB nTabCount
= rDoc
.GetTableCount();
495 for (SCTAB nTab
=0; nTab
<nTabCount
; nTab
++)
496 ScDetectiveFunc( rDoc
,nTab
).DeleteAll( ScDetectiveDelete::Arrows
); // don't remove circles
500 size_t nCount
= pList
->Count();
501 for (size_t i
=0; i
< nCount
; ++i
)
503 const ScDetOpData
& rData
= pList
->GetObject(i
);
504 const ScAddress
& aPos
= rData
.GetPos();
505 ScDetectiveFunc
aFunc( rDoc
, aPos
.Tab() );
506 SCCOL nCol
= aPos
.Col();
507 SCROW nRow
= aPos
.Row();
508 switch (rData
.GetOperation())
510 case SCDETOP_ADDSUCC
:
511 aFunc
.ShowSucc( nCol
, nRow
);
513 case SCDETOP_DELSUCC
:
514 aFunc
.DeleteSucc( nCol
, nRow
);
516 case SCDETOP_ADDPRED
:
517 aFunc
.ShowPred( nCol
, nRow
);
519 case SCDETOP_DELPRED
:
520 aFunc
.DeletePred( nCol
, nRow
);
522 case SCDETOP_ADDERROR
:
523 aFunc
.ShowError( nCol
, nRow
);
526 OSL_FAIL("wrong operation in DetectiveRefresh");
532 std::unique_ptr
<SdrUndoGroup
> pUndo
= pModel
->GetCalcUndo();
535 pUndo
->SetComment( ScResId( STR_UNDO_DETREFRESH
) );
536 // associate with the last action
537 rDocShell
.GetUndoManager()->AddUndoAction(
538 std::make_unique
<ScUndoDraw
>( std::move(pUndo
), &rDocShell
),
542 rDocShell
.SetDrawModified();
548 static void lcl_collectAllPredOrSuccRanges(
549 const ScRangeList
& rSrcRanges
, vector
<ScTokenRef
>& rRefTokens
, ScDocShell
& rDocShell
,
552 ScDocument
& rDoc
= rDocShell
.GetDocument();
553 vector
<ScTokenRef
> aRefTokens
;
554 if (rSrcRanges
.empty())
556 ScRange
const & rFrontRange
= rSrcRanges
.front();
557 ScDetectiveFunc
aDetFunc(rDoc
, rFrontRange
.aStart
.Tab());
558 for (ScRange
const & r
: rSrcRanges
)
562 aDetFunc
.GetAllPreds(
563 r
.aStart
.Col(), r
.aStart
.Row(), r
.aEnd
.Col(), r
.aEnd
.Row(), aRefTokens
);
567 aDetFunc
.GetAllSuccs(
568 r
.aStart
.Col(), r
.aStart
.Row(), r
.aEnd
.Col(), r
.aEnd
.Row(), aRefTokens
);
571 rRefTokens
.swap(aRefTokens
);
574 void ScDocFunc::DetectiveCollectAllPreds(const ScRangeList
& rSrcRanges
, vector
<ScTokenRef
>& rRefTokens
)
576 lcl_collectAllPredOrSuccRanges(rSrcRanges
, rRefTokens
, rDocShell
, true);
579 void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList
& rSrcRanges
, vector
<ScTokenRef
>& rRefTokens
)
581 lcl_collectAllPredOrSuccRanges(rSrcRanges
, rRefTokens
, rDocShell
, false);
584 bool ScDocFunc::DeleteContents(
585 const ScMarkData
& rMark
, InsertDeleteFlags nFlags
, bool bRecord
, bool bApi
)
587 ScDocShellModificator
aModificator( rDocShell
);
589 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() )
591 OSL_FAIL("ScDocFunc::DeleteContents without markings");
595 ScDocument
& rDoc
= rDocShell
.GetDocument();
597 if (bRecord
&& !rDoc
.IsUndoEnabled())
600 ScEditableTester
aTester( rDoc
, rMark
);
601 if (!aTester
.IsEditable())
604 rDocShell
.ErrorMessage(aTester
.GetMessageId());
608 ScMarkData aMultiMark
= rMark
;
609 aMultiMark
.SetMarking(false); // for MarkToMulti
611 ScDocumentUniquePtr pUndoDoc
;
612 bool bMulti
= aMultiMark
.IsMultiMarked();
613 aMultiMark
.MarkToMulti();
614 const ScRange
& aMarkRange
= aMultiMark
.GetMultiMarkArea();
615 ScRange
aExtendedRange(aMarkRange
);
616 if ( rDoc
.ExtendMerge( aExtendedRange
, true ) )
619 // no objects on protected tabs
620 bool bObjects
= (nFlags
& InsertDeleteFlags::OBJECTS
) && !sc::DocFuncUtil::hasProtectedTab(rDoc
, rMark
);
622 sal_uInt16 nExtFlags
= 0; // extra flags are needed only if attributes are deleted
623 if ( nFlags
& InsertDeleteFlags::ATTRIB
)
624 rDocShell
.UpdatePaintExt( nExtFlags
, aMarkRange
);
626 // order of operations:
628 // 2) Delete objects (DrawUndo will be filled)
629 // 3) Copy content for undo and set up undo actions
632 bool bDrawUndo
= bObjects
|| (nFlags
& InsertDeleteFlags::NOTE
);
633 if (bRecord
&& bDrawUndo
)
634 rDoc
.BeginDrawUndo();
639 rDoc
.DeleteObjectsInSelection( aMultiMark
);
641 rDoc
.DeleteObjectsInArea( aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
642 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(),
646 // To keep track of all non-empty cells within the deleted area.
647 std::shared_ptr
<ScSimpleUndo::DataSpansType
> pDataSpans
;
651 pUndoDoc
= sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc
, aMultiMark
, aMarkRange
, nFlags
, bMulti
);
652 pDataSpans
= sc::DocFuncUtil::getNonEmptyCellSpans(rDoc
, aMultiMark
, aMarkRange
);
655 rDoc
.DeleteSelection( nFlags
, aMultiMark
);
657 // add undo action after drawing undo is complete (objects and note captions)
660 sc::DocFuncUtil::addDeleteContentsUndo(
661 rDocShell
.GetUndoManager(), &rDocShell
, aMultiMark
, aExtendedRange
,
662 std::move(pUndoDoc
), nFlags
, pDataSpans
, bMulti
, bDrawUndo
);
665 if (!AdjustRowHeight( aExtendedRange
, true, bApi
))
666 rDocShell
.PostPaint( aExtendedRange
, PaintPartFlags::Grid
, nExtFlags
);
667 else if (nExtFlags
& SC_PF_LINES
)
668 lcl_PaintAbove( rDocShell
, aExtendedRange
); // for lines above the range
670 aModificator
.SetDocumentModified();
675 tools::Long
ScDocShell::GetTwipWidthHint(const ScAddress
& rPos
)
677 ScViewData
* pViewData
= GetViewData();
681 ScSizeDeviceProvider
aProv(this);
682 Fraction aZoomX
, aZoomY
;
684 pViewData
->setupSizeDeviceProviderForColWidth(aProv
, aZoomX
, aZoomY
, nPPTX
, nPPTY
);
686 ScDocument
& rDoc
= GetDocument();
687 tools::Long nWidth
= rDoc
.GetNeededSize(rPos
.Col(), rPos
.Row(), rPos
.Tab(), aProv
.GetDevice(),
688 nPPTX
, nPPTY
, aZoomX
, aZoomY
, true /*bWidth*/);
690 return (nWidth
+ 2) / nPPTX
; // same as ScColumn::GetOptimalColWidth
693 bool ScDocFunc::DeleteCell(
694 const ScAddress
& rPos
, const ScMarkData
& rMark
, InsertDeleteFlags nFlags
, bool bRecord
, bool bApi
)
696 ScDocShellModificator
aModificator(rDocShell
);
698 ScDocument
& rDoc
= rDocShell
.GetDocument();
700 if (bRecord
&& !rDoc
.IsUndoEnabled())
703 ScEditableTester
aTester(rDoc
, rPos
.Col(), rPos
.Row(), rPos
.Col(), rPos
.Row(), rMark
);
704 if (!aTester
.IsEditable())
706 rDocShell
.ErrorMessage(aTester
.GetMessageId());
710 // no objects on protected tabs
711 bool bObjects
= (nFlags
& InsertDeleteFlags::OBJECTS
) && !sc::DocFuncUtil::hasProtectedTab(rDoc
, rMark
);
713 sal_uInt16 nExtFlags
= 0; // extra flags are needed only if attributes are deleted
714 if (nFlags
& InsertDeleteFlags::ATTRIB
)
715 rDocShell
.UpdatePaintExt(nExtFlags
, ScRange(rPos
));
717 // order of operations:
719 // 2) delete objects (DrawUndo is filled)
720 // 3) copy contents for undo
721 // 4) delete contents
722 // 5) add undo-action
724 bool bDrawUndo
= bObjects
|| (nFlags
& InsertDeleteFlags::NOTE
); // needed for shown notes
725 if (bDrawUndo
&& bRecord
)
726 rDoc
.BeginDrawUndo();
729 rDoc
.DeleteObjectsInArea(rPos
.Col(), rPos
.Row(), rPos
.Col(), rPos
.Row(), rMark
);
731 // To keep track of all non-empty cells within the deleted area.
732 std::shared_ptr
<ScSimpleUndo::DataSpansType
> pDataSpans
;
734 ScDocumentUniquePtr pUndoDoc
;
737 pUndoDoc
= sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc
, rMark
, ScRange(rPos
), nFlags
, false);
738 pDataSpans
= sc::DocFuncUtil::getNonEmptyCellSpans(rDoc
, rMark
, ScRange(rPos
));
741 tools::Long
nBefore(rDocShell
.GetTwipWidthHint(rPos
));
742 rDoc
.DeleteArea(rPos
.Col(), rPos
.Row(), rPos
.Col(), rPos
.Row(), rMark
, nFlags
);
746 sc::DocFuncUtil::addDeleteContentsUndo(
747 rDocShell
.GetUndoManager(), &rDocShell
, rMark
, ScRange(rPos
), std::move(pUndoDoc
),
748 nFlags
, pDataSpans
, false, bDrawUndo
);
751 if (!AdjustRowHeight(ScRange(rPos
), true, bApi
))
753 rPos
.Col(), rPos
.Row(), rPos
.Tab(), rPos
.Col(), rPos
.Row(), rPos
.Tab(),
754 PaintPartFlags::Grid
, nExtFlags
, nBefore
);
756 aModificator
.SetDocumentModified();
761 bool ScDocFunc::TransliterateText( const ScMarkData
& rMark
, TransliterationFlags nType
,
764 ScDocShellModificator
aModificator( rDocShell
);
766 ScDocument
& rDoc
= rDocShell
.GetDocument();
768 if (!rDoc
.IsUndoEnabled())
771 ScEditableTester
aTester( rDoc
, rMark
);
772 if (!aTester
.IsEditable())
775 rDocShell
.ErrorMessage(aTester
.GetMessageId());
779 ScMarkData aMultiMark
= rMark
;
780 aMultiMark
.SetMarking(false); // for MarkToMulti
781 aMultiMark
.MarkToMulti();
782 const ScRange
& aMarkRange
= aMultiMark
.GetMultiMarkArea();
786 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
787 SCTAB nTabCount
= rDoc
.GetTableCount();
789 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
790 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nStartTab
);
791 for (const auto& rTab
: rMark
)
793 if (rTab
>= nTabCount
)
796 if (rTab
!= nStartTab
)
797 pUndoDoc
->AddUndoTab( rTab
, rTab
);
800 ScRange aCopyRange
= aMarkRange
;
801 aCopyRange
.aStart
.SetTab(0);
802 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
803 rDoc
.CopyToDocument(aCopyRange
, InsertDeleteFlags::CONTENTS
, true, *pUndoDoc
, &aMultiMark
);
805 rDocShell
.GetUndoManager()->AddUndoAction(
806 std::make_unique
<ScUndoTransliterate
>( &rDocShell
, aMultiMark
, std::move(pUndoDoc
), nType
) );
809 rDoc
.TransliterateText( aMultiMark
, nType
);
811 if (!AdjustRowHeight( aMarkRange
, true, true ))
812 rDocShell
.PostPaint( aMarkRange
, PaintPartFlags::Grid
);
814 aModificator
.SetDocumentModified();
819 bool ScDocFunc::SetNormalString( bool& o_rbNumFmtSet
, const ScAddress
& rPos
, const OUString
& rText
, bool bApi
)
821 ScDocShellModificator
aModificator( rDocShell
);
822 ScDocument
& rDoc
= rDocShell
.GetDocument();
824 bool bUndo(rDoc
.IsUndoEnabled());
825 ScEditableTester
aTester( rDoc
, rPos
.Tab(), rPos
.Col(),rPos
.Row(), rPos
.Col(),rPos
.Row() );
826 if (!aTester
.IsEditable())
829 rDocShell
.ErrorMessage(aTester
.GetMessageId());
833 bool bEditDeleted
= (rDoc
.GetCellType(rPos
) == CELLTYPE_EDIT
);
834 ScUndoEnterData::ValuesType aOldValues
;
838 ScUndoEnterData::Value aOldValue
;
840 aOldValue
.mnTab
= rPos
.Tab();
841 aOldValue
.maCell
.assign(rDoc
, rPos
);
843 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( rPos
.Col(),rPos
.Row(),rPos
.Tab() );
844 if ( const SfxUInt32Item
* pItem
= pPattern
->GetItemSet().GetItemIfSet(
845 ATTR_VALUE_FORMAT
,false) )
847 aOldValue
.mbHasFormat
= true;
848 aOldValue
.mnFormat
= pItem
->GetValue();
851 aOldValue
.mbHasFormat
= false;
853 aOldValues
.push_back(aOldValue
);
856 tools::Long
nBefore(rDocShell
.GetTwipWidthHint(rPos
));
857 o_rbNumFmtSet
= rDoc
.SetString( rPos
.Col(), rPos
.Row(), rPos
.Tab(), rText
);
858 tools::Long
nAfter(rDocShell
.GetTwipWidthHint(rPos
));
862 // because of ChangeTracking, UndoAction can be created only after SetString was called
863 rDocShell
.GetUndoManager()->AddUndoAction(
864 std::make_unique
<ScUndoEnterData
>(&rDocShell
, rPos
, aOldValues
, rText
, nullptr));
867 if ( bEditDeleted
|| rDoc
.HasAttrib( ScRange(rPos
), HasAttrFlags::NeedHeight
) )
868 AdjustRowHeight( ScRange(rPos
), true, bApi
);
870 rDocShell
.PostPaintCell( rPos
, std::max(nBefore
, nAfter
) );
871 aModificator
.SetDocumentModified();
873 // notify input handler here the same way as in PutCell
875 NotifyInputHandler( rPos
);
877 const SfxUInt32Item
* pItem
= rDoc
.GetAttr(rPos
, ATTR_VALIDDATA
);
878 const ScValidationData
* pData
= rDoc
.GetValidationEntry(pItem
->GetValue());
881 ScRefCellValue
aCell(rDoc
, rPos
);
882 if (pData
->IsDataValid(aCell
, rPos
))
883 ScDetectiveFunc(rDoc
, rPos
.Tab()).DeleteCirclesAt(rPos
.Col(), rPos
.Row());
889 bool ScDocFunc::SetValueCell( const ScAddress
& rPos
, double fVal
, bool bInteraction
)
891 ScDocShellModificator
aModificator( rDocShell
);
892 ScDocument
& rDoc
= rDocShell
.GetDocument();
893 bool bUndo
= rDoc
.IsUndoEnabled();
895 bool bHeight
= rDoc
.HasAttrib(ScRange(rPos
), HasAttrFlags::NeedHeight
);
899 aOldVal
.assign(rDoc
, rPos
);
901 rDoc
.SetValue(rPos
, fVal
);
905 SfxUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
907 aNewVal
.assign(rDoc
, rPos
);
908 pUndoMgr
->AddUndoAction(std::make_unique
<ScUndoSetCell
>(&rDocShell
, rPos
, aOldVal
, aNewVal
));
912 AdjustRowHeight(ScRange(rPos
), true, !bInteraction
);
914 rDocShell
.PostPaintCell( rPos
);
915 aModificator
.SetDocumentModified();
917 // #103934#; notify editline and cell in edit mode
919 NotifyInputHandler( rPos
);
924 void ScDocFunc::SetValueCells( const ScAddress
& rPos
, const std::vector
<double>& aVals
, bool bInteraction
)
926 ScDocument
& rDoc
= rDocShell
.GetDocument();
928 // Check for invalid range.
929 SCROW nLastRow
= rPos
.Row() + aVals
.size() - 1;
930 if (nLastRow
> rDoc
.MaxRow())
934 ScRange
aRange(rPos
);
935 aRange
.aEnd
.SetRow(nLastRow
);
937 ScDocShellModificator
aModificator(rDocShell
);
939 if (rDoc
.IsUndoEnabled())
941 std::unique_ptr
<sc::UndoSetCells
> pUndoObj(new sc::UndoSetCells(&rDocShell
, rPos
));
942 rDoc
.TransferCellValuesTo(rPos
, aVals
.size(), pUndoObj
->GetOldValues());
943 pUndoObj
->SetNewValues(aVals
);
944 SfxUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
945 pUndoMgr
->AddUndoAction(std::move(pUndoObj
));
948 rDoc
.SetValues(rPos
, aVals
);
950 rDocShell
.PostPaint(aRange
, PaintPartFlags::Grid
);
951 aModificator
.SetDocumentModified();
953 // #103934#; notify editline and cell in edit mode
955 NotifyInputHandler(rPos
);
958 bool ScDocFunc::SetStringCell( const ScAddress
& rPos
, const OUString
& rStr
, bool bInteraction
)
960 ScDocShellModificator
aModificator( rDocShell
);
961 ScDocument
& rDoc
= rDocShell
.GetDocument();
962 bool bUndo
= rDoc
.IsUndoEnabled();
964 bool bHeight
= rDoc
.HasAttrib(ScRange(rPos
), HasAttrFlags::NeedHeight
);
968 aOldVal
.assign(rDoc
, rPos
);
970 ScSetStringParam aParam
;
971 aParam
.setTextInput();
972 rDoc
.SetString(rPos
, rStr
, &aParam
);
976 SfxUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
978 aNewVal
.assign(rDoc
, rPos
);
979 pUndoMgr
->AddUndoAction(std::make_unique
<ScUndoSetCell
>(&rDocShell
, rPos
, aOldVal
, aNewVal
));
983 AdjustRowHeight(ScRange(rPos
), true, !bInteraction
);
985 rDocShell
.PostPaintCell( rPos
);
986 aModificator
.SetDocumentModified();
988 // #103934#; notify editline and cell in edit mode
990 NotifyInputHandler( rPos
);
995 bool ScDocFunc::SetEditCell( const ScAddress
& rPos
, const EditTextObject
& rStr
, bool bInteraction
)
997 ScDocShellModificator
aModificator( rDocShell
);
998 ScDocument
& rDoc
= rDocShell
.GetDocument();
999 bool bUndo
= rDoc
.IsUndoEnabled();
1001 bool bHeight
= rDoc
.HasAttrib(ScRange(rPos
), HasAttrFlags::NeedHeight
);
1003 ScCellValue aOldVal
;
1005 aOldVal
.assign(rDoc
, rPos
);
1007 rDoc
.SetEditText(rPos
, rStr
.Clone());
1011 SfxUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
1012 ScCellValue aNewVal
;
1013 aNewVal
.assign(rDoc
, rPos
);
1014 pUndoMgr
->AddUndoAction(std::make_unique
<ScUndoSetCell
>(&rDocShell
, rPos
, aOldVal
, aNewVal
));
1018 AdjustRowHeight(ScRange(rPos
), true, !bInteraction
);
1020 rDocShell
.PostPaintCell( rPos
);
1021 aModificator
.SetDocumentModified();
1023 // #103934#; notify editline and cell in edit mode
1025 NotifyInputHandler( rPos
);
1030 bool ScDocFunc::SetStringOrEditCell( const ScAddress
& rPos
, const OUString
& rStr
, bool bInteraction
)
1032 ScDocument
& rDoc
= rDocShell
.GetDocument();
1034 if (ScStringUtil::isMultiline(rStr
))
1036 ScFieldEditEngine
& rEngine
= rDoc
.GetEditEngine();
1037 rEngine
.SetTextCurrentDefaults(rStr
);
1038 std::unique_ptr
<EditTextObject
> pEditText(rEngine
.CreateTextObject());
1039 return SetEditCell(rPos
, *pEditText
, bInteraction
);
1042 return SetStringCell(rPos
, rStr
, bInteraction
);
1045 bool ScDocFunc::SetFormulaCell( const ScAddress
& rPos
, ScFormulaCell
* pCell
, bool bInteraction
)
1047 std::unique_ptr
<ScFormulaCell
> xCell(pCell
);
1049 ScDocShellModificator
aModificator( rDocShell
);
1050 ScDocument
& rDoc
= rDocShell
.GetDocument();
1051 bool bUndo
= rDoc
.IsUndoEnabled();
1053 bool bHeight
= rDoc
.HasAttrib(ScRange(rPos
), HasAttrFlags::NeedHeight
);
1055 ScCellValue aOldVal
;
1057 aOldVal
.assign(rDoc
, rPos
);
1059 pCell
= rDoc
.SetFormulaCell(rPos
, xCell
.release());
1061 // For performance reasons API calls may disable calculation while
1062 // operating and recalculate once when done. If through user interaction
1063 // and AutoCalc is disabled, calculate the formula (without its
1064 // dependencies) once so the result matches the current document's content.
1065 if (bInteraction
&& !rDoc
.GetAutoCalc() && pCell
)
1067 // calculate just the cell once and set Dirty again
1069 pCell
->SetDirtyVar();
1070 rDoc
.PutInFormulaTree( pCell
);
1075 SfxUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
1076 ScCellValue aNewVal
;
1077 aNewVal
.assign(rDoc
, rPos
);
1078 pUndoMgr
->AddUndoAction(std::make_unique
<ScUndoSetCell
>(&rDocShell
, rPos
, aOldVal
, aNewVal
));
1082 AdjustRowHeight(ScRange(rPos
), true, !bInteraction
);
1084 rDocShell
.PostPaintCell( rPos
);
1085 aModificator
.SetDocumentModified();
1087 // #103934#; notify editline and cell in edit mode
1089 NotifyInputHandler( rPos
);
1094 bool ScDocFunc::SetFormulaCells( const ScAddress
& rPos
, std::vector
<ScFormulaCell
*>& rCells
, bool bInteraction
)
1096 ScDocument
& rDoc
= rDocShell
.GetDocument();
1098 const size_t nLength
= rCells
.size();
1099 if (rPos
.Row() + nLength
- 1 > o3tl::make_unsigned(rDoc
.MaxRow()))
1103 ScRange
aRange(rPos
);
1104 aRange
.aEnd
.IncRow(nLength
- 1);
1106 ScDocShellModificator
aModificator( rDocShell
);
1107 bool bUndo
= rDoc
.IsUndoEnabled();
1109 std::unique_ptr
<sc::UndoSetCells
> pUndoObj
;
1112 pUndoObj
.reset(new sc::UndoSetCells(&rDocShell
, rPos
));
1113 rDoc
.TransferCellValuesTo(rPos
, nLength
, pUndoObj
->GetOldValues());
1116 rDoc
.SetFormulaCells(rPos
, rCells
);
1118 // For performance reasons API calls may disable calculation while
1119 // operating and recalculate once when done. If through user interaction
1120 // and AutoCalc is disabled, calculate the formula (without its
1121 // dependencies) once so the result matches the current document's content.
1122 if (bInteraction
&& !rDoc
.GetAutoCalc())
1124 for (auto* pCell
: rCells
)
1126 // calculate just the cell once and set Dirty again
1128 pCell
->SetDirtyVar();
1129 rDoc
.PutInFormulaTree( pCell
);
1135 pUndoObj
->SetNewValues(rCells
);
1136 SfxUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
1137 pUndoMgr
->AddUndoAction(std::move(pUndoObj
));
1140 rDocShell
.PostPaint(aRange
, PaintPartFlags::Grid
);
1141 aModificator
.SetDocumentModified();
1143 // #103934#; notify editline and cell in edit mode
1145 NotifyInputHandler( rPos
);
1150 void ScDocFunc::NotifyInputHandler( const ScAddress
& rPos
)
1152 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
1153 if ( !(pViewSh
&& pViewSh
->GetViewData().GetDocShell() == &rDocShell
) )
1156 ScInputHandler
* pInputHdl
= ScModule::get()->GetInputHdl();
1157 if ( pInputHdl
&& pInputHdl
->GetCursorPos() == rPos
)
1159 bool bIsEditMode(pInputHdl
->IsEditMode());
1161 // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
1162 // (the cell shows the same like the InputWindow)
1164 pInputHdl
->SetModified();
1165 pViewSh
->UpdateInputHandler(false, !bIsEditMode
);
1171 struct ScMyRememberItem
1174 SfxItemSet aItemSet
;
1176 ScMyRememberItem(SfxItemSet _aItemSet
, sal_Int32 nTempIndex
) :
1177 nIndex(nTempIndex
), aItemSet(std::move(_aItemSet
)) {}
1182 void ScDocFunc::PutData( const ScAddress
& rPos
, ScEditEngineDefaulter
& rEngine
, bool bApi
)
1184 // PutData calls PutCell or SetNormalString
1187 ScDocument
& rDoc
= rDocShell
.GetDocument();
1188 ScEditAttrTester
aTester( &rEngine
);
1189 bool bEditCell
= aTester
.NeedsObject();
1192 // #i61702# With bLoseContent set, the content of rEngine isn't restored
1193 // (used in loading XML, where after the removeActionLock call the API object's
1194 // EditEngine isn't accessed again.
1195 bool bLoseContent
= rDoc
.IsImportingXML();
1197 const bool bUpdateMode
= rEngine
.SetUpdateLayout(false);
1199 std::vector
<std::unique_ptr
<ScMyRememberItem
>> aRememberItems
;
1201 // All paragraph attributes must be removed before calling CreateTextObject,
1202 // not only alignment, so the object doesn't contain the cell attributes as
1203 // paragraph attributes. Before removing the attributes store them in a vector to
1204 // set them back to the EditEngine.
1205 sal_Int32 nCount
= rEngine
.GetParagraphCount();
1206 for (sal_Int32 i
=0; i
<nCount
; i
++)
1208 const SfxItemSet
& rOld
= rEngine
.GetParaAttribs( i
);
1211 if ( !bLoseContent
)
1213 aRememberItems
.push_back(std::make_unique
<ScMyRememberItem
>(rEngine
.GetParaAttribs(i
), i
));
1215 rEngine
.SetParaAttribs( i
, SfxItemSet( *rOld
.GetPool(), rOld
.GetRanges() ) );
1219 // A copy of pNewData will be stored in the cell.
1220 std::unique_ptr
<EditTextObject
> pNewData(rEngine
.CreateTextObject());
1221 bRet
= SetEditCell(rPos
, *pNewData
, !bApi
);
1223 // Set the paragraph attributes back to the EditEngine.
1224 for (const auto& rxItem
: aRememberItems
)
1226 rEngine
.SetParaAttribs(rxItem
->nIndex
, rxItem
->aItemSet
);
1229 // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
1230 if ( bUpdateMode
&& !bLoseContent
)
1231 rEngine
.SetUpdateLayout(true);
1235 OUString aText
= rEngine
.GetText();
1236 if (aText
.isEmpty())
1238 bool bNumFmtSet
= false;
1239 bRet
= SetNormalString( bNumFmtSet
, rPos
, aText
, bApi
);
1242 bRet
= SetStringCell(rPos
, aText
, !bApi
);
1245 if ( !(bRet
&& aTester
.NeedsCellAttr()) )
1248 const SfxItemSet
& rEditAttr
= aTester
.GetAttribs();
1249 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
1250 aPattern
.GetFromEditItemSet( &rEditAttr
);
1251 aPattern
.DeleteUnchanged( rDoc
.GetPattern( rPos
.Col(), rPos
.Row(), rPos
.Tab() ) );
1252 aPattern
.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY
); // wasn't removed above if no edit object
1253 if ( aPattern
.GetItemSet().Count() > 0 )
1255 ScMarkData
aMark(rDoc
.GetSheetLimits());
1256 aMark
.SelectTable( rPos
.Tab(), true );
1257 aMark
.SetMarkArea( ScRange( rPos
) );
1258 ApplyAttributes( aMark
, aPattern
, bApi
);
1262 bool ScDocFunc::SetCellText(
1263 const ScAddress
& rPos
, const OUString
& rText
, bool bInterpret
, bool bEnglish
, bool bApi
,
1264 const formula::FormulaGrammar::Grammar eGrammar
)
1271 ScDocument
& rDoc
= rDocShell
.GetDocument();
1273 ::std::optional
<ScExternalRefManager::ApiGuard
> pExtRefGuard
;
1275 pExtRefGuard
.emplace(rDoc
);
1277 ScInputStringType aRes
=
1278 ScStringUtil::parseInputString(rDoc
.GetNonThreadedContext(), rText
, LANGUAGE_ENGLISH_US
);
1280 switch (aRes
.meType
)
1282 case ScInputStringType::Formula
:
1283 bSet
= SetFormulaCell(rPos
, new ScFormulaCell(rDoc
, rPos
, aRes
.maText
, eGrammar
), !bApi
);
1285 case ScInputStringType::Number
:
1286 bSet
= SetValueCell(rPos
, aRes
.mfValue
, !bApi
);
1288 case ScInputStringType::Text
:
1289 bSet
= SetStringOrEditCell(rPos
, aRes
.maText
, !bApi
);
1295 // otherwise keep Null -> SetString with local formulas/number formats
1297 else if (!rText
.isEmpty())
1299 bSet
= SetStringOrEditCell(rPos
, rText
, !bApi
);
1304 bool bNumFmtSet
= false;
1305 bSet
= SetNormalString( bNumFmtSet
, rPos
, rText
, bApi
);
1310 bool ScDocFunc::ShowNote( const ScAddress
& rPos
, bool bShow
)
1312 ScDocument
& rDoc
= rDocShell
.GetDocument();
1313 ScPostIt
* pNote
= rDoc
.GetNote( rPos
);
1314 if( !pNote
|| (bShow
== pNote
->IsCaptionShown()) ||
1315 (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations()) )
1318 // move the caption to internal or hidden layer and create undo action
1319 pNote
->ShowCaption( rPos
, bShow
);
1320 if( rDoc
.IsUndoEnabled() )
1321 rDocShell
.GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoShowHideNote
>( rDocShell
, rPos
, bShow
) );
1323 rDoc
.SetStreamValid(rPos
.Tab(), false);
1325 ScTabView::OnLOKNoteStateChanged(pNote
);
1327 if (ScViewData
* pViewData
= ScDocShell::GetViewData())
1329 if (ScDrawView
* pDrawView
= pViewData
->GetScDrawView())
1330 pDrawView
->SyncForGrid( pNote
->GetCaption());
1333 rDocShell
.SetDocumentModified();
1338 void ScDocFunc::SetNoteText( const ScAddress
& rPos
, const OUString
& rText
, bool bApi
)
1340 ScDocShellModificator
aModificator( rDocShell
);
1342 ScDocument
& rDoc
= rDocShell
.GetDocument();
1343 ScEditableTester
aTester( rDoc
, rPos
.Tab(), rPos
.Col(),rPos
.Row(), rPos
.Col(),rPos
.Row() );
1344 if (!aTester
.IsEditable())
1347 rDocShell
.ErrorMessage(aTester
.GetMessageId());
1351 OUString aNewText
= convertLineEnd(rText
, GetSystemLineEnd()); //! is this necessary ???
1353 if( ScPostIt
* pNote
= (!aNewText
.isEmpty()) ? rDoc
.GetOrCreateNote( rPos
) : rDoc
.GetNote(rPos
) )
1354 pNote
->SetText( rPos
, aNewText
);
1358 rDoc
.SetStreamValid(rPos
.Tab(), false);
1360 rDocShell
.PostPaintCell( rPos
);
1361 aModificator
.SetDocumentModified();
1364 void ScDocFunc::ReplaceNote( const ScAddress
& rPos
, const OUString
& rNoteText
, const OUString
* pAuthor
, const OUString
* pDate
, bool bApi
)
1366 ScDocShellModificator
aModificator( rDocShell
);
1367 ScDocument
& rDoc
= rDocShell
.GetDocument();
1368 ScEditableTester
aTester( rDoc
, rPos
.Tab(), rPos
.Col(),rPos
.Row(), rPos
.Col(),rPos
.Row() );
1369 if (aTester
.IsEditable())
1371 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
1372 SfxUndoManager
* pUndoMgr
= (pDrawLayer
&& rDoc
.IsUndoEnabled()) ? rDocShell
.GetUndoManager() : nullptr;
1374 ScNoteData aOldData
;
1375 std::unique_ptr
<ScPostIt
> pOldNote
= rDoc
.ReleaseNote( rPos
);
1376 sal_uInt32 nNoteId
= 0;
1379 nNoteId
= pOldNote
->GetId();
1380 // ensure existing caption object before draw undo tracking starts
1381 pOldNote
->GetOrCreateCaption( rPos
);
1382 // rescue note data for undo
1383 aOldData
= pOldNote
->GetNoteData();
1386 // collect drawing undo actions for deleting/inserting caption objects
1388 pDrawLayer
->BeginCalcUndo(false);
1390 // delete the note (creates drawing undo action for the caption object)
1391 bool hadOldNote(pOldNote
);
1394 // create new note (creates drawing undo action for the new caption object)
1395 ScNoteData aNewData
;
1396 ScPostIt
* pNewNote
= nullptr;
1397 if( (pNewNote
= ScNoteUtil::CreateNoteFromString( rDoc
, rPos
, rNoteText
, false, true, nNoteId
)) )
1399 if( pAuthor
) pNewNote
->SetAuthor( *pAuthor
);
1400 if( pDate
) pNewNote
->SetDate( *pDate
);
1402 // rescue note data for undo
1403 aNewData
= pNewNote
->GetNoteData();
1406 // create the undo action
1407 if( pUndoMgr
&& (aOldData
.mxCaption
|| aNewData
.mxCaption
) )
1408 pUndoMgr
->AddUndoAction( std::make_unique
<ScUndoReplaceNote
>( rDocShell
, rPos
, aOldData
, aNewData
, pDrawLayer
->GetCalcUndo() ) );
1410 // repaint cell (to make note marker visible)
1411 rDocShell
.PostPaintCell( rPos
);
1413 rDoc
.SetStreamValid(rPos
.Tab(), false);
1415 aModificator
.SetDocumentModified();
1417 // Let our LOK clients know about the new/modified note
1420 ScDocShell::LOKCommentNotify(hadOldNote
? LOKCommentNotificationType::Modify
: LOKCommentNotificationType::Add
,
1421 rDoc
, rPos
, pNewNote
);
1426 rDocShell
.ErrorMessage(aTester
.GetMessageId());
1430 void ScDocFunc::ImportNote( const ScAddress
& rPos
,
1431 std::unique_ptr
<GenerateNoteCaption
> xGenerator
,
1432 const tools::Rectangle
& rCaptionRect
, bool bShown
)
1434 ScDocShellModificator
aModificator( rDocShell
);
1435 ScDocument
& rDoc
= rDocShell
.GetDocument();
1437 std::unique_ptr
<ScPostIt
> pOldNote
= rDoc
.ReleaseNote( rPos
);
1438 SAL_WARN_IF(pOldNote
, "sc.ui", "imported data has >1 notes on same cell? at pos " << rPos
);
1441 ScNoteUtil::CreateNoteFromGenerator(rDoc
, rPos
, std::move(xGenerator
),
1442 rCaptionRect
, bShown
);
1444 rDoc
.SetStreamValid(rPos
.Tab(), false);
1446 aModificator
.SetDocumentModified();
1449 bool ScDocFunc::ApplyAttributes( const ScMarkData
& rMark
, const ScPatternAttr
& rPattern
,
1452 ScDocument
& rDoc
= rDocShell
.GetDocument();
1453 bool bRecord
= true;
1454 if ( !rDoc
.IsUndoEnabled() )
1457 bool bImportingXML
= rDoc
.IsImportingXML();
1458 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1459 // #i62483# When loading XML, the check can be skipped altogether.
1460 bool bOnlyNotBecauseOfMatrix
;
1461 if ( !bImportingXML
&& !rDoc
.IsSelectionEditable( rMark
, &bOnlyNotBecauseOfMatrix
)
1462 && !bOnlyNotBecauseOfMatrix
)
1465 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
1469 ScDocShellModificator
aModificator( rDocShell
);
1473 ScRange aMultiRange
;
1474 bool bMulti
= rMark
.IsMultiMarked();
1476 aMultiRange
= rMark
.GetMultiMarkArea();
1478 aMultiRange
= rMark
.GetMarkArea();
1482 ScDocumentUniquePtr
pUndoDoc( new ScDocument( SCDOCMODE_UNDO
));
1483 pUndoDoc
->InitUndo( rDoc
, aMultiRange
.aStart
.Tab(), aMultiRange
.aEnd
.Tab() );
1484 rDoc
.CopyToDocument(aMultiRange
, InsertDeleteFlags::ATTRIB
, bMulti
, *pUndoDoc
, &rMark
);
1486 rDocShell
.GetUndoManager()->AddUndoAction(
1487 std::make_unique
<ScUndoSelectionAttr
>(
1489 aMultiRange
.aStart
.Col(), aMultiRange
.aStart
.Row(), aMultiRange
.aStart
.Tab(),
1490 aMultiRange
.aEnd
.Col(), aMultiRange
.aEnd
.Row(), aMultiRange
.aEnd
.Tab(),
1491 std::move(pUndoDoc
), bMulti
, &rPattern
) );
1494 // While loading XML it is not necessary to ask HasAttrib. It needs too much time.
1495 sal_uInt16 nExtFlags
= 0;
1496 if ( !bImportingXML
)
1497 rDocShell
.UpdatePaintExt( nExtFlags
, aMultiRange
); // content before the change
1499 bool bChanged
= false;
1500 rDoc
.ApplySelectionPattern( rPattern
, rMark
, nullptr, &bChanged
);
1504 if ( !bImportingXML
)
1505 rDocShell
.UpdatePaintExt( nExtFlags
, aMultiRange
); // content after the change
1507 if (!AdjustRowHeight( aMultiRange
, true, bApi
))
1508 rDocShell
.PostPaint( aMultiRange
, PaintPartFlags::Grid
, nExtFlags
);
1509 else if (nExtFlags
& SC_PF_LINES
)
1510 lcl_PaintAbove( rDocShell
, aMultiRange
); // because of lines above the range
1512 aModificator
.SetDocumentModified();
1518 bool ScDocFunc::ApplyStyle( const ScMarkData
& rMark
, const OUString
& rStyleName
,
1521 ScDocument
& rDoc
= rDocShell
.GetDocument();
1522 bool bRecord
= true;
1523 if ( !rDoc
.IsUndoEnabled() )
1526 bool bImportingXML
= rDoc
.IsImportingXML();
1527 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1528 // #i62483# When loading XML, the check can be skipped altogether.
1529 bool bOnlyNotBecauseOfMatrix
;
1530 if ( !bImportingXML
&& !rDoc
.IsSelectionEditable( rMark
, &bOnlyNotBecauseOfMatrix
)
1531 && !bOnlyNotBecauseOfMatrix
)
1534 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
1538 ScStyleSheet
* pStyleSheet
= static_cast<ScStyleSheet
*>( rDoc
.GetStyleSheetPool()->Find(
1539 rStyleName
, SfxStyleFamily::Para
));
1543 ScDocShellModificator
aModificator( rDocShell
);
1545 ScRange aMultiRange
;
1546 bool bMulti
= rMark
.IsMultiMarked();
1548 aMultiRange
= rMark
.GetMultiMarkArea();
1550 aMultiRange
= rMark
.GetMarkArea();
1554 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
1555 SCTAB nStartTab
= aMultiRange
.aStart
.Tab();
1556 SCTAB nTabCount
= rDoc
.GetTableCount();
1557 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nStartTab
);
1558 for (const auto& rTab
: rMark
)
1560 if (rTab
>= nTabCount
)
1563 if (rTab
!= nStartTab
)
1564 pUndoDoc
->AddUndoTab( rTab
, rTab
);
1567 ScRange aCopyRange
= aMultiRange
;
1568 aCopyRange
.aStart
.SetTab(0);
1569 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1570 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, bMulti
, *pUndoDoc
, &rMark
);
1572 rDocShell
.GetUndoManager()->AddUndoAction(
1573 std::make_unique
<ScUndoSelectionStyle
>(
1574 &rDocShell
, rMark
, aMultiRange
, rStyleName
, std::move(pUndoDoc
) ) );
1578 rDoc
.ApplySelectionStyle( *pStyleSheet
, rMark
);
1580 if (!AdjustRowHeight( aMultiRange
, true, bApi
))
1581 rDocShell
.PostPaint( aMultiRange
, PaintPartFlags::Grid
);
1583 aModificator
.SetDocumentModified();
1591 * Check if this insertion attempt would end up cutting one or more pivot
1592 * tables in half, which is not desirable.
1594 * @return true if this insertion can be done safely without shearing any
1595 * existing pivot tables, false otherwise.
1597 bool canInsertCellsByPivot(const ScRange
& rRange
, const ScMarkData
& rMarkData
, InsCellCmd eCmd
, const ScDocument
& rDoc
)
1599 if (!rDoc
.HasPivotTable())
1600 // This document has no pivot tables.
1603 const ScDPCollection
* pDPs
= rDoc
.GetDPCollection();
1605 ScRange
aRange(rRange
); // local copy
1608 case INS_INSROWS_BEFORE
:
1610 aRange
.aStart
.SetCol(0);
1611 aRange
.aEnd
.SetCol(rDoc
.MaxCol());
1616 auto bIntersects
= std::any_of(rMarkData
.begin(), rMarkData
.end(), [&pDPs
, &aRange
](const SCTAB
& rTab
) {
1617 return pDPs
->IntersectsTableByColumns(aRange
.aStart
.Col(), aRange
.aEnd
.Col(), aRange
.aStart
.Row(), rTab
); });
1619 // This column range cuts through at least one pivot table. Not good.
1622 // Start row must be either at the top or above any pivot tables.
1623 if (aRange
.aStart
.Row() < 0)
1624 // I don't know how to handle this case.
1627 if (aRange
.aStart
.Row() == 0)
1628 // First row is always allowed.
1631 ScRange
aTest(aRange
);
1632 aTest
.aStart
.IncRow(-1); // Test one row up.
1633 aTest
.aEnd
.SetRow(aTest
.aStart
.Row());
1634 for (const auto& rTab
: rMarkData
)
1636 aTest
.aStart
.SetTab(rTab
);
1637 aTest
.aEnd
.SetTab(rTab
);
1638 if (pDPs
->HasTable(aTest
))
1643 case INS_INSCOLS_BEFORE
:
1645 aRange
.aStart
.SetRow(0);
1646 aRange
.aEnd
.SetRow(rDoc
.MaxRow());
1649 case INS_CELLSRIGHT
:
1651 auto bIntersects
= std::any_of(rMarkData
.begin(), rMarkData
.end(), [&pDPs
, &aRange
](const SCTAB
& rTab
) {
1652 return pDPs
->IntersectsTableByRows(aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Row(), rTab
); });
1654 // This column range cuts through at least one pivot table. Not good.
1657 // Start row must be either at the top or above any pivot tables.
1658 if (aRange
.aStart
.Col() < 0)
1659 // I don't know how to handle this case.
1662 if (aRange
.aStart
.Col() == 0)
1663 // First row is always allowed.
1666 ScRange
aTest(aRange
);
1667 aTest
.aStart
.IncCol(-1); // Test one column to the left.
1668 aTest
.aEnd
.SetCol(aTest
.aStart
.Col());
1669 for (const auto& rTab
: rMarkData
)
1671 aTest
.aStart
.SetTab(rTab
);
1672 aTest
.aEnd
.SetTab(rTab
);
1673 if (pDPs
->HasTable(aTest
))
1685 * Check if this deletion attempt would end up cutting one or more pivot
1686 * tables in half, which is not desirable.
1688 * @return true if this deletion can be done safely without shearing any
1689 * existing pivot tables, false otherwise.
1691 bool canDeleteCellsByPivot(const ScRange
& rRange
, const ScMarkData
& rMarkData
, DelCellCmd eCmd
, const ScDocument
& rDoc
)
1693 if (!rDoc
.HasPivotTable())
1694 // This document has no pivot tables.
1697 const ScDPCollection
* pDPs
= rDoc
.GetDPCollection();
1699 ScRange
aRange(rRange
); // local copy
1703 case DelCellCmd::Rows
:
1705 aRange
.aStart
.SetCol(0);
1706 aRange
.aEnd
.SetCol(rDoc
.MaxCol());
1709 case DelCellCmd::CellsUp
:
1711 auto bIntersects
= std::any_of(rMarkData
.begin(), rMarkData
.end(), [&pDPs
, &aRange
](const SCTAB
& rTab
) {
1712 return pDPs
->IntersectsTableByColumns(aRange
.aStart
.Col(), aRange
.aEnd
.Col(), aRange
.aStart
.Row(), rTab
); });
1714 // This column range cuts through at least one pivot table. Not good.
1717 ScRange
aTest(aRange
);
1718 for (const auto& rTab
: rMarkData
)
1720 aTest
.aStart
.SetTab(rTab
);
1721 aTest
.aEnd
.SetTab(rTab
);
1722 if (pDPs
->HasTable(aTest
))
1727 case DelCellCmd::Cols
:
1729 aRange
.aStart
.SetRow(0);
1730 aRange
.aEnd
.SetRow(rDoc
.MaxRow());
1733 case DelCellCmd::CellsLeft
:
1735 auto bIntersects
= std::any_of(rMarkData
.begin(), rMarkData
.end(), [&pDPs
, &aRange
](const SCTAB
& rTab
) {
1736 return pDPs
->IntersectsTableByRows(aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Row(), rTab
); });
1738 // This column range cuts through at least one pivot table. Not good.
1741 ScRange
aTest(aRange
);
1742 for (const auto& rTab
: rMarkData
)
1744 aTest
.aStart
.SetTab(rTab
);
1745 aTest
.aEnd
.SetTab(rTab
);
1746 if (pDPs
->HasTable(aTest
))
1759 bool ScDocFunc::InsertCells( const ScRange
& rRange
, const ScMarkData
* pTabMark
, InsCellCmd eCmd
,
1760 bool bRecord
, bool bApi
, bool bPartOfPaste
, size_t nInsertCount
)
1762 ScDocShellModificator
aModificator( rDocShell
);
1763 ScDocument
& rDoc
= rDocShell
.GetDocument();
1765 if (rDocShell
.GetDocument().GetChangeTrack() &&
1766 ((eCmd
== INS_CELLSDOWN
&& (rRange
.aStart
.Col() != 0 || rRange
.aEnd
.Col() != rDoc
.MaxCol())) ||
1767 (eCmd
== INS_CELLSRIGHT
&& (rRange
.aStart
.Row() != 0 || rRange
.aEnd
.Row() != rDoc
.MaxRow()))))
1769 // We should not reach this via UI disabled slots.
1771 SAL_WARN("sc.ui","ScDocFunc::InsertCells - no change-tracking of partial cell shift");
1775 ScRange
aTargetRange( rRange
);
1777 // If insertion is for full cols/rows and after the current
1778 // selection, then shift the range accordingly
1779 if ( eCmd
== INS_INSROWS_AFTER
)
1781 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
1782 if (!aTargetRange
.Move(0, rRange
.aEnd
.Row() - rRange
.aStart
.Row() + 1, 0, aErrorRange
, rDoc
))
1787 if ( eCmd
== INS_INSCOLS_AFTER
)
1789 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
1790 if (!aTargetRange
.Move(rRange
.aEnd
.Col() - rRange
.aStart
.Col() + 1, 0, 0, aErrorRange
, rDoc
))
1796 SCCOL nStartCol
= aTargetRange
.aStart
.Col();
1797 SCROW nStartRow
= aTargetRange
.aStart
.Row();
1798 SCTAB nStartTab
= aTargetRange
.aStart
.Tab();
1799 SCCOL nEndCol
= aTargetRange
.aEnd
.Col() + nInsertCount
;
1800 SCROW nEndRow
= aTargetRange
.aEnd
.Row() + nInsertCount
;
1801 SCTAB nEndTab
= aTargetRange
.aEnd
.Tab();
1803 if ( !rDoc
.ValidRow(nStartRow
) || !rDoc
.ValidRow(nEndRow
) )
1805 OSL_FAIL("invalid row in InsertCells");
1809 SCTAB nTabCount
= rDoc
.GetTableCount();
1810 SCCOL nPaintStartCol
= nStartCol
;
1811 SCROW nPaintStartRow
= nStartRow
;
1812 SCCOL nPaintEndCol
= nEndCol
;
1813 SCROW nPaintEndRow
= nEndRow
;
1814 PaintPartFlags nPaintFlags
= PaintPartFlags::Grid
;
1817 ScTabViewShell
* pViewSh
= rDocShell
.GetBestViewShell(); //preserve current cursor position
1818 SCCOL nCursorCol
= 0;
1819 SCROW nCursorRow
= 0;
1822 nCursorCol
= pViewSh
->GetViewData().GetCurX();
1823 nCursorRow
= pViewSh
->GetViewData().GetCurY();
1826 if (bRecord
&& !rDoc
.IsUndoEnabled())
1829 ScMarkData
aMark(rDoc
.GetSheetLimits());
1835 for( SCTAB i
=0; i
<nTabCount
; i
++ )
1837 if( !rDoc
.IsScenario(i
) )
1840 if( nCount
== nEndTab
+1 )
1842 aMark
.SelectTable( i
, true );
1849 ScMarkData
aFullMark( aMark
); // including scenario sheets
1850 for (const auto& rTab
: aMark
)
1852 if (rTab
>= nTabCount
)
1855 for( SCTAB j
= rTab
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
1856 aFullMark
.SelectTable( j
, true );
1859 SCTAB nSelCount
= aMark
.GetSelectCount();
1861 // Adjust also related scenarios
1863 SCCOL nMergeTestStartCol
= nStartCol
;
1864 SCROW nMergeTestStartRow
= nStartRow
;
1865 SCCOL nMergeTestEndCol
= nEndCol
;
1866 SCROW nMergeTestEndRow
= nEndRow
;
1868 ScRange
aExtendMergeRange( aTargetRange
);
1870 if( aTargetRange
.aStart
== aTargetRange
.aEnd
&& rDoc
.HasAttrib(aTargetRange
, HasAttrFlags::Merged
) )
1872 rDoc
.ExtendMerge( aExtendMergeRange
);
1873 rDoc
.ExtendOverlapped( aExtendMergeRange
);
1874 nMergeTestEndCol
= aExtendMergeRange
.aEnd
.Col();
1875 nMergeTestEndRow
= aExtendMergeRange
.aEnd
.Row();
1876 nPaintEndCol
= nMergeTestEndCol
;
1877 nPaintEndRow
= nMergeTestEndRow
;
1880 if ( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
)
1882 nMergeTestStartCol
= 0;
1883 nMergeTestEndCol
= rDoc
.MaxCol();
1885 if ( eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSCOLS_AFTER
)
1887 nMergeTestStartRow
= 0;
1888 nMergeTestEndRow
= rDoc
.MaxRow();
1890 if ( eCmd
== INS_CELLSDOWN
)
1891 nMergeTestEndRow
= rDoc
.MaxRow();
1892 if ( eCmd
== INS_CELLSRIGHT
)
1893 nMergeTestEndCol
= rDoc
.MaxCol();
1895 bool bNeedRefresh
= false;
1897 SCCOL nEditTestEndCol
= (eCmd
==INS_INSCOLS_BEFORE
|| eCmd
==INS_INSCOLS_AFTER
) ? rDoc
.MaxCol() : nMergeTestEndCol
;
1898 SCROW nEditTestEndRow
= (eCmd
==INS_INSROWS_BEFORE
|| eCmd
==INS_INSROWS_AFTER
) ? rDoc
.MaxRow() : nMergeTestEndRow
;
1900 ScEditableTester aTester
;
1904 case INS_INSCOLS_BEFORE
:
1905 aTester
= ScEditableTester(
1906 rDoc
, sc::EditAction::InsertColumnsBefore
, nMergeTestStartCol
, 0, nMergeTestEndCol
, rDoc
.MaxRow(), aMark
);
1908 case INS_INSCOLS_AFTER
:
1909 aTester
= ScEditableTester(
1910 rDoc
, sc::EditAction::InsertColumnsAfter
, nMergeTestStartCol
, 0, nMergeTestEndCol
, rDoc
.MaxRow(), aMark
);
1912 case INS_INSROWS_BEFORE
:
1913 aTester
= ScEditableTester(
1914 rDoc
, sc::EditAction::InsertRowsBefore
, 0, nMergeTestStartRow
, rDoc
.MaxCol(), nMergeTestEndRow
, aMark
);
1916 case INS_INSROWS_AFTER
:
1917 aTester
= ScEditableTester(
1918 rDoc
, sc::EditAction::InsertRowsAfter
, 0, nMergeTestStartRow
, rDoc
.MaxCol(), nMergeTestEndRow
, aMark
);
1921 aTester
= ScEditableTester(
1922 rDoc
, nMergeTestStartCol
, nMergeTestStartRow
, nEditTestEndCol
, nEditTestEndRow
, aMark
);
1925 if (!aTester
.IsEditable())
1928 rDocShell
.ErrorMessage(aTester
.GetMessageId());
1932 // Check if this insertion is allowed with respect to pivot table.
1933 if (!canInsertCellsByPivot(aTargetRange
, aMark
, eCmd
, rDoc
))
1936 rDocShell
.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE
);
1940 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important due to TrackFormulas at UpdateReference
1942 ScDocumentUniquePtr pRefUndoDoc
;
1943 std::unique_ptr
<ScRefUndoData
> pUndoData
;
1946 pRefUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
1947 pRefUndoDoc
->InitUndo( rDoc
, 0, nTabCount
-1 );
1949 // pRefUndoDoc is filled in InsertCol / InsertRow
1951 pUndoData
.reset(new ScRefUndoData( &rDoc
));
1953 rDoc
.BeginDrawUndo();
1956 // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
1957 // the patch comes from mloiseleur and maoyg
1958 bool bInsertMerge
= false;
1959 std::vector
<ScRange
> qIncreaseRange
;
1960 OUString aUndo
= ScResId( STR_UNDO_INSERTCELLS
);
1963 ViewShellId
nViewShellId(-1);
1965 nViewShellId
= pViewSh
->GetViewShellId();
1966 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, nViewShellId
);
1968 std::unique_ptr
<ScUndoRemoveMerge
> pUndoRemoveMerge
;
1970 for (const SCTAB i
: aMark
)
1975 if( rDoc
.HasAttrib( nMergeTestStartCol
, nMergeTestStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
, HasAttrFlags::Merged
| HasAttrFlags::Overlapped
) )
1977 if (eCmd
==INS_CELLSRIGHT
)
1978 bNeedRefresh
= true;
1980 SCCOL nMergeStartCol
= nMergeTestStartCol
;
1981 SCROW nMergeStartRow
= nMergeTestStartRow
;
1982 SCCOL nMergeEndCol
= nMergeTestEndCol
;
1983 SCROW nMergeEndRow
= nMergeTestEndRow
;
1985 rDoc
.ExtendMerge( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
1986 rDoc
.ExtendOverlapped( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
1988 if(( eCmd
== INS_CELLSDOWN
&& ( nMergeStartCol
!= nMergeTestStartCol
|| nMergeEndCol
!= nMergeTestEndCol
)) ||
1989 (eCmd
== INS_CELLSRIGHT
&& ( nMergeStartRow
!= nMergeTestStartRow
|| nMergeEndRow
!= nMergeTestEndRow
)) )
1992 rDocShell
.ErrorMessage(STR_MSSG_INSERTCELLS_0
);
1993 rDocShell
.GetUndoManager()->LeaveListAction();
1997 SCCOL nTestCol
= -1;
1998 SCROW nTestRow1
= -1;
1999 SCROW nTestRow2
= -1;
2001 ScDocAttrIterator
aTestIter( rDoc
, i
, nMergeTestStartCol
, nMergeTestStartRow
, nMergeTestEndCol
, nMergeTestEndRow
);
2002 ScRange
aExtendRange( nMergeTestStartCol
, nMergeTestStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
);
2003 const ScPatternAttr
* pPattern
= nullptr;
2004 while ( ( pPattern
= aTestIter
.GetNext( nTestCol
, nTestRow1
, nTestRow2
) ) != nullptr )
2006 const ScMergeAttr
& rMergeFlag
= pPattern
->GetItem(ATTR_MERGE
);
2007 const ScMergeFlagAttr
& rMergeFlagAttr
= pPattern
->GetItem(ATTR_MERGE_FLAG
);
2008 ScMF nNewFlags
= rMergeFlagAttr
.GetValue() & (ScMF::Hor
| ScMF::Ver
);
2009 if (rMergeFlag
.IsMerged() || nNewFlags
== ScMF::Hor
|| nNewFlags
== ScMF::Ver
)
2011 ScRange
aRange( nTestCol
, nTestRow1
, i
);
2012 rDoc
.ExtendOverlapped(aRange
);
2013 rDoc
.ExtendMerge(aRange
, true);
2015 if( nTestRow1
< nTestRow2
&& nNewFlags
== ScMF::Hor
)
2017 for( SCROW nTestRow
= nTestRow1
; nTestRow
<= nTestRow2
; nTestRow
++ )
2019 ScRange
aTestRange( nTestCol
, nTestRow
, i
);
2020 rDoc
.ExtendOverlapped( aTestRange
);
2021 rDoc
.ExtendMerge( aTestRange
, true);
2022 ScRange
aMergeRange( aTestRange
.aStart
.Col(),aTestRange
.aStart
.Row(), i
);
2023 if( !aExtendRange
.Contains( aMergeRange
) )
2025 qIncreaseRange
.push_back( aTestRange
);
2026 bInsertMerge
= true;
2032 ScRange
aMergeRange( aRange
.aStart
.Col(),aRange
.aStart
.Row(), i
);
2033 if( !aExtendRange
.Contains( aMergeRange
) )
2035 qIncreaseRange
.push_back( aRange
);
2037 bInsertMerge
= true;
2044 if( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
|| eCmd
== INS_CELLSDOWN
)
2046 nStartRow
= aExtendMergeRange
.aStart
.Row();
2047 nEndRow
= aExtendMergeRange
.aEnd
.Row();
2049 if( eCmd
== INS_CELLSDOWN
)
2050 nEndCol
= nMergeTestEndCol
;
2054 nEndCol
= rDoc
.MaxCol();
2057 else if( eCmd
== INS_CELLSRIGHT
|| eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSCOLS_AFTER
)
2060 nStartCol
= aExtendMergeRange
.aStart
.Col();
2061 nEndCol
= aExtendMergeRange
.aEnd
.Col();
2062 if( eCmd
== INS_CELLSRIGHT
)
2064 nEndRow
= nMergeTestEndRow
;
2069 nEndRow
= rDoc
.MaxRow();
2073 if( !qIncreaseRange
.empty() )
2075 if (bRecord
&& !pUndoRemoveMerge
)
2077 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
2078 pUndoDoc
->InitUndo( rDoc
, *aMark
.begin(), *aMark
.rbegin());
2079 pUndoRemoveMerge
.reset( new ScUndoRemoveMerge( &rDocShell
, rRange
, std::move(pUndoDoc
) ));
2082 for( const ScRange
& aRange
: qIncreaseRange
)
2084 if( rDoc
.HasAttrib( aRange
, HasAttrFlags::Overlapped
| HasAttrFlags::Merged
) )
2086 UnmergeCells( aRange
, bRecord
, pUndoRemoveMerge
.get() );
2094 rDocShell
.ErrorMessage(STR_MSSG_INSERTCELLS_0
);
2095 rDocShell
.GetUndoManager()->LeaveListAction();
2101 if (bRecord
&& pUndoRemoveMerge
)
2103 rDocShell
.GetUndoManager()->AddUndoAction( std::move(pUndoRemoveMerge
));
2109 bSuccess
= rDoc
.InsertRow( nStartCol
, 0, nEndCol
, MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
.get(), &aFullMark
);
2110 nPaintEndRow
= rDoc
.MaxRow();
2112 case INS_INSROWS_BEFORE
:
2113 case INS_INSROWS_AFTER
:
2114 bSuccess
= rDoc
.InsertRow( 0, 0, rDoc
.MaxCol(), MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
.get(), &aFullMark
);
2116 nPaintEndCol
= rDoc
.MaxCol();
2117 nPaintEndRow
= rDoc
.MaxRow();
2118 nPaintFlags
|= PaintPartFlags::Left
;
2120 case INS_CELLSRIGHT
:
2121 bSuccess
= rDoc
.InsertCol( nStartRow
, 0, nEndRow
, MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
.get(), &aFullMark
);
2122 nPaintEndCol
= rDoc
.MaxCol();
2124 case INS_INSCOLS_BEFORE
:
2125 case INS_INSCOLS_AFTER
:
2126 bSuccess
= rDoc
.InsertCol( 0, 0, rDoc
.MaxRow(), MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
.get(), &aFullMark
);
2128 nPaintEndRow
= rDoc
.MaxRow();
2129 nPaintEndCol
= rDoc
.MaxCol();
2130 nPaintFlags
|= PaintPartFlags::Top
;
2133 OSL_FAIL("Wrong code at inserting");
2144 std::unique_ptr
<SCTAB
[]> pTabs(new SCTAB
[nSelCount
]);
2145 std::unique_ptr
<SCTAB
[]> pScenarios(new SCTAB
[nSelCount
]);
2147 for (const auto& rTab
: aMark
)
2149 if (rTab
>= nTabCount
)
2153 for( SCTAB j
=rTab
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2156 pScenarios
[nUndoPos
] = nCount
;
2157 pTabs
[nUndoPos
] = rTab
;
2163 rDocShell
.GetUndoManager()->LeaveListAction();
2166 rDocShell
.GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoInsertCells
>(
2167 &rDocShell
, ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
),
2168 nUndoPos
, std::move(pTabs
), std::move(pScenarios
), eCmd
, std::move(pRefUndoDoc
), std::move(pUndoData
), bPartOfPaste
) );
2171 // #i8302 : we remerge growing ranges, with the new part inserted
2173 while( !qIncreaseRange
.empty() )
2175 ScRange aRange
= qIncreaseRange
.back();
2176 if( !rDoc
.HasAttrib( aRange
, HasAttrFlags::Overlapped
| HasAttrFlags::Merged
) )
2181 case INS_INSROWS_BEFORE
:
2182 case INS_INSROWS_AFTER
:
2183 aRange
.aEnd
.IncRow(static_cast<SCCOL
>(nEndRow
-nStartRow
+1));
2185 case INS_CELLSRIGHT
:
2186 case INS_INSCOLS_BEFORE
:
2187 case INS_INSCOLS_AFTER
:
2188 aRange
.aEnd
.IncCol(static_cast<SCCOL
>(nEndCol
-nStartCol
+1));
2193 ScCellMergeOption
aMergeOption(
2194 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2195 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
2196 aMergeOption
.maTabs
.insert(aRange
.aStart
.Tab());
2197 MergeCells(aMergeOption
, false, true, true);
2199 qIncreaseRange
.pop_back();
2203 rDocShell
.GetUndoManager()->LeaveListAction();
2205 for (const SCTAB i
: aMark
)
2210 rDoc
.SetDrawPageSize(i
);
2213 rDoc
.ExtendMerge( nMergeTestStartCol
, nMergeTestStartRow
, nMergeTestEndCol
, nMergeTestEndRow
, i
, true );
2215 rDoc
.RefreshAutoFilter( nMergeTestStartCol
, nMergeTestStartRow
, nMergeTestEndCol
, nMergeTestEndRow
, i
);
2217 if ( eCmd
== INS_INSROWS_BEFORE
||eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
||eCmd
== INS_INSCOLS_AFTER
)
2218 rDoc
.UpdatePageBreaks( i
);
2220 sal_uInt16 nExtFlags
= 0;
2221 rDocShell
.UpdatePaintExt( nExtFlags
, nPaintStartCol
, nPaintStartRow
, i
, nPaintEndCol
, nPaintEndRow
, i
);
2223 SCTAB nScenarioCount
= 0;
2225 for( SCTAB j
= i
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2228 bool bAdjusted
= ( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
) ?
2229 AdjustRowHeight(ScRange(0, nStartRow
, i
, rDoc
.MaxCol(), nEndRow
, i
+nScenarioCount
), true, bApi
) :
2230 AdjustRowHeight(ScRange(0, nPaintStartRow
, i
, rDoc
.MaxCol(), nPaintEndRow
, i
+nScenarioCount
), true, bApi
);
2233 // paint only what is not done by AdjustRowHeight
2234 if (nPaintFlags
& PaintPartFlags::Top
)
2235 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, i
, nPaintEndCol
, nPaintEndRow
, i
+nScenarioCount
, PaintPartFlags::Top
);
2238 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, i
, nPaintEndCol
, nPaintEndRow
, i
+nScenarioCount
, nPaintFlags
, nExtFlags
);
2245 while( !qIncreaseRange
.empty() )
2247 ScRange aRange
= qIncreaseRange
.back();
2248 ScCellMergeOption
aMergeOption(
2249 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2250 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
2251 MergeCells(aMergeOption
, false, true, true);
2252 qIncreaseRange
.pop_back();
2257 pViewSh
->MarkRange( aTargetRange
, false );
2258 pViewSh
->SetCursor( nCursorCol
, nCursorRow
);
2262 rDocShell
.GetUndoManager()->LeaveListAction();
2263 rDocShell
.GetUndoManager()->RemoveLastUndoAction();
2265 pRefUndoDoc
.reset();
2267 rDocShell
.ErrorMessage(STR_INSERT_FULL
); // column/row full
2270 // The cursor position needs to be modified earlier than updating
2271 // any enabled edit view which is triggered by SetDocumentModified below.
2274 bool bInsertCols
= ( eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSCOLS_AFTER
);
2275 bool bInsertRows
= ( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
);
2279 pViewSh
->OnLOKInsertDeleteColumn(rRange
.aStart
.Col() - (eCmd
== INS_INSCOLS_BEFORE
? 1: 0), 1);
2284 pViewSh
->OnLOKInsertDeleteRow(rRange
.aStart
.Row() - (eCmd
== INS_INSROWS_BEFORE
? 1: 0), 1);
2288 aModificator
.SetDocumentModified();
2290 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
2294 bool ScDocFunc::DeleteCells( const ScRange
& rRange
, const ScMarkData
* pTabMark
, DelCellCmd eCmd
,
2297 ScDocShellModificator
aModificator( rDocShell
);
2298 ScDocument
& rDoc
= rDocShell
.GetDocument();
2300 if (rDocShell
.GetDocument().GetChangeTrack() &&
2301 ((eCmd
== DelCellCmd::CellsUp
&& (rRange
.aStart
.Col() != 0 || rRange
.aEnd
.Col() != rDoc
.MaxCol())) ||
2302 (eCmd
== DelCellCmd::CellsLeft
&& (rRange
.aStart
.Row() != 0 || rRange
.aEnd
.Row() != rDoc
.MaxRow()))))
2304 // We should not reach this via UI disabled slots.
2306 SAL_WARN("sc.ui","ScDocFunc::DeleteCells - no change-tracking of partial cell shift");
2310 SCCOL nStartCol
= rRange
.aStart
.Col();
2311 SCROW nStartRow
= rRange
.aStart
.Row();
2312 SCTAB nStartTab
= rRange
.aStart
.Tab();
2313 SCCOL nEndCol
= rRange
.aEnd
.Col();
2314 SCROW nEndRow
= rRange
.aEnd
.Row();
2315 SCTAB nEndTab
= rRange
.aEnd
.Tab();
2317 if ( !rDoc
.ValidRow(nStartRow
) || !rDoc
.ValidRow(nEndRow
) )
2319 OSL_FAIL("invalid row in DeleteCells");
2323 SCTAB nTabCount
= rDoc
.GetTableCount();
2324 SCCOL nPaintStartCol
= nStartCol
;
2325 SCROW nPaintStartRow
= nStartRow
;
2326 SCCOL nPaintEndCol
= nEndCol
;
2327 SCROW nPaintEndRow
= nEndRow
;
2328 PaintPartFlags nPaintFlags
= PaintPartFlags::Grid
;
2330 bool bRecord
= true;
2331 if (!rDoc
.IsUndoEnabled())
2334 ScMarkData
aMark(rDoc
.GetSheetLimits());
2340 for(SCTAB i
=0; i
<nTabCount
; i
++ )
2342 if( !rDoc
.IsScenario(i
) )
2345 if( nCount
== nEndTab
+1 )
2347 aMark
.SelectTable(i
, true);
2354 ScMarkData
aFullMark( aMark
); // including scenario sheets
2355 for (const auto& rTab
: aMark
)
2357 if (rTab
>= nTabCount
)
2360 for( SCTAB j
= rTab
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2361 aFullMark
.SelectTable( j
, true );
2364 SCTAB nSelCount
= aMark
.GetSelectCount();
2366 SCCOL nUndoStartCol
= nStartCol
;
2367 SCROW nUndoStartRow
= nStartRow
;
2368 SCCOL nUndoEndCol
= nEndCol
;
2369 SCROW nUndoEndRow
= nEndRow
;
2371 ScRange
aExtendMergeRange( rRange
);
2373 if( rRange
.aStart
== rRange
.aEnd
&& rDoc
.HasAttrib(rRange
, HasAttrFlags::Merged
) )
2375 rDoc
.ExtendMerge( aExtendMergeRange
);
2376 rDoc
.ExtendOverlapped( aExtendMergeRange
);
2377 nUndoEndCol
= aExtendMergeRange
.aEnd
.Col();
2378 nUndoEndRow
= aExtendMergeRange
.aEnd
.Row();
2379 nPaintEndCol
= nUndoEndCol
;
2380 nPaintEndRow
= nUndoEndRow
;
2383 if (eCmd
==DelCellCmd::Rows
)
2386 nUndoEndCol
= rDoc
.MaxCol();
2388 if (eCmd
==DelCellCmd::Cols
)
2391 nUndoEndRow
= rDoc
.MaxRow();
2393 // Test for cell protection
2395 SCCOL nEditTestEndX
= nUndoEndCol
;
2396 if ( eCmd
==DelCellCmd::Cols
|| eCmd
==DelCellCmd::CellsLeft
)
2397 nEditTestEndX
= rDoc
.MaxCol();
2398 SCROW nEditTestEndY
= nUndoEndRow
;
2399 if ( eCmd
==DelCellCmd::Rows
|| eCmd
==DelCellCmd::CellsUp
)
2400 nEditTestEndY
= rDoc
.MaxRow();
2402 ScEditableTester aTester
;
2406 case DelCellCmd::Cols
:
2407 aTester
= ScEditableTester(
2408 rDoc
, sc::EditAction::DeleteColumns
, nUndoStartCol
, 0, nUndoEndCol
, rDoc
.MaxRow(), aMark
);
2410 case DelCellCmd::Rows
:
2411 aTester
= ScEditableTester(
2412 rDoc
, sc::EditAction::DeleteRows
, 0, nUndoStartRow
, rDoc
.MaxCol(), nUndoEndRow
, aMark
);
2415 aTester
= ScEditableTester(
2416 rDoc
, nUndoStartCol
, nUndoStartRow
, nEditTestEndX
, nEditTestEndY
, aMark
);
2419 if (!aTester
.IsEditable())
2422 rDocShell
.ErrorMessage(aTester
.GetMessageId());
2426 if (!canDeleteCellsByPivot(rRange
, aMark
, eCmd
, rDoc
))
2429 rDocShell
.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE
);
2432 // Test for merged cells
2434 SCCOL nMergeTestEndCol
= (eCmd
==DelCellCmd::CellsLeft
) ? rDoc
.MaxCol() : nUndoEndCol
;
2435 SCROW nMergeTestEndRow
= (eCmd
==DelCellCmd::CellsUp
) ? rDoc
.MaxRow() : nUndoEndRow
;
2436 SCCOL nExtendStartCol
= nUndoStartCol
;
2437 SCROW nExtendStartRow
= nUndoStartRow
;
2438 bool bNeedRefresh
= false;
2440 //Issue 8302 want to be able to insert into the middle of merged cells
2441 //the patch comes from maoyg
2442 ::std::vector
<ScRange
> qDecreaseRange
;
2443 bool bDeletingMerge
= false;
2444 OUString aUndo
= ScResId( STR_UNDO_DELETECELLS
);
2447 ViewShellId
nViewShellId(-1);
2448 if (ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell())
2449 nViewShellId
= pViewSh
->GetViewShellId();
2450 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, nViewShellId
);
2452 std::unique_ptr
<ScUndoRemoveMerge
> pUndoRemoveMerge
;
2454 for (const SCTAB i
: aMark
)
2459 if ( rDoc
.HasAttrib( nUndoStartCol
, nUndoStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
, HasAttrFlags::Merged
| HasAttrFlags::Overlapped
))
2461 SCCOL nMergeStartCol
= nUndoStartCol
;
2462 SCROW nMergeStartRow
= nUndoStartRow
;
2463 SCCOL nMergeEndCol
= nMergeTestEndCol
;
2464 SCROW nMergeEndRow
= nMergeTestEndRow
;
2466 rDoc
.ExtendMerge( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
2467 rDoc
.ExtendOverlapped( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
2468 if( ( eCmd
== DelCellCmd::CellsUp
&& ( nMergeStartCol
!= nUndoStartCol
|| nMergeEndCol
!= nMergeTestEndCol
))||
2469 ( eCmd
== DelCellCmd::CellsLeft
&& ( nMergeStartRow
!= nUndoStartRow
|| nMergeEndRow
!= nMergeTestEndRow
)))
2472 rDocShell
.ErrorMessage(STR_MSSG_DELETECELLS_0
);
2473 rDocShell
.GetUndoManager()->LeaveListAction();
2477 nExtendStartCol
= nMergeStartCol
;
2478 nExtendStartRow
= nMergeStartRow
;
2479 SCCOL nTestCol
= -1;
2480 SCROW nTestRow1
= -1;
2481 SCROW nTestRow2
= -1;
2483 ScDocAttrIterator
aTestIter( rDoc
, i
, nUndoStartCol
, nUndoStartRow
, nMergeTestEndCol
, nMergeTestEndRow
);
2484 ScRange
aExtendRange( nUndoStartCol
, nUndoStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
);
2485 const ScPatternAttr
* pPattern
= nullptr;
2486 while ( ( pPattern
= aTestIter
.GetNext( nTestCol
, nTestRow1
, nTestRow2
) ) != nullptr )
2488 const ScMergeAttr
& rMergeFlag
= pPattern
->GetItem(ATTR_MERGE
);
2489 const ScMergeFlagAttr
& rMergeFlagAttr
= pPattern
->GetItem(ATTR_MERGE_FLAG
);
2490 ScMF nNewFlags
= rMergeFlagAttr
.GetValue() & (ScMF::Hor
| ScMF::Ver
);
2491 if (rMergeFlag
.IsMerged() || nNewFlags
== ScMF::Hor
|| nNewFlags
== ScMF::Ver
)
2493 ScRange
aRange( nTestCol
, nTestRow1
, i
);
2494 rDoc
.ExtendOverlapped( aRange
);
2495 rDoc
.ExtendMerge( aRange
, true );
2497 if( nTestRow1
< nTestRow2
&& nNewFlags
== ScMF::Hor
)
2499 for( SCROW nTestRow
= nTestRow1
; nTestRow
<= nTestRow2
; nTestRow
++ )
2501 ScRange
aTestRange( nTestCol
, nTestRow
, i
);
2502 rDoc
.ExtendOverlapped( aTestRange
);
2503 rDoc
.ExtendMerge( aTestRange
, true );
2504 ScRange
aMergeRange( aTestRange
.aStart
.Col(),aTestRange
.aStart
.Row(), i
);
2505 if( !aExtendRange
.Contains( aMergeRange
) )
2507 qDecreaseRange
.push_back( aTestRange
);
2508 bDeletingMerge
= true;
2514 ScRange
aMergeRange( aRange
.aStart
.Col(),aRange
.aStart
.Row(), i
);
2515 if( !aExtendRange
.Contains( aMergeRange
) )
2517 qDecreaseRange
.push_back( aRange
);
2519 bDeletingMerge
= true;
2524 if( bDeletingMerge
)
2527 if( eCmd
== DelCellCmd::Rows
|| eCmd
== DelCellCmd::CellsUp
)
2529 nStartRow
= aExtendMergeRange
.aStart
.Row();
2530 nEndRow
= aExtendMergeRange
.aEnd
.Row();
2531 bNeedRefresh
= true;
2533 if( eCmd
== DelCellCmd::CellsUp
)
2535 nEndCol
= aExtendMergeRange
.aEnd
.Col();
2540 nEndCol
= rDoc
.MaxCol();
2543 else if( eCmd
== DelCellCmd::CellsLeft
|| eCmd
== DelCellCmd::Cols
)
2546 nStartCol
= aExtendMergeRange
.aStart
.Col();
2547 nEndCol
= aExtendMergeRange
.aEnd
.Col();
2548 if( eCmd
== DelCellCmd::CellsLeft
)
2550 nEndRow
= aExtendMergeRange
.aEnd
.Row();
2551 bNeedRefresh
= true;
2556 nEndRow
= rDoc
.MaxRow();
2560 if( !qDecreaseRange
.empty() )
2562 if (bRecord
&& !pUndoRemoveMerge
)
2564 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
2565 pUndoDoc
->InitUndo( rDoc
, *aMark
.begin(), *aMark
.rbegin());
2566 pUndoRemoveMerge
.reset( new ScUndoRemoveMerge( &rDocShell
, rRange
, std::move(pUndoDoc
) ));
2569 for( const ScRange
& aRange
: qDecreaseRange
)
2571 if( rDoc
.HasAttrib( aRange
, HasAttrFlags::Overlapped
| HasAttrFlags::Merged
) )
2573 UnmergeCells( aRange
, bRecord
, pUndoRemoveMerge
.get() );
2581 rDocShell
.ErrorMessage(STR_MSSG_DELETECELLS_0
);
2582 rDocShell
.GetUndoManager()->LeaveListAction();
2588 if (bRecord
&& pUndoRemoveMerge
)
2590 rDocShell
.GetUndoManager()->AddUndoAction( std::move(pUndoRemoveMerge
));
2595 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference
2597 ScDocumentUniquePtr pUndoDoc
;
2598 std::unique_ptr
<ScDocument
> pRefUndoDoc
;
2599 std::unique_ptr
<ScRefUndoData
> pUndoData
;
2602 // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
2603 // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
2605 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
2606 pUndoDoc
->InitUndo( rDoc
, 0, nTabCount
-1, (eCmd
==DelCellCmd::Cols
), (eCmd
==DelCellCmd::Rows
) );
2607 for (const auto& rTab
: aMark
)
2609 if (rTab
>= nTabCount
)
2612 SCTAB nScenarioCount
= 0;
2614 for( SCTAB j
= rTab
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2617 rDoc
.CopyToDocument( nUndoStartCol
, nUndoStartRow
, rTab
, nUndoEndCol
, nUndoEndRow
, rTab
+nScenarioCount
,
2618 InsertDeleteFlags::ALL
| InsertDeleteFlags::NOCAPTIONS
, false, *pUndoDoc
);
2621 pRefUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
2622 pRefUndoDoc
->InitUndo( rDoc
, 0, nTabCount
-1 );
2624 pUndoData
.reset(new ScRefUndoData( &rDoc
));
2626 rDoc
.BeginDrawUndo();
2629 sal_uInt16 nExtFlags
= 0;
2630 for (const auto& rTab
: aMark
)
2632 if (rTab
>= nTabCount
)
2635 rDocShell
.UpdatePaintExt( nExtFlags
, nStartCol
, nStartRow
, rTab
, nEndCol
, nEndRow
, rTab
);
2640 case DelCellCmd::CellsUp
:
2641 case DelCellCmd::CellsLeft
:
2642 rDoc
.DeleteObjectsInArea(nStartCol
, nStartRow
, nEndCol
, nEndRow
, aMark
, true);
2644 case DelCellCmd::Rows
:
2645 rDoc
.DeleteObjectsInArea(0, nStartRow
, rDoc
.MaxCol(), nEndRow
, aMark
, true);
2647 case DelCellCmd::Cols
:
2648 rDoc
.DeleteObjectsInArea(nStartCol
, 0, nEndCol
, rDoc
.MaxRow(), aMark
, true);
2655 bool bUndoOutline
= false;
2658 case DelCellCmd::CellsUp
:
2659 rDoc
.DeleteRow( nStartCol
, 0, nEndCol
, MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
.get(), nullptr, &aFullMark
);
2660 nPaintEndRow
= rDoc
.MaxRow();
2662 case DelCellCmd::Rows
:
2663 rDoc
.DeleteRow( 0, 0, rDoc
.MaxCol(), MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
.get(), &bUndoOutline
, &aFullMark
);
2665 nPaintEndCol
= rDoc
.MaxCol();
2666 nPaintEndRow
= rDoc
.MaxRow();
2667 nPaintFlags
|= PaintPartFlags::Left
;
2669 case DelCellCmd::CellsLeft
:
2670 rDoc
.DeleteCol( nStartRow
, 0, nEndRow
, MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
.get(), nullptr, &aFullMark
);
2671 nPaintEndCol
= rDoc
.MaxCol();
2673 case DelCellCmd::Cols
:
2674 rDoc
.DeleteCol( 0, 0, rDoc
.MaxRow(), MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
.get(), &bUndoOutline
, &aFullMark
);
2676 nPaintEndRow
= rDoc
.MaxRow();
2677 nPaintEndCol
= rDoc
.MaxCol();
2678 nPaintFlags
|= PaintPartFlags::Top
;
2681 OSL_FAIL("Wrong code at deleting");
2685 //! Test if the size of outline has changed
2689 for (const auto& rTab
: aFullMark
)
2691 if (rTab
>= nTabCount
)
2694 pRefUndoDoc
->DeleteAreaTab(nUndoStartCol
,nUndoStartRow
,nUndoEndCol
,nUndoEndRow
, rTab
, InsertDeleteFlags::ALL
);
2697 // for all sheets, so that formulas can be copied
2698 pUndoDoc
->AddUndoTab( 0, nTabCount
-1 );
2700 // copy with bColRowFlags=false (#54194#)
2701 pRefUndoDoc
->CopyToDocument(0,0,0,rDoc
.MaxCol(),rDoc
.MaxRow(),MAXTAB
,InsertDeleteFlags::FORMULA
,false,*pUndoDoc
,nullptr,false);
2702 pRefUndoDoc
.reset();
2704 std::unique_ptr
<SCTAB
[]> pTabs( new SCTAB
[nSelCount
]);
2705 std::unique_ptr
<SCTAB
[]> pScenarios( new SCTAB
[nSelCount
]);
2708 for (const auto& rTab
: aMark
)
2710 if (rTab
>= nTabCount
)
2714 for( SCTAB j
=rTab
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2717 pScenarios
[nUndoPos
] = nCount
;
2718 pTabs
[nUndoPos
] = rTab
;
2722 if( !bDeletingMerge
)
2724 rDocShell
.GetUndoManager()->LeaveListAction();
2727 rDocShell
.GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoDeleteCells
>(
2728 &rDocShell
, ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
),
2729 nUndoPos
, std::move(pTabs
), std::move(pScenarios
),
2730 eCmd
, std::move(pUndoDoc
), std::move(pUndoData
) ) );
2733 // #i8302 want to be able to insert into the middle of merged cells
2734 // the patch comes from maoyg
2736 while( !qDecreaseRange
.empty() )
2738 ScRange aRange
= qDecreaseRange
.back();
2740 sal_Int32 nDecreaseRowCount
= 0;
2741 sal_Int32 nDecreaseColCount
= 0;
2742 if( eCmd
== DelCellCmd::CellsUp
|| eCmd
== DelCellCmd::Rows
)
2744 if( nStartRow
>= aRange
.aStart
.Row() && nStartRow
<= aRange
.aEnd
.Row() && nEndRow
>= aRange
.aStart
.Row() && nEndRow
<= aRange
.aEnd
.Row() )
2745 nDecreaseRowCount
= nEndRow
-nStartRow
+1;
2746 else if( nStartRow
>= aRange
.aStart
.Row() && nStartRow
<= aRange
.aEnd
.Row() && nEndRow
>= aRange
.aStart
.Row() && nEndRow
>= aRange
.aEnd
.Row() )
2747 nDecreaseRowCount
= aRange
.aEnd
.Row()-nStartRow
+1;
2748 else if( nStartRow
>= aRange
.aStart
.Row() && nStartRow
>= aRange
.aEnd
.Row() && nEndRow
>= aRange
.aStart
.Row() && nEndRow
<= aRange
.aEnd
.Row() )
2749 nDecreaseRowCount
= aRange
.aEnd
.Row()-nEndRow
+1;
2751 else if( eCmd
== DelCellCmd::CellsLeft
|| eCmd
== DelCellCmd::Cols
)
2753 if( nStartCol
>= aRange
.aStart
.Col() && nStartCol
<= aRange
.aEnd
.Col() && nEndCol
>= aRange
.aStart
.Col() && nEndCol
<= aRange
.aEnd
.Col() )
2754 nDecreaseColCount
= nEndCol
-nStartCol
+1;
2755 else if( nStartCol
>= aRange
.aStart
.Col() && nStartCol
<= aRange
.aEnd
.Col() && nEndCol
>= aRange
.aStart
.Col() && nEndCol
>= aRange
.aEnd
.Col() )
2756 nDecreaseColCount
= aRange
.aEnd
.Col()-nStartCol
+1;
2757 else if( nStartCol
>= aRange
.aStart
.Col() && nStartCol
>= aRange
.aEnd
.Col() && nEndCol
>= aRange
.aStart
.Col() && nEndCol
<= aRange
.aEnd
.Col() )
2758 nDecreaseColCount
= aRange
.aEnd
.Col()-nEndCol
+1;
2763 case DelCellCmd::CellsUp
:
2764 case DelCellCmd::Rows
:
2765 aRange
.aEnd
.SetRow(static_cast<SCCOL
>( aRange
.aEnd
.Row()-nDecreaseRowCount
));
2767 case DelCellCmd::CellsLeft
:
2768 case DelCellCmd::Cols
:
2769 aRange
.aEnd
.SetCol(static_cast<SCCOL
>( aRange
.aEnd
.Col()-nDecreaseColCount
));
2775 if( !rDoc
.HasAttrib( aRange
, HasAttrFlags::Overlapped
| HasAttrFlags::Merged
) )
2777 ScCellMergeOption
aMergeOption(aRange
);
2778 MergeCells( aMergeOption
, false, true, true );
2780 qDecreaseRange
.pop_back();
2783 if( bDeletingMerge
)
2784 rDocShell
.GetUndoManager()->LeaveListAction();
2786 if ( eCmd
==DelCellCmd::Cols
|| eCmd
==DelCellCmd::CellsLeft
)
2787 nMergeTestEndCol
= rDoc
.MaxCol();
2788 if ( eCmd
==DelCellCmd::Rows
|| eCmd
==DelCellCmd::CellsUp
)
2789 nMergeTestEndRow
= rDoc
.MaxRow();
2792 // #i51445# old merge flag attributes must be deleted also for single cells,
2793 // not only for whole columns/rows
2795 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
2796 aPattern
.GetItemSet().Put( ScMergeFlagAttr() );
2798 rDoc
.ApplyPatternArea( nExtendStartCol
, nExtendStartRow
, nMergeTestEndCol
, nMergeTestEndRow
, aMark
, aPattern
);
2800 for (const auto& rTab
: aMark
)
2802 if (rTab
>= nTabCount
)
2805 SCTAB nScenarioCount
= 0;
2807 for( SCTAB j
= rTab
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2810 ScRange
aMergedRange( nExtendStartCol
, nExtendStartRow
, rTab
, nMergeTestEndCol
, nMergeTestEndRow
, rTab
+nScenarioCount
);
2811 rDoc
.ExtendMerge( aMergedRange
, true );
2815 for (const auto& rTab
: aMark
)
2817 if (rTab
>= nTabCount
)
2820 rDoc
.RefreshAutoFilter( nExtendStartCol
, nExtendStartRow
, nMergeTestEndCol
, nMergeTestEndRow
, rTab
);
2823 for (const auto& rTab
: aMark
)
2825 if (rTab
>= nTabCount
)
2828 rDoc
.SetDrawPageSize(rTab
);
2830 if ( eCmd
== DelCellCmd::Cols
|| eCmd
== DelCellCmd::Rows
)
2831 rDoc
.UpdatePageBreaks( rTab
);
2833 rDocShell
.UpdatePaintExt( nExtFlags
, nPaintStartCol
, nPaintStartRow
, rTab
, nPaintEndCol
, nPaintEndRow
, rTab
);
2835 SCTAB nScenarioCount
= 0;
2837 for( SCTAB j
= rTab
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2840 // delete entire rows: do not adjust
2841 if ( eCmd
== DelCellCmd::Rows
|| !AdjustRowHeight(ScRange( 0, nPaintStartRow
, rTab
, rDoc
.MaxCol(), nPaintEndRow
, rTab
+nScenarioCount
), true, bApi
) )
2842 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, rTab
, nPaintEndCol
, nPaintEndRow
, rTab
+nScenarioCount
, nPaintFlags
, nExtFlags
);
2845 // paint only what is not done by AdjustRowHeight
2846 if (nExtFlags
& SC_PF_LINES
)
2847 lcl_PaintAbove( rDocShell
, ScRange( nPaintStartCol
, nPaintStartRow
, rTab
, nPaintEndCol
, nPaintEndRow
, rTab
+nScenarioCount
) );
2848 if (nPaintFlags
& PaintPartFlags::Top
)
2849 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, rTab
, nPaintEndCol
, nPaintEndRow
, rTab
+nScenarioCount
, PaintPartFlags::Top
);
2853 // The cursor position needs to be modified earlier than updating
2854 // any enabled edit view which is triggered by SetDocumentModified below.
2855 ScTabViewShell
* pViewSh
= rDocShell
.GetBestViewShell();
2858 if (eCmd
== DelCellCmd::Cols
)
2860 pViewSh
->OnLOKInsertDeleteColumn(rRange
.aStart
.Col(), -1 * (rRange
.aEnd
.Col() - rRange
.aStart
.Col() + 1));
2862 if (eCmd
== DelCellCmd::Rows
)
2864 pViewSh
->OnLOKInsertDeleteRow(rRange
.aStart
.Row(), -1 * (rRange
.aEnd
.Row() - rRange
.aStart
.Row() + 1));
2868 aModificator
.SetDocumentModified();
2870 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
2875 bool ScDocFunc::MoveBlock( const ScRange
& rSource
, const ScAddress
& rDestPos
,
2876 bool bCut
, bool bRecord
, bool bPaint
, bool bApi
)
2878 ScDocShellModificator
aModificator( rDocShell
);
2880 SCCOL nStartCol
= rSource
.aStart
.Col();
2881 SCROW nStartRow
= rSource
.aStart
.Row();
2882 SCTAB nStartTab
= rSource
.aStart
.Tab();
2883 SCCOL nEndCol
= rSource
.aEnd
.Col();
2884 SCROW nEndRow
= rSource
.aEnd
.Row();
2885 SCTAB nEndTab
= rSource
.aEnd
.Tab();
2886 SCCOL nDestCol
= rDestPos
.Col();
2887 SCROW nDestRow
= rDestPos
.Row();
2888 SCTAB nDestTab
= rDestPos
.Tab();
2890 ScDocument
& rDoc
= rDocShell
.GetDocument();
2891 if ( !rDoc
.ValidRow(nStartRow
) || !rDoc
.ValidRow(nEndRow
) || !rDoc
.ValidRow(nDestRow
) )
2893 OSL_FAIL("invalid row in MoveBlock");
2897 // adjust related scenarios too - but only when moved within one sheet
2898 bool bScenariosAdded
= false;
2899 if (bRecord
&& !rDoc
.IsUndoEnabled())
2902 SCTAB nTabCount
= rDoc
.GetTableCount();
2903 if ( nDestTab
== nStartTab
&& !rDoc
.IsScenario(nEndTab
) )
2904 while ( nEndTab
+1 < nTabCount
&& rDoc
.IsScenario(nEndTab
+1) )
2907 bScenariosAdded
= true;
2910 SCTAB nSrcTabCount
= nEndTab
-nStartTab
+1;
2911 SCTAB nDestEndTab
= nDestTab
+nSrcTabCount
-1;
2914 ScDocumentUniquePtr
pClipDoc(new ScDocument(SCDOCMODE_CLIP
));
2916 ScMarkData
aSourceMark(rDoc
.GetSheetLimits());
2917 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2918 aSourceMark
.SelectTable( nTab
, true ); // select source
2919 aSourceMark
.SetMarkArea( rSource
);
2921 ScDocShellRef aDragShellRef
;
2922 if ( rDoc
.HasOLEObjectsInArea( rSource
) )
2924 aDragShellRef
= new ScDocShell
; // DocShell needs a Ref immediately
2925 aDragShellRef
->DoInitNew();
2927 ScDrawLayer::SetGlobalDrawPersist( aDragShellRef
.get() );
2929 ScClipParam
aClipParam(ScRange(nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nStartTab
), bCut
);
2930 rDoc
.CopyToClip(aClipParam
, pClipDoc
.get(), &aSourceMark
, bScenariosAdded
, true);
2932 ScDrawLayer::SetGlobalDrawPersist(nullptr);
2934 SCCOL nOldEndCol
= nEndCol
;
2935 SCROW nOldEndRow
= nEndRow
;
2936 bool bClipOver
= false;
2937 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2939 SCCOL nTmpEndCol
= nOldEndCol
;
2940 SCROW nTmpEndRow
= nOldEndRow
;
2941 if (rDoc
.ExtendMerge( nStartCol
, nStartRow
, nTmpEndCol
, nTmpEndRow
, nTab
))
2943 if ( nTmpEndCol
> nEndCol
) nEndCol
= nTmpEndCol
;
2944 if ( nTmpEndRow
> nEndRow
) nEndRow
= nTmpEndRow
;
2947 SCCOL nDestEndCol
= nDestCol
+ ( nOldEndCol
-nStartCol
);
2948 SCROW nDestEndRow
= nDestRow
+ ( nOldEndRow
-nStartRow
);
2950 SCCOL nUndoEndCol
= nDestCol
+ ( nEndCol
-nStartCol
); // extended in destination block
2951 SCROW nUndoEndRow
= nDestRow
+ ( nEndRow
-nStartRow
);
2953 bool bIncludeFiltered
= bCut
;
2954 if ( !bIncludeFiltered
)
2956 // adjust sizes to include only non-filtered rows
2960 pClipDoc
->GetClipArea( nClipX
, nClipY
, false );
2961 SCROW nUndoAdd
= nUndoEndRow
- nDestEndRow
;
2962 nDestEndRow
= nDestRow
+ nClipY
;
2963 nUndoEndRow
= nDestEndRow
+ nUndoAdd
;
2966 if (!rDoc
.ValidCol(nUndoEndCol
) || !rDoc
.ValidRow(nUndoEndRow
))
2969 rDocShell
.ErrorMessage(STR_PASTE_FULL
);
2973 // Test for cell protection
2975 ScEditableTester aTester
;
2976 for (nTab
=nDestTab
; nTab
<=nDestEndTab
; nTab
++)
2977 aTester
.TestBlock( rDoc
, nTab
, nDestCol
,nDestRow
, nUndoEndCol
,nUndoEndRow
);
2979 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2980 aTester
.TestBlock( rDoc
, nTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
);
2982 if (!aTester
.IsEditable())
2985 rDocShell
.ErrorMessage(aTester
.GetMessageId());
2989 // Test for merged cells- when moving after delete
2991 if (bClipOver
&& !bCut
)
2992 if (rDoc
.HasAttrib( nDestCol
,nDestRow
,nDestTab
, nUndoEndCol
,nUndoEndRow
,nDestEndTab
,
2993 HasAttrFlags::Merged
| HasAttrFlags::Overlapped
))
2994 { // "Merge of already merged cells not possible"
2996 rDocShell
.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0
);
3000 // Are there borders in the cells? (for painting)
3002 sal_uInt16 nSourceExt
= 0;
3003 rDocShell
.UpdatePaintExt( nSourceExt
, nStartCol
,nStartRow
,nStartTab
, nEndCol
,nEndRow
,nEndTab
);
3004 sal_uInt16 nDestExt
= 0;
3005 rDocShell
.UpdatePaintExt( nDestExt
, nDestCol
,nDestRow
,nDestTab
, nDestEndCol
,nDestEndRow
,nDestEndTab
);
3009 ScDocumentUniquePtr pUndoDoc
;
3013 bool bWholeCols
= ( nStartRow
== 0 && nEndRow
== rDoc
.MaxRow() );
3014 bool bWholeRows
= ( nStartCol
== 0 && nEndCol
== rDoc
.MaxCol() );
3015 InsertDeleteFlags nUndoFlags
= (InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
) | InsertDeleteFlags::NOCAPTIONS
;
3017 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
3018 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nEndTab
, bWholeCols
, bWholeRows
);
3022 rDoc
.CopyToDocument( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
,
3023 nUndoFlags
, false, *pUndoDoc
);
3026 if ( nDestTab
!= nStartTab
)
3027 pUndoDoc
->AddUndoTab( nDestTab
, nDestEndTab
, bWholeCols
, bWholeRows
);
3028 rDoc
.CopyToDocument( nDestCol
, nDestRow
, nDestTab
,
3029 nDestEndCol
, nDestEndRow
, nDestEndTab
,
3030 nUndoFlags
, false, *pUndoDoc
);
3031 rDoc
.BeginDrawUndo();
3034 bool bSourceHeight
= false; // adjust heights?
3037 ScMarkData
aDelMark(rDoc
.GetSheetLimits()); // only for tables
3038 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
3040 rDoc
.DeleteAreaTab( nStartCol
,nStartRow
, nOldEndCol
,nOldEndRow
, nTab
, InsertDeleteFlags::ALL
);
3041 aDelMark
.SelectTable( nTab
, true );
3043 rDoc
.DeleteObjectsInArea( nStartCol
,nStartRow
, nOldEndCol
,nOldEndRow
, aDelMark
);
3045 // Test for merged cells
3048 if (rDoc
.HasAttrib( nDestCol
,nDestRow
,nDestTab
,
3049 nUndoEndCol
,nUndoEndRow
,nDestEndTab
,
3050 HasAttrFlags::Merged
| HasAttrFlags::Overlapped
))
3052 rDoc
.CopyFromClip( rSource
, aSourceMark
, InsertDeleteFlags::ALL
, nullptr, pClipDoc
.get() );
3053 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
3055 SCCOL nTmpEndCol
= nEndCol
;
3056 SCROW nTmpEndRow
= nEndRow
;
3057 rDoc
.ExtendMerge( nStartCol
, nStartRow
, nTmpEndCol
, nTmpEndRow
, nTab
, true );
3060 // Report error only after restoring content
3061 if (!bApi
) // "Merge of already merged cells not possible"
3062 rDocShell
.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0
);
3067 bSourceHeight
= AdjustRowHeight( rSource
, false, bApi
);
3070 ScRange
aPasteDest( nDestCol
, nDestRow
, nDestTab
, nDestEndCol
, nDestEndRow
, nDestEndTab
);
3072 ScMarkData
aDestMark(rDoc
.GetSheetLimits());
3073 for (nTab
=nDestTab
; nTab
<=nDestEndTab
; nTab
++)
3074 aDestMark
.SelectTable( nTab
, true ); // select destination
3075 aDestMark
.SetMarkArea( aPasteDest
);
3077 /* Do not copy drawing objects here. While pasting, the
3078 function ScDocument::UpdateReference() is called which calls
3079 ScDrawLayer::MoveCells() which may move away inserted objects to wrong
3080 positions (e.g. if source and destination range overlaps).*/
3083 aPasteDest
, aDestMark
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
,
3084 pUndoDoc
.get(), pClipDoc
.get(), true, false, bIncludeFiltered
);
3086 // skipped rows and merged cells don't mix
3087 if ( !bIncludeFiltered
&& pClipDoc
->HasClipFilteredRows() )
3088 UnmergeCells( aPasteDest
, false, nullptr );
3090 bool bDestHeight
= AdjustRowHeight(
3091 ScRange( 0,nDestRow
,nDestTab
, rDoc
.MaxCol(),nDestEndRow
,nDestEndTab
),
3094 /* Paste drawing objects after adjusting formula references
3095 and row heights. There are no cell notes or drawing objects, if the
3096 clipdoc does not contain a drawing layer.*/
3097 if ( pClipDoc
->GetDrawLayer() )
3098 rDoc
.CopyFromClip( aPasteDest
, aDestMark
, InsertDeleteFlags::OBJECTS
,
3099 nullptr, pClipDoc
.get(), true, false, bIncludeFiltered
);
3103 ScRange
aUndoRange(nStartCol
, nStartRow
, nStartTab
, nOldEndCol
, nOldEndRow
, nEndTab
);
3104 ScAddress
aDestPos(nDestCol
, nDestRow
, nDestTab
);
3106 rDocShell
.GetUndoManager()->AddUndoAction(
3107 std::make_unique
<ScUndoDragDrop
>(
3108 &rDocShell
, aUndoRange
, aDestPos
, bCut
, std::move(pUndoDoc
), bScenariosAdded
));
3111 SCCOL nDestPaintEndCol
= nDestEndCol
;
3112 SCROW nDestPaintEndRow
= nDestEndRow
;
3113 for (nTab
=nDestTab
; nTab
<=nDestEndTab
; nTab
++)
3115 SCCOL nTmpEndCol
= nDestEndCol
;
3116 SCROW nTmpEndRow
= nDestEndRow
;
3117 rDoc
.ExtendMerge( nDestCol
, nDestRow
, nTmpEndCol
, nTmpEndRow
, nTab
, true );
3118 if (nTmpEndCol
> nDestPaintEndCol
) nDestPaintEndCol
= nTmpEndCol
;
3119 if (nTmpEndRow
> nDestPaintEndRow
) nDestPaintEndRow
= nTmpEndRow
;
3123 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
3124 rDoc
.RefreshAutoFilter( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
);
3128 // destination range:
3130 SCCOL nPaintStartX
= nDestCol
;
3131 SCROW nPaintStartY
= nDestRow
;
3132 SCCOL nPaintEndX
= nDestPaintEndCol
;
3133 SCROW nPaintEndY
= nDestPaintEndRow
;
3134 PaintPartFlags nFlags
= PaintPartFlags::Grid
;
3136 if ( nStartRow
==0 && nEndRow
==rDoc
.MaxRow() ) // copy widths too?
3138 nPaintEndX
= rDoc
.MaxCol();
3140 nPaintEndY
= rDoc
.MaxRow();
3141 nFlags
|= PaintPartFlags::Top
;
3143 if ( bDestHeight
|| ( nStartCol
== 0 && nEndCol
== rDoc
.MaxCol() ) )
3145 nPaintEndY
= rDoc
.MaxRow();
3147 nPaintEndX
= rDoc
.MaxCol();
3148 nFlags
|= PaintPartFlags::Left
;
3150 if ( bScenariosAdded
)
3154 nPaintEndX
= rDoc
.MaxCol();
3155 nPaintEndY
= rDoc
.MaxRow();
3158 rDocShell
.PostPaint( nPaintStartX
,nPaintStartY
,nDestTab
,
3159 nPaintEndX
,nPaintEndY
,nDestEndTab
, nFlags
, nSourceExt
| nDestExt
);
3165 nPaintStartX
= nStartCol
;
3166 nPaintStartY
= nStartRow
;
3167 nPaintEndX
= nEndCol
;
3168 nPaintEndY
= nEndRow
;
3169 nFlags
= PaintPartFlags::Grid
;
3171 if ( bSourceHeight
)
3173 nPaintEndY
= rDoc
.MaxRow();
3175 nPaintEndX
= rDoc
.MaxCol();
3176 nFlags
|= PaintPartFlags::Left
;
3178 if ( bScenariosAdded
)
3182 nPaintEndX
= rDoc
.MaxCol();
3183 nPaintEndY
= rDoc
.MaxRow();
3186 rDocShell
.PostPaint( nPaintStartX
,nPaintStartY
,nStartTab
,
3187 nPaintEndX
,nPaintEndY
,nEndTab
, nFlags
, nSourceExt
);
3191 aModificator
.SetDocumentModified();
3193 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
3198 static uno::Reference
< uno::XInterface
> GetDocModuleObject( const SfxObjectShell
& rDocSh
, const OUString
& sCodeName
)
3200 uno::Reference
< lang::XMultiServiceFactory
> xSF(rDocSh
.GetModel(), uno::UNO_QUERY
);
3201 uno::Reference
< container::XNameAccess
> xVBACodeNamedObjectAccess
;
3202 uno::Reference
< uno::XInterface
> xDocModuleApiObject
;
3205 xVBACodeNamedObjectAccess
.set( xSF
->createInstance(u
"ooo.vba.VBAObjectModuleObjectProvider"_ustr
), uno::UNO_QUERY
);
3206 xDocModuleApiObject
.set( xVBACodeNamedObjectAccess
->getByName( sCodeName
), uno::UNO_QUERY
);
3208 return xDocModuleApiObject
;
3212 static script::ModuleInfo
lcl_InitModuleInfo( const SfxObjectShell
& rDocSh
, const OUString
& sModule
)
3214 script::ModuleInfo sModuleInfo
;
3215 sModuleInfo
.ModuleType
= script::ModuleType::DOCUMENT
;
3216 sModuleInfo
.ModuleObject
= GetDocModuleObject( rDocSh
, sModule
);
3220 void VBA_InsertModule( ScDocument
& rDoc
, SCTAB nTab
, const OUString
& sSource
)
3222 ScDocShell
& rDocSh
= *rDoc
.GetDocumentShell();
3223 uno::Reference
< script::XLibraryContainer
> xLibContainer
= rDocSh
.GetBasicContainer();
3224 OSL_ENSURE( xLibContainer
.is(), "No BasicContainer!" );
3226 uno::Reference
< container::XNameContainer
> xLib
;
3227 if( xLibContainer
.is() )
3229 OUString
aLibName( u
"Standard"_ustr
);
3230 #if HAVE_FEATURE_SCRIPTING
3231 if ( rDocSh
.GetBasicManager() && !rDocSh
.GetBasicManager()->GetName().isEmpty() )
3233 aLibName
= rDocSh
.GetBasicManager()->GetName();
3236 uno::Any aLibAny
= xLibContainer
->getByName( aLibName
);
3242 // if the Module with codename exists then find a new name
3244 OUString genModuleName
= u
"Sheet1"_ustr
;
3245 while( xLib
->hasByName( genModuleName
) )
3246 genModuleName
= "Sheet" + OUString::number( ++nNum
);
3248 uno::Any aSourceAny
;
3249 OUString sTmpSource
= sSource
;
3250 if ( sTmpSource
.isEmpty() )
3251 sTmpSource
= "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n";
3252 aSourceAny
<<= sTmpSource
;
3253 uno::Reference
< script::vba::XVBAModuleInfo
> xVBAModuleInfo( xLib
, uno::UNO_QUERY
);
3254 if ( xVBAModuleInfo
.is() )
3256 rDoc
.SetCodeName( nTab
, genModuleName
);
3257 script::ModuleInfo sModuleInfo
= lcl_InitModuleInfo( rDocSh
, genModuleName
);
3258 xVBAModuleInfo
->insertModuleInfo( genModuleName
, sModuleInfo
);
3259 xLib
->insertByName( genModuleName
, aSourceAny
);
3263 void VBA_DeleteModule( ScDocShell
& rDocSh
, const OUString
& sModuleName
)
3265 uno::Reference
< script::XLibraryContainer
> xLibContainer
= rDocSh
.GetBasicContainer();
3266 OSL_ENSURE( xLibContainer
.is(), "No BasicContainer!" );
3268 uno::Reference
< container::XNameContainer
> xLib
;
3269 if( xLibContainer
.is() )
3271 OUString
aLibName( u
"Standard"_ustr
);
3272 #if HAVE_FEATURE_SCRIPTING
3273 if ( rDocSh
.GetBasicManager() && !rDocSh
.GetBasicManager()->GetName().isEmpty() )
3275 aLibName
= rDocSh
.GetBasicManager()->GetName();
3278 uno::Any aLibAny
= xLibContainer
->getByName( aLibName
);
3283 uno::Reference
< script::vba::XVBAModuleInfo
> xVBAModuleInfo( xLib
, uno::UNO_QUERY
);
3284 if( xLib
->hasByName( sModuleName
) )
3285 xLib
->removeByName( sModuleName
);
3286 if ( xVBAModuleInfo
.is() && xVBAModuleInfo
->hasModuleInfo(sModuleName
) )
3287 xVBAModuleInfo
->removeModuleInfo( sModuleName
);
3292 bool ScDocFunc::InsertTable( SCTAB nTab
, const OUString
& rName
, bool bRecord
, bool bApi
)
3294 bool bSuccess
= false;
3295 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
3297 ScDocShellModificator
aModificator( rDocShell
);
3299 ScDocument
& rDoc
= rDocShell
.GetDocument();
3301 // Strange loop, also basic is loaded too early ( InsertTable )
3302 // is called via the xml import for sheets in described in ODF
3303 bool bInsertDocModule
= false;
3305 if( !rDocShell
.GetDocument().IsImportingXML() )
3307 bInsertDocModule
= rDoc
.IsInVBAMode();
3309 if ( bInsertDocModule
|| ( bRecord
&& !rDoc
.IsUndoEnabled() ) )
3313 rDoc
.BeginDrawUndo(); // InsertTab generates SdrUndoNewPage
3315 SCTAB nTabCount
= rDoc
.GetTableCount();
3316 bool bAppend
= ( nTab
>= nTabCount
);
3318 nTab
= nTabCount
; // important for Undo
3320 if (rDoc
.InsertTab( nTab
, rName
))
3323 rDocShell
.GetUndoManager()->AddUndoAction(
3324 std::make_unique
<ScUndoInsertTab
>( &rDocShell
, nTab
, bAppend
, rName
));
3326 // Only insert vba modules if vba mode ( and not currently importing XML )
3327 if( bInsertDocModule
)
3329 VBA_InsertModule( rDoc
, nTab
, OUString() );
3331 rDocShell
.Broadcast( ScTablesHint( SC_TAB_INSERTED
, nTab
) );
3333 rDocShell
.PostPaintExtras();
3334 aModificator
.SetDocumentModified();
3335 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3339 rDocShell
.ErrorMessage(STR_TABINSERT_ERROR
);
3344 bool ScDocFunc::DeleteTable( SCTAB nTab
, bool bRecord
)
3346 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
3348 ScDocShellModificator
aModificator( rDocShell
);
3350 bool bSuccess
= false;
3351 ScDocument
& rDoc
= rDocShell
.GetDocument();
3352 bool bVbaEnabled
= rDoc
.IsInVBAMode();
3353 if (bRecord
&& !rDoc
.IsUndoEnabled())
3357 bool bWasLinked
= rDoc
.IsLinked(nTab
);
3358 ScDocumentUniquePtr pUndoDoc
;
3359 std::unique_ptr
<ScRefUndoData
> pUndoData
;
3362 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
3363 SCTAB nCount
= rDoc
.GetTableCount();
3365 pUndoDoc
->InitUndo( rDoc
, nTab
, nTab
, true, true ); // only nTab with Flags
3366 pUndoDoc
->AddUndoTab( 0, nCount
-1 ); // all sheets for references
3368 rDoc
.CopyToDocument(0,0,nTab
, rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
, InsertDeleteFlags::ALL
,false, *pUndoDoc
);
3370 rDoc
.GetName( nTab
, aOldName
);
3371 pUndoDoc
->RenameTab( nTab
, aOldName
);
3373 pUndoDoc
->SetLink( nTab
, rDoc
.GetLinkMode(nTab
), rDoc
.GetLinkDoc(nTab
),
3374 rDoc
.GetLinkFlt(nTab
), rDoc
.GetLinkOpt(nTab
),
3375 rDoc
.GetLinkTab(nTab
),
3376 rDoc
.GetLinkRefreshDelay(nTab
) );
3378 if ( rDoc
.IsScenario(nTab
) )
3380 pUndoDoc
->SetScenario( nTab
, true );
3383 ScScenarioFlags nScenFlags
;
3384 rDoc
.GetScenarioData( nTab
, aComment
, aColor
, nScenFlags
);
3385 pUndoDoc
->SetScenarioData( nTab
, aComment
, aColor
, nScenFlags
);
3386 bool bActive
= rDoc
.IsActiveScenario( nTab
);
3387 pUndoDoc
->SetActiveScenario( nTab
, bActive
);
3389 pUndoDoc
->SetVisible( nTab
, rDoc
.IsVisible( nTab
) );
3390 pUndoDoc
->SetTabBgColor( nTab
, rDoc
.GetTabBgColor(nTab
) );
3391 auto pSheetEvents
= rDoc
.GetSheetEvents( nTab
);
3392 pUndoDoc
->SetSheetEvents( nTab
, std::unique_ptr
<ScSheetEvents
>(pSheetEvents
? new ScSheetEvents(*pSheetEvents
) : nullptr) );
3394 // Drawing-Layer has to take care of its own undo!!!
3395 rDoc
.BeginDrawUndo(); // DeleteTab generates SdrUndoDelPage
3397 pUndoData
.reset(new ScRefUndoData( &rDoc
));
3400 if (rDoc
.DeleteTab(nTab
))
3404 vector
<SCTAB
> theTabs
;
3405 theTabs
.push_back(nTab
);
3406 rDocShell
.GetUndoManager()->AddUndoAction(
3407 std::make_unique
<ScUndoDeleteTab
>( &rDocShell
, theTabs
, std::move(pUndoDoc
), std::move(pUndoData
) ));
3413 if( rDoc
.GetCodeName( nTab
, sCodeName
) )
3415 VBA_DeleteModule( rDocShell
, sCodeName
);
3418 rDocShell
.Broadcast( ScTablesHint( SC_TAB_DELETED
, nTab
) );
3422 rDocShell
.UpdateLinks(); // update Link-Manager
3423 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3425 pBindings
->Invalidate(SID_LINKS
);
3428 rDocShell
.PostPaintExtras();
3429 aModificator
.SetDocumentModified();
3431 SfxApplication
* pSfxApp
= SfxGetpApp(); // Navigator
3432 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3433 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScAreasChanged
) );
3434 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged
) );
3435 pSfxApp
->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
3442 void ScDocFunc::SetTableVisible( SCTAB nTab
, bool bVisible
, bool bApi
)
3444 ScDocument
& rDoc
= rDocShell
.GetDocument();
3445 bool bUndo(rDoc
.IsUndoEnabled());
3446 if ( rDoc
.IsVisible( nTab
) == bVisible
)
3447 return; // nothing to do - ok
3449 if ( !rDoc
.IsDocEditable() )
3452 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
3456 ScDocShellModificator
aModificator( rDocShell
);
3458 if ( !bVisible
&& !rDoc
.IsImportingXML() ) // #i57869# allow hiding in any order for loading
3460 // do not disable all sheets
3462 sal_uInt16 nVisCount
= 0;
3463 SCTAB nCount
= rDoc
.GetTableCount();
3464 for (SCTAB i
=0; i
<nCount
&& nVisCount
<2; i
++)
3465 if (rDoc
.IsVisible(i
))
3471 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //! separate error message?
3476 rDoc
.SetVisible( nTab
, bVisible
);
3479 std::vector
<SCTAB
> undoTabs
{ nTab
};
3480 rDocShell
.GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoShowHideTab
>( &rDocShell
, std::move(undoTabs
), bVisible
) );
3485 rDocShell
.Broadcast( ScTablesHint( SC_TAB_HIDDEN
, nTab
) );
3487 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3488 rDocShell
.PostPaint(0,0,0,rDoc
.MaxCol(),rDoc
.MaxRow(),MAXTAB
, PaintPartFlags::Extras
);
3489 aModificator
.SetDocumentModified();
3492 bool ScDocFunc::SetLayoutRTL( SCTAB nTab
, bool bRTL
)
3494 ScDocument
& rDoc
= rDocShell
.GetDocument();
3495 bool bUndo(rDoc
.IsUndoEnabled());
3496 if ( rDoc
.IsLayoutRTL( nTab
) == bRTL
)
3497 return true; // nothing to do - ok
3499 //! protection (sheet or document?)
3501 ScDocShellModificator
aModificator( rDocShell
);
3503 rDoc
.SetLayoutRTL( nTab
, bRTL
, ScObjectHandling::MirrorRTLMode
);
3507 rDocShell
.GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoLayoutRTL
>( &rDocShell
, nTab
, bRTL
) );
3510 rDocShell
.PostPaint( 0,0,nTab
,rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
, PaintPartFlags::All
);
3511 aModificator
.SetDocumentModified();
3513 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3516 pBindings
->Invalidate( FID_TAB_RTL
);
3517 pBindings
->Invalidate( SID_ATTR_SIZE
);
3523 bool ScDocFunc::RenameTable( SCTAB nTab
, const OUString
& rName
, bool bRecord
, bool bApi
)
3525 ScDocument
& rDoc
= rDocShell
.GetDocument();
3526 if (bRecord
&& !rDoc
.IsUndoEnabled())
3528 if ( !rDoc
.IsDocEditable() )
3531 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
3535 ScDocShellModificator
aModificator( rDocShell
);
3537 bool bSuccess
= false;
3539 rDoc
.GetName(nTab
, sOldName
);
3540 if (rDoc
.RenameTab( nTab
, rName
))
3544 rDocShell
.GetUndoManager()->AddUndoAction(
3545 std::make_unique
<ScUndoRenameTab
>( &rDocShell
, nTab
, sOldName
, rName
));
3547 rDocShell
.PostPaintExtras();
3548 aModificator
.SetDocumentModified();
3549 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3550 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged
) );
3557 bool ScDocFunc::SetTabBgColor( SCTAB nTab
, const Color
& rColor
, bool bRecord
, bool bApi
)
3560 ScDocument
& rDoc
= rDocShell
.GetDocument();
3561 if (bRecord
&& !rDoc
.IsUndoEnabled())
3563 if ( !rDoc
.IsDocEditable() || rDoc
.IsTabProtected(nTab
) )
3566 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //TODO Check to see what this string is...
3570 Color aOldTabBgColor
= rDoc
.GetTabBgColor(nTab
);
3572 bool bSuccess
= false;
3573 rDoc
.SetTabBgColor(nTab
, rColor
);
3574 if ( rDoc
.GetTabBgColor(nTab
) == rColor
)
3580 rDocShell
.GetUndoManager()->AddUndoAction(
3581 std::make_unique
<ScUndoTabColor
>( &rDocShell
, nTab
, aOldTabBgColor
, rColor
));
3583 rDocShell
.PostPaintExtras();
3584 ScDocShellModificator
aModificator( rDocShell
);
3585 aModificator
.SetDocumentModified();
3586 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
3593 bool ScDocFunc::SetTabBgColor(
3594 ScUndoTabColorInfo::List
& rUndoTabColorList
, bool bApi
)
3596 ScDocument
& rDoc
= rDocShell
.GetDocument();
3597 bool bRecord
= true;
3598 if (!rDoc
.IsUndoEnabled())
3601 if ( !rDoc
.IsDocEditable() )
3604 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //TODO Get a better String Error...
3609 Color aNewTabBgColor
;
3610 bool bSuccess
= true;
3611 size_t nTabProtectCount
= 0;
3612 size_t nTabListCount
= rUndoTabColorList
.size();
3613 for ( size_t i
= 0; i
< nTabListCount
; ++i
)
3615 ScUndoTabColorInfo
& rInfo
= rUndoTabColorList
[i
];
3616 nTab
= rInfo
.mnTabId
;
3617 if ( !rDoc
.IsTabProtected(nTab
) )
3619 aNewTabBgColor
= rInfo
.maNewTabBgColor
;
3620 rInfo
.maOldTabBgColor
= rDoc
.GetTabBgColor(nTab
);
3621 rDoc
.SetTabBgColor(nTab
, aNewTabBgColor
);
3622 if ( rDoc
.GetTabBgColor(nTab
) != aNewTabBgColor
)
3634 if ( nTabProtectCount
== nTabListCount
)
3637 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //TODO Get a better String Error...
3645 rDocShell
.GetUndoManager()->AddUndoAction(
3646 std::make_unique
<ScUndoTabColor
>( &rDocShell
, std::vector(rUndoTabColorList
)));
3648 rDocShell
.PostPaintExtras();
3649 ScDocShellModificator
aModificator( rDocShell
);
3650 aModificator
.SetDocumentModified();
3655 //! SetWidthOrHeight - duplicated in ViewFunc !!!!!!
3657 //! - Optimal height of text cells is different for a printer and a screen
3658 //! - Optimal width needs a selection in order to take only selected cells into account
3660 static sal_uInt16
lcl_GetOptimalColWidth( ScDocShell
& rDocShell
, SCCOL nCol
, SCTAB nTab
)
3662 ScSizeDeviceProvider
aProv(&rDocShell
);
3663 OutputDevice
* pDev
= aProv
.GetDevice(); // has pixel MapMode
3664 double nPPTX
= aProv
.GetPPTX();
3665 double nPPTY
= aProv
.GetPPTY();
3667 ScDocument
& rDoc
= rDocShell
.GetDocument();
3669 sal_uInt16 nTwips
= rDoc
.GetOptimalColWidth( nCol
, nTab
, pDev
, nPPTX
, nPPTY
, aOne
, aOne
,
3670 false/*bFormula*/ );
3675 bool ScDocFunc::SetWidthOrHeight(
3676 bool bWidth
, const std::vector
<sc::ColRowSpan
>& rRanges
, SCTAB nTab
,
3677 ScSizeMode eMode
, sal_uInt16 nSizeTwips
, bool bRecord
, bool bApi
)
3679 ScDocShellModificator
aModificator( rDocShell
);
3681 if (rRanges
.empty())
3684 ScDocument
& rDoc
= rDocShell
.GetDocument();
3685 if ( bRecord
&& !rDoc
.IsUndoEnabled() )
3688 // import into read-only document is possible
3689 if ( !rDoc
.IsChangeReadOnlyEnabled() && !rDocShell
.IsEditable() )
3692 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //! separate error message?
3696 SCCOLROW nStart
= rRanges
[0].mnStart
;
3697 SCCOLROW nEnd
= rRanges
[0].mnEnd
;
3699 if ( eMode
== SC_SIZE_OPTIMAL
)
3701 //! Option "Show formulas" - but where to get them from?
3704 ScDocumentUniquePtr pUndoDoc
;
3705 std::unique_ptr
<ScOutlineTable
> pUndoTab
;
3706 std::vector
<sc::ColRowSpan
> aUndoRanges
;
3710 rDoc
.BeginDrawUndo(); // Drawing Updates
3712 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
3715 pUndoDoc
->InitUndo( rDoc
, nTab
, nTab
, true );
3716 rDoc
.CopyToDocument( static_cast<SCCOL
>(nStart
), 0, nTab
, static_cast<SCCOL
>(nEnd
), rDoc
.MaxRow(), nTab
, InsertDeleteFlags::NONE
, false, *pUndoDoc
);
3720 pUndoDoc
->InitUndo( rDoc
, nTab
, nTab
, false, true );
3721 rDoc
.CopyToDocument( 0, static_cast<SCROW
>(nStart
), nTab
, rDoc
.MaxCol(), static_cast<SCROW
>(nEnd
), nTab
, InsertDeleteFlags::NONE
, false, *pUndoDoc
);
3724 aUndoRanges
= rRanges
;
3726 ScOutlineTable
* pTable
= rDoc
.GetOutlineTable( nTab
);
3728 pUndoTab
.reset(new ScOutlineTable( *pTable
));
3731 bool bShow
= nSizeTwips
> 0 || eMode
!= SC_SIZE_DIRECT
;
3732 bool bOutline
= false;
3734 for (const sc::ColRowSpan
& rRange
: rRanges
)
3736 SCCOLROW nStartNo
= rRange
.mnStart
;
3737 SCCOLROW nEndNo
= rRange
.mnEnd
;
3739 if ( !bWidth
) // deal with heights always in blocks
3741 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
3743 bool bAll
= ( eMode
==SC_SIZE_OPTIMAL
);
3746 // delete for all that have CRFlags::ManualSize enabled
3747 // then SetOptimalHeight with bShrink = FALSE
3748 for (SCROW nRow
=nStartNo
; nRow
<=nEndNo
; nRow
++)
3750 CRFlags nOld
= rDoc
.GetRowFlags(nRow
,nTab
);
3751 SCROW nLastRow
= -1;
3752 bool bHidden
= rDoc
.RowHidden(nRow
, nTab
, nullptr, &nLastRow
);
3753 if ( !bHidden
&& ( nOld
& CRFlags::ManualSize
) )
3754 rDoc
.SetRowFlags( nRow
, nTab
, nOld
& ~CRFlags::ManualSize
);
3758 ScSizeDeviceProvider
aProv( &rDocShell
);
3760 sc::RowHeightContext
aCxt(rDoc
.MaxRow(), aProv
.GetPPTX(), aProv
.GetPPTY(), aOne
, aOne
, aProv
.GetDevice());
3761 aCxt
.setForceAutoSize(bAll
);
3762 rDoc
.SetOptimalHeight(aCxt
, nStartNo
, nEndNo
, nTab
, bApi
);
3765 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, true );
3767 // Manual flag will be set already in SetOptimalHeight if bAll=true
3768 // (it is on when Extra-Height, otherwise off).
3770 else if ( eMode
==SC_SIZE_DIRECT
|| eMode
==SC_SIZE_ORIGINAL
)
3774 rDoc
.SetRowHeightRange( nStartNo
, nEndNo
, nTab
, nSizeTwips
);
3775 rDoc
.SetManualHeight( nStartNo
, nEndNo
, nTab
, true ); // height was set manually
3777 if ( eMode
!= SC_SIZE_ORIGINAL
)
3778 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, nSizeTwips
!= 0 );
3780 else if ( eMode
==SC_SIZE_SHOW
)
3782 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, true );
3785 else // Column widths
3787 for (SCCOL nCol
=static_cast<SCCOL
>(nStartNo
); nCol
<=static_cast<SCCOL
>(nEndNo
); nCol
++)
3789 if ( eMode
!= SC_SIZE_VISOPT
|| !rDoc
.ColHidden(nCol
, nTab
) )
3791 sal_uInt16 nThisSize
= nSizeTwips
;
3793 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
3794 nThisSize
= nSizeTwips
+
3795 lcl_GetOptimalColWidth( rDocShell
, nCol
, nTab
);
3797 rDoc
.SetColWidth( nCol
, nTab
, nThisSize
);
3799 if ( eMode
!= SC_SIZE_ORIGINAL
)
3800 rDoc
.ShowCol( nCol
, nTab
, bShow
);
3807 if ( eMode
!= SC_SIZE_ORIGINAL
)
3810 bOutline
= bOutline
|| rDoc
.UpdateOutlineCol(
3811 static_cast<SCCOL
>(nStartNo
),
3812 static_cast<SCCOL
>(nEndNo
), nTab
, bShow
);
3814 bOutline
= bOutline
|| rDoc
.UpdateOutlineRow(
3815 static_cast<SCROW
>(nStartNo
),
3816 static_cast<SCROW
>(nEndNo
), nTab
, bShow
);
3819 rDoc
.SetDrawPageSize(nTab
);
3826 ScMarkData
aMark(rDoc
.GetSheetLimits());
3827 aMark
.SelectOneTable( nTab
);
3828 rDocShell
.GetUndoManager()->AddUndoAction(
3829 std::make_unique
<ScUndoWidthOrHeight
>(
3830 &rDocShell
, aMark
, nStart
, nTab
, nEnd
, nTab
, std::move(pUndoDoc
),
3831 std::move(aUndoRanges
), std::move(pUndoTab
), eMode
, nSizeTwips
, bWidth
));
3834 rDoc
.UpdatePageBreaks( nTab
);
3836 ScTabViewShell
* pViewSh
= rDocShell
.GetBestViewShell();
3838 pViewSh
->OnLOKSetWidthOrHeight(nStart
, bWidth
);
3840 rDocShell
.PostPaint(0,0,nTab
,rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
,PaintPartFlags::All
);
3841 aModificator
.SetDocumentModified();
3846 bool ScDocFunc::InsertPageBreak( bool bColumn
, const ScAddress
& rPos
,
3847 bool bRecord
, bool bSetModified
)
3849 ScDocShellModificator
aModificator( rDocShell
);
3851 ScDocument
& rDoc
= rDocShell
.GetDocument();
3852 if (bRecord
&& !rDoc
.IsUndoEnabled())
3854 SCTAB nTab
= rPos
.Tab();
3855 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3857 SCCOLROW nPos
= bColumn
? static_cast<SCCOLROW
>(rPos
.Col()) :
3858 static_cast<SCCOLROW
>(rPos
.Row());
3860 return false; // first column / row
3862 ScBreakType nBreak
= bColumn
?
3863 rDoc
.HasColBreak(static_cast<SCCOL
>(nPos
), nTab
) :
3864 rDoc
.HasRowBreak(static_cast<SCROW
>(nPos
), nTab
);
3865 if (nBreak
& ScBreakType::Manual
)
3869 rDocShell
.GetUndoManager()->AddUndoAction(
3870 std::make_unique
<ScUndoPageBreak
>( &rDocShell
, rPos
.Col(), rPos
.Row(), nTab
, bColumn
, true ) );
3873 rDoc
.SetColBreak(static_cast<SCCOL
>(nPos
), nTab
, false, true);
3875 rDoc
.SetRowBreak(static_cast<SCROW
>(nPos
), nTab
, false, true);
3877 rDoc
.InvalidatePageBreaks(nTab
);
3878 rDoc
.UpdatePageBreaks( nTab
);
3880 rDoc
.SetStreamValid(nTab
, false);
3884 rDocShell
.PostPaint( static_cast<SCCOL
>(nPos
)-1, 0, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, PaintPartFlags::Grid
);
3887 pBindings
->Invalidate( FID_INS_COLBRK
);
3888 pBindings
->Invalidate( FID_DEL_COLBRK
);
3893 rDocShell
.PostPaint( 0, static_cast<SCROW
>(nPos
)-1, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, PaintPartFlags::Grid
);
3896 pBindings
->Invalidate( FID_INS_ROWBRK
);
3897 pBindings
->Invalidate( FID_DEL_ROWBRK
);
3901 pBindings
->Invalidate( FID_DEL_MANUALBREAKS
);
3904 aModificator
.SetDocumentModified();
3909 bool ScDocFunc::RemovePageBreak( bool bColumn
, const ScAddress
& rPos
,
3910 bool bRecord
, bool bSetModified
)
3912 ScDocShellModificator
aModificator( rDocShell
);
3914 ScDocument
& rDoc
= rDocShell
.GetDocument();
3915 if (bRecord
&& !rDoc
.IsUndoEnabled())
3917 SCTAB nTab
= rPos
.Tab();
3918 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3920 SCCOLROW nPos
= bColumn
? static_cast<SCCOLROW
>(rPos
.Col()) :
3921 static_cast<SCCOLROW
>(rPos
.Row());
3925 nBreak
= rDoc
.HasColBreak(static_cast<SCCOL
>(nPos
), nTab
);
3927 nBreak
= rDoc
.HasRowBreak(static_cast<SCROW
>(nPos
), nTab
);
3928 if (!(nBreak
& ScBreakType::Manual
))
3929 // There is no manual break.
3933 rDocShell
.GetUndoManager()->AddUndoAction(
3934 std::make_unique
<ScUndoPageBreak
>( &rDocShell
, rPos
.Col(), rPos
.Row(), nTab
, bColumn
, false ) );
3937 rDoc
.RemoveColBreak(static_cast<SCCOL
>(nPos
), nTab
, false, true);
3939 rDoc
.RemoveRowBreak(static_cast<SCROW
>(nPos
), nTab
, false, true);
3941 rDoc
.UpdatePageBreaks( nTab
);
3943 rDoc
.SetStreamValid(nTab
, false);
3947 rDocShell
.PostPaint( static_cast<SCCOL
>(nPos
)-1, 0, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, PaintPartFlags::Grid
);
3950 pBindings
->Invalidate( FID_INS_COLBRK
);
3951 pBindings
->Invalidate( FID_DEL_COLBRK
);
3956 rDocShell
.PostPaint( 0, nPos
-1, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, PaintPartFlags::Grid
);
3959 pBindings
->Invalidate( FID_INS_ROWBRK
);
3960 pBindings
->Invalidate( FID_DEL_ROWBRK
);
3964 pBindings
->Invalidate( FID_DEL_MANUALBREAKS
);
3967 aModificator
.SetDocumentModified();
3972 void ScDocFunc::ProtectSheet( SCTAB nTab
, const ScTableProtection
& rProtect
)
3974 ScDocument
& rDoc
= rDocShell
.GetDocument();
3976 std::unique_ptr
<ScTableProtection
> p
;
3977 if (!rProtect
.isProtected() && rDoc
.IsUndoEnabled())
3979 // In case of unprotecting, use a copy of passed ScTableProtection object for undo
3980 p
= std::make_unique
<ScTableProtection
>(rProtect
);
3982 rDoc
.SetTabProtection(nTab
, &rProtect
);
3983 if (rDoc
.IsUndoEnabled())
3987 // For protection case, use a copy of resulting ScTableProtection for undo
3988 const ScTableProtection
* pProtect
= rDoc
.GetTabProtection(nTab
);
3989 p
= std::make_unique
<ScTableProtection
>(*pProtect
);
3991 rDocShell
.GetUndoManager()->AddUndoAction(
3992 std::make_unique
<ScUndoTabProtect
>(&rDocShell
, nTab
, std::move(p
)));
3993 // ownership of unique_ptr now transferred to ScUndoTabProtect.
3995 for (SfxViewFrame
* fr
= SfxViewFrame::GetFirst(&rDocShell
); fr
;
3996 fr
= SfxViewFrame::GetNext(*fr
, &rDocShell
))
3997 if (ScTabViewShell
* pTabViewShell
= dynamic_cast<ScTabViewShell
*>(fr
->GetViewShell()))
3998 pTabViewShell
->SetTabProtectionSymbol(nTab
, rProtect
.isProtected());
3999 rDocShell
.PostPaintGridAll();
4000 ScDocShellModificator
aModificator(rDocShell
);
4001 aModificator
.SetDocumentModified();
4004 void ScDocFunc::ProtectDocument(const ScDocProtection
& rProtect
)
4006 ScDocument
& rDoc
= rDocShell
.GetDocument();
4008 std::unique_ptr
<ScDocProtection
> p
;
4009 if (!rProtect
.isProtected() && rDoc
.IsUndoEnabled())
4011 // In case of unprotecting, use a copy of passed ScTableProtection object for undo
4012 p
= std::make_unique
<ScDocProtection
>(rProtect
);
4014 rDoc
.SetDocProtection(&rProtect
);
4015 if (rDoc
.IsUndoEnabled())
4019 // For protection case, use a copy of resulting ScTableProtection for undo
4020 ScDocProtection
* pProtect
= rDoc
.GetDocProtection();
4021 p
= std::make_unique
<ScDocProtection
>(*pProtect
);
4023 rDocShell
.GetUndoManager()->AddUndoAction(
4024 std::make_unique
<ScUndoDocProtect
>(&rDocShell
, std::move(p
)));
4025 // ownership of unique_ptr now transferred to ScUndoTabProtect.
4028 rDocShell
.PostPaintGridAll();
4029 ScDocShellModificator
aModificator(rDocShell
);
4030 aModificator
.SetDocumentModified();
4033 bool ScDocFunc::Protect( SCTAB nTab
, const OUString
& rPassword
)
4035 if (nTab
== TABLEID_DOC
)
4037 // document protection
4038 ScDocProtection aProtection
;
4039 aProtection
.setProtected(true);
4040 aProtection
.setPassword(rPassword
);
4041 ProtectDocument(aProtection
);
4048 const ScTableProtection
* pOldProtection
= rDocShell
.GetDocument().GetTabProtection(nTab
);
4049 ::std::unique_ptr
<ScTableProtection
> pNewProtection(pOldProtection
? new ScTableProtection(*pOldProtection
) : new ScTableProtection());
4050 pNewProtection
->setProtected(true);
4051 pNewProtection
->setPassword(rPassword
);
4052 ProtectSheet(nTab
, *pNewProtection
);
4057 bool ScDocFunc::Unprotect( SCTAB nTab
, const OUString
& rPassword
, bool bApi
)
4059 ScDocument
& rDoc
= rDocShell
.GetDocument();
4061 if (nTab
== TABLEID_DOC
)
4063 // document protection
4065 ScDocProtection
* pDocProtect
= rDoc
.GetDocProtection();
4066 if (!pDocProtect
|| !pDocProtect
->isProtected())
4067 // already unprotected (should not happen)!
4070 if (!pDocProtect
->verifyPassword(rPassword
))
4074 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
4075 VclMessageType::Info
, VclButtonsType::Ok
,
4076 ScResId(SCSTR_WRONGPASSWORD
)));
4082 ScDocProtection
aNewProtection(*pDocProtect
);
4083 aNewProtection
.setProtected(false);
4084 ProtectDocument(aNewProtection
);
4091 const ScTableProtection
* pTabProtect
= rDoc
.GetTabProtection(nTab
);
4092 if (!pTabProtect
|| !pTabProtect
->isProtected())
4093 // already unprotected (should not happen)!
4095 if (!pTabProtect
->verifyPassword(rPassword
))
4099 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
4100 VclMessageType::Info
, VclButtonsType::Ok
,
4101 ScResId(SCSTR_WRONGPASSWORD
)));
4107 ScTableProtection
aNewProtection(*pTabProtect
);
4108 aNewProtection
.setProtected(false);
4109 ProtectSheet(nTab
, aNewProtection
);
4115 void ScDocFunc::ClearItems( const ScMarkData
& rMark
, const sal_uInt16
* pWhich
, bool bApi
)
4117 ScDocShellModificator
aModificator( rDocShell
);
4119 ScDocument
& rDoc
= rDocShell
.GetDocument();
4120 bool bUndo (rDoc
.IsUndoEnabled());
4121 ScEditableTester
aTester( rDoc
, rMark
);
4122 if (!aTester
.IsEditable())
4125 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4129 // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
4130 // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
4133 ScMarkData aMultiMark
= rMark
;
4134 aMultiMark
.SetMarking(false); // for MarkToMulti
4135 aMultiMark
.MarkToMulti();
4136 const ScRange
& aMarkRange
= aMultiMark
.GetMultiMarkArea();
4140 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
4141 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
4143 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
4144 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nEndTab
);
4145 rDoc
.CopyToDocument( aMarkRange
, InsertDeleteFlags::ATTRIB
, true, *pUndoDoc
, &aMultiMark
);
4147 rDocShell
.GetUndoManager()->AddUndoAction(
4148 std::make_unique
<ScUndoClearItems
>( &rDocShell
, aMultiMark
, std::move(pUndoDoc
), pWhich
) );
4151 rDoc
.ClearSelectionItems( pWhich
, aMultiMark
);
4153 rDocShell
.PostPaint( aMarkRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
4154 aModificator
.SetDocumentModified();
4156 //! Bindings-Invalidate etc.?
4159 bool ScDocFunc::ChangeIndent( const ScMarkData
& rMark
, bool bIncrement
, bool bApi
)
4161 ScDocShellModificator
aModificator( rDocShell
);
4163 ScDocument
& rDoc
= rDocShell
.GetDocument();
4164 bool bUndo(rDoc
.IsUndoEnabled());
4165 ScEditableTester
aTester( rDoc
, rMark
);
4166 if (!aTester
.IsEditable())
4169 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4173 const ScRange
& aMarkRange
= rMark
.GetMultiMarkArea();
4177 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
4178 SCTAB nTabCount
= rDoc
.GetTableCount();
4180 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
4181 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nStartTab
);
4182 for (const auto& rTab
: rMark
)
4184 if (rTab
>= nTabCount
)
4187 if (rTab
!= nStartTab
)
4188 pUndoDoc
->AddUndoTab( rTab
, rTab
);
4191 ScRange aCopyRange
= aMarkRange
;
4192 aCopyRange
.aStart
.SetTab(0);
4193 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
4194 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, true, *pUndoDoc
, &rMark
);
4196 rDocShell
.GetUndoManager()->AddUndoAction(
4197 std::make_unique
<ScUndoIndent
>( &rDocShell
, rMark
, std::move(pUndoDoc
), bIncrement
) );
4200 rDoc
.ChangeSelectionIndent( bIncrement
, rMark
);
4202 rDocShell
.PostPaint( aMarkRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
4203 aModificator
.SetDocumentModified();
4205 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
4208 pBindings
->Invalidate( SID_ALIGNLEFT
); // ChangeIndent aligns left
4209 pBindings
->Invalidate( SID_ALIGNRIGHT
);
4210 pBindings
->Invalidate( SID_ALIGNBLOCK
);
4211 pBindings
->Invalidate( SID_ALIGNCENTERHOR
);
4212 pBindings
->Invalidate( SID_ATTR_LRSPACE
);
4213 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_LEFT
);
4214 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT
);
4215 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK
);
4216 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_CENTER
);
4217 // pseudo slots for Format menu
4218 pBindings
->Invalidate( SID_ALIGN_ANY_HDEFAULT
);
4219 pBindings
->Invalidate( SID_ALIGN_ANY_LEFT
);
4220 pBindings
->Invalidate( SID_ALIGN_ANY_HCENTER
);
4221 pBindings
->Invalidate( SID_ALIGN_ANY_RIGHT
);
4222 pBindings
->Invalidate( SID_ALIGN_ANY_JUSTIFIED
);
4228 bool ScDocFunc::AutoFormat( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4229 sal_uInt16 nFormatNo
, bool bApi
)
4231 ScDocShellModificator
aModificator( rDocShell
);
4233 ScDocument
& rDoc
= rDocShell
.GetDocument();
4234 SCCOL nStartCol
= rRange
.aStart
.Col();
4235 SCROW nStartRow
= rRange
.aStart
.Row();
4236 SCTAB nStartTab
= rRange
.aStart
.Tab();
4237 SCCOL nEndCol
= rRange
.aEnd
.Col();
4238 SCROW nEndRow
= rRange
.aEnd
.Row();
4239 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4241 bool bRecord
= true;
4242 if (!rDoc
.IsUndoEnabled())
4244 ScMarkData
aMark(rDoc
.GetSheetLimits());
4249 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4250 aMark
.SelectTable( nTab
, true );
4253 ScAutoFormat
* pAutoFormat
= ScGlobal::GetOrCreateAutoFormat();
4254 ScEditableTester
aTester( rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4255 if ( nFormatNo
< pAutoFormat
->size() && aTester
.IsEditable() )
4257 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4259 bool bSize
= pAutoFormat
->findByIndex(nFormatNo
)->GetIncludeWidthHeight();
4260 if (sal_uInt64(nEndCol
- nStartCol
+ 1) * sal_uInt64(nEndRow
- nStartRow
+ 1) > AUTOFORMAT_WARN_SIZE
)
4262 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
4263 VclMessageType::Warning
, VclButtonsType::YesNo
,
4264 ScResId(STR_AUTOFORMAT_WAIT_WARNING
)));
4265 xQueryBox
->set_default_response(RET_NO
);
4266 if (xQueryBox
->run() != RET_YES
)
4270 SCTAB nTabCount
= rDoc
.GetTableCount();
4271 ScDocumentUniquePtr pUndoDoc
;
4274 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
4275 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nStartTab
, bSize
, bSize
);
4276 for (const auto& rTab
: aMark
)
4278 if (rTab
>= nTabCount
)
4281 if (rTab
!= nStartTab
)
4282 pUndoDoc
->AddUndoTab( rTab
, rTab
, bSize
, bSize
);
4285 ScRange aCopyRange
= rRange
;
4286 aCopyRange
.aStart
.SetTab(0);
4287 aCopyRange
.aStart
.SetTab(nTabCount
-1);
4288 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, false, *pUndoDoc
, &aMark
);
4291 rDoc
.CopyToDocument( nStartCol
,0,0, nEndCol
,rDoc
.MaxRow(),nTabCount
-1,
4292 InsertDeleteFlags::NONE
, false, *pUndoDoc
, &aMark
);
4293 rDoc
.CopyToDocument( 0,nStartRow
,0, rDoc
.MaxCol(),nEndRow
,nTabCount
-1,
4294 InsertDeleteFlags::NONE
, false, *pUndoDoc
, &aMark
);
4296 rDoc
.BeginDrawUndo();
4299 rDoc
.AutoFormat( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nFormatNo
, aMark
);
4303 std::vector
<sc::ColRowSpan
> aCols(1, sc::ColRowSpan(nStartCol
,nEndCol
));
4304 std::vector
<sc::ColRowSpan
> aRows(1, sc::ColRowSpan(nStartRow
,nEndRow
));
4306 for (const auto& rTab
: aMark
)
4308 if (rTab
>= nTabCount
)
4311 SetWidthOrHeight(true, aCols
, rTab
, SC_SIZE_VISOPT
, STD_EXTRA_WIDTH
, false, true);
4312 SetWidthOrHeight(false, aRows
, rTab
, SC_SIZE_VISOPT
, 0, false, false);
4313 rDocShell
.PostPaint( 0,0,rTab
, rDoc
.MaxCol(),rDoc
.MaxRow(),rTab
,
4314 PaintPartFlags::Grid
| PaintPartFlags::Left
| PaintPartFlags::Top
);
4319 for (const auto& rTab
: aMark
)
4321 if (rTab
>= nTabCount
)
4324 bool bAdj
= AdjustRowHeight( ScRange(nStartCol
, nStartRow
, rTab
,
4325 nEndCol
, nEndRow
, rTab
), false, bApi
);
4327 rDocShell
.PostPaint( 0,nStartRow
,rTab
, rDoc
.MaxCol(),rDoc
.MaxRow(),rTab
,
4328 PaintPartFlags::Grid
| PaintPartFlags::Left
);
4330 rDocShell
.PostPaint( nStartCol
, nStartRow
, rTab
,
4331 nEndCol
, nEndRow
, rTab
, PaintPartFlags::Grid
);
4335 if ( bRecord
) // only now is Draw-Undo available
4337 rDocShell
.GetUndoManager()->AddUndoAction(
4338 std::make_unique
<ScUndoAutoFormat
>( &rDocShell
, rRange
, std::move(pUndoDoc
), aMark
, bSize
, nFormatNo
) );
4341 aModificator
.SetDocumentModified();
4344 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4349 bool ScDocFunc::EnterMatrix( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4350 const ScTokenArray
* pTokenArray
, const OUString
& rString
, bool bApi
, bool bEnglish
,
4351 const OUString
& rFormulaNmsp
, const formula::FormulaGrammar::Grammar eGrammar
)
4353 if (ScViewData::SelectionFillDOOM( rRange
))
4356 ScDocShellModificator
aModificator( rDocShell
);
4358 bool bSuccess
= false;
4359 ScDocument
& rDoc
= rDocShell
.GetDocument();
4360 SCCOL nStartCol
= rRange
.aStart
.Col();
4361 SCROW nStartRow
= rRange
.aStart
.Row();
4362 SCTAB nStartTab
= rRange
.aStart
.Tab();
4363 SCCOL nEndCol
= rRange
.aEnd
.Col();
4364 SCROW nEndRow
= rRange
.aEnd
.Row();
4365 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4367 ScMarkData
aMark(rDoc
.GetSheetLimits());
4372 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4373 aMark
.SelectTable( nTab
, true );
4376 ScEditableTester
aTester( rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4377 if ( aTester
.IsEditable() )
4379 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4381 ScDocumentUniquePtr pUndoDoc
;
4383 const bool bUndo(rDoc
.IsUndoEnabled());
4386 //! take selected sheets into account also when undoing
4387 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
4388 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nEndTab
);
4389 rDoc
.CopyToDocument( rRange
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::NOTE
, false, *pUndoDoc
);
4392 // use TokenArray if given, string (and flags) otherwise
4395 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4396 aMark
, OUString(), pTokenArray
, eGrammar
);
4398 else if ( rDoc
.IsImportingXML() )
4400 ScTokenArray
aCode(rDoc
);
4401 aCode
.AssignXMLString( rString
,
4402 ((eGrammar
== formula::FormulaGrammar::GRAM_EXTERNAL
) ? rFormulaNmsp
: OUString()));
4403 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4404 aMark
, OUString(), &aCode
, eGrammar
);
4405 rDoc
.IncXMLImportedFormulaCount( rString
.getLength() );
4409 ScCompiler
aComp( rDoc
, rRange
.aStart
, eGrammar
);
4410 std::unique_ptr
<ScTokenArray
> pCode
= aComp
.CompileString( rString
);
4411 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4412 aMark
, OUString(), pCode
.get(), eGrammar
);
4415 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4416 aMark
, rString
, nullptr, eGrammar
);
4420 //! take selected sheets into account also when undoing
4421 rDocShell
.GetUndoManager()->AddUndoAction(
4422 std::make_unique
<ScUndoEnterMatrix
>( &rDocShell
, rRange
, std::move(pUndoDoc
), rString
) );
4425 // Err522 painting of DDE-Formulas will be intercepted during interpreting
4426 rDocShell
.PostPaint( nStartCol
,nStartRow
,nStartTab
,nEndCol
,nEndRow
,nEndTab
, PaintPartFlags::Grid
);
4427 aModificator
.SetDocumentModified();
4432 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4437 bool ScDocFunc::TabOp( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4438 const ScTabOpParam
& rParam
, bool bRecord
, bool bApi
)
4440 ScDocShellModificator
aModificator( rDocShell
);
4442 bool bSuccess
= false;
4443 ScDocument
& rDoc
= rDocShell
.GetDocument();
4444 SCCOL nStartCol
= rRange
.aStart
.Col();
4445 SCROW nStartRow
= rRange
.aStart
.Row();
4446 SCTAB nStartTab
= rRange
.aStart
.Tab();
4447 SCCOL nEndCol
= rRange
.aEnd
.Col();
4448 SCROW nEndRow
= rRange
.aEnd
.Row();
4449 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4451 if (bRecord
&& !rDoc
.IsUndoEnabled())
4454 ScMarkData
aMark(rDoc
.GetSheetLimits());
4459 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4460 aMark
.SelectTable( nTab
, true );
4463 ScEditableTester
aTester( rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4464 if ( aTester
.IsEditable() )
4466 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4467 rDoc
.SetDirty( rRange
, false );
4470 //! take selected sheets into account also when undoing
4471 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
4472 pUndoDoc
->InitUndo( rDoc
, nStartTab
, nEndTab
);
4473 rDoc
.CopyToDocument( rRange
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::NOTE
, false, *pUndoDoc
);
4475 rDocShell
.GetUndoManager()->AddUndoAction(
4476 std::make_unique
<ScUndoTabOp
>( &rDocShell
,
4477 nStartCol
, nStartRow
, nStartTab
,
4478 nEndCol
, nEndRow
, nEndTab
, std::move(pUndoDoc
),
4479 rParam
.aRefFormulaCell
,
4480 rParam
.aRefFormulaEnd
,
4485 rDoc
.InsertTableOp(rParam
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, aMark
);
4486 rDocShell
.PostPaintGridAll();
4487 aModificator
.SetDocumentModified();
4491 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4496 static ScDirection
DirFromFillDir( FillDir eDir
)
4498 if (eDir
==FILL_TO_BOTTOM
)
4500 else if (eDir
==FILL_TO_RIGHT
)
4502 else if (eDir
==FILL_TO_TOP
)
4504 else // if (eDir==FILL_TO_LEFT)
4511 * Expand the fill range as necessary, to allow copying of adjacent cell(s)
4512 * even when those cells are not in the original range.
4514 void adjustFillRangeForAdjacentCopy(const ScDocument
&rDoc
, ScRange
& rRange
, FillDir eDir
)
4518 case FILL_TO_BOTTOM
:
4520 if (rRange
.aStart
.Row() == 0)
4523 if (rRange
.aStart
.Row() != rRange
.aEnd
.Row())
4526 // Include the above row.
4527 ScAddress
& s
= rRange
.aStart
;
4528 s
.SetRow(s
.Row()-1);
4533 if (rRange
.aStart
.Row() == rDoc
.MaxRow())
4536 if (rRange
.aStart
.Row() != rRange
.aEnd
.Row())
4539 // Include the row below.
4540 ScAddress
& e
= rRange
.aEnd
;
4541 e
.SetRow(e
.Row()+1);
4546 if (rRange
.aStart
.Col() == rDoc
.MaxCol())
4549 if (rRange
.aStart
.Col() != rRange
.aEnd
.Col())
4552 // Include the column to the right.
4553 ScAddress
& e
= rRange
.aEnd
;
4554 e
.SetCol(e
.Col()+1);
4559 if (rRange
.aStart
.Col() == 0)
4562 if (rRange
.aStart
.Col() != rRange
.aEnd
.Col())
4565 // Include the column to the left.
4566 ScAddress
& s
= rRange
.aStart
;
4567 s
.SetCol(s
.Col()-1);
4577 bool ScDocFunc::FillSimple( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4578 FillDir eDir
, bool bApi
)
4580 ScDocShellModificator
aModificator( rDocShell
);
4581 ScDocument
& rDoc
= rDocShell
.GetDocument();
4583 bool bSuccess
= false;
4584 ScRange aRange
= rRange
;
4585 adjustFillRangeForAdjacentCopy(rDoc
, aRange
, eDir
);
4587 SCCOL nStartCol
= aRange
.aStart
.Col();
4588 SCROW nStartRow
= aRange
.aStart
.Row();
4589 SCTAB nStartTab
= aRange
.aStart
.Tab();
4590 SCCOL nEndCol
= aRange
.aEnd
.Col();
4591 SCROW nEndRow
= aRange
.aEnd
.Row();
4592 SCTAB nEndTab
= aRange
.aEnd
.Tab();
4594 bool bRecord
= true;
4595 if (!rDoc
.IsUndoEnabled())
4598 ScMarkData
aMark(rDoc
.GetSheetLimits());
4603 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4604 aMark
.SelectTable( nTab
, true );
4607 ScEditableTester
aTester( rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4608 if ( aTester
.IsEditable() )
4610 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4612 ScRange aSourceArea
= aRange
;
4613 ScRange aDestArea
= aRange
;
4615 SCCOLROW nCount
= 0;
4618 case FILL_TO_BOTTOM
:
4619 nCount
= aSourceArea
.aEnd
.Row()-aSourceArea
.aStart
.Row();
4620 aSourceArea
.aEnd
.SetRow( aSourceArea
.aStart
.Row() );
4623 nCount
= aSourceArea
.aEnd
.Col()-aSourceArea
.aStart
.Col();
4624 aSourceArea
.aEnd
.SetCol( aSourceArea
.aStart
.Col() );
4627 nCount
= aSourceArea
.aEnd
.Row()-aSourceArea
.aStart
.Row();
4628 aSourceArea
.aStart
.SetRow( aSourceArea
.aEnd
.Row() );
4631 nCount
= aSourceArea
.aEnd
.Col()-aSourceArea
.aStart
.Col();
4632 aSourceArea
.aStart
.SetCol( aSourceArea
.aEnd
.Col() );
4636 ScDocumentUniquePtr pUndoDoc
;
4639 SCTAB nTabCount
= rDoc
.GetTableCount();
4640 SCTAB nDestStartTab
= aDestArea
.aStart
.Tab();
4642 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
4643 pUndoDoc
->InitUndo( rDoc
, nDestStartTab
, nDestStartTab
);
4644 for (const auto& rTab
: aMark
)
4646 if (rTab
>= nTabCount
)
4649 if (rTab
!= nDestStartTab
)
4650 pUndoDoc
->AddUndoTab( rTab
, rTab
);
4653 ScRange aCopyRange
= aDestArea
;
4654 aCopyRange
.aStart
.SetTab(0);
4655 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
4656 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::AUTOFILL
, false, *pUndoDoc
, &aMark
);
4659 sal_uLong nProgCount
;
4660 if (eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
)
4661 nProgCount
= aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1;
4663 nProgCount
= aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1;
4664 nProgCount
*= nCount
;
4665 ScProgress
aProgress( rDoc
.GetDocumentShell(),
4666 ScResId(STR_FILL_SERIES_PROGRESS
), nProgCount
, true );
4668 rDoc
.Fill( aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(),
4669 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), &aProgress
,
4670 aMark
, nCount
, eDir
, FILL_SIMPLE
);
4671 AdjustRowHeight(aRange
, true, bApi
);
4673 if ( bRecord
) // only now is Draw-Undo available
4675 rDocShell
.GetUndoManager()->AddUndoAction(
4676 std::make_unique
<ScUndoAutoFill
>( &rDocShell
, aDestArea
, aSourceArea
, std::move(pUndoDoc
), aMark
,
4677 eDir
, FILL_SIMPLE
, FILL_DAY
, MAXDOUBLE
, 1.0, 1e307
) );
4680 rDocShell
.PostPaintGridAll();
4681 aModificator
.SetDocumentModified();
4686 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4691 bool ScDocFunc::FillSeries( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4692 FillDir eDir
, FillCmd eCmd
, FillDateCmd eDateCmd
,
4693 double fStart
, double fStep
, double fMax
,
4696 ScDocShellModificator
aModificator( rDocShell
);
4698 bool bSuccess
= false;
4699 ScDocument
& rDoc
= rDocShell
.GetDocument();
4700 SCCOL nStartCol
= rRange
.aStart
.Col();
4701 SCROW nStartRow
= rRange
.aStart
.Row();
4702 SCTAB nStartTab
= rRange
.aStart
.Tab();
4703 SCCOL nEndCol
= rRange
.aEnd
.Col();
4704 SCROW nEndRow
= rRange
.aEnd
.Row();
4705 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4707 bool bRecord
= true;
4708 if (!rDoc
.IsUndoEnabled())
4711 ScMarkData
aMark(rDoc
.GetSheetLimits());
4716 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4717 aMark
.SelectTable( nTab
, true );
4720 ScEditableTester
aTester( rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4721 if ( aTester
.IsEditable() )
4723 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4725 ScRange aSourceArea
= rRange
;
4726 ScRange aDestArea
= rRange
;
4728 SCSIZE nCount
= rDoc
.GetEmptyLinesInBlock(
4729 aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(), aSourceArea
.aStart
.Tab(),
4730 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), aSourceArea
.aEnd
.Tab(),
4731 DirFromFillDir(eDir
) );
4733 // keep at least one row/column as source range
4734 SCSIZE nTotLines
= ( eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
) ?
4735 static_cast<SCSIZE
>( aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1 ) :
4736 static_cast<SCSIZE
>( aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1 );
4737 if ( nCount
>= nTotLines
)
4739 assert(nTotLines
> 0 && "coverity 2023.12.2");
4740 nCount
= nTotLines
- 1;
4745 case FILL_TO_BOTTOM
:
4746 aSourceArea
.aEnd
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aEnd
.Row() - nCount
) );
4749 aSourceArea
.aEnd
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aEnd
.Col() - nCount
) );
4752 aSourceArea
.aStart
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aStart
.Row() + nCount
) );
4755 aSourceArea
.aStart
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aStart
.Col() + nCount
) );
4759 ScDocumentUniquePtr pUndoDoc
;
4762 SCTAB nTabCount
= rDoc
.GetTableCount();
4763 SCTAB nDestStartTab
= aDestArea
.aStart
.Tab();
4765 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
4766 pUndoDoc
->InitUndo( rDoc
, nDestStartTab
, nDestStartTab
);
4767 for (const auto& rTab
: aMark
)
4769 if (rTab
>= nTabCount
)
4772 if (rTab
!= nDestStartTab
)
4773 pUndoDoc
->AddUndoTab( rTab
, rTab
);
4776 rDoc
.CopyToDocument(
4777 aDestArea
.aStart
.Col(), aDestArea
.aStart
.Row(), 0,
4778 aDestArea
.aEnd
.Col(), aDestArea
.aEnd
.Row(), nTabCount
-1,
4779 InsertDeleteFlags::AUTOFILL
, false, *pUndoDoc
, &aMark
);
4782 if (aDestArea
.aStart
.Col() <= aDestArea
.aEnd
.Col() &&
4783 aDestArea
.aStart
.Row() <= aDestArea
.aEnd
.Row())
4785 if ( fStart
!= MAXDOUBLE
)
4787 SCCOL nValX
= (eDir
== FILL_TO_LEFT
) ? aDestArea
.aEnd
.Col() : aDestArea
.aStart
.Col();
4788 SCROW nValY
= (eDir
== FILL_TO_TOP
) ? aDestArea
.aEnd
.Row() : aDestArea
.aStart
.Row();
4789 SCTAB nTab
= aDestArea
.aStart
.Tab();
4790 rDoc
.SetValue( nValX
, nValY
, nTab
, fStart
);
4793 sal_uLong nProgCount
;
4794 if (eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
)
4795 nProgCount
= aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1;
4797 nProgCount
= aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1;
4798 nProgCount
*= nCount
;
4799 ScProgress
aProgress( rDoc
.GetDocumentShell(),
4800 ScResId(STR_FILL_SERIES_PROGRESS
), nProgCount
, true );
4802 rDoc
.Fill( aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(),
4803 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), &aProgress
,
4804 aMark
, nCount
, eDir
, eCmd
, eDateCmd
, fStep
, fMax
);
4805 AdjustRowHeight(rRange
, true, bApi
);
4807 rDocShell
.PostPaintGridAll();
4808 aModificator
.SetDocumentModified();
4811 if ( bRecord
) // only now is Draw-Undo available
4813 rDocShell
.GetUndoManager()->AddUndoAction(
4814 std::make_unique
<ScUndoAutoFill
>( &rDocShell
, aDestArea
, aSourceArea
, std::move(pUndoDoc
), aMark
,
4815 eDir
, eCmd
, eDateCmd
, fStart
, fStep
, fMax
) );
4821 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4826 bool ScDocFunc::FillAuto( ScRange
& rRange
, const ScMarkData
* pTabMark
,
4827 FillDir eDir
, sal_uLong nCount
, bool bApi
)
4829 return FillAuto( rRange
, pTabMark
, eDir
, FILL_AUTO
, FILL_DAY
, nCount
, 1.0/*fStep*/, MAXDOUBLE
/*fMax*/, true/*bRecord*/, bApi
);
4832 bool ScDocFunc::FillAuto( ScRange
& rRange
, const ScMarkData
* pTabMark
, FillDir eDir
, FillCmd eCmd
, FillDateCmd eDateCmd
, sal_uLong nCount
, double fStep
, double fMax
, bool bRecord
, bool bApi
)
4834 ScDocShellModificator
aModificator( rDocShell
);
4836 ScDocument
& rDoc
= rDocShell
.GetDocument();
4837 SCCOL nStartCol
= rRange
.aStart
.Col();
4838 SCROW nStartRow
= rRange
.aStart
.Row();
4839 SCTAB nStartTab
= rRange
.aStart
.Tab();
4840 SCCOL nEndCol
= rRange
.aEnd
.Col();
4841 SCROW nEndRow
= rRange
.aEnd
.Row();
4842 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4844 if (bRecord
&& !rDoc
.IsUndoEnabled())
4847 ScMarkData
aMark(rDoc
.GetSheetLimits());
4852 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4853 aMark
.SelectTable( nTab
, true );
4856 ScRange aSourceArea
= rRange
;
4857 ScRange aDestArea
= rRange
;
4861 case FILL_TO_BOTTOM
:
4862 aDestArea
.aEnd
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aEnd
.Row() + nCount
) );
4865 if (nCount
> sal::static_int_cast
<sal_uLong
>( aSourceArea
.aStart
.Row() ))
4867 OSL_FAIL("FillAuto: Row < 0");
4868 nCount
= aSourceArea
.aStart
.Row();
4870 aDestArea
.aStart
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aStart
.Row() - nCount
) );
4873 aDestArea
.aEnd
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aEnd
.Col() + nCount
) );
4876 if (nCount
> sal::static_int_cast
<sal_uLong
>( aSourceArea
.aStart
.Col() ))
4878 OSL_FAIL("FillAuto: Col < 0");
4879 nCount
= aSourceArea
.aStart
.Col();
4881 aDestArea
.aStart
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aStart
.Col() - nCount
) );
4884 OSL_FAIL("Wrong direction with FillAuto");
4888 // Test for cell protection
4889 //! Source range can be protected !!!
4890 //! but can't contain matrix fragments !!!
4892 ScEditableTester
aTester( rDoc
, aDestArea
, sc::EditAction::Unknown
);
4893 if ( !aTester
.IsEditable() )
4896 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4900 if ( rDoc
.HasSelectedBlockMatrixFragment( nStartCol
, nStartRow
,
4901 nEndCol
, nEndRow
, aMark
) )
4904 rDocShell
.ErrorMessage(STR_MATRIXFRAGMENTERR
);
4908 // FID_FILL_... slots should already had been disabled, check here for API
4909 // calls, no message.
4910 if (ScViewData::SelectionFillDOOM( aDestArea
))
4913 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4915 ScDocumentUniquePtr pUndoDoc
;
4918 SCTAB nTabCount
= rDoc
.GetTableCount();
4919 SCTAB nDestStartTab
= aDestArea
.aStart
.Tab();
4921 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
4922 pUndoDoc
->InitUndo( rDoc
, nDestStartTab
, nDestStartTab
);
4923 for (const auto& rTab
: aMark
)
4925 if (rTab
>= nTabCount
)
4928 if (rTab
!= nDestStartTab
)
4929 pUndoDoc
->AddUndoTab( rTab
, rTab
);
4932 // do not clone note captions in undo document
4933 rDoc
.CopyToDocument(
4934 aDestArea
.aStart
.Col(), aDestArea
.aStart
.Row(), 0,
4935 aDestArea
.aEnd
.Col(), aDestArea
.aEnd
.Row(), nTabCount
-1,
4936 InsertDeleteFlags::AUTOFILL
, false, *pUndoDoc
, &aMark
);
4939 sal_uLong nProgCount
;
4940 if (eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
)
4941 nProgCount
= aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1;
4943 nProgCount
= aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1;
4944 nProgCount
*= nCount
;
4945 ScProgress
aProgress( rDoc
.GetDocumentShell(),
4946 ScResId(STR_FILL_SERIES_PROGRESS
), nProgCount
, true );
4948 rDoc
.Fill( aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(),
4949 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), &aProgress
,
4950 aMark
, nCount
, eDir
, eCmd
, eDateCmd
, fStep
, fMax
);
4952 AdjustRowHeight(aDestArea
, true, bApi
);
4954 if ( bRecord
) // only now is Draw-Undo available
4956 rDocShell
.GetUndoManager()->AddUndoAction(
4957 std::make_unique
<ScUndoAutoFill
>( &rDocShell
, aDestArea
, aSourceArea
, std::move(pUndoDoc
), aMark
,
4958 eDir
, eCmd
, eDateCmd
, MAXDOUBLE
, fStep
, fMax
) );
4961 rDocShell
.PostPaintGridAll();
4962 aModificator
.SetDocumentModified();
4964 rRange
= aDestArea
; // return destination range (for marking)
4968 bool ScDocFunc::MergeCells( const ScCellMergeOption
& rOption
, bool bContents
, bool bRecord
, bool bApi
, bool bEmptyMergedCells
/*=false*/ )
4972 ScDocShellModificator
aModificator( rDocShell
);
4974 SCCOL nStartCol
= rOption
.mnStartCol
;
4975 SCROW nStartRow
= rOption
.mnStartRow
;
4976 SCCOL nEndCol
= rOption
.mnEndCol
;
4977 SCROW nEndRow
= rOption
.mnEndRow
;
4978 if ((nStartCol
== nEndCol
&& nStartRow
== nEndRow
) || rOption
.maTabs
.empty())
4980 // Nothing to do. Bail out quickly
4984 ScDocument
& rDoc
= rDocShell
.GetDocument();
4985 SCTAB nTab1
= *rOption
.maTabs
.begin(), nTab2
= *rOption
.maTabs
.rbegin();
4987 if (bRecord
&& !rDoc
.IsUndoEnabled())
4990 for (const auto& rTab
: rOption
.maTabs
)
4992 ScEditableTester
aTester( rDoc
, rTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
);
4993 if (!aTester
.IsEditable())
4996 rDocShell
.ErrorMessage(aTester
.GetMessageId());
5000 if ( rDoc
.HasAttrib( nStartCol
, nStartRow
, rTab
, nEndCol
, nEndRow
, rTab
,
5001 HasAttrFlags::Merged
| HasAttrFlags::Overlapped
) )
5003 // "Merge of already merged cells not possible"
5005 rDocShell
.ErrorMessage(STR_MSSG_MERGECELLS_0
);
5010 ScDocumentUniquePtr pUndoDoc
;
5011 bool bNeedContentsUndo
= false;
5012 for (const SCTAB nTab
: rOption
.maTabs
)
5014 bool bIsBlockEmpty
= ( nStartRow
== nEndRow
)
5015 ? rDoc
.IsEmptyData( nStartCol
+1,nStartRow
, nEndCol
,nEndRow
, nTab
)
5016 : rDoc
.IsEmptyData( nStartCol
,nStartRow
+1, nStartCol
,nEndRow
, nTab
) &&
5017 rDoc
.IsEmptyData( nStartCol
+1,nStartRow
, nEndCol
,nEndRow
, nTab
);
5018 bool bNeedContents
= bContents
&& !bIsBlockEmpty
;
5019 bool bNeedEmpty
= bEmptyMergedCells
&& !bIsBlockEmpty
&& !bNeedContents
; // if DoMergeContents then cells are emptied
5023 // test if the range contains other notes which also implies that we need an undo document
5024 bool bHasNotes
= rDoc
.HasNote(nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
);
5027 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
5028 pUndoDoc
->InitUndo(rDoc
, nTab1
, nTab2
);
5030 // note captions are collected by drawing undo
5031 rDoc
.CopyToDocument( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
,
5032 InsertDeleteFlags::ALL
|InsertDeleteFlags::NOCAPTIONS
, false, *pUndoDoc
);
5034 rDoc
.BeginDrawUndo();
5038 rDoc
.DoMergeContents( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nTab
);
5039 else if ( bNeedEmpty
)
5040 rDoc
.DoEmptyBlock( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nTab
);
5041 rDoc
.DoMerge( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nTab
);
5043 if (rOption
.mbCenter
)
5045 rDoc
.ApplyAttr( nStartCol
, nStartRow
, nTab
, SvxHorJustifyItem( SvxCellHorJustify::Center
, ATTR_HOR_JUSTIFY
) );
5046 rDoc
.ApplyAttr( nStartCol
, nStartRow
, nTab
, SvxVerJustifyItem( SvxCellVerJustify::Center
, ATTR_VER_JUSTIFY
) );
5049 if ( !AdjustRowHeight( ScRange( 0,nStartRow
,nTab
, rDoc
.MaxCol(),nEndRow
,nTab
), true, bApi
) )
5050 rDocShell
.PostPaint( nStartCol
, nStartRow
, nTab
,
5051 nEndCol
, nEndRow
, nTab
, PaintPartFlags::Grid
);
5052 if (bNeedContents
|| rOption
.mbCenter
)
5054 ScRange
aRange(nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
5055 rDoc
.SetDirty(aRange
, true);
5058 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).DeleteAll( ScDetectiveDelete::Circles
);
5060 DetectiveMarkInvalid(nTab
);
5062 bNeedContentsUndo
|= bNeedContents
;
5067 std::unique_ptr
<SdrUndoGroup
> pDrawUndo
= rDoc
.GetDrawLayer() ? rDoc
.GetDrawLayer()->GetCalcUndo() : nullptr;
5068 rDocShell
.GetUndoManager()->AddUndoAction(
5069 std::make_unique
<ScUndoMerge
>(&rDocShell
, rOption
, bNeedContentsUndo
, std::move(pUndoDoc
), std::move(pDrawUndo
)) );
5072 aModificator
.SetDocumentModified();
5074 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
5077 pBindings
->Invalidate( FID_MERGE_ON
);
5078 pBindings
->Invalidate( FID_MERGE_OFF
);
5079 pBindings
->Invalidate( FID_MERGE_TOGGLE
);
5085 bool ScDocFunc::UnmergeCells( const ScRange
& rRange
, bool bRecord
, ScUndoRemoveMerge
* pUndoRemoveMerge
)
5087 ScCellMergeOption
aOption(rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row());
5088 SCTAB nTab1
= rRange
.aStart
.Tab(), nTab2
= rRange
.aEnd
.Tab();
5089 for (SCTAB i
= nTab1
; i
<= nTab2
; ++i
)
5090 aOption
.maTabs
.insert(i
);
5092 return UnmergeCells(aOption
, bRecord
, pUndoRemoveMerge
);
5095 bool ScDocFunc::UnmergeCells( const ScCellMergeOption
& rOption
, bool bRecord
, ScUndoRemoveMerge
* pUndoRemoveMerge
)
5099 if (rOption
.maTabs
.empty())
5100 // Nothing to unmerge.
5103 ScDocShellModificator
aModificator( rDocShell
);
5104 ScDocument
& rDoc
= rDocShell
.GetDocument();
5106 if (bRecord
&& !rDoc
.IsUndoEnabled())
5109 ScDocument
* pUndoDoc
= (pUndoRemoveMerge
? pUndoRemoveMerge
->GetUndoDoc() : nullptr);
5110 assert( pUndoDoc
|| !pUndoRemoveMerge
);
5111 for (const SCTAB nTab
: rOption
.maTabs
)
5113 ScRange aRange
= rOption
.getSingleRange(nTab
);
5114 if ( !rDoc
.HasAttrib(aRange
, HasAttrFlags::Merged
) )
5117 ScRange aExtended
= aRange
;
5118 rDoc
.ExtendMerge(aExtended
);
5119 ScRange aRefresh
= aExtended
;
5120 rDoc
.ExtendOverlapped(aRefresh
);
5126 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
5127 pUndoDoc
->InitUndo(rDoc
, *rOption
.maTabs
.begin(), *rOption
.maTabs
.rbegin());
5129 rDoc
.CopyToDocument(aExtended
, InsertDeleteFlags::ATTRIB
, false, *pUndoDoc
);
5132 const SfxPoolItem
& rDefAttr
= rDoc
.GetPool()->GetUserOrPoolDefaultItem( ATTR_MERGE
);
5133 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
5134 aPattern
.GetItemSet().Put( rDefAttr
);
5135 rDoc
.ApplyPatternAreaTab( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
5136 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), nTab
,
5139 rDoc
.RemoveFlagsTab( aExtended
.aStart
.Col(), aExtended
.aStart
.Row(),
5140 aExtended
.aEnd
.Col(), aExtended
.aEnd
.Row(), nTab
,
5141 ScMF::Hor
| ScMF::Ver
);
5143 rDoc
.ExtendMerge( aRefresh
, true );
5145 if ( !AdjustRowHeight( aExtended
, true, true ) )
5146 rDocShell
.PostPaint( aExtended
, PaintPartFlags::Grid
);
5148 bool bDone
= ScDetectiveFunc(rDoc
, nTab
).DeleteAll( ScDetectiveDelete::Circles
);
5150 DetectiveMarkInvalid(nTab
);
5155 if (pUndoRemoveMerge
)
5157 // If pUndoRemoveMerge was passed, the caller is responsible for
5158 // adding it to Undo. Just add the current option.
5159 pUndoRemoveMerge
->AddCellMergeOption( rOption
);
5163 rDocShell
.GetUndoManager()->AddUndoAction(
5164 std::make_unique
<ScUndoRemoveMerge
>( &rDocShell
, rOption
, ScDocumentUniquePtr(pUndoDoc
) ) );
5167 aModificator
.SetDocumentModified();
5172 void ScDocFunc::ModifyRangeNames( const ScRangeName
& rNewRanges
, SCTAB nTab
)
5174 SetNewRangeNames( std::unique_ptr
<ScRangeName
>(new ScRangeName(rNewRanges
)), true, nTab
);
5177 void ScDocFunc::SetNewRangeNames( std::unique_ptr
<ScRangeName
> pNewRanges
, bool bModifyDoc
, SCTAB nTab
) // takes ownership of pNewRanges
5179 ScDocShellModificator
aModificator( rDocShell
);
5181 OSL_ENSURE( pNewRanges
, "pNewRanges is 0" );
5182 ScDocument
& rDoc
= rDocShell
.GetDocument();
5183 bool bUndo(rDoc
.IsUndoEnabled());
5190 pOld
= rDoc
.GetRangeName(nTab
);
5194 pOld
= rDoc
.GetRangeName();
5196 std::unique_ptr
<ScRangeName
> pUndoRanges(new ScRangeName(*pOld
));
5197 std::unique_ptr
<ScRangeName
> pRedoRanges(new ScRangeName(*pNewRanges
));
5198 rDocShell
.GetUndoManager()->AddUndoAction(
5199 std::make_unique
<ScUndoRangeNames
>( &rDocShell
, std::move(pUndoRanges
), std::move(pRedoRanges
), nTab
) );
5202 // #i55926# While loading XML, formula cells only have a single string token,
5203 // so CompileNameFormula would never find any name (index) tokens, and would
5204 // unnecessarily loop through all cells.
5205 bool bCompile
= ( !rDoc
.IsImportingXML() && rDoc
.GetNamedRangesLockCount() == 0 );
5208 rDoc
.PreprocessRangeNameUpdate();
5210 rDoc
.SetRangeName( nTab
, std::move(pNewRanges
) ); // takes ownership
5212 rDoc
.SetRangeName( std::move(pNewRanges
) ); // takes ownership
5214 rDoc
.CompileHybridFormula();
5218 aModificator
.SetDocumentModified();
5219 SfxGetpApp()->Broadcast( SfxHint(SfxHintId::ScAreasChanged
) );
5223 void ScDocFunc::ModifyAllRangeNames(const std::map
<OUString
, ScRangeName
>& rRangeMap
)
5225 ScDocShellModificator
aModificator(rDocShell
);
5226 ScDocument
& rDoc
= rDocShell
.GetDocument();
5228 if (rDoc
.IsUndoEnabled())
5230 std::map
<OUString
, ScRangeName
*> aOldRangeMap
;
5231 rDoc
.GetRangeNameMap(aOldRangeMap
);
5232 rDocShell
.GetUndoManager()->AddUndoAction(
5233 std::make_unique
<ScUndoAllRangeNames
>(&rDocShell
, aOldRangeMap
, rRangeMap
));
5236 rDoc
.PreprocessAllRangeNamesUpdate(rRangeMap
);
5237 rDoc
.SetAllRangeNames(rRangeMap
);
5238 rDoc
.CompileHybridFormula();
5240 aModificator
.SetDocumentModified();
5241 SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreasChanged
));
5244 void ScDocFunc::CreateOneName( ScRangeName
& rList
,
5245 SCCOL nPosX
, SCROW nPosY
, SCTAB nTab
,
5246 SCCOL nX1
, SCROW nY1
, SCCOL nX2
, SCROW nY2
,
5247 bool& rCancel
, bool bApi
)
5252 ScDocument
& rDoc
= rDocShell
.GetDocument();
5253 if (rDoc
.HasValueData( nPosX
, nPosY
, nTab
))
5256 OUString aName
= rDoc
.GetString(nPosX
, nPosY
, nTab
);
5257 ScRangeData::MakeValidName(rDoc
, aName
);
5258 if (aName
.isEmpty())
5261 OUString
aContent( ScRange( nX1
, nY1
, nTab
, nX2
, nY2
, nTab
).Format(
5262 rDoc
, ScRefFlags::RANGE_ABS_3D
, ScAddress::Details( rDoc
.GetAddressConvention(), nPosY
, nPosX
)));
5264 bool bInsert
= false;
5265 ScRangeData
* pOld
= rList
.findByUpperName(ScGlobal::getCharClass().uppercase(aName
));
5268 OUString aOldStr
= pOld
->GetSymbol();
5269 if (aOldStr
!= aContent
)
5272 bInsert
= true; // don't check via API
5275 OUString aTemplate
= ScResId( STR_CREATENAME_REPLACE
);
5276 OUString aMessage
= o3tl::getToken(aTemplate
, 0, '#' ) + aName
+ o3tl::getToken(aTemplate
, 1, '#' );
5278 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
5279 VclMessageType::Question
, VclButtonsType::YesNo
,
5281 xQueryBox
->add_button(GetStandardText(StandardButtonType::Cancel
), RET_CANCEL
);
5282 xQueryBox
->set_default_response(RET_YES
);
5284 short nResult
= xQueryBox
->run();
5285 if ( nResult
== RET_YES
)
5290 else if ( nResult
== RET_CANCEL
)
5300 ScRangeData
* pData
= new ScRangeData( rDoc
, aName
, aContent
,
5301 ScAddress( nPosX
, nPosY
, nTab
));
5302 if (!rList
.insert(pData
))
5309 bool ScDocFunc::CreateNames( const ScRange
& rRange
, CreateNameFlags nFlags
, bool bApi
, SCTAB aTab
)
5311 if (nFlags
== CreateNameFlags::NONE
)
5312 return false; // was nothing
5314 ScDocShellModificator
aModificator( rDocShell
);
5317 SCCOL nStartCol
= rRange
.aStart
.Col();
5318 SCROW nStartRow
= rRange
.aStart
.Row();
5319 SCCOL nEndCol
= rRange
.aEnd
.Col();
5320 SCROW nEndRow
= rRange
.aEnd
.Row();
5321 SCTAB nTab
= rRange
.aStart
.Tab();
5322 OSL_ENSURE(rRange
.aEnd
.Tab() == nTab
, "CreateNames: multiple tables not possible");
5325 if ( nFlags
& ( CreateNameFlags::Top
| CreateNameFlags::Bottom
) )
5326 if ( nStartRow
== nEndRow
)
5328 if ( nFlags
& ( CreateNameFlags::Left
| CreateNameFlags::Right
) )
5329 if ( nStartCol
== nEndCol
)
5334 ScDocument
& rDoc
= rDocShell
.GetDocument();
5335 ScRangeName
* pNames
;
5337 pNames
= rDoc
.GetRangeName(nTab
);
5339 pNames
= rDoc
.GetRangeName();
5342 return false; // shouldn't happen
5343 ScRangeName
aNewRanges( *pNames
);
5345 bool bTop ( nFlags
& CreateNameFlags::Top
);
5346 bool bLeft ( nFlags
& CreateNameFlags::Left
);
5347 bool bBottom( nFlags
& CreateNameFlags::Bottom
);
5348 bool bRight ( nFlags
& CreateNameFlags::Right
);
5350 SCCOL nContX1
= nStartCol
;
5351 SCROW nContY1
= nStartRow
;
5352 SCCOL nContX2
= nEndCol
;
5353 SCROW nContY2
= nEndRow
;
5364 bool bCancel
= false;
5369 for (i
=nContX1
; i
<=nContX2
; i
++)
5370 CreateOneName( aNewRanges
, i
,nStartRow
,nTab
, i
,nContY1
,i
,nContY2
, bCancel
, bApi
);
5372 for (j
=nContY1
; j
<=nContY2
; j
++)
5373 CreateOneName( aNewRanges
, nStartCol
,j
,nTab
, nContX1
,j
,nContX2
,j
, bCancel
, bApi
);
5375 for (i
=nContX1
; i
<=nContX2
; i
++)
5376 CreateOneName( aNewRanges
, i
,nEndRow
,nTab
, i
,nContY1
,i
,nContY2
, bCancel
, bApi
);
5378 for (j
=nContY1
; j
<=nContY2
; j
++)
5379 CreateOneName( aNewRanges
, nEndCol
,j
,nTab
, nContX1
,j
,nContX2
,j
, bCancel
, bApi
);
5381 if ( bTop
&& bLeft
)
5382 CreateOneName( aNewRanges
, nStartCol
,nStartRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5383 if ( bTop
&& bRight
)
5384 CreateOneName( aNewRanges
, nEndCol
,nStartRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5385 if ( bBottom
&& bLeft
)
5386 CreateOneName( aNewRanges
, nStartCol
,nEndRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5387 if ( bBottom
&& bRight
)
5388 CreateOneName( aNewRanges
, nEndCol
,nEndRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5390 ModifyRangeNames( aNewRanges
, aTab
);
5398 bool ScDocFunc::InsertNameList( const ScAddress
& rStartPos
, bool bApi
)
5400 ScDocShellModificator
aModificator( rDocShell
);
5403 ScDocument
& rDoc
= rDocShell
.GetDocument();
5404 const bool bRecord
= rDoc
.IsUndoEnabled();
5405 SCTAB nTab
= rStartPos
.Tab();
5407 //local names have higher priority than global names
5408 ScRangeName
* pLocalList
= rDoc
.GetRangeName(nTab
);
5409 sal_uInt16 nValidCount
= 0;
5410 for (const auto& rEntry
: *pLocalList
)
5412 const ScRangeData
& r
= *rEntry
.second
;
5413 if (!r
.HasType(ScRangeData::Type::Database
))
5416 ScRangeName
* pList
= rDoc
.GetRangeName();
5417 for (const auto& rEntry
: *pList
)
5419 const ScRangeData
& r
= *rEntry
.second
;
5420 if (!r
.HasType(ScRangeData::Type::Database
) && !pLocalList
->findByUpperName(r
.GetUpperName()))
5426 SCCOL nStartCol
= rStartPos
.Col();
5427 SCROW nStartRow
= rStartPos
.Row();
5428 SCCOL nEndCol
= nStartCol
+ 1;
5429 SCROW nEndRow
= nStartRow
+ static_cast<SCROW
>(nValidCount
) - 1;
5431 ScEditableTester
aTester( rDoc
, nTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
);
5432 if (aTester
.IsEditable())
5434 ScDocumentUniquePtr pUndoDoc
;
5438 pUndoDoc
.reset(new ScDocument( SCDOCMODE_UNDO
));
5439 pUndoDoc
->InitUndo( rDoc
, nTab
, nTab
);
5440 rDoc
.CopyToDocument(nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
,
5441 InsertDeleteFlags::ALL
, false, *pUndoDoc
);
5443 rDoc
.BeginDrawUndo(); // because of adjusting heights
5446 std::unique_ptr
<ScRangeData
*[]> ppSortArray(new ScRangeData
* [ nValidCount
]);
5448 for (const auto& rEntry
: *pLocalList
)
5450 ScRangeData
& r
= *rEntry
.second
;
5451 if (!r
.HasType(ScRangeData::Type::Database
))
5452 ppSortArray
[j
++] = &r
;
5454 for (const auto& [rName
, rxData
] : *pList
)
5456 ScRangeData
& r
= *rxData
;
5457 if (!r
.HasType(ScRangeData::Type::Database
) && !pLocalList
->findByUpperName(rName
))
5458 ppSortArray
[j
++] = &r
;
5460 qsort( static_cast<void*>(ppSortArray
.get()), nValidCount
, sizeof(ScRangeData
*),
5461 &ScRangeData_QsortNameCompare
);
5463 OUStringBuffer aContent
;
5465 SCROW nOutRow
= nStartRow
;
5466 for (j
=0; j
<nValidCount
; j
++)
5468 ScRangeData
* pData
= ppSortArray
[j
];
5469 pData
->GetName(aName
);
5470 // adjust relative references to the left column in Excel-compliant way:
5471 pData
->UpdateSymbol(aContent
, ScAddress( nStartCol
, nOutRow
, nTab
));
5472 aFormula
= "=" + aContent
;
5473 ScSetStringParam aParam
;
5474 aParam
.setTextInput();
5475 rDoc
.SetString(ScAddress(nStartCol
,nOutRow
,nTab
), aName
, &aParam
);
5476 rDoc
.SetString(ScAddress(nEndCol
,nOutRow
,nTab
), aFormula
, &aParam
);
5480 ppSortArray
.reset();
5484 ScDocumentUniquePtr
pRedoDoc(new ScDocument( SCDOCMODE_UNDO
));
5485 pRedoDoc
->InitUndo( rDoc
, nTab
, nTab
);
5486 rDoc
.CopyToDocument(nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
,
5487 InsertDeleteFlags::ALL
, false, *pRedoDoc
);
5489 rDocShell
.GetUndoManager()->AddUndoAction(
5490 std::make_unique
<ScUndoListNames
>( &rDocShell
,
5491 ScRange( nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
),
5492 std::move(pUndoDoc
), std::move(pRedoDoc
) ) );
5495 if (!AdjustRowHeight(ScRange(0,nStartRow
,nTab
,rDoc
.MaxCol(),nEndRow
,nTab
), true, true))
5496 rDocShell
.PostPaint( nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
, PaintPartFlags::Grid
);
5498 aModificator
.SetDocumentModified();
5502 rDocShell
.ErrorMessage(aTester
.GetMessageId());
5507 void ScDocFunc::ResizeMatrix( const ScRange
& rOldRange
, const ScAddress
& rNewEnd
)
5509 ScDocument
& rDoc
= rDocShell
.GetDocument();
5510 SCCOL nStartCol
= rOldRange
.aStart
.Col();
5511 SCROW nStartRow
= rOldRange
.aStart
.Row();
5512 SCTAB nTab
= rOldRange
.aStart
.Tab();
5514 OUString aFormula
= rDoc
.GetFormula( nStartCol
, nStartRow
, nTab
);
5515 if ( !(aFormula
.startsWith("{") && aFormula
.endsWith("}")) )
5518 OUString aUndo
= ScResId( STR_UNDO_RESIZEMATRIX
);
5519 bool bUndo(rDoc
.IsUndoEnabled());
5522 ViewShellId
nViewShellId(1);
5523 if (ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell())
5524 nViewShellId
= pViewSh
->GetViewShellId();
5525 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, nViewShellId
);
5528 aFormula
= aFormula
.copy(1, aFormula
.getLength()-2);
5530 ScMarkData
aMark(rDoc
.GetSheetLimits());
5531 aMark
.SetMarkArea( rOldRange
);
5532 aMark
.SelectTable( nTab
, true );
5533 ScRange
aNewRange( rOldRange
.aStart
, rNewEnd
);
5535 if ( DeleteContents( aMark
, InsertDeleteFlags::CONTENTS
, true, false/*bApi*/ ) )
5537 // Formula string was obtained in document grammar.
5538 if (!EnterMatrix( aNewRange
, &aMark
, nullptr, aFormula
, false/*bApi*/, false, OUString(), rDoc
.GetGrammar() ))
5540 // try to restore the previous state
5541 EnterMatrix( rOldRange
, &aMark
, nullptr, aFormula
, false/*bApi*/, false, OUString(), rDoc
.GetGrammar() );
5546 rDocShell
.GetUndoManager()->LeaveListAction();
5549 void ScDocFunc::InsertAreaLink( const OUString
& rFile
, const OUString
& rFilter
,
5550 const OUString
& rOptions
, const OUString
& rSource
,
5551 const ScRange
& rDestRange
, sal_Int32 nRefreshDelaySeconds
,
5552 bool bFitBlock
, bool bApi
)
5554 ScDocument
& rDoc
= rDocShell
.GetDocument();
5555 bool bUndo (rDoc
.IsUndoEnabled());
5557 sfx2::LinkManager
* pLinkManager
= rDoc
.GetLinkManager();
5559 // #i52120# if other area links exist at the same start position,
5560 // remove them first (file format specifies only one link definition
5563 sal_uInt16 nLinkCount
= pLinkManager
->GetLinks().size();
5564 sal_uInt16 nRemoved
= 0;
5565 sal_uInt16 nLinkPos
= 0;
5566 while (nLinkPos
<nLinkCount
)
5568 ::sfx2::SvBaseLink
* pBase
= pLinkManager
->GetLinks()[nLinkPos
].get();
5569 ScAreaLink
* pLink
= dynamic_cast<ScAreaLink
*>(pBase
);
5570 if (pLink
&& pLink
->GetDestArea().aStart
== rDestRange
.aStart
)
5576 // group all remove and the insert action
5577 OUString aUndo
= ScResId( STR_UNDO_INSERTAREALINK
);
5578 ViewShellId
nViewShellId(-1);
5579 if (ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell())
5580 nViewShellId
= pViewSh
->GetViewShellId();
5581 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, nViewShellId
);
5584 ScAreaLink
* pOldArea
= static_cast<ScAreaLink
*>(pBase
);
5585 rDocShell
.GetUndoManager()->AddUndoAction(
5586 std::make_unique
<ScUndoRemoveAreaLink
>( &rDocShell
,
5587 pOldArea
->GetFile(), pOldArea
->GetFilter(), pOldArea
->GetOptions(),
5588 pOldArea
->GetSource(), pOldArea
->GetDestArea(), pOldArea
->GetRefreshDelaySeconds() ) );
5590 pLinkManager
->Remove( pBase
);
5591 nLinkCount
= pLinkManager
->GetLinks().size();
5598 OUString aFilterName
= rFilter
;
5599 OUString aNewOptions
= rOptions
;
5600 if (aFilterName
.isEmpty())
5601 ScDocumentLoader::GetFilterName( rFile
, aFilterName
, aNewOptions
, true, !bApi
);
5603 // remove application prefix from filter name here, so the filter options
5604 // aren't reset when the filter name is changed in ScAreaLink::DataChanged
5605 ScDocumentLoader::RemoveAppPrefix( aFilterName
);
5607 ScAreaLink
* pLink
= new ScAreaLink( &rDocShell
, rFile
, aFilterName
,
5608 aNewOptions
, rSource
, rDestRange
, nRefreshDelaySeconds
);
5609 OUString aTmp
= aFilterName
;
5610 pLinkManager
->InsertFileLink( *pLink
, sfx2::SvBaseLinkObjectType::ClientFile
, rFile
, &aTmp
, &rSource
);
5612 // Undo for an empty link
5616 rDocShell
.GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoInsertAreaLink
>( &rDocShell
,
5617 rFile
, aFilterName
, aNewOptions
,
5618 rSource
, rDestRange
, nRefreshDelaySeconds
) );
5620 rDocShell
.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
5623 // Update has its own undo
5624 if (rDoc
.IsExecuteLinkEnabled())
5626 pLink
->SetDoInsert(bFitBlock
); // if applicable, don't insert anything on first update
5627 pLink
->Update(); // no SetInCreate -> carry out update
5629 pLink
->SetDoInsert(true); // Default = true
5631 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
5633 pBindings
->Invalidate( SID_LINKS
);
5635 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) ); // Navigator
5638 void ScDocFunc::ReplaceConditionalFormat( sal_uLong nOldFormat
, std::unique_ptr
<ScConditionalFormat
> pFormat
, SCTAB nTab
, const ScRangeList
& rRanges
)
5640 ScDocShellModificator
aModificator(rDocShell
);
5641 ScDocument
& rDoc
= rDocShell
.GetDocument();
5642 if(rDoc
.IsTabProtected(nTab
))
5645 ScRange aCombinedRange
= rRanges
.Combine();
5646 std::unique_ptr
<ScUndoConditionalFormat
> pUndo
;
5647 if (rDoc
.IsUndoEnabled())
5648 pUndo
.reset(new ScUndoConditionalFormat(&rDocShell
, nTab
));
5650 std::unique_ptr
<ScRange
> pRepaintRange
;
5653 ScConditionalFormat
* pOldFormat
= rDoc
.GetCondFormList(nTab
)->GetFormat(nOldFormat
);
5656 pRepaintRange
.reset(new ScRange( pOldFormat
->GetRange().Combine() ));
5657 rDoc
.RemoveCondFormatData(pOldFormat
->GetRange(), nTab
, pOldFormat
->GetKey());
5660 rDoc
.DeleteConditionalFormat(nOldFormat
, nTab
);
5661 rDoc
.SetStreamValid(nTab
, false);
5666 pRepaintRange
->ExtendTo(aCombinedRange
);
5668 pRepaintRange
.reset(new ScRange(aCombinedRange
));
5670 sal_uInt32 nIndex
= rDoc
.AddCondFormat(std::move(pFormat
), nTab
);
5672 rDoc
.AddCondFormatData(rRanges
, nTab
, nIndex
);
5673 rDoc
.SetStreamValid(nTab
, false);
5678 pUndo
->setRedoData();
5679 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndo
));
5683 rDocShell
.PostPaint(*pRepaintRange
, PaintPartFlags::Grid
, SC_PF_TESTMERGE
);
5685 aModificator
.SetDocumentModified();
5686 SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreasChanged
));
5689 void ScDocFunc::SetConditionalFormatList( ScConditionalFormatList
* pList
, SCTAB nTab
)
5691 ScDocShellModificator
aModificator(rDocShell
);
5692 ScDocument
& rDoc
= rDocShell
.GetDocument();
5693 if(rDoc
.IsTabProtected(nTab
))
5696 bool bUndo
= rDoc
.IsUndoEnabled();
5697 ScDocumentUniquePtr pUndoDoc
;
5700 pUndoDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
5701 pUndoDoc
->InitUndo( rDoc
, nTab
, nTab
);
5703 ScConditionalFormatList
* pOld
= rDoc
.GetCondFormList(nTab
);
5706 pUndoDoc
->SetCondFormList(new ScConditionalFormatList(*pUndoDoc
, *pOld
), nTab
);
5708 pUndoDoc
->SetCondFormList(nullptr, nTab
);
5712 // first remove all old entries
5713 ScConditionalFormatList
* pOldList
= rDoc
.GetCondFormList(nTab
);
5714 pOldList
->RemoveFromDocument(rDoc
);
5716 // then set new entries
5717 pList
->AddToDocument(rDoc
);
5719 rDoc
.SetCondFormList(pList
, nTab
);
5720 rDocShell
.PostPaintGridAll();
5724 ScDocumentUniquePtr
pRedoDoc(new ScDocument(SCDOCMODE_UNDO
));
5725 pRedoDoc
->InitUndo( rDoc
, nTab
, nTab
);
5726 pRedoDoc
->SetCondFormList(new ScConditionalFormatList(*pRedoDoc
, *pList
), nTab
);
5728 rDocShell
.GetUndoManager()->AddUndoAction(
5729 std::make_unique
<ScUndoConditionalFormatList
>(&rDocShell
, std::move(pUndoDoc
), std::move(pRedoDoc
), nTab
));
5732 rDoc
.SetStreamValid(nTab
, false);
5733 aModificator
.SetDocumentModified();
5734 SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScAreasChanged
));
5737 void ScDocFunc::ConvertFormulaToValue( const ScRange
& rRange
, bool bInteraction
)
5739 ScDocShellModificator
aModificator(rDocShell
);
5740 ScDocument
& rDoc
= rDocShell
.GetDocument();
5741 bool bRecord
= true;
5742 if (!rDoc
.IsUndoEnabled())
5745 ScEditableTester
aTester(rDoc
, rRange
, sc::EditAction::Unknown
);
5746 if (!aTester
.IsEditable())
5749 rDocShell
.ErrorMessage(aTester
.GetMessageId());
5753 sc::TableValues
aUndoVals(rRange
);
5754 sc::TableValues
* pUndoVals
= bRecord
? &aUndoVals
: nullptr;
5756 rDoc
.ConvertFormulaToValue(rRange
, pUndoVals
);
5758 if (bRecord
&& pUndoVals
)
5760 rDocShell
.GetUndoManager()->AddUndoAction(
5761 std::make_unique
<sc::UndoFormulaToValue
>(&rDocShell
, *pUndoVals
));
5764 rDocShell
.PostPaint(rRange
, PaintPartFlags::Grid
);
5765 rDocShell
.PostDataChanged();
5766 rDoc
.BroadcastCells(rRange
, SfxHintId::ScDataChanged
);
5767 aModificator
.SetDocumentModified();
5770 void ScDocFunc::EnterListAction(TranslateId pNameResId
)
5772 OUString
aUndo(ScResId(pNameResId
));
5773 ViewShellId
nViewShellId(-1);
5774 if (ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell())
5775 nViewShellId
= pViewSh
->GetViewShellId();
5776 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
, 0, nViewShellId
);
5779 void ScDocFunc::EndListAction()
5781 rDocShell
.GetUndoManager()->LeaveListAction();
5784 bool ScDocFunc::InsertSparklines(ScRange
const& rDataRange
, ScRange
const& rSparklineRange
,
5785 const std::shared_ptr
<sc::SparklineGroup
>& pSparklineGroup
)
5787 std::vector
<sc::SparklineData
> aSparklineDataVector
;
5789 if (rSparklineRange
.aStart
.Col() == rSparklineRange
.aEnd
.Col())
5791 sal_Int32 nOutputRowSize
= rSparklineRange
.aEnd
.Row() - rSparklineRange
.aStart
.Row();
5793 auto eInputOrientation
= sc::calculateOrientation(nOutputRowSize
, rDataRange
);
5795 if (eInputOrientation
== sc::RangeOrientation::Unknown
)
5798 sal_Int32 nIndex
= 0;
5800 for (ScAddress aAddress
= rSparklineRange
.aStart
; aAddress
.Row() <= rSparklineRange
.aEnd
.Row();
5803 ScRange aInputRangeSlice
= rDataRange
;
5804 if (eInputOrientation
== sc::RangeOrientation::Row
)
5806 aInputRangeSlice
.aStart
.SetRow(rDataRange
.aStart
.Row() + nIndex
);
5807 aInputRangeSlice
.aEnd
.SetRow(rDataRange
.aStart
.Row() + nIndex
);
5811 aInputRangeSlice
.aStart
.SetCol(rDataRange
.aStart
.Col() + nIndex
);
5812 aInputRangeSlice
.aEnd
.SetCol(rDataRange
.aStart
.Col() + nIndex
);
5815 aSparklineDataVector
.emplace_back(aAddress
, aInputRangeSlice
);
5820 else if (rSparklineRange
.aStart
.Row() == rSparklineRange
.aEnd
.Row())
5822 sal_Int32 nOutputColSize
= rSparklineRange
.aEnd
.Col() - rSparklineRange
.aStart
.Col();
5824 auto eInputOrientation
= sc::calculateOrientation(nOutputColSize
, rDataRange
);
5826 if (eInputOrientation
== sc::RangeOrientation::Unknown
)
5829 sal_Int32 nIndex
= 0;
5831 for (ScAddress aAddress
= rSparklineRange
.aStart
; aAddress
.Col() <= rSparklineRange
.aEnd
.Col();
5834 ScRange aInputRangeSlice
= rDataRange
;
5835 if (eInputOrientation
== sc::RangeOrientation::Row
)
5837 aInputRangeSlice
.aStart
.SetRow(rDataRange
.aStart
.Row() + nIndex
);
5838 aInputRangeSlice
.aEnd
.SetRow(rDataRange
.aStart
.Row() + nIndex
);
5842 aInputRangeSlice
.aStart
.SetCol(rDataRange
.aStart
.Col() + nIndex
);
5843 aInputRangeSlice
.aEnd
.SetCol(rDataRange
.aStart
.Col() + nIndex
);
5846 aSparklineDataVector
.emplace_back(aAddress
, aInputRangeSlice
);
5852 if (aSparklineDataVector
.empty())
5855 auto pUndoInsertSparkline
= std::make_unique
<sc::UndoInsertSparkline
>(rDocShell
, aSparklineDataVector
, pSparklineGroup
);
5856 // insert the sparkline by "redoing"
5857 pUndoInsertSparkline
->Redo();
5858 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndoInsertSparkline
));
5863 bool ScDocFunc::DeleteSparkline(ScAddress
const& rAddress
)
5865 auto& rDocument
= rDocShell
.GetDocument();
5867 if (!rDocument
.HasSparkline(rAddress
))
5870 auto pUndoDeleteSparkline
= std::make_unique
<sc::UndoDeleteSparkline
>(rDocShell
, rAddress
);
5871 // delete sparkline by "redoing"
5872 pUndoDeleteSparkline
->Redo();
5873 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndoDeleteSparkline
));
5878 bool ScDocFunc::DeleteSparklineGroup(std::shared_ptr
<sc::SparklineGroup
> const& pSparklineGroup
, SCTAB nTab
)
5880 if (!pSparklineGroup
)
5883 auto& rDocument
= rDocShell
.GetDocument();
5885 if (!rDocument
.HasTable(nTab
))
5888 auto pUndo
= std::make_unique
<sc::UndoDeleteSparklineGroup
>(rDocShell
, pSparklineGroup
, nTab
);
5889 // delete sparkline group by "redoing"
5891 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndo
));
5895 bool ScDocFunc::ChangeSparklineGroupAttributes(std::shared_ptr
<sc::SparklineGroup
> const& pExistingSparklineGroup
,
5896 sc::SparklineAttributes
const& rNewAttributes
)
5898 auto pUndo
= std::make_unique
<sc::UndoEditSparklneGroup
>(rDocShell
, pExistingSparklineGroup
, rNewAttributes
);
5899 // change sparkline group attributes by "redoing"
5901 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndo
));
5905 bool ScDocFunc::GroupSparklines(ScRange
const& rRange
, std::shared_ptr
<sc::SparklineGroup
> const& rpGroup
)
5907 auto pUndo
= std::make_unique
<sc::UndoGroupSparklines
>(rDocShell
, rRange
, rpGroup
);
5908 // group sparklines by "redoing"
5910 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndo
));
5914 bool ScDocFunc::UngroupSparklines(ScRange
const& rRange
)
5916 auto pUndo
= std::make_unique
<sc::UndoUngroupSparklines
>(rDocShell
, rRange
);
5917 // ungroup sparklines by "redoing"
5919 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndo
));
5923 bool ScDocFunc::ChangeSparkline(std::shared_ptr
<sc::Sparkline
> const& rpSparkline
, SCTAB nTab
, ScRangeList
const& rDataRange
)
5925 auto pUndo
= std::make_unique
<sc::UndoEditSparkline
>(rDocShell
, rpSparkline
, nTab
, rDataRange
);
5926 // change sparkline by "redoing"
5928 rDocShell
.GetUndoManager()->AddUndoAction(std::move(pUndo
));
5932 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */