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 <sfx2/app.hxx>
23 #include <editeng/editobj.hxx>
24 #include <sfx2/linkmgr.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <vcl/msgbox.hxx>
27 #include <vcl/virdev.hxx>
28 #include <vcl/waitobj.hxx>
29 #include <svl/PasswordHelper.hxx>
31 #include <com/sun/star/container/XNameContainer.hpp>
32 #include <com/sun/star/script/ModuleType.hpp>
33 #include <com/sun/star/script/XLibraryContainer.hpp>
34 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
36 #include "docfunc.hxx"
40 #include "arealink.hxx"
42 #include "dociter.hxx"
43 #include "autoform.hxx"
44 #include "formulacell.hxx"
45 #include "cellmergeoption.hxx"
46 #include "detdata.hxx"
47 #include "detfunc.hxx"
48 #include "docpool.hxx"
50 #include "drwlayer.hxx"
51 #include "editutil.hxx"
52 #include "globstr.hrc"
53 #include "globalnames.hxx"
54 #include "olinetab.hxx"
55 #include "patattr.hxx"
56 #include "rangenam.hxx"
57 #include "rangeutl.hxx"
58 #include "refundo.hxx"
59 #include "scresid.hxx"
60 #include "stlpool.hxx"
61 #include "stlsheet.hxx"
62 #include "tablink.hxx"
63 #include "tabvwsh.hxx"
64 #include "uiitems.hxx"
65 #include "undoblk.hxx"
66 #include "undocell.hxx"
67 #include "undodraw.hxx"
68 #include "undotab.hxx"
69 #include "waitoff.hxx"
70 #include "sizedev.hxx"
72 #include "inputhdl.hxx"
73 #include "inputwin.hxx"
74 #include "editable.hxx"
75 #include "compiler.hxx"
76 #include "scui_def.hxx"
77 #include "tabprotection.hxx"
78 #include "clipparam.hxx"
79 #include "externalrefmgr.hxx"
80 #include "undorangename.hxx"
81 #include "progress.hxx"
82 #include "dpobject.hxx"
83 #include "stringutil.hxx"
84 #include "cellvalue.hxx"
85 #include "tokenarray.hxx"
86 #include <rowheightcontext.hxx>
87 #include <cellvalues.hxx>
88 #include <undoconvert.hxx>
89 #include <docfuncutil.hxx>
93 #include <basic/basmgr.hxx>
98 using namespace com::sun::star
;
101 IMPL_LINK_TYPED( ScDocFunc
, NotifyDrawUndo
, SdrUndoAction
*, pUndoAction
, void )
103 // #i101118# if drawing layer collects the undo actions, add it there
104 ScDrawLayer
* pDrawLayer
= rDocShell
.GetDocument().GetDrawLayer();
105 if( pDrawLayer
&& pDrawLayer
->IsRecording() )
106 pDrawLayer
->AddCalcUndo( pUndoAction
);
108 rDocShell
.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction
, &rDocShell
) );
109 rDocShell
.SetDrawModified();
111 // the affected sheet isn't known, so all stream positions are invalidated
112 ScDocument
& rDoc
= rDocShell
.GetDocument();
113 SCTAB nTabCount
= rDoc
.GetTableCount();
114 for (SCTAB nTab
=0; nTab
<nTabCount
; nTab
++)
115 if (rDoc
.IsStreamValid(nTab
))
116 rDoc
.SetStreamValid(nTab
, false);
119 // Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
121 static void lcl_PaintAbove( ScDocShell
& rDocShell
, const ScRange
& rRange
)
123 SCROW nRow
= rRange
.aStart
.Row();
126 SCTAB nTab
= rRange
.aStart
.Tab(); //! alle?
128 rDocShell
.PostPaint( ScRange(0,nRow
,nTab
, MAXCOL
,nRow
,nTab
), PAINT_GRID
);
132 bool ScDocFunc::AdjustRowHeight( const ScRange
& rRange
, bool bPaint
)
134 ScDocument
& rDoc
= rDocShell
.GetDocument();
135 if ( rDoc
.IsImportingXML() )
137 // for XML import, all row heights are updated together after importing
140 if ( !rDoc
.IsAdjustHeightEnabled() )
145 SCTAB nTab
= rRange
.aStart
.Tab();
146 SCROW nStartRow
= rRange
.aStart
.Row();
147 SCROW nEndRow
= rRange
.aEnd
.Row();
149 ScSizeDeviceProvider
aProv( &rDocShell
);
152 sc::RowHeightContext
aCxt(aProv
.GetPPTX(), aProv
.GetPPTY(), aOne
, aOne
, aProv
.GetDevice());
153 bool bChanged
= rDoc
.SetOptimalHeight(aCxt
, nStartRow
, nEndRow
, nTab
);
155 if ( bPaint
&& bChanged
)
156 rDocShell
.PostPaint(ScRange(0, nStartRow
, nTab
, MAXCOL
, MAXROW
, nTab
),
157 PAINT_GRID
| PAINT_LEFT
);
162 bool ScDocFunc::DetectiveAddPred(const ScAddress
& rPos
)
164 ScDocShellModificator
aModificator( rDocShell
);
166 rDocShell
.MakeDrawLayer();
167 ScDocument
& rDoc
= rDocShell
.GetDocument();
168 bool bUndo (rDoc
.IsUndoEnabled());
169 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
170 SCCOL nCol
= rPos
.Col();
171 SCROW nRow
= rPos
.Row();
172 SCTAB nTab
= rPos
.Tab();
175 pModel
->BeginCalcUndo(false);
176 bool bDone
= ScDetectiveFunc( &rDoc
,nTab
).ShowPred( nCol
, nRow
);
177 SdrUndoGroup
* pUndo
= nullptr;
179 pUndo
= pModel
->GetCalcUndo();
182 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_ADDPRED
);
183 rDoc
.AddDetectiveOperation( aOperation
);
186 rDocShell
.GetUndoManager()->AddUndoAction(
187 new ScUndoDetective( &rDocShell
, pUndo
, &aOperation
) );
189 aModificator
.SetDocumentModified();
190 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
192 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
200 bool ScDocFunc::DetectiveDelPred(const ScAddress
& rPos
)
202 ScDocument
& rDoc
= rDocShell
.GetDocument();
204 bool bUndo(rDoc
.IsUndoEnabled());
205 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
209 ScDocShellModificator
aModificator( rDocShell
);
211 SCCOL nCol
= rPos
.Col();
212 SCROW nRow
= rPos
.Row();
213 SCTAB nTab
= rPos
.Tab();
216 pModel
->BeginCalcUndo(false);
217 bool bDone
= ScDetectiveFunc( &rDoc
,nTab
).DeletePred( nCol
, nRow
);
218 SdrUndoGroup
* pUndo
= nullptr;
220 pUndo
= pModel
->GetCalcUndo();
223 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_DELPRED
);
224 rDoc
.AddDetectiveOperation( aOperation
);
227 rDocShell
.GetUndoManager()->AddUndoAction(
228 new ScUndoDetective( &rDocShell
, pUndo
, &aOperation
) );
230 aModificator
.SetDocumentModified();
231 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
233 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
241 bool ScDocFunc::DetectiveAddSucc(const ScAddress
& rPos
)
243 ScDocShellModificator
aModificator( rDocShell
);
245 rDocShell
.MakeDrawLayer();
246 ScDocument
& rDoc
= rDocShell
.GetDocument();
248 bool bUndo(rDoc
.IsUndoEnabled());
249 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
250 SCCOL nCol
= rPos
.Col();
251 SCROW nRow
= rPos
.Row();
252 SCTAB nTab
= rPos
.Tab();
255 pModel
->BeginCalcUndo(false);
256 bool bDone
= ScDetectiveFunc( &rDoc
,nTab
).ShowSucc( nCol
, nRow
);
257 SdrUndoGroup
* pUndo
= nullptr;
259 pUndo
= pModel
->GetCalcUndo();
262 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_ADDSUCC
);
263 rDoc
.AddDetectiveOperation( aOperation
);
266 rDocShell
.GetUndoManager()->AddUndoAction(
267 new ScUndoDetective( &rDocShell
, pUndo
, &aOperation
) );
269 aModificator
.SetDocumentModified();
270 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
272 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
280 bool ScDocFunc::DetectiveDelSucc(const ScAddress
& rPos
)
282 ScDocument
& rDoc
= rDocShell
.GetDocument();
284 bool bUndo (rDoc
.IsUndoEnabled());
285 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
289 ScDocShellModificator
aModificator( rDocShell
);
291 SCCOL nCol
= rPos
.Col();
292 SCROW nRow
= rPos
.Row();
293 SCTAB nTab
= rPos
.Tab();
296 pModel
->BeginCalcUndo(false);
297 bool bDone
= ScDetectiveFunc( &rDoc
,nTab
).DeleteSucc( nCol
, nRow
);
298 SdrUndoGroup
* pUndo
= nullptr;
300 pUndo
= pModel
->GetCalcUndo();
303 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_DELSUCC
);
304 rDoc
.AddDetectiveOperation( aOperation
);
307 rDocShell
.GetUndoManager()->AddUndoAction(
308 new ScUndoDetective( &rDocShell
, pUndo
, &aOperation
) );
310 aModificator
.SetDocumentModified();
311 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
313 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
321 bool ScDocFunc::DetectiveAddError(const ScAddress
& rPos
)
323 ScDocShellModificator
aModificator( rDocShell
);
325 rDocShell
.MakeDrawLayer();
326 ScDocument
& rDoc
= rDocShell
.GetDocument();
328 bool bUndo (rDoc
.IsUndoEnabled());
329 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
330 SCCOL nCol
= rPos
.Col();
331 SCROW nRow
= rPos
.Row();
332 SCTAB nTab
= rPos
.Tab();
335 pModel
->BeginCalcUndo(false);
336 bool bDone
= ScDetectiveFunc( &rDoc
,nTab
).ShowError( nCol
, nRow
);
337 SdrUndoGroup
* pUndo
= nullptr;
339 pUndo
= pModel
->GetCalcUndo();
342 ScDetOpData
aOperation( ScAddress(nCol
,nRow
,nTab
), SCDETOP_ADDERROR
);
343 rDoc
.AddDetectiveOperation( aOperation
);
346 rDocShell
.GetUndoManager()->AddUndoAction(
347 new ScUndoDetective( &rDocShell
, pUndo
, &aOperation
) );
349 aModificator
.SetDocumentModified();
350 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
352 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
360 bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab
)
362 ScDocShellModificator
aModificator( rDocShell
);
364 rDocShell
.MakeDrawLayer();
365 ScDocument
& rDoc
= rDocShell
.GetDocument();
367 bool bUndo (rDoc
.IsUndoEnabled());
368 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
370 vcl::Window
* pWaitWin
= ScDocShell::GetActiveDialogParent();
372 pWaitWin
->EnterWait();
374 pModel
->BeginCalcUndo(false);
376 bool bDone
= ScDetectiveFunc( &rDoc
,nTab
).MarkInvalid( bOverflow
);
377 SdrUndoGroup
* pUndo
= nullptr;
379 pUndo
= pModel
->GetCalcUndo();
381 pWaitWin
->LeaveWait();
386 pUndo
->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID
) );
387 rDocShell
.GetUndoManager()->AddUndoAction( pUndo
);
389 aModificator
.SetDocumentModified();
392 ScopedVclPtrInstance
<InfoBox
>( nullptr,
393 ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW
) )->Execute();
402 bool ScDocFunc::DetectiveDelAll(SCTAB nTab
)
404 ScDocument
& rDoc
= rDocShell
.GetDocument();
406 bool bUndo (rDoc
.IsUndoEnabled());
407 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
411 ScDocShellModificator
aModificator( rDocShell
);
414 pModel
->BeginCalcUndo(false);
415 bool bDone
= ScDetectiveFunc( &rDoc
,nTab
).DeleteAll( SC_DET_DETECTIVE
);
416 SdrUndoGroup
* pUndo
= nullptr;
418 pUndo
= pModel
->GetCalcUndo();
421 ScDetOpList
* pOldList
= rDoc
.GetDetOpList();
422 ScDetOpList
* pUndoList
= nullptr;
424 pUndoList
= pOldList
? new ScDetOpList(*pOldList
) : nullptr;
426 rDoc
.ClearDetectiveOperations();
430 rDocShell
.GetUndoManager()->AddUndoAction(
431 new ScUndoDetective( &rDocShell
, pUndo
, nullptr, pUndoList
) );
433 aModificator
.SetDocumentModified();
434 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
436 pBindings
->Invalidate( SID_DETECTIVE_REFRESH
);
444 bool ScDocFunc::DetectiveRefresh( bool bAutomatic
)
447 ScDocument
& rDoc
= rDocShell
.GetDocument();
449 ScDetOpList
* pList
= rDoc
.GetDetOpList();
450 if ( pList
&& pList
->Count() )
452 rDocShell
.MakeDrawLayer();
453 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
454 const bool bUndo (rDoc
.IsUndoEnabled());
456 pModel
->BeginCalcUndo(false);
458 // Loeschen auf allen Tabellen
460 SCTAB nTabCount
= rDoc
.GetTableCount();
461 for (SCTAB nTab
=0; nTab
<nTabCount
; nTab
++)
462 ScDetectiveFunc( &rDoc
,nTab
).DeleteAll( SC_DET_ARROWS
); // don't remove circles
466 size_t nCount
= pList
->Count();
467 for (size_t i
=0; i
< nCount
; ++i
)
469 const ScDetOpData
& rData
= pList
->GetObject(i
);
470 const ScAddress
& aPos
= rData
.GetPos();
471 ScDetectiveFunc
aFunc( &rDoc
, aPos
.Tab() );
472 SCCOL nCol
= aPos
.Col();
473 SCROW nRow
= aPos
.Row();
474 switch (rData
.GetOperation())
476 case SCDETOP_ADDSUCC
:
477 aFunc
.ShowSucc( nCol
, nRow
);
479 case SCDETOP_DELSUCC
:
480 aFunc
.DeleteSucc( nCol
, nRow
);
482 case SCDETOP_ADDPRED
:
483 aFunc
.ShowPred( nCol
, nRow
);
485 case SCDETOP_DELPRED
:
486 aFunc
.DeletePred( nCol
, nRow
);
488 case SCDETOP_ADDERROR
:
489 aFunc
.ShowError( nCol
, nRow
);
492 OSL_FAIL("falsche Op bei DetectiveRefresh");
498 SdrUndoGroup
* pUndo
= pModel
->GetCalcUndo();
501 pUndo
->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH
) );
502 // wenn automatisch, an letzte Aktion anhaengen
503 rDocShell
.GetUndoManager()->AddUndoAction(
504 new ScUndoDraw( pUndo
, &rDocShell
),
508 rDocShell
.SetDrawModified();
514 static void lcl_collectAllPredOrSuccRanges(
515 const ScRangeList
& rSrcRanges
, vector
<ScTokenRef
>& rRefTokens
, ScDocShell
& rDocShell
,
518 ScDocument
& rDoc
= rDocShell
.GetDocument();
519 vector
<ScTokenRef
> aRefTokens
;
520 ScRangeList
aSrcRanges(rSrcRanges
);
521 if (aSrcRanges
.empty())
523 ScRange
* p
= aSrcRanges
.front();
524 ScDetectiveFunc
aDetFunc(&rDoc
, p
->aStart
.Tab());
525 ScRangeList aDestRanges
;
526 for (size_t i
= 0, n
= aSrcRanges
.size(); i
< n
; ++i
)
531 aDetFunc
.GetAllPreds(
532 p
->aStart
.Col(), p
->aStart
.Row(), p
->aEnd
.Col(), p
->aEnd
.Row(), aRefTokens
);
536 aDetFunc
.GetAllSuccs(
537 p
->aStart
.Col(), p
->aStart
.Row(), p
->aEnd
.Col(), p
->aEnd
.Row(), aRefTokens
);
540 rRefTokens
.swap(aRefTokens
);
543 void ScDocFunc::DetectiveCollectAllPreds(const ScRangeList
& rSrcRanges
, vector
<ScTokenRef
>& rRefTokens
)
545 lcl_collectAllPredOrSuccRanges(rSrcRanges
, rRefTokens
, rDocShell
, true);
548 void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList
& rSrcRanges
, vector
<ScTokenRef
>& rRefTokens
)
550 lcl_collectAllPredOrSuccRanges(rSrcRanges
, rRefTokens
, rDocShell
, false);
553 bool ScDocFunc::DeleteContents(
554 const ScMarkData
& rMark
, InsertDeleteFlags nFlags
, bool bRecord
, bool bApi
)
556 ScDocShellModificator
aModificator( rDocShell
);
558 if ( !rMark
.IsMarked() && !rMark
.IsMultiMarked() )
560 OSL_FAIL("ScDocFunc::DeleteContents ohne Markierung");
564 ScDocument
& rDoc
= rDocShell
.GetDocument();
566 if (bRecord
&& !rDoc
.IsUndoEnabled())
569 ScEditableTester
aTester( &rDoc
, rMark
);
570 if (!aTester
.IsEditable())
573 rDocShell
.ErrorMessage(aTester
.GetMessageId());
579 ScMarkData aMultiMark
= rMark
;
580 aMultiMark
.SetMarking(false); // fuer MarkToMulti
582 std::unique_ptr
<ScDocument
> pUndoDoc
;
583 bool bMulti
= aMultiMark
.IsMultiMarked();
584 aMultiMark
.MarkToMulti();
585 aMultiMark
.GetMultiMarkArea( aMarkRange
);
586 ScRange
aExtendedRange(aMarkRange
);
587 if ( rDoc
.ExtendMerge( aExtendedRange
, true ) )
590 // no objects on protected tabs
591 bool bObjects
= (nFlags
& InsertDeleteFlags::OBJECTS
) && !sc::DocFuncUtil::hasProtectedTab(rDoc
, rMark
);
593 sal_uInt16 nExtFlags
= 0; // extra flags are needed only if attributes are deleted
594 if ( nFlags
& InsertDeleteFlags::ATTRIB
)
595 rDocShell
.UpdatePaintExt( nExtFlags
, aMarkRange
);
599 // 2) Objekte loeschen (DrawUndo wird gefuellt)
600 // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
601 // 4) Inhalte loeschen
603 bool bDrawUndo
= bObjects
|| (nFlags
& InsertDeleteFlags::NOTE
);
604 if (bRecord
&& bDrawUndo
)
605 rDoc
.BeginDrawUndo();
610 rDoc
.DeleteObjectsInSelection( aMultiMark
);
612 rDoc
.DeleteObjectsInArea( aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
613 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(),
617 // To keep track of all non-empty cells within the deleted area.
618 std::shared_ptr
<ScSimpleUndo::DataSpansType
> pDataSpans
;
622 pUndoDoc
= sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc
, aMultiMark
, aMarkRange
, nFlags
, bMulti
);
623 pDataSpans
= sc::DocFuncUtil::getNonEmptyCellSpans(rDoc
, aMultiMark
, aMarkRange
);
626 rDoc
.DeleteSelection( nFlags
, aMultiMark
);
628 // add undo action after drawing undo is complete (objects and note captions)
631 sc::DocFuncUtil::addDeleteContentsUndo(
632 rDocShell
.GetUndoManager(), &rDocShell
, aMultiMark
, aExtendedRange
,
633 std::move(pUndoDoc
), nFlags
, pDataSpans
, bMulti
, bDrawUndo
);
636 if (!AdjustRowHeight( aExtendedRange
))
637 rDocShell
.PostPaint( aExtendedRange
, PAINT_GRID
, nExtFlags
);
638 else if (nExtFlags
& SC_PF_LINES
)
639 lcl_PaintAbove( rDocShell
, aExtendedRange
); // fuer Linien ueber dem Bereich
641 aModificator
.SetDocumentModified();
646 bool ScDocFunc::DeleteCell(
647 const ScAddress
& rPos
, const ScMarkData
& rMark
, InsertDeleteFlags nFlags
, bool bRecord
)
649 ScDocShellModificator
aModificator(rDocShell
);
651 ScDocument
& rDoc
= rDocShell
.GetDocument();
653 if (bRecord
&& !rDoc
.IsUndoEnabled())
656 ScEditableTester
aTester(&rDoc
, rPos
.Col(), rPos
.Row(), rPos
.Col(), rPos
.Row(), rMark
);
657 if (!aTester
.IsEditable())
659 rDocShell
.ErrorMessage(aTester
.GetMessageId());
663 // no objects on protected tabs
664 bool bObjects
= (nFlags
& InsertDeleteFlags::OBJECTS
) && !sc::DocFuncUtil::hasProtectedTab(rDoc
, rMark
);
666 sal_uInt16 nExtFlags
= 0; // extra flags are needed only if attributes are deleted
667 if (nFlags
& InsertDeleteFlags::ATTRIB
)
668 rDocShell
.UpdatePaintExt(nExtFlags
, rPos
);
670 // order op opeeration:
672 // 2) delete objects (DrawUndo is filled)
673 // 3) copy contents for undo
674 // 4) delete contents
675 // 5) add undo-action
677 bool bDrawUndo
= bObjects
|| (nFlags
& InsertDeleteFlags::NOTE
); // needed for shown notes
678 if (bDrawUndo
&& bRecord
)
679 rDoc
.BeginDrawUndo();
682 rDoc
.DeleteObjectsInArea(rPos
.Col(), rPos
.Row(), rPos
.Col(), rPos
.Row(), rMark
);
684 // To keep track of all non-empty cells within the deleted area.
685 std::shared_ptr
<ScSimpleUndo::DataSpansType
> pDataSpans
;
687 std::unique_ptr
<ScDocument
> pUndoDoc
;
690 pUndoDoc
= sc::DocFuncUtil::createDeleteContentsUndoDoc(rDoc
, rMark
, rPos
, nFlags
, false);
691 pDataSpans
= sc::DocFuncUtil::getNonEmptyCellSpans(rDoc
, rMark
, rPos
);
694 rDoc
.DeleteArea(rPos
.Col(), rPos
.Row(), rPos
.Col(), rPos
.Row(), rMark
, nFlags
);
698 sc::DocFuncUtil::addDeleteContentsUndo(
699 rDocShell
.GetUndoManager(), &rDocShell
, rMark
, rPos
, std::move(pUndoDoc
),
700 nFlags
, pDataSpans
, false, bDrawUndo
);
703 if (!AdjustRowHeight(rPos
))
705 rPos
.Col(), rPos
.Row(), rPos
.Tab(), rPos
.Col(), rPos
.Row(), rPos
.Tab(),
706 PAINT_GRID
, nExtFlags
);
708 aModificator
.SetDocumentModified();
713 bool ScDocFunc::TransliterateText( const ScMarkData
& rMark
, sal_Int32 nType
,
716 ScDocShellModificator
aModificator( rDocShell
);
718 ScDocument
& rDoc
= rDocShell
.GetDocument();
720 if (bRecord
&& !rDoc
.IsUndoEnabled())
723 ScEditableTester
aTester( &rDoc
, rMark
);
724 if (!aTester
.IsEditable())
727 rDocShell
.ErrorMessage(aTester
.GetMessageId());
732 ScMarkData aMultiMark
= rMark
;
733 aMultiMark
.SetMarking(false); // for MarkToMulti
734 aMultiMark
.MarkToMulti();
735 aMultiMark
.GetMultiMarkArea( aMarkRange
);
739 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
740 SCTAB nTabCount
= rDoc
.GetTableCount();
742 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
743 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nStartTab
);
744 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
745 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
746 if (*itr
!= nStartTab
)
747 pUndoDoc
->AddUndoTab( *itr
, *itr
);
749 ScRange aCopyRange
= aMarkRange
;
750 aCopyRange
.aStart
.SetTab(0);
751 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
752 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::CONTENTS
, true, pUndoDoc
, &aMultiMark
);
754 rDocShell
.GetUndoManager()->AddUndoAction(
755 new ScUndoTransliterate( &rDocShell
, aMultiMark
, pUndoDoc
, nType
) );
758 rDoc
.TransliterateText( aMultiMark
, nType
);
760 if (!AdjustRowHeight( aMarkRange
))
761 rDocShell
.PostPaint( aMarkRange
, PAINT_GRID
);
763 aModificator
.SetDocumentModified();
768 bool ScDocFunc::SetNormalString( bool& o_rbNumFmtSet
, const ScAddress
& rPos
, const OUString
& rText
, bool bApi
)
770 ScDocShellModificator
aModificator( rDocShell
);
771 ScDocument
& rDoc
= rDocShell
.GetDocument();
773 bool bUndo(rDoc
.IsUndoEnabled());
774 ScEditableTester
aTester( &rDoc
, rPos
.Tab(), rPos
.Col(),rPos
.Row(), rPos
.Col(),rPos
.Row() );
775 if (!aTester
.IsEditable())
778 rDocShell
.ErrorMessage(aTester
.GetMessageId());
782 bool bEditDeleted
= (rDoc
.GetCellType(rPos
) == CELLTYPE_EDIT
);
783 ScUndoEnterData::ValuesType aOldValues
;
787 ScUndoEnterData::Value aOldValue
;
789 aOldValue
.mnTab
= rPos
.Tab();
790 aOldValue
.maCell
.assign(rDoc
, rPos
);
792 const SfxPoolItem
* pItem
;
793 const ScPatternAttr
* pPattern
= rDoc
.GetPattern( rPos
.Col(),rPos
.Row(),rPos
.Tab() );
794 if ( SfxItemState::SET
== pPattern
->GetItemSet().GetItemState(
795 ATTR_VALUE_FORMAT
,false,&pItem
) )
797 aOldValue
.mbHasFormat
= true;
798 aOldValue
.mnFormat
= static_cast<const SfxUInt32Item
*>(pItem
)->GetValue();
801 aOldValue
.mbHasFormat
= false;
803 aOldValues
.push_back(aOldValue
);
806 o_rbNumFmtSet
= rDoc
.SetString( rPos
.Col(), rPos
.Row(), rPos
.Tab(), rText
);
810 // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
811 rDocShell
.GetUndoManager()->AddUndoAction(
812 new ScUndoEnterData(&rDocShell
, rPos
, aOldValues
, rText
, nullptr));
815 if ( bEditDeleted
|| rDoc
.HasAttrib( ScRange(rPos
), HASATTR_NEEDHEIGHT
) )
816 AdjustRowHeight( ScRange(rPos
) );
818 rDocShell
.PostPaintCell( rPos
);
819 aModificator
.SetDocumentModified();
821 // notify input handler here the same way as in PutCell
823 NotifyInputHandler( rPos
);
828 bool ScDocFunc::SetValueCell( const ScAddress
& rPos
, double fVal
, bool bInteraction
)
830 ScDocShellModificator
aModificator( rDocShell
);
831 ScDocument
& rDoc
= rDocShell
.GetDocument();
832 bool bUndo
= rDoc
.IsUndoEnabled();
834 bool bHeight
= rDoc
.HasAttrib(rPos
, HASATTR_NEEDHEIGHT
);
838 aOldVal
.assign(rDoc
, rPos
);
840 rDoc
.SetValue(rPos
, fVal
);
844 svl::IUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
846 aNewVal
.assign(rDoc
, rPos
);
847 pUndoMgr
->AddUndoAction(new ScUndoSetCell(&rDocShell
, rPos
, aOldVal
, aNewVal
));
851 AdjustRowHeight(rPos
);
853 rDocShell
.PostPaintCell( rPos
);
854 aModificator
.SetDocumentModified();
856 // #103934#; notify editline and cell in edit mode
858 NotifyInputHandler( rPos
);
863 void ScDocFunc::SetValueCells( const ScAddress
& rPos
, const std::vector
<double>& aVals
, bool bInteraction
)
865 // Check for invalid range.
866 SCROW nLastRow
= rPos
.Row() + aVals
.size() - 1;
867 if (nLastRow
> MAXROW
)
871 ScRange
aRange(rPos
);
872 aRange
.aEnd
.SetRow(nLastRow
);
874 ScDocShellModificator
aModificator(rDocShell
);
875 ScDocument
& rDoc
= rDocShell
.GetDocument();
877 if (rDoc
.IsUndoEnabled())
879 sc::UndoSetCells
* pUndoObj
= new sc::UndoSetCells(&rDocShell
, rPos
);
880 rDoc
.TransferCellValuesTo(rPos
, aVals
.size(), pUndoObj
->GetOldValues());
881 pUndoObj
->SetNewValues(aVals
);
882 svl::IUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
883 pUndoMgr
->AddUndoAction(pUndoObj
);
886 rDoc
.SetValues(rPos
, aVals
);
888 rDocShell
.PostPaint(aRange
, PAINT_GRID
);
889 aModificator
.SetDocumentModified();
891 // #103934#; notify editline and cell in edit mode
893 NotifyInputHandler(rPos
);
896 bool ScDocFunc::SetStringCell( const ScAddress
& rPos
, const OUString
& rStr
, bool bInteraction
)
898 ScDocShellModificator
aModificator( rDocShell
);
899 ScDocument
& rDoc
= rDocShell
.GetDocument();
900 bool bUndo
= rDoc
.IsUndoEnabled();
902 bool bHeight
= rDoc
.HasAttrib(rPos
, HASATTR_NEEDHEIGHT
);
906 aOldVal
.assign(rDoc
, rPos
);
908 ScSetStringParam aParam
;
909 aParam
.setTextInput();
910 rDoc
.SetString(rPos
, rStr
, &aParam
);
914 svl::IUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
916 aNewVal
.assign(rDoc
, rPos
);
917 pUndoMgr
->AddUndoAction(new ScUndoSetCell(&rDocShell
, rPos
, aOldVal
, aNewVal
));
921 AdjustRowHeight(rPos
);
923 rDocShell
.PostPaintCell( rPos
);
924 aModificator
.SetDocumentModified();
926 // #103934#; notify editline and cell in edit mode
928 NotifyInputHandler( rPos
);
933 bool ScDocFunc::SetEditCell( const ScAddress
& rPos
, const EditTextObject
& rStr
, bool bInteraction
)
935 ScDocShellModificator
aModificator( rDocShell
);
936 ScDocument
& rDoc
= rDocShell
.GetDocument();
937 bool bUndo
= rDoc
.IsUndoEnabled();
939 bool bHeight
= rDoc
.HasAttrib(rPos
, HASATTR_NEEDHEIGHT
);
943 aOldVal
.assign(rDoc
, rPos
);
945 rDoc
.SetEditText(rPos
, rStr
.Clone());
949 svl::IUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
951 aNewVal
.assign(rDoc
, rPos
);
952 pUndoMgr
->AddUndoAction(new ScUndoSetCell(&rDocShell
, rPos
, aOldVal
, aNewVal
));
956 AdjustRowHeight(rPos
);
958 rDocShell
.PostPaintCell( rPos
);
959 aModificator
.SetDocumentModified();
961 // #103934#; notify editline and cell in edit mode
963 NotifyInputHandler( rPos
);
968 bool ScDocFunc::SetStringOrEditCell( const ScAddress
& rPos
, const OUString
& rStr
, bool bInteraction
)
970 ScDocument
& rDoc
= rDocShell
.GetDocument();
972 if (ScStringUtil::isMultiline(rStr
))
974 ScFieldEditEngine
& rEngine
= rDoc
.GetEditEngine();
975 rEngine
.SetText(rStr
);
976 std::unique_ptr
<EditTextObject
> pEditText(rEngine
.CreateTextObject());
977 return SetEditCell(rPos
, *pEditText
, bInteraction
);
980 return SetStringCell(rPos
, rStr
, bInteraction
);
983 bool ScDocFunc::SetFormulaCell( const ScAddress
& rPos
, ScFormulaCell
* pCell
, bool bInteraction
)
985 std::unique_ptr
<ScFormulaCell
> xCell(pCell
);
987 ScDocShellModificator
aModificator( rDocShell
);
988 ScDocument
& rDoc
= rDocShell
.GetDocument();
989 bool bUndo
= rDoc
.IsUndoEnabled();
991 bool bHeight
= rDoc
.HasAttrib(rPos
, HASATTR_NEEDHEIGHT
);
995 aOldVal
.assign(rDoc
, rPos
);
997 pCell
= rDoc
.SetFormulaCell(rPos
, xCell
.release());
999 // For performance reasons API calls may disable calculation while
1000 // operating and recalculate once when done. If through user interaction
1001 // and AutoCalc is disabled, calculate the formula (without its
1002 // dependencies) once so the result matches the current document's content.
1003 if (bInteraction
&& !rDoc
.GetAutoCalc() && pCell
)
1005 // calculate just the cell once and set Dirty again
1007 pCell
->SetDirtyVar();
1008 rDoc
.PutInFormulaTree( pCell
);
1013 svl::IUndoManager
* pUndoMgr
= rDocShell
.GetUndoManager();
1014 ScCellValue aNewVal
;
1015 aNewVal
.assign(rDoc
, rPos
);
1016 pUndoMgr
->AddUndoAction(new ScUndoSetCell(&rDocShell
, rPos
, aOldVal
, aNewVal
));
1020 AdjustRowHeight(rPos
);
1022 rDocShell
.PostPaintCell( rPos
);
1023 aModificator
.SetDocumentModified();
1025 // #103934#; notify editline and cell in edit mode
1027 NotifyInputHandler( rPos
);
1032 void ScDocFunc::NotifyInputHandler( const ScAddress
& rPos
)
1034 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
1035 if ( pViewSh
&& pViewSh
->GetViewData().GetDocShell() == &rDocShell
)
1037 ScInputHandler
* pInputHdl
= SC_MOD()->GetInputHdl();
1038 if ( pInputHdl
&& pInputHdl
->GetCursorPos() == rPos
)
1040 bool bIsEditMode(pInputHdl
->IsEditMode());
1042 // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
1043 // (the cell shows the same like the InputWindow)
1045 pInputHdl
->SetModified();
1046 pViewSh
->UpdateInputHandler(false, !bIsEditMode
);
1051 struct ScMyRememberItem
1054 SfxItemSet aItemSet
;
1056 ScMyRememberItem(const SfxItemSet
& rItemSet
, sal_Int32 nTempIndex
) :
1057 nIndex(nTempIndex
), aItemSet(rItemSet
) {}
1060 typedef ::std::list
<ScMyRememberItem
*> ScMyRememberItemList
;
1062 void ScDocFunc::PutData( const ScAddress
& rPos
, ScEditEngineDefaulter
& rEngine
, bool bApi
)
1064 // PutData ruft PutCell oder SetNormalString
1067 ScDocument
& rDoc
= rDocShell
.GetDocument();
1068 ScEditAttrTester
aTester( &rEngine
);
1069 bool bEditCell
= aTester
.NeedsObject();
1072 // #i61702# With bLoseContent set, the content of rEngine isn't restored
1073 // (used in loading XML, where after the removeActionLock call the API object's
1074 // EditEngine isn't accessed again.
1075 bool bLoseContent
= rDoc
.IsImportingXML();
1077 bool bUpdateMode(rEngine
.GetUpdateMode());
1079 rEngine
.SetUpdateMode(false);
1081 ScMyRememberItemList aRememberItems
;
1082 ScMyRememberItem
* pRememberItem
= nullptr;
1084 // All paragraph attributes must be removed before calling CreateTextObject,
1085 // not only alignment, so the object doesn't contain the cell attributes as
1086 // paragraph attributes. Before remove the attributes store they in a list to
1087 // set they back to the EditEngine.
1088 sal_Int32 nCount
= rEngine
.GetParagraphCount();
1089 for (sal_Int32 i
=0; i
<nCount
; i
++)
1091 const SfxItemSet
& rOld
= rEngine
.GetParaAttribs( i
);
1094 if ( !bLoseContent
)
1096 pRememberItem
= new ScMyRememberItem(rEngine
.GetParaAttribs(i
), i
);
1097 aRememberItems
.push_back(pRememberItem
);
1099 rEngine
.SetParaAttribs( i
, SfxItemSet( *rOld
.GetPool(), rOld
.GetRanges() ) );
1103 // A copy of pNewData will be stored in the cell.
1104 std::unique_ptr
<EditTextObject
> pNewData(rEngine
.CreateTextObject());
1105 bRet
= SetEditCell(rPos
, *pNewData
, !bApi
);
1107 // Set the paragraph attributes back to the EditEngine.
1108 if (!aRememberItems
.empty())
1110 ScMyRememberItemList::iterator aItr
= aRememberItems
.begin();
1111 while (aItr
!= aRememberItems
.end())
1113 pRememberItem
= *aItr
;
1114 rEngine
.SetParaAttribs(pRememberItem
->nIndex
, pRememberItem
->aItemSet
);
1115 delete pRememberItem
;
1116 aItr
= aRememberItems
.erase(aItr
);
1120 // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
1121 if ( bUpdateMode
&& !bLoseContent
)
1122 rEngine
.SetUpdateMode(true);
1126 OUString aText
= rEngine
.GetText();
1127 if (aText
.isEmpty())
1129 bool bNumFmtSet
= false;
1130 bRet
= SetNormalString( bNumFmtSet
, rPos
, aText
, bApi
);
1133 bRet
= SetStringCell(rPos
, aText
, !bApi
);
1136 if ( bRet
&& aTester
.NeedsCellAttr() )
1138 const SfxItemSet
& rEditAttr
= aTester
.GetAttribs();
1139 ScPatternAttr
aPattern( rDoc
.GetPool() );
1140 aPattern
.GetFromEditItemSet( &rEditAttr
);
1141 aPattern
.DeleteUnchanged( rDoc
.GetPattern( rPos
.Col(), rPos
.Row(), rPos
.Tab() ) );
1142 aPattern
.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY
); // wasn't removed above if no edit object
1143 if ( aPattern
.GetItemSet().Count() > 0 )
1146 aMark
.SelectTable( rPos
.Tab(), true );
1147 aMark
.SetMarkArea( ScRange( rPos
) );
1148 ApplyAttributes( aMark
, aPattern
, bApi
);
1153 static ScTokenArray
* lcl_ScDocFunc_CreateTokenArrayXML( const OUString
& rText
, const OUString
& rFormulaNmsp
, const formula::FormulaGrammar::Grammar eGrammar
)
1155 ScTokenArray
* pCode
= new ScTokenArray
;
1156 pCode
->AddStringXML( rText
);
1157 if( (eGrammar
== formula::FormulaGrammar::GRAM_EXTERNAL
) && (!rFormulaNmsp
.isEmpty()) )
1158 pCode
->AddStringXML( rFormulaNmsp
);
1162 bool ScDocFunc::SetCellText(
1163 const ScAddress
& rPos
, const OUString
& rText
, bool bInterpret
, bool bEnglish
, bool bApi
,
1164 const formula::FormulaGrammar::Grammar eGrammar
)
1171 ScDocument
& rDoc
= rDocShell
.GetDocument();
1173 ::std::unique_ptr
<ScExternalRefManager::ApiGuard
> pExtRefGuard
;
1175 pExtRefGuard
.reset(new ScExternalRefManager::ApiGuard(&rDoc
));
1177 ScInputStringType aRes
=
1178 ScStringUtil::parseInputString(*rDoc
.GetFormatTable(), rText
, LANGUAGE_ENGLISH_US
);
1180 switch (aRes
.meType
)
1182 case ScInputStringType::Formula
:
1183 bSet
= SetFormulaCell(rPos
, new ScFormulaCell(&rDoc
, rPos
, aRes
.maText
, eGrammar
), !bApi
);
1185 case ScInputStringType::Number
:
1186 bSet
= SetValueCell(rPos
, aRes
.mfValue
, !bApi
);
1188 case ScInputStringType::Text
:
1189 bSet
= SetStringOrEditCell(rPos
, aRes
.maText
, !bApi
);
1195 // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
1197 else if (!rText
.isEmpty())
1199 bSet
= SetStringOrEditCell(rPos
, rText
, !bApi
);
1204 bool bNumFmtSet
= false;
1205 bSet
= SetNormalString( bNumFmtSet
, rPos
, rText
, bApi
);
1210 bool ScDocFunc::ShowNote( const ScAddress
& rPos
, bool bShow
)
1212 ScDocument
& rDoc
= rDocShell
.GetDocument();
1213 ScPostIt
* pNote
= rDoc
.GetNote( rPos
);
1214 if( !pNote
|| (bShow
== pNote
->IsCaptionShown()) ) return false;
1216 // move the caption to internal or hidden layer and create undo action
1217 pNote
->ShowCaption( rPos
, bShow
);
1218 if( rDoc
.IsUndoEnabled() )
1219 rDocShell
.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell
, rPos
, bShow
) );
1221 if (rDoc
.IsStreamValid(rPos
.Tab()))
1222 rDoc
.SetStreamValid(rPos
.Tab(), false);
1224 rDocShell
.SetDocumentModified();
1229 void ScDocFunc::SetNoteText( const ScAddress
& rPos
, const OUString
& rText
, bool bApi
)
1231 ScDocShellModificator
aModificator( rDocShell
);
1233 ScDocument
& rDoc
= rDocShell
.GetDocument();
1234 ScEditableTester
aTester( &rDoc
, rPos
.Tab(), rPos
.Col(),rPos
.Row(), rPos
.Col(),rPos
.Row() );
1235 if (!aTester
.IsEditable())
1238 rDocShell
.ErrorMessage(aTester
.GetMessageId());
1242 OUString aNewText
= convertLineEnd(rText
, GetSystemLineEnd()); //! ist das noetig ???
1244 if( ScPostIt
* pNote
= (!aNewText
.isEmpty()) ? rDoc
.GetOrCreateNote( rPos
) : rDoc
.GetNote(rPos
) )
1245 pNote
->SetText( rPos
, aNewText
);
1249 if (rDoc
.IsStreamValid(rPos
.Tab()))
1250 rDoc
.SetStreamValid(rPos
.Tab(), false);
1252 rDocShell
.PostPaintCell( rPos
);
1253 aModificator
.SetDocumentModified();
1256 void ScDocFunc::ReplaceNote( const ScAddress
& rPos
, const OUString
& rNoteText
, const OUString
* pAuthor
, const OUString
* pDate
, bool bApi
)
1258 ScDocShellModificator
aModificator( rDocShell
);
1259 ScDocument
& rDoc
= rDocShell
.GetDocument();
1260 ScEditableTester
aTester( &rDoc
, rPos
.Tab(), rPos
.Col(),rPos
.Row(), rPos
.Col(),rPos
.Row() );
1261 if (aTester
.IsEditable())
1263 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
1264 ::svl::IUndoManager
* pUndoMgr
= (pDrawLayer
&& rDoc
.IsUndoEnabled()) ? rDocShell
.GetUndoManager() : nullptr;
1266 ScNoteData aOldData
;
1267 ScPostIt
* pOldNote
= rDoc
.ReleaseNote( rPos
);
1270 // ensure existing caption object before draw undo tracking starts
1271 pOldNote
->GetOrCreateCaption( rPos
);
1272 // rescue note data for undo
1273 aOldData
= pOldNote
->GetNoteData();
1276 // collect drawing undo actions for deleting/inserting caption objects
1278 pDrawLayer
->BeginCalcUndo(false);
1280 // delete the note (creates drawing undo action for the caption object)
1283 // create new note (creates drawing undo action for the new caption object)
1284 ScNoteData aNewData
;
1285 if( ScPostIt
* pNewNote
= ScNoteUtil::CreateNoteFromString( rDoc
, rPos
, rNoteText
, false, true ) )
1287 if( pAuthor
) pNewNote
->SetAuthor( *pAuthor
);
1288 if( pDate
) pNewNote
->SetDate( *pDate
);
1289 // rescue note data for undo
1290 aNewData
= pNewNote
->GetNoteData();
1293 // create the undo action
1294 if( pUndoMgr
&& (aOldData
.mpCaption
|| aNewData
.mpCaption
) )
1295 pUndoMgr
->AddUndoAction( new ScUndoReplaceNote( rDocShell
, rPos
, aOldData
, aNewData
, pDrawLayer
->GetCalcUndo() ) );
1297 // repaint cell (to make note marker visible)
1298 rDocShell
.PostPaintCell( rPos
);
1300 if (rDoc
.IsStreamValid(rPos
.Tab()))
1301 rDoc
.SetStreamValid(rPos
.Tab(), false);
1303 aModificator
.SetDocumentModified();
1307 rDocShell
.ErrorMessage(aTester
.GetMessageId());
1311 bool ScDocFunc::ApplyAttributes( const ScMarkData
& rMark
, const ScPatternAttr
& rPattern
,
1314 ScDocument
& rDoc
= rDocShell
.GetDocument();
1315 bool bRecord
= true;
1316 if ( bRecord
&& !rDoc
.IsUndoEnabled() )
1319 bool bImportingXML
= rDoc
.IsImportingXML();
1320 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1321 // #i62483# When loading XML, the check can be skipped altogether.
1322 bool bOnlyNotBecauseOfMatrix
;
1323 if ( !bImportingXML
&& !rDoc
.IsSelectionEditable( rMark
, &bOnlyNotBecauseOfMatrix
)
1324 && !bOnlyNotBecauseOfMatrix
)
1327 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
1331 ScDocShellModificator
aModificator( rDocShell
);
1335 ScRange aMultiRange
;
1336 bool bMulti
= rMark
.IsMultiMarked();
1338 rMark
.GetMultiMarkArea( aMultiRange
);
1340 rMark
.GetMarkArea( aMultiRange
);
1344 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1345 pUndoDoc
->InitUndo( &rDoc
, aMultiRange
.aStart
.Tab(), aMultiRange
.aEnd
.Tab() );
1346 rDoc
.CopyToDocument( aMultiRange
, InsertDeleteFlags::ATTRIB
, bMulti
, pUndoDoc
, &rMark
);
1348 rDocShell
.GetUndoManager()->AddUndoAction(
1349 new ScUndoSelectionAttr(
1351 aMultiRange
.aStart
.Col(), aMultiRange
.aStart
.Row(), aMultiRange
.aStart
.Tab(),
1352 aMultiRange
.aEnd
.Col(), aMultiRange
.aEnd
.Row(), aMultiRange
.aEnd
.Tab(),
1353 pUndoDoc
, bMulti
, &rPattern
) );
1356 // While loading XML it is not necessary to ask HasAttrib. It needs too much time.
1357 sal_uInt16 nExtFlags
= 0;
1358 if ( !bImportingXML
)
1359 rDocShell
.UpdatePaintExt( nExtFlags
, aMultiRange
); // content before the change
1360 rDoc
.ApplySelectionPattern( rPattern
, rMark
);
1361 if ( !bImportingXML
)
1362 rDocShell
.UpdatePaintExt( nExtFlags
, aMultiRange
); // content after the change
1364 if (!AdjustRowHeight( aMultiRange
))
1365 rDocShell
.PostPaint( aMultiRange
, PAINT_GRID
, nExtFlags
);
1366 else if (nExtFlags
& SC_PF_LINES
)
1367 lcl_PaintAbove( rDocShell
, aMultiRange
); // fuer Linien ueber dem Bereich
1369 aModificator
.SetDocumentModified();
1374 bool ScDocFunc::ApplyStyle( const ScMarkData
& rMark
, const OUString
& rStyleName
,
1377 ScDocument
& rDoc
= rDocShell
.GetDocument();
1378 bool bRecord
= true;
1379 if ( bRecord
&& !rDoc
.IsUndoEnabled() )
1382 bool bImportingXML
= rDoc
.IsImportingXML();
1383 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1384 // #i62483# When loading XML, the check can be skipped altogether.
1385 bool bOnlyNotBecauseOfMatrix
;
1386 if ( !bImportingXML
&& !rDoc
.IsSelectionEditable( rMark
, &bOnlyNotBecauseOfMatrix
)
1387 && !bOnlyNotBecauseOfMatrix
)
1390 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
1394 ScStyleSheet
* pStyleSheet
= static_cast<ScStyleSheet
*>( rDoc
.GetStyleSheetPool()->Find(
1395 rStyleName
, SfxStyleFamily::Para
));
1399 ScDocShellModificator
aModificator( rDocShell
);
1401 ScRange aMultiRange
;
1402 bool bMulti
= rMark
.IsMultiMarked();
1404 rMark
.GetMultiMarkArea( aMultiRange
);
1406 rMark
.GetMarkArea( aMultiRange
);
1410 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1411 SCTAB nStartTab
= aMultiRange
.aStart
.Tab();
1412 SCTAB nTabCount
= rDoc
.GetTableCount();
1413 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nStartTab
);
1414 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
1415 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
1416 if (*itr
!= nStartTab
)
1417 pUndoDoc
->AddUndoTab( *itr
, *itr
);
1419 ScRange aCopyRange
= aMultiRange
;
1420 aCopyRange
.aStart
.SetTab(0);
1421 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1422 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, bMulti
, pUndoDoc
, &rMark
);
1424 rDocShell
.GetUndoManager()->AddUndoAction(
1425 new ScUndoSelectionStyle(
1426 &rDocShell
, rMark
, aMultiRange
, rStyleName
, pUndoDoc
) );
1430 rDoc
.ApplySelectionStyle( (ScStyleSheet
&)*pStyleSheet
, rMark
);
1432 if (!AdjustRowHeight( aMultiRange
))
1433 rDocShell
.PostPaint( aMultiRange
, PAINT_GRID
);
1435 aModificator
.SetDocumentModified();
1443 * Check if this insertion attempt would end up cutting one or more pivot
1444 * tables in half, which is not desirable.
1446 * @return true if this insertion can be done safely without shearing any
1447 * existing pivot tables, false otherwise.
1449 bool canInsertCellsByPivot(const ScRange
& rRange
, const ScMarkData
& rMarkData
, InsCellCmd eCmd
, const ScDocument
* pDoc
)
1451 if (!pDoc
->HasPivotTable())
1452 // This document has no pivot tables.
1455 const ScDPCollection
* pDPs
= pDoc
->GetDPCollection();
1456 ScMarkData::const_iterator itBeg
= rMarkData
.begin(), itEnd
= rMarkData
.end();
1458 ScRange
aRange(rRange
); // local copy
1461 case INS_INSROWS_BEFORE
:
1463 aRange
.aStart
.SetCol(0);
1464 aRange
.aEnd
.SetCol(MAXCOL
);
1469 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1471 if (pDPs
->IntersectsTableByColumns(aRange
.aStart
.Col(), aRange
.aEnd
.Col(), aRange
.aStart
.Row(), *it
))
1472 // This column range cuts through at least one pivot table. Not good.
1476 // Start row must be either at the top or above any pivot tables.
1477 if (aRange
.aStart
.Row() < 0)
1478 // I don't know how to handle this case.
1481 if (aRange
.aStart
.Row() == 0)
1482 // First row is always allowed.
1485 ScRange
aTest(aRange
);
1486 aTest
.aStart
.IncRow(-1); // Test one row up.
1487 aTest
.aEnd
.SetRow(aTest
.aStart
.Row());
1488 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1490 aTest
.aStart
.SetTab(*it
);
1491 aTest
.aEnd
.SetTab(*it
);
1492 if (pDPs
->HasTable(aTest
))
1497 case INS_INSCOLS_BEFORE
:
1499 aRange
.aStart
.SetRow(0);
1500 aRange
.aEnd
.SetRow(MAXROW
);
1503 case INS_CELLSRIGHT
:
1505 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1507 if (pDPs
->IntersectsTableByRows(aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Row(), *it
))
1508 // This column range cuts through at least one pivot table. Not good.
1512 // Start row must be either at the top or above any pivot tables.
1513 if (aRange
.aStart
.Col() < 0)
1514 // I don't know how to handle this case.
1517 if (aRange
.aStart
.Col() == 0)
1518 // First row is always allowed.
1521 ScRange
aTest(aRange
);
1522 aTest
.aStart
.IncCol(-1); // Test one column to the left.
1523 aTest
.aEnd
.SetCol(aTest
.aStart
.Col());
1524 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1526 aTest
.aStart
.SetTab(*it
);
1527 aTest
.aEnd
.SetTab(*it
);
1528 if (pDPs
->HasTable(aTest
))
1540 * Check if this deletion attempt would end up cutting one or more pivot
1541 * tables in half, which is not desirable.
1543 * @return true if this deletion can be done safely without shearing any
1544 * existing pivot tables, false otherwise.
1546 bool canDeleteCellsByPivot(const ScRange
& rRange
, const ScMarkData
& rMarkData
, DelCellCmd eCmd
, const ScDocument
* pDoc
)
1548 if (!pDoc
->HasPivotTable())
1549 // This document has no pivot tables.
1552 const ScDPCollection
* pDPs
= pDoc
->GetDPCollection();
1553 ScMarkData::const_iterator itBeg
= rMarkData
.begin(), itEnd
= rMarkData
.end();
1555 ScRange
aRange(rRange
); // local copy
1561 aRange
.aStart
.SetCol(0);
1562 aRange
.aEnd
.SetCol(MAXCOL
);
1567 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1569 if (pDPs
->IntersectsTableByColumns(aRange
.aStart
.Col(), aRange
.aEnd
.Col(), aRange
.aStart
.Row(), *it
))
1570 // This column range cuts through at least one pivot table. Not good.
1574 ScRange
aTest(aRange
);
1575 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1577 aTest
.aStart
.SetTab(*it
);
1578 aTest
.aEnd
.SetTab(*it
);
1579 if (pDPs
->HasTable(aTest
))
1586 aRange
.aStart
.SetRow(0);
1587 aRange
.aEnd
.SetRow(MAXROW
);
1592 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1594 if (pDPs
->IntersectsTableByRows(aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Row(), *it
))
1595 // This column range cuts through at least one pivot table. Not good.
1599 ScRange
aTest(aRange
);
1600 for (ScMarkData::const_iterator it
= itBeg
; it
!= itEnd
; ++it
)
1602 aTest
.aStart
.SetTab(*it
);
1603 aTest
.aEnd
.SetTab(*it
);
1604 if (pDPs
->HasTable(aTest
))
1617 bool ScDocFunc::InsertCells( const ScRange
& rRange
, const ScMarkData
* pTabMark
, InsCellCmd eCmd
,
1618 bool bRecord
, bool bApi
, bool bPartOfPaste
)
1620 ScDocShellModificator
aModificator( rDocShell
);
1622 if (rDocShell
.GetDocument().GetChangeTrack() &&
1623 ((eCmd
== INS_CELLSDOWN
&& (rRange
.aStart
.Col() != 0 || rRange
.aEnd
.Col() != MAXCOL
)) ||
1624 (eCmd
== INS_CELLSRIGHT
&& (rRange
.aStart
.Row() != 0 || rRange
.aEnd
.Row() != MAXROW
))))
1626 // We should not reach this via UI disabled slots.
1628 SAL_WARN("sc.ui","ScDocFunc::InsertCells - no change-tracking of partial cell shift");
1632 ScRange
aTargetRange( rRange
);
1634 // If insertion is for full cols/rows and after the current
1635 // selection, then shift the range accordingly
1636 if ( eCmd
== INS_INSROWS_AFTER
)
1638 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
1639 if (!aTargetRange
.Move(0, rRange
.aEnd
.Row() - rRange
.aStart
.Row() + 1, 0, aErrorRange
))
1641 assert(!"can't move");
1644 if ( eCmd
== INS_INSCOLS_AFTER
)
1646 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
1647 if (!aTargetRange
.Move(rRange
.aEnd
.Col() - rRange
.aStart
.Col() + 1, 0, 0, aErrorRange
))
1649 assert(!"can't move");
1653 SCCOL nStartCol
= aTargetRange
.aStart
.Col();
1654 SCROW nStartRow
= aTargetRange
.aStart
.Row();
1655 SCTAB nStartTab
= aTargetRange
.aStart
.Tab();
1656 SCCOL nEndCol
= aTargetRange
.aEnd
.Col();
1657 SCROW nEndRow
= aTargetRange
.aEnd
.Row();
1658 SCTAB nEndTab
= aTargetRange
.aEnd
.Tab();
1660 if ( !ValidRow(nStartRow
) || !ValidRow(nEndRow
) )
1662 OSL_FAIL("invalid row in InsertCells");
1666 ScDocument
& rDoc
= rDocShell
.GetDocument();
1667 SCTAB nTabCount
= rDoc
.GetTableCount();
1668 SCCOL nPaintStartCol
= nStartCol
;
1669 SCROW nPaintStartRow
= nStartRow
;
1670 SCCOL nPaintEndCol
= nEndCol
;
1671 SCROW nPaintEndRow
= nEndRow
;
1672 sal_uInt16 nPaintFlags
= PAINT_GRID
;
1676 ScTabViewShell
* pViewSh
= rDocShell
.GetBestViewShell(); //preserve current cursor position
1677 SCCOL nCursorCol
= 0;
1678 SCROW nCursorRow
= 0;
1681 nCursorCol
= pViewSh
->GetViewData().GetCurX();
1682 nCursorRow
= pViewSh
->GetViewData().GetCurY();
1685 if (bRecord
&& !rDoc
.IsUndoEnabled())
1694 for( i
=0; i
<nTabCount
; i
++ )
1696 if( !rDoc
.IsScenario(i
) )
1699 if( nCount
== nEndTab
+1 )
1701 aMark
.SelectTable( i
, true );
1708 ScMarkData
aFullMark( aMark
); // including scenario sheets
1709 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
1710 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
1711 for( SCTAB j
= *itr
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
1712 aFullMark
.SelectTable( j
, true );
1714 SCTAB nSelCount
= aMark
.GetSelectCount();
1716 // Adjust also related scenarios
1718 SCCOL nMergeTestStartCol
= nStartCol
;
1719 SCROW nMergeTestStartRow
= nStartRow
;
1720 SCCOL nMergeTestEndCol
= nEndCol
;
1721 SCROW nMergeTestEndRow
= nEndRow
;
1723 ScRange
aExtendMergeRange( aTargetRange
);
1725 if( aTargetRange
.aStart
== aTargetRange
.aEnd
&& rDoc
.HasAttrib(aTargetRange
, HASATTR_MERGED
) )
1727 rDoc
.ExtendMerge( aExtendMergeRange
);
1728 rDoc
.ExtendOverlapped( aExtendMergeRange
);
1729 nMergeTestEndCol
= aExtendMergeRange
.aEnd
.Col();
1730 nMergeTestEndRow
= aExtendMergeRange
.aEnd
.Row();
1731 nPaintEndCol
= nMergeTestEndCol
;
1732 nPaintEndRow
= nMergeTestEndRow
;
1735 if ( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
)
1737 nMergeTestStartCol
= 0;
1738 nMergeTestEndCol
= MAXCOL
;
1740 if ( eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSCOLS_AFTER
)
1742 nMergeTestStartRow
= 0;
1743 nMergeTestEndRow
= MAXROW
;
1745 if ( eCmd
== INS_CELLSDOWN
)
1746 nMergeTestEndRow
= MAXROW
;
1747 if ( eCmd
== INS_CELLSRIGHT
)
1748 nMergeTestEndCol
= MAXCOL
;
1750 bool bNeedRefresh
= false;
1752 SCCOL nEditTestEndCol
= (eCmd
==INS_INSCOLS_BEFORE
|| eCmd
==INS_INSCOLS_AFTER
) ? MAXCOL
: nMergeTestEndCol
;
1753 SCROW nEditTestEndRow
= (eCmd
==INS_INSROWS_BEFORE
|| eCmd
==INS_INSROWS_AFTER
) ? MAXROW
: nMergeTestEndRow
;
1754 ScEditableTester
aTester( &rDoc
, nMergeTestStartCol
, nMergeTestStartRow
, nEditTestEndCol
, nEditTestEndRow
, aMark
);
1755 if (!aTester
.IsEditable())
1758 rDocShell
.ErrorMessage(aTester
.GetMessageId());
1762 // Check if this insertion is allowed with respect to pivot table.
1763 if (!canInsertCellsByPivot(aTargetRange
, aMark
, eCmd
, &rDoc
))
1766 rDocShell
.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE
);
1770 WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
1772 ScDocument
* pRefUndoDoc
= nullptr;
1773 ScRefUndoData
* pUndoData
= nullptr;
1776 pRefUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1777 pRefUndoDoc
->InitUndo( &rDoc
, 0, nTabCount
-1 );
1779 // pRefUndoDoc is filled in InsertCol / InsertRow
1781 pUndoData
= new ScRefUndoData( &rDoc
);
1783 rDoc
.BeginDrawUndo();
1786 // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
1787 // the patch comes from mloiseleur and maoyg
1788 bool bInsertMerge
= false;
1789 std::vector
<ScRange
> qIncreaseRange
;
1790 OUString aUndo
= ScGlobal::GetRscString( STR_UNDO_INSERTCELLS
);
1792 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
);
1793 std::unique_ptr
<ScUndoRemoveMerge
> pUndoRemoveMerge
;
1795 itr
= aMark
.begin();
1796 for (; itr
!= itrEnd
&& nTabCount
; ++itr
)
1799 if( rDoc
.HasAttrib( nMergeTestStartCol
, nMergeTestStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1801 if (eCmd
==INS_CELLSRIGHT
)
1802 bNeedRefresh
= true;
1804 SCCOL nMergeStartCol
= nMergeTestStartCol
;
1805 SCROW nMergeStartRow
= nMergeTestStartRow
;
1806 SCCOL nMergeEndCol
= nMergeTestEndCol
;
1807 SCROW nMergeEndRow
= nMergeTestEndRow
;
1809 rDoc
.ExtendMerge( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
1810 rDoc
.ExtendOverlapped( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
1812 if(( eCmd
== INS_CELLSDOWN
&& ( nMergeStartCol
!= nMergeTestStartCol
|| nMergeEndCol
!= nMergeTestEndCol
)) ||
1813 (eCmd
== INS_CELLSRIGHT
&& ( nMergeStartRow
!= nMergeTestStartRow
|| nMergeEndRow
!= nMergeTestEndRow
)) )
1816 rDocShell
.ErrorMessage(STR_MSSG_INSERTCELLS_0
);
1817 rDocShell
.GetUndoManager()->LeaveListAction();
1822 SCCOL nTestCol
= -1;
1823 SCROW nTestRow1
= -1;
1824 SCROW nTestRow2
= -1;
1826 ScDocAttrIterator
aTestIter( &rDoc
, i
, nMergeTestStartCol
, nMergeTestStartRow
, nMergeTestEndCol
, nMergeTestEndRow
);
1827 ScRange
aExtendRange( nMergeTestStartCol
, nMergeTestStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
);
1828 const ScPatternAttr
* pPattern
= nullptr;
1829 const ScMergeFlagAttr
* pMergeFlagAttr
= nullptr;
1830 while ( ( pPattern
= aTestIter
.GetNext( nTestCol
, nTestRow1
, nTestRow2
) ) != nullptr )
1832 const ScMergeAttr
* pMergeFlag
= static_cast<const ScMergeAttr
*>( &pPattern
->GetItem(ATTR_MERGE
) );
1833 pMergeFlagAttr
= static_cast<const ScMergeFlagAttr
*>( &pPattern
->GetItem(ATTR_MERGE_FLAG
) );
1834 ScMF nNewFlags
= pMergeFlagAttr
->GetValue() & ( ScMF::Hor
| ScMF::Ver
);
1835 if( ( pMergeFlag
&& pMergeFlag
->IsMerged() ) || nNewFlags
== ScMF::Hor
|| nNewFlags
== ScMF::Ver
)
1837 ScRange
aRange( nTestCol
, nTestRow1
, i
);
1838 rDoc
.ExtendOverlapped(aRange
);
1839 rDoc
.ExtendMerge(aRange
, true);
1841 if( nTestRow1
< nTestRow2
&& nNewFlags
== ScMF::Hor
)
1843 for( SCROW nTestRow
= nTestRow1
; nTestRow
<= nTestRow2
; nTestRow
++ )
1845 ScRange
aTestRange( nTestCol
, nTestRow
, i
);
1846 rDoc
.ExtendOverlapped( aTestRange
);
1847 rDoc
.ExtendMerge( aTestRange
, true);
1848 ScRange
aMergeRange( aTestRange
.aStart
.Col(),aTestRange
.aStart
.Row(), i
);
1849 if( !aExtendRange
.In( aMergeRange
) )
1851 qIncreaseRange
.push_back( aTestRange
);
1852 bInsertMerge
= true;
1858 ScRange
aMergeRange( aRange
.aStart
.Col(),aRange
.aStart
.Row(), i
);
1859 if( !aExtendRange
.In( aMergeRange
) )
1861 qIncreaseRange
.push_back( aRange
);
1863 bInsertMerge
= true;
1870 if( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
|| eCmd
== INS_CELLSDOWN
)
1872 nStartRow
= aExtendMergeRange
.aStart
.Row();
1873 nEndRow
= aExtendMergeRange
.aEnd
.Row();
1875 if( eCmd
== INS_CELLSDOWN
)
1876 nEndCol
= nMergeTestEndCol
;
1883 else if( eCmd
== INS_CELLSRIGHT
|| eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSCOLS_AFTER
)
1886 nStartCol
= aExtendMergeRange
.aStart
.Col();
1887 nEndCol
= aExtendMergeRange
.aEnd
.Col();
1888 if( eCmd
== INS_CELLSRIGHT
)
1890 nEndRow
= nMergeTestEndRow
;
1899 if( !qIncreaseRange
.empty() )
1901 if (bRecord
&& !pUndoRemoveMerge
)
1903 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
1904 pUndoDoc
->InitUndo( &rDoc
, *aMark
.begin(), *aMark
.rbegin());
1905 pUndoRemoveMerge
.reset( new ScUndoRemoveMerge( &rDocShell
, rRange
, pUndoDoc
));
1908 for( ::std::vector
<ScRange
>::const_iterator
iIter( qIncreaseRange
.begin()); iIter
!= qIncreaseRange
.end(); ++iIter
)
1910 ScRange
aRange( *iIter
);
1911 if( rDoc
.HasAttrib( aRange
, HASATTR_OVERLAPPED
| HASATTR_MERGED
) )
1913 UnmergeCells( aRange
, bRecord
, pUndoRemoveMerge
.get() );
1921 rDocShell
.ErrorMessage(STR_MSSG_INSERTCELLS_0
);
1922 rDocShell
.GetUndoManager()->LeaveListAction();
1929 if (bRecord
&& pUndoRemoveMerge
)
1931 rDocShell
.GetUndoManager()->AddUndoAction( pUndoRemoveMerge
.release());
1937 bSuccess
= rDoc
.InsertRow( nStartCol
, 0, nEndCol
, MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
, &aFullMark
);
1938 nPaintEndRow
= MAXROW
;
1940 case INS_INSROWS_BEFORE
:
1941 case INS_INSROWS_AFTER
:
1942 bSuccess
= rDoc
.InsertRow( 0, 0, MAXCOL
, MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
, &aFullMark
);
1944 nPaintEndCol
= MAXCOL
;
1945 nPaintEndRow
= MAXROW
;
1946 nPaintFlags
|= PAINT_LEFT
;
1948 case INS_CELLSRIGHT
:
1949 bSuccess
= rDoc
.InsertCol( nStartRow
, 0, nEndRow
, MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
, &aFullMark
);
1950 nPaintEndCol
= MAXCOL
;
1952 case INS_INSCOLS_BEFORE
:
1953 case INS_INSCOLS_AFTER
:
1954 bSuccess
= rDoc
.InsertCol( 0, 0, MAXROW
, MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
, &aFullMark
);
1956 nPaintEndRow
= MAXROW
;
1957 nPaintEndCol
= MAXCOL
;
1958 nPaintFlags
|= PAINT_TOP
;
1961 OSL_FAIL("Falscher Code beim Einfuegen");
1972 SCTAB
* pTabs
= new SCTAB
[nSelCount
];
1973 SCTAB
* pScenarios
= new SCTAB
[nSelCount
];
1975 itr
= aMark
.begin();
1976 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
1979 for( SCTAB j
=*itr
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
1982 pScenarios
[nUndoPos
] = nCount
;
1983 pTabs
[nUndoPos
] = *itr
;
1989 rDocShell
.GetUndoManager()->LeaveListAction();
1992 rDocShell
.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
1993 &rDocShell
, ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
),
1994 nUndoPos
, pTabs
, pScenarios
, eCmd
, pRefUndoDoc
, pUndoData
, bPartOfPaste
) );
1997 // #i8302 : we remerge growing ranges, with the new part inserted
1999 while( !qIncreaseRange
.empty() )
2001 ScRange aRange
= qIncreaseRange
.back();
2002 if( !rDoc
.HasAttrib( aRange
, HASATTR_OVERLAPPED
| HASATTR_MERGED
) )
2007 case INS_INSROWS_BEFORE
:
2008 case INS_INSROWS_AFTER
:
2009 aRange
.aEnd
.IncRow(static_cast<SCsCOL
>(nEndRow
-nStartRow
+1));
2011 case INS_CELLSRIGHT
:
2012 case INS_INSCOLS_BEFORE
:
2013 case INS_INSCOLS_AFTER
:
2014 aRange
.aEnd
.IncCol(static_cast<SCsCOL
>(nEndCol
-nStartCol
+1));
2019 ScCellMergeOption
aMergeOption(
2020 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2021 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
2022 aMergeOption
.maTabs
.insert(aRange
.aStart
.Tab());
2023 MergeCells(aMergeOption
, false, true, true);
2025 qIncreaseRange
.pop_back();
2029 rDocShell
.GetUndoManager()->LeaveListAction();
2031 itr
= aMark
.begin();
2032 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2035 rDoc
.SetDrawPageSize(i
);
2038 rDoc
.ExtendMerge( nMergeTestStartCol
, nMergeTestStartRow
, nMergeTestEndCol
, nMergeTestEndRow
, i
, true );
2040 rDoc
.RefreshAutoFilter( nMergeTestStartCol
, nMergeTestStartRow
, nMergeTestEndCol
, nMergeTestEndRow
, i
);
2042 if ( eCmd
== INS_INSROWS_BEFORE
||eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
||eCmd
== INS_INSCOLS_AFTER
)
2043 rDoc
.UpdatePageBreaks( i
);
2045 sal_uInt16 nExtFlags
= 0;
2046 rDocShell
.UpdatePaintExt( nExtFlags
, nPaintStartCol
, nPaintStartRow
, i
, nPaintEndCol
, nPaintEndRow
, i
);
2048 SCTAB nScenarioCount
= 0;
2050 for( SCTAB j
= i
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2053 bool bAdjusted
= ( eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
) ?
2054 AdjustRowHeight(ScRange(0, nStartRow
, i
, MAXCOL
, nEndRow
, i
+nScenarioCount
)) :
2055 AdjustRowHeight(ScRange(0, nPaintStartRow
, i
, MAXCOL
, nPaintEndRow
, i
+nScenarioCount
));
2058 // paint only what is not done by AdjustRowHeight
2059 if (nPaintFlags
& PAINT_TOP
)
2060 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, i
, nPaintEndCol
, nPaintEndRow
, i
+nScenarioCount
, PAINT_TOP
);
2063 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, i
, nPaintEndCol
, nPaintEndRow
, i
+nScenarioCount
, nPaintFlags
, nExtFlags
);
2070 while( !qIncreaseRange
.empty() )
2072 ScRange aRange
= qIncreaseRange
.back();
2073 ScCellMergeOption
aMergeOption(
2074 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
2075 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
2076 MergeCells(aMergeOption
, false, true, true);
2077 qIncreaseRange
.pop_back();
2082 pViewSh
->MarkRange( aTargetRange
, false );
2083 pViewSh
->SetCursor( nCursorCol
, nCursorRow
);
2087 rDocShell
.GetUndoManager()->LeaveListAction();
2088 rDocShell
.GetUndoManager()->RemoveLastUndoAction();
2093 rDocShell
.ErrorMessage(STR_INSERT_FULL
); // Spalte/Zeile voll
2096 aModificator
.SetDocumentModified();
2098 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) );
2102 bool ScDocFunc::DeleteCells( const ScRange
& rRange
, const ScMarkData
* pTabMark
, DelCellCmd eCmd
,
2105 ScDocShellModificator
aModificator( rDocShell
);
2107 if (rDocShell
.GetDocument().GetChangeTrack() &&
2108 ((eCmd
== DEL_CELLSUP
&& (rRange
.aStart
.Col() != 0 || rRange
.aEnd
.Col() != MAXCOL
)) ||
2109 (eCmd
== DEL_CELLSLEFT
&& (rRange
.aStart
.Row() != 0 || rRange
.aEnd
.Row() != MAXROW
))))
2111 // We should not reach this via UI disabled slots.
2113 SAL_WARN("sc.ui","ScDocFunc::DeleteCells - no change-tracking of partial cell shift");
2117 SCCOL nStartCol
= rRange
.aStart
.Col();
2118 SCROW nStartRow
= rRange
.aStart
.Row();
2119 SCTAB nStartTab
= rRange
.aStart
.Tab();
2120 SCCOL nEndCol
= rRange
.aEnd
.Col();
2121 SCROW nEndRow
= rRange
.aEnd
.Row();
2122 SCTAB nEndTab
= rRange
.aEnd
.Tab();
2124 if ( !ValidRow(nStartRow
) || !ValidRow(nEndRow
) )
2126 OSL_FAIL("invalid row in DeleteCells");
2130 ScDocument
& rDoc
= rDocShell
.GetDocument();
2131 SCTAB nTabCount
= rDoc
.GetTableCount();
2132 SCCOL nPaintStartCol
= nStartCol
;
2133 SCROW nPaintStartRow
= nStartRow
;
2134 SCCOL nPaintEndCol
= nEndCol
;
2135 SCROW nPaintEndRow
= nEndRow
;
2136 sal_uInt16 nPaintFlags
= PAINT_GRID
;
2138 bool bRecord
= true;
2139 if (bRecord
&& !rDoc
.IsUndoEnabled())
2148 for(SCTAB i
=0; i
<nTabCount
; i
++ )
2150 if( !rDoc
.IsScenario(i
) )
2153 if( nCount
== nEndTab
+1 )
2155 aMark
.SelectTable(i
, true);
2162 ScMarkData
aFullMark( aMark
); // including scenario sheets
2163 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
2164 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2165 for( SCTAB j
= *itr
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2166 aFullMark
.SelectTable( j
, true );
2168 SCTAB nSelCount
= aMark
.GetSelectCount();
2170 SCCOL nUndoStartCol
= nStartCol
;
2171 SCROW nUndoStartRow
= nStartRow
;
2172 SCCOL nUndoEndCol
= nEndCol
;
2173 SCROW nUndoEndRow
= nEndRow
;
2175 ScRange
aExtendMergeRange( rRange
);
2177 if( rRange
.aStart
== rRange
.aEnd
&& rDoc
.HasAttrib(rRange
, HASATTR_MERGED
) )
2179 rDoc
.ExtendMerge( aExtendMergeRange
);
2180 rDoc
.ExtendOverlapped( aExtendMergeRange
);
2181 nUndoEndCol
= aExtendMergeRange
.aEnd
.Col();
2182 nUndoEndRow
= aExtendMergeRange
.aEnd
.Row();
2183 nPaintEndCol
= nUndoEndCol
;
2184 nPaintEndRow
= nUndoEndRow
;
2187 if (eCmd
==DEL_DELROWS
)
2190 nUndoEndCol
= MAXCOL
;
2192 if (eCmd
==DEL_DELCOLS
)
2195 nUndoEndRow
= MAXROW
;
2199 SCCOL nEditTestEndX
= nUndoEndCol
;
2200 if ( eCmd
==DEL_DELCOLS
|| eCmd
==DEL_CELLSLEFT
)
2201 nEditTestEndX
= MAXCOL
;
2202 SCROW nEditTestEndY
= nUndoEndRow
;
2203 if ( eCmd
==DEL_DELROWS
|| eCmd
==DEL_CELLSUP
)
2204 nEditTestEndY
= MAXROW
;
2205 ScEditableTester
aTester( &rDoc
, nUndoStartCol
, nUndoStartRow
, nEditTestEndX
, nEditTestEndY
, aMark
);
2206 if (!aTester
.IsEditable())
2209 rDocShell
.ErrorMessage(aTester
.GetMessageId());
2213 if (!canDeleteCellsByPivot(rRange
, aMark
, eCmd
, &rDoc
))
2216 rDocShell
.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE
);
2219 // Test zusammengefasste
2221 SCCOL nMergeTestEndCol
= (eCmd
==DEL_CELLSLEFT
) ? MAXCOL
: nUndoEndCol
;
2222 SCROW nMergeTestEndRow
= (eCmd
==DEL_CELLSUP
) ? MAXROW
: nUndoEndRow
;
2223 SCCOL nExtendStartCol
= nUndoStartCol
;
2224 SCROW nExtendStartRow
= nUndoStartRow
;
2225 bool bNeedRefresh
= false;
2227 //Issue 8302 want to be able to insert into the middle of merged cells
2228 //the patch comes from maoyg
2229 ::std::vector
<ScRange
> qDecreaseRange
;
2230 bool bDeletingMerge
= false;
2231 OUString aUndo
= ScGlobal::GetRscString( STR_UNDO_DELETECELLS
);
2233 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
);
2234 std::unique_ptr
<ScUndoRemoveMerge
> pUndoRemoveMerge
;
2236 itr
= aMark
.begin();
2237 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2240 if ( rDoc
.HasAttrib( nUndoStartCol
, nUndoStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
, HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2242 SCCOL nMergeStartCol
= nUndoStartCol
;
2243 SCROW nMergeStartRow
= nUndoStartRow
;
2244 SCCOL nMergeEndCol
= nMergeTestEndCol
;
2245 SCROW nMergeEndRow
= nMergeTestEndRow
;
2247 rDoc
.ExtendMerge( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
2248 rDoc
.ExtendOverlapped( nMergeStartCol
, nMergeStartRow
, nMergeEndCol
, nMergeEndRow
, i
);
2249 if( ( eCmd
== DEL_CELLSUP
&& ( nMergeStartCol
!= nUndoStartCol
|| nMergeEndCol
!= nMergeTestEndCol
))||
2250 ( eCmd
== DEL_CELLSLEFT
&& ( nMergeStartRow
!= nUndoStartRow
|| nMergeEndRow
!= nMergeTestEndRow
)))
2253 rDocShell
.ErrorMessage(STR_MSSG_DELETECELLS_0
);
2254 rDocShell
.GetUndoManager()->LeaveListAction();
2258 nExtendStartCol
= nMergeStartCol
;
2259 nExtendStartRow
= nMergeStartRow
;
2260 SCCOL nTestCol
= -1;
2261 SCROW nTestRow1
= -1;
2262 SCROW nTestRow2
= -1;
2264 ScDocAttrIterator
aTestIter( &rDoc
, i
, nUndoStartCol
, nUndoStartRow
, nMergeTestEndCol
, nMergeTestEndRow
);
2265 ScRange
aExtendRange( nUndoStartCol
, nUndoStartRow
, i
, nMergeTestEndCol
, nMergeTestEndRow
, i
);
2266 const ScPatternAttr
* pPattern
= nullptr;
2267 const ScMergeFlagAttr
* pMergeFlagAttr
= nullptr;
2268 while ( ( pPattern
= aTestIter
.GetNext( nTestCol
, nTestRow1
, nTestRow2
) ) != nullptr )
2270 const ScMergeAttr
* pMergeFlag
= static_cast<const ScMergeAttr
*>( &pPattern
->GetItem( ATTR_MERGE
) );
2271 pMergeFlagAttr
= static_cast<const ScMergeFlagAttr
*>( &pPattern
->GetItem( ATTR_MERGE_FLAG
) );
2272 ScMF nNewFlags
= pMergeFlagAttr
->GetValue() & ( ScMF::Hor
| ScMF::Ver
);
2273 if( ( pMergeFlag
&& pMergeFlag
->IsMerged() ) || nNewFlags
== ScMF::Hor
|| nNewFlags
== ScMF::Ver
)
2275 ScRange
aRange( nTestCol
, nTestRow1
, i
);
2276 rDoc
.ExtendOverlapped( aRange
);
2277 rDoc
.ExtendMerge( aRange
, true );
2279 if( nTestRow1
< nTestRow2
&& nNewFlags
== ScMF::Hor
)
2281 for( SCROW nTestRow
= nTestRow1
; nTestRow
<= nTestRow2
; nTestRow
++ )
2283 ScRange
aTestRange( nTestCol
, nTestRow
, i
);
2284 rDoc
.ExtendOverlapped( aTestRange
);
2285 rDoc
.ExtendMerge( aTestRange
, true );
2286 ScRange
aMergeRange( aTestRange
.aStart
.Col(),aTestRange
.aStart
.Row(), i
);
2287 if( !aExtendRange
.In( aMergeRange
) )
2289 qDecreaseRange
.push_back( aTestRange
);
2290 bDeletingMerge
= true;
2296 ScRange
aMergeRange( aRange
.aStart
.Col(),aRange
.aStart
.Row(), i
);
2297 if( !aExtendRange
.In( aMergeRange
) )
2299 qDecreaseRange
.push_back( aRange
);
2301 bDeletingMerge
= true;
2306 if( bDeletingMerge
)
2309 if( eCmd
== DEL_DELROWS
|| eCmd
== DEL_CELLSUP
)
2311 nStartRow
= aExtendMergeRange
.aStart
.Row();
2312 nEndRow
= aExtendMergeRange
.aEnd
.Row();
2313 bNeedRefresh
= true;
2315 if( eCmd
== DEL_CELLSUP
)
2317 nEndCol
= aExtendMergeRange
.aEnd
.Col();
2325 else if( eCmd
== DEL_CELLSLEFT
|| eCmd
== DEL_DELCOLS
)
2328 nStartCol
= aExtendMergeRange
.aStart
.Col();
2329 nEndCol
= aExtendMergeRange
.aEnd
.Col();
2330 if( eCmd
== DEL_CELLSLEFT
)
2332 nEndRow
= aExtendMergeRange
.aEnd
.Row();
2333 bNeedRefresh
= true;
2342 if( !qDecreaseRange
.empty() )
2344 if (bRecord
&& !pUndoRemoveMerge
)
2346 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
2347 pUndoDoc
->InitUndo( &rDoc
, *aMark
.begin(), *aMark
.rbegin());
2348 pUndoRemoveMerge
.reset( new ScUndoRemoveMerge( &rDocShell
, rRange
, pUndoDoc
));
2351 for( ::std::vector
<ScRange
>::const_iterator
iIter( qDecreaseRange
.begin()); iIter
!= qDecreaseRange
.end(); ++iIter
)
2353 ScRange
aRange( *iIter
);
2354 if( rDoc
.HasAttrib( aRange
, HASATTR_OVERLAPPED
| HASATTR_MERGED
) )
2356 UnmergeCells( aRange
, bRecord
, pUndoRemoveMerge
.get() );
2364 rDocShell
.ErrorMessage(STR_MSSG_DELETECELLS_0
);
2365 rDocShell
.GetUndoManager()->LeaveListAction();
2371 if (bRecord
&& pUndoRemoveMerge
)
2373 rDocShell
.GetUndoManager()->AddUndoAction( pUndoRemoveMerge
.release());
2378 WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
2380 ScDocument
* pUndoDoc
= nullptr;
2381 ScDocument
* pRefUndoDoc
= nullptr;
2382 ScRefUndoData
* pUndoData
= nullptr;
2385 // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
2386 // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
2388 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
2389 pUndoDoc
->InitUndo( &rDoc
, 0, nTabCount
-1, (eCmd
==DEL_DELCOLS
), (eCmd
==DEL_DELROWS
) );
2390 itr
= aMark
.begin();
2391 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2393 SCTAB nScenarioCount
= 0;
2395 for( SCTAB j
= *itr
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2398 rDoc
.CopyToDocument( nUndoStartCol
, nUndoStartRow
, *itr
, nUndoEndCol
, nUndoEndRow
, *itr
+nScenarioCount
,
2399 InsertDeleteFlags::ALL
| InsertDeleteFlags::NOCAPTIONS
, false, pUndoDoc
);
2402 pRefUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
2403 pRefUndoDoc
->InitUndo( &rDoc
, 0, nTabCount
-1 );
2405 pUndoData
= new ScRefUndoData( &rDoc
);
2407 rDoc
.BeginDrawUndo();
2410 sal_uInt16 nExtFlags
= 0;
2411 itr
= aMark
.begin();
2412 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2414 rDocShell
.UpdatePaintExt( nExtFlags
, nStartCol
, nStartRow
, *itr
, nEndCol
, nEndRow
, *itr
);
2417 bool bUndoOutline
= false;
2421 rDoc
.DeleteRow( nStartCol
, 0, nEndCol
, MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
, nullptr, &aFullMark
);
2422 nPaintEndRow
= MAXROW
;
2425 rDoc
.DeleteRow( 0, 0, MAXCOL
, MAXTAB
, nStartRow
, static_cast<SCSIZE
>(nEndRow
-nStartRow
+1), pRefUndoDoc
, &bUndoOutline
, &aFullMark
);
2427 nPaintEndCol
= MAXCOL
;
2428 nPaintEndRow
= MAXROW
;
2429 nPaintFlags
|= PAINT_LEFT
;
2432 rDoc
.DeleteCol( nStartRow
, 0, nEndRow
, MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
, nullptr, &aFullMark
);
2433 nPaintEndCol
= MAXCOL
;
2436 rDoc
.DeleteCol( 0, 0, MAXROW
, MAXTAB
, nStartCol
, static_cast<SCSIZE
>(nEndCol
-nStartCol
+1), pRefUndoDoc
, &bUndoOutline
, &aFullMark
);
2438 nPaintEndRow
= MAXROW
;
2439 nPaintEndCol
= MAXCOL
;
2440 nPaintFlags
|= PAINT_TOP
;
2443 OSL_FAIL("Falscher Code beim Loeschen");
2447 //! Test, ob Outline in Groesse geaendert
2451 itr
= aFullMark
.begin();
2452 itrEnd
= aFullMark
.end();
2453 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2454 pRefUndoDoc
->DeleteAreaTab(nUndoStartCol
,nUndoStartRow
,nUndoEndCol
,nUndoEndRow
, *itr
, InsertDeleteFlags::ALL
);
2456 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2457 pUndoDoc
->AddUndoTab( 0, nTabCount
-1 );
2459 // kopieren mit bColRowFlags=false (#54194#)
2460 pRefUndoDoc
->CopyToDocument(0,0,0,MAXCOL
,MAXROW
,MAXTAB
,InsertDeleteFlags::FORMULA
,false,pUndoDoc
,nullptr,false);
2463 SCTAB
* pTabs
= new SCTAB
[nSelCount
];
2464 SCTAB
* pScenarios
= new SCTAB
[nSelCount
];
2467 itr
= aMark
.begin();
2468 itrEnd
= aMark
.end();
2469 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2472 for( SCTAB j
=*itr
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2475 pScenarios
[nUndoPos
] = nCount
;
2476 pTabs
[nUndoPos
] = *itr
;
2480 if( !bDeletingMerge
)
2482 rDocShell
.GetUndoManager()->LeaveListAction();
2485 rDocShell
.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
2486 &rDocShell
, ScRange( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
),nUndoPos
, pTabs
, pScenarios
,
2487 eCmd
, pUndoDoc
, pUndoData
) );
2490 // #i8302 want to be able to insert into the middle of merged cells
2491 // the patch comes from maoyg
2493 while( !qDecreaseRange
.empty() )
2495 ScRange aRange
= qDecreaseRange
.back();
2497 long nDecreaseRowCount
= 0;
2498 long nDecreaseColCount
= 0;
2499 if( eCmd
== DEL_CELLSUP
|| eCmd
== DEL_DELROWS
)
2501 if( nStartRow
>= aRange
.aStart
.Row() && nStartRow
<= aRange
.aEnd
.Row() && nEndRow
>= aRange
.aStart
.Row() && nEndRow
<= aRange
.aEnd
.Row() )
2502 nDecreaseRowCount
= nEndRow
-nStartRow
+1;
2503 else if( nStartRow
>= aRange
.aStart
.Row() && nStartRow
<= aRange
.aEnd
.Row() && nEndRow
>= aRange
.aStart
.Row() && nEndRow
>= aRange
.aEnd
.Row() )
2504 nDecreaseRowCount
= aRange
.aEnd
.Row()-nStartRow
+1;
2505 else if( nStartRow
>= aRange
.aStart
.Row() && nStartRow
>= aRange
.aEnd
.Row() && nEndRow
>= aRange
.aStart
.Row() && nEndRow
<= aRange
.aEnd
.Row() )
2506 nDecreaseRowCount
= aRange
.aEnd
.Row()-nEndRow
+1;
2508 else if( eCmd
== DEL_CELLSLEFT
|| eCmd
== DEL_DELCOLS
)
2510 if( nStartCol
>= aRange
.aStart
.Col() && nStartCol
<= aRange
.aEnd
.Col() && nEndCol
>= aRange
.aStart
.Col() && nEndCol
<= aRange
.aEnd
.Col() )
2511 nDecreaseColCount
= nEndCol
-nStartCol
+1;
2512 else if( nStartCol
>= aRange
.aStart
.Col() && nStartCol
<= aRange
.aEnd
.Col() && nEndCol
>= aRange
.aStart
.Col() && nEndCol
>= aRange
.aEnd
.Col() )
2513 nDecreaseColCount
= aRange
.aEnd
.Col()-nStartCol
+1;
2514 else if( nStartCol
>= aRange
.aStart
.Col() && nStartCol
>= aRange
.aEnd
.Col() && nEndCol
>= aRange
.aStart
.Col() && nEndCol
<= aRange
.aEnd
.Col() )
2515 nDecreaseColCount
= aRange
.aEnd
.Col()-nEndCol
+1;
2522 aRange
.aEnd
.SetRow(static_cast<SCsCOL
>( aRange
.aEnd
.Row()-nDecreaseRowCount
));
2526 aRange
.aEnd
.SetCol(static_cast<SCsCOL
>( aRange
.aEnd
.Col()-nDecreaseColCount
));
2532 if( !rDoc
.HasAttrib( aRange
, HASATTR_OVERLAPPED
| HASATTR_MERGED
) )
2534 ScCellMergeOption
aMergeOption(aRange
);
2535 MergeCells( aMergeOption
, false, true, true );
2537 qDecreaseRange
.pop_back();
2540 if( bDeletingMerge
)
2541 rDocShell
.GetUndoManager()->LeaveListAction();
2545 // #i51445# old merge flag attributes must be deleted also for single cells,
2546 // not only for whole columns/rows
2548 if ( eCmd
==DEL_DELCOLS
|| eCmd
==DEL_CELLSLEFT
)
2549 nMergeTestEndCol
= MAXCOL
;
2550 if ( eCmd
==DEL_DELROWS
|| eCmd
==DEL_CELLSUP
)
2551 nMergeTestEndRow
= MAXROW
;
2552 ScPatternAttr
aPattern( rDoc
.GetPool() );
2553 aPattern
.GetItemSet().Put( ScMergeFlagAttr() );
2555 rDoc
.ApplyPatternArea( nExtendStartCol
, nExtendStartRow
, nMergeTestEndCol
, nMergeTestEndRow
, aMark
, aPattern
);
2557 itr
= aMark
.begin();
2558 itrEnd
= aMark
.end();
2559 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2561 SCTAB nScenarioCount
= 0;
2563 for( SCTAB j
= *itr
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2566 ScRange
aMergedRange( nExtendStartCol
, nExtendStartRow
, *itr
, nMergeTestEndCol
, nMergeTestEndRow
, *itr
+nScenarioCount
);
2567 rDoc
.ExtendMerge( aMergedRange
, true );
2571 itr
= aMark
.begin();
2572 itrEnd
= aMark
.end();
2573 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
2575 rDoc
.SetDrawPageSize(*itr
);
2577 if ( eCmd
== DEL_DELCOLS
|| eCmd
== DEL_DELROWS
)
2578 rDoc
.UpdatePageBreaks( *itr
);
2580 rDocShell
.UpdatePaintExt( nExtFlags
, nPaintStartCol
, nPaintStartRow
, *itr
, nPaintEndCol
, nPaintEndRow
, *itr
);
2582 SCTAB nScenarioCount
= 0;
2584 for( SCTAB j
= *itr
+1; j
<nTabCount
&& rDoc
.IsScenario(j
); j
++ )
2587 // ganze Zeilen loeschen: nichts anpassen
2588 if ( eCmd
== DEL_DELROWS
|| !AdjustRowHeight(ScRange( 0, nPaintStartRow
, *itr
, MAXCOL
, nPaintEndRow
, *itr
+nScenarioCount
)) )
2589 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, *itr
, nPaintEndCol
, nPaintEndRow
, *itr
+nScenarioCount
, nPaintFlags
, nExtFlags
);
2592 // paint only what is not done by AdjustRowHeight
2593 if (nExtFlags
& SC_PF_LINES
)
2594 lcl_PaintAbove( rDocShell
, ScRange( nPaintStartCol
, nPaintStartRow
, *itr
, nPaintEndCol
, nPaintEndRow
, *itr
+nScenarioCount
) );
2595 if (nPaintFlags
& PAINT_TOP
)
2596 rDocShell
.PostPaint( nPaintStartCol
, nPaintStartRow
, *itr
, nPaintEndCol
, nPaintEndRow
, *itr
+nScenarioCount
, PAINT_TOP
);
2600 aModificator
.SetDocumentModified();
2602 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) );
2607 bool ScDocFunc::MoveBlock( const ScRange
& rSource
, const ScAddress
& rDestPos
,
2608 bool bCut
, bool bRecord
, bool bPaint
, bool bApi
)
2610 ScDocShellModificator
aModificator( rDocShell
);
2612 SCCOL nStartCol
= rSource
.aStart
.Col();
2613 SCROW nStartRow
= rSource
.aStart
.Row();
2614 SCTAB nStartTab
= rSource
.aStart
.Tab();
2615 SCCOL nEndCol
= rSource
.aEnd
.Col();
2616 SCROW nEndRow
= rSource
.aEnd
.Row();
2617 SCTAB nEndTab
= rSource
.aEnd
.Tab();
2618 SCCOL nDestCol
= rDestPos
.Col();
2619 SCROW nDestRow
= rDestPos
.Row();
2620 SCTAB nDestTab
= rDestPos
.Tab();
2622 if ( !ValidRow(nStartRow
) || !ValidRow(nEndRow
) || !ValidRow(nDestRow
) )
2624 OSL_FAIL("invalid row in MoveBlock");
2628 // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
2629 bool bScenariosAdded
= false;
2630 ScDocument
& rDoc
= rDocShell
.GetDocument();
2631 if (bRecord
&& !rDoc
.IsUndoEnabled())
2634 SCTAB nTabCount
= rDoc
.GetTableCount();
2635 if ( nDestTab
== nStartTab
&& !rDoc
.IsScenario(nEndTab
) )
2636 while ( nEndTab
+1 < nTabCount
&& rDoc
.IsScenario(nEndTab
+1) )
2639 bScenariosAdded
= true;
2642 SCTAB nSrcTabCount
= nEndTab
-nStartTab
+1;
2643 SCTAB nDestEndTab
= nDestTab
+nSrcTabCount
-1;
2646 ScDocument
* pClipDoc
= new ScDocument( SCDOCMODE_CLIP
);
2648 ScMarkData aSourceMark
;
2649 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2650 aSourceMark
.SelectTable( nTab
, true ); // Source selektieren
2651 aSourceMark
.SetMarkArea( rSource
);
2653 ScDocShellRef aDragShellRef
;
2654 if ( rDoc
.HasOLEObjectsInArea( rSource
) )
2656 aDragShellRef
= new ScDocShell
; // DocShell needs a Ref immediately
2657 aDragShellRef
->DoInitNew();
2659 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef
);
2661 ScClipParam
aClipParam(ScRange(nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nStartTab
), bCut
);
2662 rDoc
.CopyToClip(aClipParam
, pClipDoc
, &aSourceMark
, bScenariosAdded
, true);
2664 ScDrawLayer::SetGlobalDrawPersist(nullptr);
2666 SCCOL nOldEndCol
= nEndCol
;
2667 SCROW nOldEndRow
= nEndRow
;
2668 bool bClipOver
= false;
2669 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2671 SCCOL nTmpEndCol
= nOldEndCol
;
2672 SCROW nTmpEndRow
= nOldEndRow
;
2673 if (rDoc
.ExtendMerge( nStartCol
, nStartRow
, nTmpEndCol
, nTmpEndRow
, nTab
))
2675 if ( nTmpEndCol
> nEndCol
) nEndCol
= nTmpEndCol
;
2676 if ( nTmpEndRow
> nEndRow
) nEndRow
= nTmpEndRow
;
2679 SCCOL nDestEndCol
= nDestCol
+ ( nOldEndCol
-nStartCol
);
2680 SCROW nDestEndRow
= nDestRow
+ ( nOldEndRow
-nStartRow
);
2682 SCCOL nUndoEndCol
= nDestCol
+ ( nEndCol
-nStartCol
); // erweitert im Zielblock
2683 SCROW nUndoEndRow
= nDestRow
+ ( nEndRow
-nStartRow
);
2685 bool bIncludeFiltered
= bCut
;
2686 if ( !bIncludeFiltered
)
2688 // adjust sizes to include only non-filtered rows
2692 pClipDoc
->GetClipArea( nClipX
, nClipY
, false );
2693 SCROW nUndoAdd
= nUndoEndRow
- nDestEndRow
;
2694 nDestEndRow
= nDestRow
+ nClipY
;
2695 nUndoEndRow
= nDestEndRow
+ nUndoAdd
;
2698 if (!ValidCol(nUndoEndCol
) || !ValidRow(nUndoEndRow
))
2701 rDocShell
.ErrorMessage(STR_PASTE_FULL
);
2706 // Test auf Zellschutz
2708 ScEditableTester aTester
;
2709 for (nTab
=nDestTab
; nTab
<=nDestEndTab
; nTab
++)
2710 aTester
.TestBlock( &rDoc
, nTab
, nDestCol
,nDestRow
, nUndoEndCol
,nUndoEndRow
);
2712 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2713 aTester
.TestBlock( &rDoc
, nTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
);
2715 if (!aTester
.IsEditable())
2718 rDocShell
.ErrorMessage(aTester
.GetMessageId());
2723 // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
2725 if (bClipOver
&& !bCut
)
2726 if (rDoc
.HasAttrib( nDestCol
,nDestRow
,nDestTab
, nUndoEndCol
,nUndoEndRow
,nDestEndTab
,
2727 HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2728 { // "Zusammenfassen nicht verschachteln !"
2730 rDocShell
.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0
);
2735 // Are there borders in the cells? (for painting)
2737 sal_uInt16 nSourceExt
= 0;
2738 rDocShell
.UpdatePaintExt( nSourceExt
, nStartCol
,nStartRow
,nStartTab
, nEndCol
,nEndRow
,nEndTab
);
2739 sal_uInt16 nDestExt
= 0;
2740 rDocShell
.UpdatePaintExt( nDestExt
, nDestCol
,nDestRow
,nDestTab
, nDestEndCol
,nDestEndRow
,nDestEndTab
);
2744 ScDocument
* pUndoDoc
= nullptr;
2748 bool bWholeCols
= ( nStartRow
== 0 && nEndRow
== MAXROW
);
2749 bool bWholeRows
= ( nStartCol
== 0 && nEndCol
== MAXCOL
);
2750 InsertDeleteFlags nUndoFlags
= (InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
) | InsertDeleteFlags::NOCAPTIONS
;
2752 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
2753 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nEndTab
, bWholeCols
, bWholeRows
);
2757 rDoc
.CopyToDocument( nStartCol
, nStartRow
, nStartTab
, nEndCol
, nEndRow
, nEndTab
,
2758 nUndoFlags
, false, pUndoDoc
);
2761 if ( nDestTab
!= nStartTab
)
2762 pUndoDoc
->AddUndoTab( nDestTab
, nDestEndTab
, bWholeCols
, bWholeRows
);
2763 rDoc
.CopyToDocument( nDestCol
, nDestRow
, nDestTab
,
2764 nDestEndCol
, nDestEndRow
, nDestEndTab
,
2765 nUndoFlags
, false, pUndoDoc
);
2766 rDoc
.BeginDrawUndo();
2769 bool bSourceHeight
= false; // Hoehen angepasst?
2772 ScMarkData aDelMark
; // only for tables
2773 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2775 rDoc
.DeleteAreaTab( nStartCol
,nStartRow
, nOldEndCol
,nOldEndRow
, nTab
, InsertDeleteFlags::ALL
);
2776 aDelMark
.SelectTable( nTab
, true );
2778 rDoc
.DeleteObjectsInArea( nStartCol
,nStartRow
, nOldEndCol
,nOldEndRow
, aDelMark
);
2780 // Test auf zusammengefasste
2783 if (rDoc
.HasAttrib( nDestCol
,nDestRow
,nDestTab
,
2784 nUndoEndCol
,nUndoEndRow
,nDestEndTab
,
2785 HASATTR_MERGED
| HASATTR_OVERLAPPED
))
2787 rDoc
.CopyFromClip( rSource
, aSourceMark
, InsertDeleteFlags::ALL
, nullptr, pClipDoc
);
2788 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2790 SCCOL nTmpEndCol
= nEndCol
;
2791 SCROW nTmpEndRow
= nEndRow
;
2792 rDoc
.ExtendMerge( nStartCol
, nStartRow
, nTmpEndCol
, nTmpEndRow
, nTab
, true );
2795 // Fehlermeldung erst nach dem Wiederherstellen des Inhalts
2796 if (!bApi
) // "Zusammenfassen nicht verschachteln !"
2797 rDocShell
.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0
);
2804 bSourceHeight
= AdjustRowHeight( rSource
, false );
2807 ScRange
aPasteDest( nDestCol
, nDestRow
, nDestTab
, nDestEndCol
, nDestEndRow
, nDestEndTab
);
2809 ScMarkData aDestMark
;
2810 for (nTab
=nDestTab
; nTab
<=nDestEndTab
; nTab
++)
2811 aDestMark
.SelectTable( nTab
, true ); // Destination selektieren
2812 aDestMark
.SetMarkArea( aPasteDest
);
2814 /* Do not drawing objects here. While pasting, the
2815 function ScDocument::UpdateReference() is called which calls
2816 ScDrawLayer::MoveCells() which may move away inserted objects to wrong
2817 positions (e.g. if source and destination range overlaps).*/
2818 rDoc
.CopyFromClip( aPasteDest
, aDestMark
, InsertDeleteFlags::ALL
& ~(InsertDeleteFlags::OBJECTS
),
2819 nullptr, pClipDoc
, true, false, bIncludeFiltered
);
2821 // skipped rows and merged cells don't mix
2822 if ( !bIncludeFiltered
&& pClipDoc
->HasClipFilteredRows() )
2823 UnmergeCells( aPasteDest
, false, nullptr );
2825 bool bDestHeight
= AdjustRowHeight(
2826 ScRange( 0,nDestRow
,nDestTab
, MAXCOL
,nDestEndRow
,nDestEndTab
),
2829 /* Paste drawing objects after adjusting formula references
2830 and row heights. There are no cell notes or drawing objects, if the
2831 clipdoc does not contain a drawing layer.*/
2832 if ( pClipDoc
->GetDrawLayer() )
2833 rDoc
.CopyFromClip( aPasteDest
, aDestMark
, InsertDeleteFlags::OBJECTS
,
2834 nullptr, pClipDoc
, true, false, bIncludeFiltered
);
2838 rDocShell
.GetUndoManager()->AddUndoAction(
2839 new ScUndoDragDrop( &rDocShell
, ScRange(
2840 nStartCol
, nStartRow
, nStartTab
,
2841 nOldEndCol
, nOldEndRow
, nEndTab
),
2842 ScAddress( nDestCol
, nDestRow
, nDestTab
),
2843 bCut
, pUndoDoc
, nullptr, bScenariosAdded
) );
2846 SCCOL nDestPaintEndCol
= nDestEndCol
;
2847 SCROW nDestPaintEndRow
= nDestEndRow
;
2848 for (nTab
=nDestTab
; nTab
<=nDestEndTab
; nTab
++)
2850 SCCOL nTmpEndCol
= nDestEndCol
;
2851 SCROW nTmpEndRow
= nDestEndRow
;
2852 rDoc
.ExtendMerge( nDestCol
, nDestRow
, nTmpEndCol
, nTmpEndRow
, nTab
, true );
2853 if (nTmpEndCol
> nDestPaintEndCol
) nDestPaintEndCol
= nTmpEndCol
;
2854 if (nTmpEndRow
> nDestPaintEndRow
) nDestPaintEndRow
= nTmpEndRow
;
2858 for (nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
2859 rDoc
.RefreshAutoFilter( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
);
2865 SCCOL nPaintStartX
= nDestCol
;
2866 SCROW nPaintStartY
= nDestRow
;
2867 SCCOL nPaintEndX
= nDestPaintEndCol
;
2868 SCROW nPaintEndY
= nDestPaintEndRow
;
2869 sal_uInt16 nFlags
= PAINT_GRID
;
2871 if ( nStartRow
==0 && nEndRow
==MAXROW
) // Breiten mitkopiert?
2873 nPaintEndX
= MAXCOL
;
2875 nPaintEndY
= MAXROW
;
2876 nFlags
|= PAINT_TOP
;
2878 if ( bDestHeight
|| ( nStartCol
== 0 && nEndCol
== MAXCOL
) )
2880 nPaintEndY
= MAXROW
;
2882 nPaintEndX
= MAXCOL
;
2883 nFlags
|= PAINT_LEFT
;
2885 if ( bScenariosAdded
)
2889 nPaintEndX
= MAXCOL
;
2890 nPaintEndY
= MAXROW
;
2893 rDocShell
.PostPaint( nPaintStartX
,nPaintStartY
,nDestTab
,
2894 nPaintEndX
,nPaintEndY
,nDestEndTab
, nFlags
, nSourceExt
| nDestExt
);
2900 nPaintStartX
= nStartCol
;
2901 nPaintStartY
= nStartRow
;
2902 nPaintEndX
= nEndCol
;
2903 nPaintEndY
= nEndRow
;
2904 nFlags
= PAINT_GRID
;
2906 if ( bSourceHeight
)
2908 nPaintEndY
= MAXROW
;
2910 nPaintEndX
= MAXCOL
;
2911 nFlags
|= PAINT_LEFT
;
2913 if ( bScenariosAdded
)
2917 nPaintEndX
= MAXCOL
;
2918 nPaintEndY
= MAXROW
;
2921 rDocShell
.PostPaint( nPaintStartX
,nPaintStartY
,nStartTab
,
2922 nPaintEndX
,nPaintEndY
,nEndTab
, nFlags
, nSourceExt
);
2926 aModificator
.SetDocumentModified();
2928 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) );
2934 uno::Reference
< uno::XInterface
> GetDocModuleObject( SfxObjectShell
& rDocSh
, OUString
& sCodeName
)
2936 uno::Reference
< lang::XMultiServiceFactory
> xSF(rDocSh
.GetModel(), uno::UNO_QUERY
);
2937 uno::Reference
< container::XNameAccess
> xVBACodeNamedObjectAccess
;
2938 uno::Reference
< uno::XInterface
> xDocModuleApiObject
;
2941 xVBACodeNamedObjectAccess
.set( xSF
->createInstance("ooo.vba.VBAObjectModuleObjectProvider"), uno::UNO_QUERY
);
2942 xDocModuleApiObject
.set( xVBACodeNamedObjectAccess
->getByName( sCodeName
), uno::UNO_QUERY
);
2944 return xDocModuleApiObject
;
2948 static script::ModuleInfo
lcl_InitModuleInfo( SfxObjectShell
& rDocSh
, OUString
& sModule
)
2950 script::ModuleInfo sModuleInfo
;
2951 sModuleInfo
.ModuleType
= script::ModuleType::DOCUMENT
;
2952 sModuleInfo
.ModuleObject
= GetDocModuleObject( rDocSh
, sModule
);
2956 void VBA_InsertModule( ScDocument
& rDoc
, SCTAB nTab
, const OUString
& sModuleName
, const OUString
& sSource
)
2958 SfxObjectShell
& rDocSh
= *rDoc
.GetDocumentShell();
2959 uno::Reference
< script::XLibraryContainer
> xLibContainer
= rDocSh
.GetBasicContainer();
2960 OSL_ENSURE( xLibContainer
.is(), "No BasicContainer!" );
2962 uno::Reference
< container::XNameContainer
> xLib
;
2963 if( xLibContainer
.is() )
2965 OUString
aLibName( "Standard" );
2966 if ( rDocSh
.GetBasicManager() && !rDocSh
.GetBasicManager()->GetName().isEmpty() )
2968 aLibName
= rDocSh
.GetBasicManager()->GetName();
2970 uno::Any aLibAny
= xLibContainer
->getByName( aLibName
);
2975 // if the Module with codename exists then find a new name
2977 OUString genModuleName
;
2978 if ( !sModuleName
.isEmpty() )
2979 genModuleName
= sModuleName
;
2982 genModuleName
= "Sheet1";
2985 while( xLib
->hasByName( genModuleName
) )
2986 genModuleName
= "Sheet" + OUString::number( ++nNum
);
2988 uno::Any aSourceAny
;
2989 OUString sTmpSource
= sSource
;
2990 if ( sTmpSource
.isEmpty() )
2991 sTmpSource
= "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n";
2992 aSourceAny
<<= sTmpSource
;
2993 uno::Reference
< script::vba::XVBAModuleInfo
> xVBAModuleInfo( xLib
, uno::UNO_QUERY
);
2994 if ( xVBAModuleInfo
.is() )
2996 rDoc
.SetCodeName( nTab
, genModuleName
);
2997 script::ModuleInfo sModuleInfo
= lcl_InitModuleInfo( rDocSh
, genModuleName
);
2998 xVBAModuleInfo
->insertModuleInfo( genModuleName
, sModuleInfo
);
2999 xLib
->insertByName( genModuleName
, aSourceAny
);
3005 void VBA_DeleteModule( ScDocShell
& rDocSh
, const OUString
& sModuleName
)
3007 uno::Reference
< script::XLibraryContainer
> xLibContainer
= rDocSh
.GetBasicContainer();
3008 OSL_ENSURE( xLibContainer
.is(), "No BasicContainer!" );
3010 uno::Reference
< container::XNameContainer
> xLib
;
3011 if( xLibContainer
.is() )
3013 OUString
aLibName( "Standard" );
3014 if ( rDocSh
.GetBasicManager() && !rDocSh
.GetBasicManager()->GetName().isEmpty() )
3016 aLibName
= rDocSh
.GetBasicManager()->GetName();
3018 uno::Any aLibAny
= xLibContainer
->getByName( aLibName
);
3023 uno::Reference
< script::vba::XVBAModuleInfo
> xVBAModuleInfo( xLib
, uno::UNO_QUERY
);
3024 if( xLib
->hasByName( sModuleName
) )
3025 xLib
->removeByName( sModuleName
);
3026 if ( xVBAModuleInfo
.is() && xVBAModuleInfo
->hasModuleInfo(sModuleName
) )
3027 xVBAModuleInfo
->removeModuleInfo( sModuleName
);
3032 bool ScDocFunc::InsertTable( SCTAB nTab
, const OUString
& rName
, bool bRecord
, bool bApi
)
3034 bool bSuccess
= false;
3035 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
3037 ScDocShellModificator
aModificator( rDocShell
);
3039 ScDocument
& rDoc
= rDocShell
.GetDocument();
3041 // Strange loop, also basic is loaded too early ( InsertTable )
3042 // is called via the xml import for sheets in described in ODF
3043 bool bInsertDocModule
= false;
3045 if( !rDocShell
.GetDocument().IsImportingXML() )
3047 bInsertDocModule
= rDoc
.IsInVBAMode();
3049 if ( bInsertDocModule
|| ( bRecord
&& !rDoc
.IsUndoEnabled() ) )
3053 rDoc
.BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage
3055 SCTAB nTabCount
= rDoc
.GetTableCount();
3056 bool bAppend
= ( nTab
>= nTabCount
);
3058 nTab
= nTabCount
; // wichtig fuer Undo
3060 if (rDoc
.InsertTab( nTab
, rName
))
3063 rDocShell
.GetUndoManager()->AddUndoAction(
3064 new ScUndoInsertTab( &rDocShell
, nTab
, bAppend
, rName
));
3066 // Only insert vba modules if vba mode ( and not currently importing XML )
3067 if( bInsertDocModule
)
3069 OUString sSource
, sCodeName
;
3070 VBA_InsertModule( rDoc
, nTab
, sCodeName
, sSource
);
3072 rDocShell
.Broadcast( ScTablesHint( SC_TAB_INSERTED
, nTab
) );
3074 rDocShell
.PostPaintExtras();
3075 aModificator
.SetDocumentModified();
3076 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED
) );
3080 rDocShell
.ErrorMessage(STR_TABINSERT_ERROR
);
3085 bool ScDocFunc::DeleteTable( SCTAB nTab
, bool bRecord
, bool /* bApi */ )
3087 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
3089 ScDocShellModificator
aModificator( rDocShell
);
3091 bool bSuccess
= false;
3092 ScDocument
& rDoc
= rDocShell
.GetDocument();
3093 bool bVbaEnabled
= rDoc
.IsInVBAMode();
3094 if (bRecord
&& !rDoc
.IsUndoEnabled())
3098 bool bWasLinked
= rDoc
.IsLinked(nTab
);
3099 ScDocument
* pUndoDoc
= nullptr;
3100 ScRefUndoData
* pUndoData
= nullptr;
3103 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
3104 SCTAB nCount
= rDoc
.GetTableCount();
3106 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
, true, true ); // nur nTab mit Flags
3107 pUndoDoc
->AddUndoTab( 0, nCount
-1 ); // alle Tabs fuer Referenzen
3109 rDoc
.CopyToDocument(0,0,nTab
, MAXCOL
,MAXROW
,nTab
, InsertDeleteFlags::ALL
,false, pUndoDoc
);
3111 rDoc
.GetName( nTab
, aOldName
);
3112 pUndoDoc
->RenameTab( nTab
, aOldName
, false );
3114 pUndoDoc
->SetLink( nTab
, rDoc
.GetLinkMode(nTab
), rDoc
.GetLinkDoc(nTab
),
3115 rDoc
.GetLinkFlt(nTab
), rDoc
.GetLinkOpt(nTab
),
3116 rDoc
.GetLinkTab(nTab
),
3117 rDoc
.GetLinkRefreshDelay(nTab
) );
3119 if ( rDoc
.IsScenario(nTab
) )
3121 pUndoDoc
->SetScenario( nTab
, true );
3124 sal_uInt16 nScenFlags
;
3125 rDoc
.GetScenarioData( nTab
, aComment
, aColor
, nScenFlags
);
3126 pUndoDoc
->SetScenarioData( nTab
, aComment
, aColor
, nScenFlags
);
3127 bool bActive
= rDoc
.IsActiveScenario( nTab
);
3128 pUndoDoc
->SetActiveScenario( nTab
, bActive
);
3130 pUndoDoc
->SetVisible( nTab
, rDoc
.IsVisible( nTab
) );
3131 pUndoDoc
->SetTabBgColor( nTab
, rDoc
.GetTabBgColor(nTab
) );
3132 pUndoDoc
->SetSheetEvents( nTab
, rDoc
.GetSheetEvents( nTab
) );
3134 // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
3135 rDoc
.BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage
3137 pUndoData
= new ScRefUndoData( &rDoc
);
3140 if (rDoc
.DeleteTab(nTab
))
3144 vector
<SCTAB
> theTabs
;
3145 theTabs
.push_back(nTab
);
3146 rDocShell
.GetUndoManager()->AddUndoAction(
3147 new ScUndoDeleteTab( &rDocShell
, theTabs
, pUndoDoc
, pUndoData
));
3153 if( rDoc
.GetCodeName( nTab
, sCodeName
) )
3155 VBA_DeleteModule( rDocShell
, sCodeName
);
3158 rDocShell
.Broadcast( ScTablesHint( SC_TAB_DELETED
, nTab
) );
3162 rDocShell
.UpdateLinks(); // Link-Manager updaten
3163 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3165 pBindings
->Invalidate(SID_LINKS
);
3168 rDocShell
.PostPaintExtras();
3169 aModificator
.SetDocumentModified();
3171 SfxApplication
* pSfxApp
= SfxGetpApp(); // Navigator
3172 pSfxApp
->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED
) );
3173 pSfxApp
->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED
) );
3174 pSfxApp
->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) );
3186 void ScDocFunc::SetTableVisible( SCTAB nTab
, bool bVisible
, bool bApi
)
3188 ScDocument
& rDoc
= rDocShell
.GetDocument();
3189 bool bUndo(rDoc
.IsUndoEnabled());
3190 if ( rDoc
.IsVisible( nTab
) == bVisible
)
3191 return; // nichts zu tun - ok
3193 if ( !rDoc
.IsDocEditable() )
3196 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
3200 ScDocShellModificator
aModificator( rDocShell
);
3202 if ( !bVisible
&& !rDoc
.IsImportingXML() ) // #i57869# allow hiding in any order for loading
3204 // nicht alle Tabellen ausblenden
3206 sal_uInt16 nVisCount
= 0;
3207 SCTAB nCount
= rDoc
.GetTableCount();
3208 for (SCTAB i
=0; i
<nCount
&& nVisCount
<2; i
++)
3209 if (rDoc
.IsVisible(i
))
3215 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //! eigene Meldung?
3220 rDoc
.SetVisible( nTab
, bVisible
);
3223 std::vector
<SCTAB
> undoTabs
;
3224 undoTabs
.push_back(nTab
);
3225 rDocShell
.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell
, undoTabs
, bVisible
) );
3230 rDocShell
.Broadcast( ScTablesHint( SC_TAB_HIDDEN
, nTab
) );
3232 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED
) );
3233 rDocShell
.PostPaint(0,0,0,MAXCOL
,MAXROW
,MAXTAB
, PAINT_EXTRAS
);
3234 aModificator
.SetDocumentModified();
3237 bool ScDocFunc::SetLayoutRTL( SCTAB nTab
, bool bRTL
, bool /* bApi */ )
3239 ScDocument
& rDoc
= rDocShell
.GetDocument();
3240 bool bUndo(rDoc
.IsUndoEnabled());
3241 if ( rDoc
.IsLayoutRTL( nTab
) == bRTL
)
3242 return true; // nothing to do - ok
3244 //! protection (sheet or document?)
3246 ScDocShellModificator
aModificator( rDocShell
);
3248 rDoc
.SetLayoutRTL( nTab
, bRTL
);
3252 rDocShell
.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell
, nTab
, bRTL
) );
3255 rDocShell
.PostPaint( 0,0,0,MAXCOL
,MAXROW
,MAXTAB
, PAINT_ALL
);
3256 aModificator
.SetDocumentModified();
3258 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3261 pBindings
->Invalidate( FID_TAB_RTL
);
3262 pBindings
->Invalidate( SID_ATTR_SIZE
);
3268 bool ScDocFunc::RenameTable( SCTAB nTab
, const OUString
& rName
, bool bRecord
, bool bApi
)
3270 ScDocument
& rDoc
= rDocShell
.GetDocument();
3271 if (bRecord
&& !rDoc
.IsUndoEnabled())
3273 if ( !rDoc
.IsDocEditable() )
3276 rDocShell
.ErrorMessage(STR_PROTECTIONERR
);
3280 ScDocShellModificator
aModificator( rDocShell
);
3282 bool bSuccess
= false;
3284 rDoc
.GetName(nTab
, sOldName
);
3285 if (rDoc
.RenameTab( nTab
, rName
))
3289 rDocShell
.GetUndoManager()->AddUndoAction(
3290 new ScUndoRenameTab( &rDocShell
, nTab
, sOldName
, rName
));
3292 rDocShell
.PostPaintExtras();
3293 aModificator
.SetDocumentModified();
3294 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED
) );
3301 bool ScDocFunc::SetTabBgColor( SCTAB nTab
, const Color
& rColor
, bool bRecord
, bool bApi
)
3304 ScDocument
& rDoc
= rDocShell
.GetDocument();
3305 if (bRecord
&& !rDoc
.IsUndoEnabled())
3307 if ( !rDoc
.IsDocEditable() || rDoc
.IsTabProtected(nTab
) )
3310 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //TODO Check to see what this string is...
3314 Color aOldTabBgColor
;
3315 aOldTabBgColor
= rDoc
.GetTabBgColor(nTab
);
3317 bool bSuccess
= false;
3318 rDoc
.SetTabBgColor(nTab
, rColor
);
3319 if ( rDoc
.GetTabBgColor(nTab
) == rColor
)
3325 rDocShell
.GetUndoManager()->AddUndoAction(
3326 new ScUndoTabColor( &rDocShell
, nTab
, aOldTabBgColor
, rColor
));
3328 rDocShell
.PostPaintExtras();
3329 ScDocShellModificator
aModificator( rDocShell
);
3330 aModificator
.SetDocumentModified();
3331 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED
) );
3338 bool ScDocFunc::SetTabBgColor(
3339 ScUndoTabColorInfo::List
& rUndoTabColorList
, bool bApi
)
3341 ScDocument
& rDoc
= rDocShell
.GetDocument();
3342 bool bRecord
= true;
3343 if (!rDoc
.IsUndoEnabled())
3346 if ( !rDoc
.IsDocEditable() )
3349 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //TODO Get a better String Error...
3354 Color aNewTabBgColor
;
3355 bool bSuccess
= true;
3356 size_t nTabProtectCount
= 0;
3357 size_t nTabListCount
= rUndoTabColorList
.size();
3358 for ( size_t i
= 0; i
< nTabListCount
; ++i
)
3360 ScUndoTabColorInfo
& rInfo
= rUndoTabColorList
[i
];
3361 nTab
= rInfo
.mnTabId
;
3362 if ( !rDoc
.IsTabProtected(nTab
) )
3364 aNewTabBgColor
= rInfo
.maNewTabBgColor
;
3365 rInfo
.maOldTabBgColor
= rDoc
.GetTabBgColor(nTab
);
3366 rDoc
.SetTabBgColor(nTab
, aNewTabBgColor
);
3367 if ( rDoc
.GetTabBgColor(nTab
) != aNewTabBgColor
)
3379 if ( nTabProtectCount
== nTabListCount
)
3382 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //TODO Get a better String Error...
3390 rDocShell
.GetUndoManager()->AddUndoAction(
3391 new ScUndoTabColor( &rDocShell
, rUndoTabColorList
));
3393 rDocShell
.PostPaintExtras();
3394 ScDocShellModificator
aModificator( rDocShell
);
3395 aModificator
.SetDocumentModified();
3400 //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
3402 //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
3403 //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
3405 static sal_uInt16
lcl_GetOptimalColWidth( ScDocShell
& rDocShell
, SCCOL nCol
, SCTAB nTab
, bool bFormula
)
3407 ScSizeDeviceProvider
aProv(&rDocShell
);
3408 OutputDevice
* pDev
= aProv
.GetDevice(); // has pixel MapMode
3409 double nPPTX
= aProv
.GetPPTX();
3410 double nPPTY
= aProv
.GetPPTY();
3412 ScDocument
& rDoc
= rDocShell
.GetDocument();
3414 sal_uInt16 nTwips
= rDoc
.GetOptimalColWidth( nCol
, nTab
, pDev
, nPPTX
, nPPTY
, aOne
, aOne
,
3420 bool ScDocFunc::SetWidthOrHeight(
3421 bool bWidth
, const std::vector
<sc::ColRowSpan
>& rRanges
, SCTAB nTab
,
3422 ScSizeMode eMode
, sal_uInt16 nSizeTwips
, bool bRecord
, bool bApi
)
3424 ScDocShellModificator
aModificator( rDocShell
);
3426 if (rRanges
.empty())
3429 ScDocument
& rDoc
= rDocShell
.GetDocument();
3430 if ( bRecord
&& !rDoc
.IsUndoEnabled() )
3433 // import into read-only document is possible
3434 if ( !rDoc
.IsChangeReadOnlyEnabled() && !rDocShell
.IsEditable() )
3437 rDocShell
.ErrorMessage(STR_PROTECTIONERR
); //! eigene Meldung?
3441 bool bSuccess
= false;
3442 SCCOLROW nStart
= rRanges
[0].mnStart
;
3443 SCCOLROW nEnd
= rRanges
[0].mnEnd
;
3445 bool bFormula
= false;
3446 if ( eMode
== SC_SIZE_OPTIMAL
)
3448 //! Option "Formeln anzeigen" - woher nehmen?
3451 ScDocument
* pUndoDoc
= nullptr;
3452 ScOutlineTable
* pUndoTab
= nullptr;
3453 std::vector
<sc::ColRowSpan
> aUndoRanges
;
3457 rDoc
.BeginDrawUndo(); // Drawing Updates
3459 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
3462 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
, true );
3463 rDoc
.CopyToDocument( static_cast<SCCOL
>(nStart
), 0, nTab
, static_cast<SCCOL
>(nEnd
), MAXROW
, nTab
, InsertDeleteFlags::NONE
, false, pUndoDoc
);
3467 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
, false, true );
3468 rDoc
.CopyToDocument( 0, static_cast<SCROW
>(nStart
), nTab
, MAXCOL
, static_cast<SCROW
>(nEnd
), nTab
, InsertDeleteFlags::NONE
, false, pUndoDoc
);
3471 aUndoRanges
= rRanges
;
3473 ScOutlineTable
* pTable
= rDoc
.GetOutlineTable( nTab
);
3475 pUndoTab
= new ScOutlineTable( *pTable
);
3478 bool bShow
= nSizeTwips
> 0 || eMode
!= SC_SIZE_DIRECT
;
3479 bool bOutline
= false;
3481 for (const sc::ColRowSpan
& rRange
: rRanges
)
3483 SCCOLROW nStartNo
= rRange
.mnStart
;
3484 SCCOLROW nEndNo
= rRange
.mnEnd
;
3486 if ( !bWidth
) // Hoehen immer blockweise
3488 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
3490 bool bAll
= ( eMode
==SC_SIZE_OPTIMAL
);
3493 // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
3494 // dann SetOptimalHeight mit bShrink = FALSE
3495 for (SCROW nRow
=nStartNo
; nRow
<=nEndNo
; nRow
++)
3497 sal_uInt8 nOld
= rDoc
.GetRowFlags(nRow
,nTab
);
3498 SCROW nLastRow
= -1;
3499 bool bHidden
= rDoc
.RowHidden(nRow
, nTab
, nullptr, &nLastRow
);
3500 if ( !bHidden
&& ( nOld
& CR_MANUALSIZE
) )
3501 rDoc
.SetRowFlags( nRow
, nTab
, nOld
& ~CR_MANUALSIZE
);
3505 ScSizeDeviceProvider
aProv( &rDocShell
);
3507 sc::RowHeightContext
aCxt(aProv
.GetPPTX(), aProv
.GetPPTY(), aOne
, aOne
, aProv
.GetDevice());
3508 aCxt
.setForceAutoSize(bAll
);
3509 rDoc
.SetOptimalHeight(aCxt
, nStartNo
, nEndNo
, nTab
);
3512 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, true );
3514 // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt
3515 // (an bei Extra-Height, sonst aus).
3517 else if ( eMode
==SC_SIZE_DIRECT
|| eMode
==SC_SIZE_ORIGINAL
)
3521 rDoc
.SetRowHeightRange( nStartNo
, nEndNo
, nTab
, nSizeTwips
);
3522 rDoc
.SetManualHeight( nStartNo
, nEndNo
, nTab
, true ); // height was set manually
3524 if ( eMode
!= SC_SIZE_ORIGINAL
)
3525 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, nSizeTwips
!= 0 );
3527 else if ( eMode
==SC_SIZE_SHOW
)
3529 rDoc
.ShowRows( nStartNo
, nEndNo
, nTab
, true );
3532 else // Spaltenbreiten
3534 for (SCCOL nCol
=static_cast<SCCOL
>(nStartNo
); nCol
<=static_cast<SCCOL
>(nEndNo
); nCol
++)
3536 if ( eMode
!= SC_SIZE_VISOPT
|| !rDoc
.ColHidden(nCol
, nTab
) )
3538 sal_uInt16 nThisSize
= nSizeTwips
;
3540 if ( eMode
==SC_SIZE_OPTIMAL
|| eMode
==SC_SIZE_VISOPT
)
3541 nThisSize
= nSizeTwips
+
3542 lcl_GetOptimalColWidth( rDocShell
, nCol
, nTab
, bFormula
);
3544 rDoc
.SetColWidth( nCol
, nTab
, nThisSize
);
3546 if ( eMode
!= SC_SIZE_ORIGINAL
)
3547 rDoc
.ShowCol( nCol
, nTab
, bShow
);
3554 if ( eMode
!= SC_SIZE_ORIGINAL
)
3557 bOutline
= bOutline
|| rDoc
.UpdateOutlineCol(
3558 static_cast<SCCOL
>(nStartNo
),
3559 static_cast<SCCOL
>(nEndNo
), nTab
, bShow
);
3561 bOutline
= bOutline
|| rDoc
.UpdateOutlineRow(
3562 static_cast<SCROW
>(nStartNo
),
3563 static_cast<SCROW
>(nEndNo
), nTab
, bShow
);
3566 rDoc
.SetDrawPageSize(nTab
);
3574 aMark
.SelectOneTable( nTab
);
3575 rDocShell
.GetUndoManager()->AddUndoAction(
3576 new ScUndoWidthOrHeight(
3577 &rDocShell
, aMark
, nStart
, nTab
, nEnd
, nTab
, pUndoDoc
,
3578 aUndoRanges
, pUndoTab
, eMode
, nSizeTwips
, bWidth
));
3581 rDoc
.UpdatePageBreaks( nTab
);
3583 rDocShell
.PostPaint(0,0,nTab
,MAXCOL
,MAXROW
,nTab
,PAINT_ALL
);
3584 aModificator
.SetDocumentModified();
3589 bool ScDocFunc::InsertPageBreak( bool bColumn
, const ScAddress
& rPos
,
3590 bool bRecord
, bool bSetModified
, bool /* bApi */ )
3592 ScDocShellModificator
aModificator( rDocShell
);
3594 ScDocument
& rDoc
= rDocShell
.GetDocument();
3595 if (bRecord
&& !rDoc
.IsUndoEnabled())
3597 SCTAB nTab
= rPos
.Tab();
3598 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3600 SCCOLROW nPos
= bColumn
? static_cast<SCCOLROW
>(rPos
.Col()) :
3601 static_cast<SCCOLROW
>(rPos
.Row());
3603 return false; // erste Spalte / Zeile
3605 ScBreakType nBreak
= bColumn
?
3606 rDoc
.HasColBreak(static_cast<SCCOL
>(nPos
), nTab
) :
3607 rDoc
.HasRowBreak(static_cast<SCROW
>(nPos
), nTab
);
3608 if (nBreak
& BREAK_MANUAL
)
3612 rDocShell
.GetUndoManager()->AddUndoAction(
3613 new ScUndoPageBreak( &rDocShell
, rPos
.Col(), rPos
.Row(), nTab
, bColumn
, true ) );
3616 rDoc
.SetColBreak(static_cast<SCCOL
>(nPos
), nTab
, false, true);
3618 rDoc
.SetRowBreak(static_cast<SCROW
>(nPos
), nTab
, false, true);
3620 rDoc
.InvalidatePageBreaks(nTab
);
3621 rDoc
.UpdatePageBreaks( nTab
);
3623 if (rDoc
.IsStreamValid(nTab
))
3624 rDoc
.SetStreamValid(nTab
, false);
3628 rDocShell
.PostPaint( static_cast<SCCOL
>(nPos
)-1, 0, nTab
, MAXCOL
, MAXROW
, nTab
, PAINT_GRID
);
3631 pBindings
->Invalidate( FID_INS_COLBRK
);
3632 pBindings
->Invalidate( FID_DEL_COLBRK
);
3637 rDocShell
.PostPaint( 0, static_cast<SCROW
>(nPos
)-1, nTab
, MAXCOL
, MAXROW
, nTab
, PAINT_GRID
);
3640 pBindings
->Invalidate( FID_INS_ROWBRK
);
3641 pBindings
->Invalidate( FID_DEL_ROWBRK
);
3645 pBindings
->Invalidate( FID_DEL_MANUALBREAKS
);
3648 aModificator
.SetDocumentModified();
3653 bool ScDocFunc::RemovePageBreak( bool bColumn
, const ScAddress
& rPos
,
3654 bool bRecord
, bool bSetModified
, bool /* bApi */ )
3656 ScDocShellModificator
aModificator( rDocShell
);
3658 ScDocument
& rDoc
= rDocShell
.GetDocument();
3659 if (bRecord
&& !rDoc
.IsUndoEnabled())
3661 SCTAB nTab
= rPos
.Tab();
3662 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3664 SCCOLROW nPos
= bColumn
? static_cast<SCCOLROW
>(rPos
.Col()) :
3665 static_cast<SCCOLROW
>(rPos
.Row());
3669 nBreak
= rDoc
.HasColBreak(static_cast<SCCOL
>(nPos
), nTab
);
3671 nBreak
= rDoc
.HasRowBreak(static_cast<SCROW
>(nPos
), nTab
);
3672 if ((nBreak
& BREAK_MANUAL
) == 0)
3673 // There is no manual break.
3677 rDocShell
.GetUndoManager()->AddUndoAction(
3678 new ScUndoPageBreak( &rDocShell
, rPos
.Col(), rPos
.Row(), nTab
, bColumn
, false ) );
3681 rDoc
.RemoveColBreak(static_cast<SCCOL
>(nPos
), nTab
, false, true);
3683 rDoc
.RemoveRowBreak(static_cast<SCROW
>(nPos
), nTab
, false, true);
3685 rDoc
.UpdatePageBreaks( nTab
);
3687 if (rDoc
.IsStreamValid(nTab
))
3688 rDoc
.SetStreamValid(nTab
, false);
3692 rDocShell
.PostPaint( static_cast<SCCOL
>(nPos
)-1, 0, nTab
, MAXCOL
, MAXROW
, nTab
, PAINT_GRID
);
3695 pBindings
->Invalidate( FID_INS_COLBRK
);
3696 pBindings
->Invalidate( FID_DEL_COLBRK
);
3701 rDocShell
.PostPaint( 0, nPos
-1, nTab
, MAXCOL
, MAXROW
, nTab
, PAINT_GRID
);
3704 pBindings
->Invalidate( FID_INS_ROWBRK
);
3705 pBindings
->Invalidate( FID_DEL_ROWBRK
);
3709 pBindings
->Invalidate( FID_DEL_MANUALBREAKS
);
3712 aModificator
.SetDocumentModified();
3717 void ScDocFunc::ProtectSheet( SCTAB nTab
, const ScTableProtection
& rProtect
)
3719 ScDocument
& rDoc
= rDocShell
.GetDocument();
3721 rDoc
.SetTabProtection(nTab
, &rProtect
);
3722 if (rDoc
.IsUndoEnabled())
3724 ScTableProtection
* pProtect
= rDoc
.GetTabProtection(nTab
);
3725 OSL_ENSURE(pProtect
, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3728 ::std::unique_ptr
<ScTableProtection
> p(new ScTableProtection(*pProtect
));
3729 p
->setProtected(true); // just in case ...
3730 rDocShell
.GetUndoManager()->AddUndoAction(
3731 new ScUndoTabProtect(&rDocShell
, nTab
, std::move(p
)) );
3733 // ownership of unique_ptr now transferred to ScUndoTabProtect.
3737 rDocShell
.PostPaintGridAll();
3738 ScDocShellModificator
aModificator(rDocShell
);
3739 aModificator
.SetDocumentModified();
3742 bool ScDocFunc::Protect( SCTAB nTab
, const OUString
& rPassword
, bool /*bApi*/ )
3744 ScDocument
& rDoc
= rDocShell
.GetDocument();
3745 if (nTab
== TABLEID_DOC
)
3747 // document protection
3748 ScDocProtection aProtection
;
3749 aProtection
.setProtected(true);
3750 aProtection
.setPassword(rPassword
);
3751 rDoc
.SetDocProtection(&aProtection
);
3752 if (rDoc
.IsUndoEnabled())
3754 ScDocProtection
* pProtect
= rDoc
.GetDocProtection();
3755 OSL_ENSURE(pProtect
, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
3758 ::std::unique_ptr
<ScDocProtection
> p(new ScDocProtection(*pProtect
));
3759 p
->setProtected(true); // just in case ...
3760 rDocShell
.GetUndoManager()->AddUndoAction(
3761 new ScUndoDocProtect(&rDocShell
, std::move(p
)) );
3762 // ownership of unique_ptr is transferred to ScUndoDocProtect.
3770 ScTableProtection aProtection
;
3771 aProtection
.setProtected(true);
3772 aProtection
.setPassword(rPassword
);
3773 rDoc
.SetTabProtection(nTab
, &aProtection
);
3774 if (rDoc
.IsUndoEnabled())
3776 ScTableProtection
* pProtect
= rDoc
.GetTabProtection(nTab
);
3777 OSL_ENSURE(pProtect
, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3780 ::std::unique_ptr
<ScTableProtection
> p(new ScTableProtection(*pProtect
));
3781 p
->setProtected(true); // just in case ...
3782 rDocShell
.GetUndoManager()->AddUndoAction(
3783 new ScUndoTabProtect(&rDocShell
, nTab
, std::move(p
)) );
3784 // ownership of unique_ptr now transferred to ScUndoTabProtect.
3789 rDocShell
.PostPaintGridAll();
3790 ScDocShellModificator
aModificator( rDocShell
);
3791 aModificator
.SetDocumentModified();
3796 bool ScDocFunc::Unprotect( SCTAB nTab
, const OUString
& rPassword
, bool bApi
)
3798 ScDocument
& rDoc
= rDocShell
.GetDocument();
3800 if (nTab
== TABLEID_DOC
)
3802 // document protection
3804 ScDocProtection
* pDocProtect
= rDoc
.GetDocProtection();
3805 if (!pDocProtect
|| !pDocProtect
->isProtected())
3806 // already unprotected (should not happen)!
3809 // save the protection state before unprotect (for undo).
3810 ::std::unique_ptr
<ScDocProtection
> pProtectCopy(new ScDocProtection(*pDocProtect
));
3812 if (!pDocProtect
->verifyPassword(rPassword
))
3816 ScopedVclPtrInstance
< InfoBox
> aBox( ScDocShell::GetActiveDialogParent(), OUString( ScResId( SCSTR_WRONGPASSWORD
) ) );
3822 rDoc
.SetDocProtection(nullptr);
3823 if (rDoc
.IsUndoEnabled())
3825 pProtectCopy
->setProtected(false);
3826 rDocShell
.GetUndoManager()->AddUndoAction(
3827 new ScUndoDocProtect(&rDocShell
, std::move(pProtectCopy
)) );
3828 // ownership of unique_ptr now transferred to ScUndoDocProtect.
3835 ScTableProtection
* pTabProtect
= rDoc
.GetTabProtection(nTab
);
3836 if (!pTabProtect
|| !pTabProtect
->isProtected())
3837 // already unprotected (should not happen)!
3840 // save the protection state before unprotect (for undo).
3841 ::std::unique_ptr
<ScTableProtection
> pProtectCopy(new ScTableProtection(*pTabProtect
));
3842 if (!pTabProtect
->verifyPassword(rPassword
))
3846 ScopedVclPtrInstance
< InfoBox
> aBox( ScDocShell::GetActiveDialogParent(), OUString( ScResId( SCSTR_WRONGPASSWORD
) ) );
3852 rDoc
.SetTabProtection(nTab
, nullptr);
3853 if (rDoc
.IsUndoEnabled())
3855 pProtectCopy
->setProtected(false);
3856 rDocShell
.GetUndoManager()->AddUndoAction(
3857 new ScUndoTabProtect(&rDocShell
, nTab
, std::move(pProtectCopy
)) );
3858 // ownership of unique_ptr now transferred to ScUndoTabProtect.
3862 rDocShell
.PostPaintGridAll();
3863 ScDocShellModificator
aModificator( rDocShell
);
3864 aModificator
.SetDocumentModified();
3869 void ScDocFunc::ClearItems( const ScMarkData
& rMark
, const sal_uInt16
* pWhich
, bool bApi
)
3871 ScDocShellModificator
aModificator( rDocShell
);
3873 ScDocument
& rDoc
= rDocShell
.GetDocument();
3874 bool bUndo (rDoc
.IsUndoEnabled());
3875 ScEditableTester
aTester( &rDoc
, rMark
);
3876 if (!aTester
.IsEditable())
3879 rDocShell
.ErrorMessage(aTester
.GetMessageId());
3883 // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
3884 // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
3888 ScMarkData aMultiMark
= rMark
;
3889 aMultiMark
.SetMarking(false); // for MarkToMulti
3890 aMultiMark
.MarkToMulti();
3891 aMultiMark
.GetMultiMarkArea( aMarkRange
);
3895 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
3896 SCTAB nEndTab
= aMarkRange
.aEnd
.Tab();
3898 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
3899 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nEndTab
);
3900 rDoc
.CopyToDocument( aMarkRange
, InsertDeleteFlags::ATTRIB
, true, pUndoDoc
, &aMultiMark
);
3902 rDocShell
.GetUndoManager()->AddUndoAction(
3903 new ScUndoClearItems( &rDocShell
, aMultiMark
, pUndoDoc
, pWhich
) );
3906 rDoc
.ClearSelectionItems( pWhich
, aMultiMark
);
3908 rDocShell
.PostPaint( aMarkRange
, PAINT_GRID
, SC_PF_LINES
| SC_PF_TESTMERGE
);
3909 aModificator
.SetDocumentModified();
3911 //! Bindings-Invalidate etc.?
3914 bool ScDocFunc::ChangeIndent( const ScMarkData
& rMark
, bool bIncrement
, bool bApi
)
3916 ScDocShellModificator
aModificator( rDocShell
);
3918 ScDocument
& rDoc
= rDocShell
.GetDocument();
3919 bool bUndo(rDoc
.IsUndoEnabled());
3920 ScEditableTester
aTester( &rDoc
, rMark
);
3921 if (!aTester
.IsEditable())
3924 rDocShell
.ErrorMessage(aTester
.GetMessageId());
3929 rMark
.GetMultiMarkArea( aMarkRange
);
3933 SCTAB nStartTab
= aMarkRange
.aStart
.Tab();
3934 SCTAB nTabCount
= rDoc
.GetTableCount();
3936 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
3937 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nStartTab
);
3938 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
3939 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
3940 if (*itr
!= nStartTab
)
3941 pUndoDoc
->AddUndoTab( *itr
, *itr
);
3943 ScRange aCopyRange
= aMarkRange
;
3944 aCopyRange
.aStart
.SetTab(0);
3945 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
3946 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, true, pUndoDoc
, &rMark
);
3948 rDocShell
.GetUndoManager()->AddUndoAction(
3949 new ScUndoIndent( &rDocShell
, rMark
, pUndoDoc
, bIncrement
) );
3952 rDoc
.ChangeSelectionIndent( bIncrement
, rMark
);
3954 rDocShell
.PostPaint( aMarkRange
, PAINT_GRID
, SC_PF_LINES
| SC_PF_TESTMERGE
);
3955 aModificator
.SetDocumentModified();
3957 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
3960 pBindings
->Invalidate( SID_ALIGNLEFT
); // ChangeIndent setzt auf links
3961 pBindings
->Invalidate( SID_ALIGNRIGHT
);
3962 pBindings
->Invalidate( SID_ALIGNBLOCK
);
3963 pBindings
->Invalidate( SID_ALIGNCENTERHOR
);
3964 pBindings
->Invalidate( SID_ATTR_LRSPACE
);
3965 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_LEFT
);
3966 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT
);
3967 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK
);
3968 pBindings
->Invalidate( SID_ATTR_PARA_ADJUST_CENTER
);
3969 // pseudo slots for Format menu
3970 pBindings
->Invalidate( SID_ALIGN_ANY_HDEFAULT
);
3971 pBindings
->Invalidate( SID_ALIGN_ANY_LEFT
);
3972 pBindings
->Invalidate( SID_ALIGN_ANY_HCENTER
);
3973 pBindings
->Invalidate( SID_ALIGN_ANY_RIGHT
);
3974 pBindings
->Invalidate( SID_ALIGN_ANY_JUSTIFIED
);
3980 bool ScDocFunc::AutoFormat( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
3981 sal_uInt16 nFormatNo
, bool bApi
)
3983 ScDocShellModificator
aModificator( rDocShell
);
3985 bool bSuccess
= false;
3986 ScDocument
& rDoc
= rDocShell
.GetDocument();
3987 SCCOL nStartCol
= rRange
.aStart
.Col();
3988 SCROW nStartRow
= rRange
.aStart
.Row();
3989 SCTAB nStartTab
= rRange
.aStart
.Tab();
3990 SCCOL nEndCol
= rRange
.aEnd
.Col();
3991 SCROW nEndRow
= rRange
.aEnd
.Row();
3992 SCTAB nEndTab
= rRange
.aEnd
.Tab();
3994 bool bRecord
= true;
3995 if (!rDoc
.IsUndoEnabled())
4002 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4003 aMark
.SelectTable( nTab
, true );
4006 ScAutoFormat
* pAutoFormat
= ScGlobal::GetOrCreateAutoFormat();
4007 ScEditableTester
aTester( &rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4008 if ( nFormatNo
< pAutoFormat
->size() && aTester
.IsEditable() )
4010 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4012 bool bSize
= pAutoFormat
->findByIndex(nFormatNo
)->GetIncludeWidthHeight();
4014 SCTAB nTabCount
= rDoc
.GetTableCount();
4015 ScDocument
* pUndoDoc
= nullptr;
4018 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4019 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nStartTab
, bSize
, bSize
);
4020 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
4021 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
4022 if (*itr
!= nStartTab
)
4023 pUndoDoc
->AddUndoTab( *itr
, *itr
, bSize
, bSize
);
4025 ScRange aCopyRange
= rRange
;
4026 aCopyRange
.aStart
.SetTab(0);
4027 aCopyRange
.aStart
.SetTab(nTabCount
-1);
4028 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::ATTRIB
, false, pUndoDoc
, &aMark
);
4031 rDoc
.CopyToDocument( nStartCol
,0,0, nEndCol
,MAXROW
,nTabCount
-1,
4032 InsertDeleteFlags::NONE
, false, pUndoDoc
, &aMark
);
4033 rDoc
.CopyToDocument( 0,nStartRow
,0, MAXCOL
,nEndRow
,nTabCount
-1,
4034 InsertDeleteFlags::NONE
, false, pUndoDoc
, &aMark
);
4036 rDoc
.BeginDrawUndo();
4039 rDoc
.AutoFormat( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nFormatNo
, aMark
);
4043 std::vector
<sc::ColRowSpan
> aCols(1, sc::ColRowSpan(nStartCol
,nEndCol
));
4044 std::vector
<sc::ColRowSpan
> aRows(1, sc::ColRowSpan(nStartRow
,nEndRow
));
4046 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
4047 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
4049 SetWidthOrHeight(true, aCols
, *itr
, SC_SIZE_VISOPT
, STD_EXTRA_WIDTH
, false, true);
4050 SetWidthOrHeight(false, aRows
, *itr
, SC_SIZE_VISOPT
, 0, false, false);
4051 rDocShell
.PostPaint( 0,0,*itr
, MAXCOL
,MAXROW
,*itr
,
4052 PAINT_GRID
| PAINT_LEFT
| PAINT_TOP
);
4057 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
4058 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
4060 bool bAdj
= AdjustRowHeight( ScRange(nStartCol
, nStartRow
, *itr
,
4061 nEndCol
, nEndRow
, *itr
), false );
4063 rDocShell
.PostPaint( 0,nStartRow
,*itr
, MAXCOL
,MAXROW
,*itr
,
4064 PAINT_GRID
| PAINT_LEFT
);
4066 rDocShell
.PostPaint( nStartCol
, nStartRow
, *itr
,
4067 nEndCol
, nEndRow
, *itr
, PAINT_GRID
);
4071 if ( bRecord
) // Draw-Undo erst jetzt verfuegbar
4073 rDocShell
.GetUndoManager()->AddUndoAction(
4074 new ScUndoAutoFormat( &rDocShell
, rRange
, pUndoDoc
, aMark
, bSize
, nFormatNo
) );
4077 aModificator
.SetDocumentModified();
4080 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4085 bool ScDocFunc::EnterMatrix( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4086 const ScTokenArray
* pTokenArray
, const OUString
& rString
, bool bApi
, bool bEnglish
,
4087 const OUString
& rFormulaNmsp
, const formula::FormulaGrammar::Grammar eGrammar
)
4089 if (ScViewData::SelectionFillDOOM( rRange
))
4092 ScDocShellModificator
aModificator( rDocShell
);
4094 bool bSuccess
= false;
4095 ScDocument
& rDoc
= rDocShell
.GetDocument();
4096 SCCOL nStartCol
= rRange
.aStart
.Col();
4097 SCROW nStartRow
= rRange
.aStart
.Row();
4098 SCTAB nStartTab
= rRange
.aStart
.Tab();
4099 SCCOL nEndCol
= rRange
.aEnd
.Col();
4100 SCROW nEndRow
= rRange
.aEnd
.Row();
4101 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4108 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4109 aMark
.SelectTable( nTab
, true );
4112 ScEditableTester
aTester( &rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4113 if ( aTester
.IsEditable() )
4115 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4117 ScDocument
* pUndoDoc
= nullptr;
4119 const bool bUndo(rDoc
.IsUndoEnabled());
4122 //! auch bei Undo selektierte Tabellen beruecksichtigen
4123 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4124 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nEndTab
);
4125 rDoc
.CopyToDocument( rRange
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::NOTE
, false, pUndoDoc
);
4128 // use TokenArray if given, string (and flags) otherwise
4131 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4132 aMark
, EMPTY_OUSTRING
, pTokenArray
, eGrammar
);
4134 else if ( rDoc
.IsImportingXML() )
4136 ScTokenArray
* pCode
= lcl_ScDocFunc_CreateTokenArrayXML( rString
, rFormulaNmsp
, eGrammar
);
4137 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4138 aMark
, EMPTY_OUSTRING
, pCode
, eGrammar
);
4140 rDoc
.IncXMLImportedFormulaCount( rString
.getLength() );
4144 ScCompiler
aComp( &rDoc
, rRange
.aStart
);
4145 aComp
.SetGrammar(eGrammar
);
4146 ScTokenArray
* pCode
= aComp
.CompileString( rString
);
4147 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4148 aMark
, EMPTY_OUSTRING
, pCode
, eGrammar
);
4152 rDoc
.InsertMatrixFormula( nStartCol
, nStartRow
, nEndCol
, nEndRow
,
4153 aMark
, rString
, nullptr, eGrammar
);
4157 //! auch bei Undo selektierte Tabellen beruecksichtigen
4158 rDocShell
.GetUndoManager()->AddUndoAction(
4159 new ScUndoEnterMatrix( &rDocShell
, rRange
, pUndoDoc
, rString
) );
4162 // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
4163 rDocShell
.PostPaint( nStartCol
,nStartRow
,nStartTab
,nEndCol
,nEndRow
,nEndTab
, PAINT_GRID
);
4164 aModificator
.SetDocumentModified();
4169 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4174 bool ScDocFunc::TabOp( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4175 const ScTabOpParam
& rParam
, bool bRecord
, bool bApi
)
4177 ScDocShellModificator
aModificator( rDocShell
);
4179 bool bSuccess
= false;
4180 ScDocument
& rDoc
= rDocShell
.GetDocument();
4181 SCCOL nStartCol
= rRange
.aStart
.Col();
4182 SCROW nStartRow
= rRange
.aStart
.Row();
4183 SCTAB nStartTab
= rRange
.aStart
.Tab();
4184 SCCOL nEndCol
= rRange
.aEnd
.Col();
4185 SCROW nEndRow
= rRange
.aEnd
.Row();
4186 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4188 if (bRecord
&& !rDoc
.IsUndoEnabled())
4196 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4197 aMark
.SelectTable( nTab
, true );
4200 ScEditableTester
aTester( &rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4201 if ( aTester
.IsEditable() )
4203 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4204 rDoc
.SetDirty( rRange
, false );
4207 //! auch bei Undo selektierte Tabellen beruecksichtigen
4208 ScDocument
* pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4209 pUndoDoc
->InitUndo( &rDoc
, nStartTab
, nEndTab
);
4210 rDoc
.CopyToDocument( rRange
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::NOTE
, false, pUndoDoc
);
4212 rDocShell
.GetUndoManager()->AddUndoAction(
4213 new ScUndoTabOp( &rDocShell
,
4214 nStartCol
, nStartRow
, nStartTab
,
4215 nEndCol
, nEndRow
, nEndTab
, pUndoDoc
,
4216 rParam
.aRefFormulaCell
,
4217 rParam
.aRefFormulaEnd
,
4222 rDoc
.InsertTableOp(rParam
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, aMark
);
4223 rDocShell
.PostPaintGridAll();
4224 aModificator
.SetDocumentModified();
4228 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4233 inline ScDirection
DirFromFillDir( FillDir eDir
)
4235 if (eDir
==FILL_TO_BOTTOM
)
4237 else if (eDir
==FILL_TO_RIGHT
)
4239 else if (eDir
==FILL_TO_TOP
)
4241 else // if (eDir==FILL_TO_LEFT)
4248 * Expand the fill range as necessary, to allow copying of adjacent cell(s)
4249 * even when those cells are not in the original range.
4251 void adjustFillRangeForAdjacentCopy(ScRange
& rRange
, FillDir eDir
)
4255 case FILL_TO_BOTTOM
:
4257 if (rRange
.aStart
.Row() == 0)
4260 if (rRange
.aStart
.Row() != rRange
.aEnd
.Row())
4263 // Include the above row.
4264 ScAddress
& s
= rRange
.aStart
;
4265 s
.SetRow(s
.Row()-1);
4270 if (rRange
.aStart
.Row() == MAXROW
)
4273 if (rRange
.aStart
.Row() != rRange
.aEnd
.Row())
4276 // Include the row below.
4277 ScAddress
& e
= rRange
.aEnd
;
4278 e
.SetRow(e
.Row()+1);
4283 if (rRange
.aStart
.Col() == MAXCOL
)
4286 if (rRange
.aStart
.Col() != rRange
.aEnd
.Col())
4289 // Include the column to the right.
4290 ScAddress
& e
= rRange
.aEnd
;
4291 e
.SetCol(e
.Col()+1);
4296 if (rRange
.aStart
.Col() == 0)
4299 if (rRange
.aStart
.Col() != rRange
.aEnd
.Col())
4302 // Include the column to the left.
4303 ScAddress
& s
= rRange
.aStart
;
4304 s
.SetCol(s
.Col()-1);
4314 bool ScDocFunc::FillSimple( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4315 FillDir eDir
, bool bApi
)
4317 ScDocShellModificator
aModificator( rDocShell
);
4318 ScDocument
& rDoc
= rDocShell
.GetDocument();
4320 bool bSuccess
= false;
4321 ScRange aRange
= rRange
;
4322 adjustFillRangeForAdjacentCopy(aRange
, eDir
);
4324 SCCOL nStartCol
= aRange
.aStart
.Col();
4325 SCROW nStartRow
= aRange
.aStart
.Row();
4326 SCTAB nStartTab
= aRange
.aStart
.Tab();
4327 SCCOL nEndCol
= aRange
.aEnd
.Col();
4328 SCROW nEndRow
= aRange
.aEnd
.Row();
4329 SCTAB nEndTab
= aRange
.aEnd
.Tab();
4331 bool bRecord
= true;
4332 if (!rDoc
.IsUndoEnabled())
4340 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4341 aMark
.SelectTable( nTab
, true );
4344 ScEditableTester
aTester( &rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4345 if ( aTester
.IsEditable() )
4347 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4349 ScRange aSourceArea
= aRange
;
4350 ScRange aDestArea
= aRange
;
4352 SCCOLROW nCount
= 0;
4355 case FILL_TO_BOTTOM
:
4356 nCount
= aSourceArea
.aEnd
.Row()-aSourceArea
.aStart
.Row();
4357 aSourceArea
.aEnd
.SetRow( aSourceArea
.aStart
.Row() );
4360 nCount
= aSourceArea
.aEnd
.Col()-aSourceArea
.aStart
.Col();
4361 aSourceArea
.aEnd
.SetCol( aSourceArea
.aStart
.Col() );
4364 nCount
= aSourceArea
.aEnd
.Row()-aSourceArea
.aStart
.Row();
4365 aSourceArea
.aStart
.SetRow( aSourceArea
.aEnd
.Row() );
4368 nCount
= aSourceArea
.aEnd
.Col()-aSourceArea
.aStart
.Col();
4369 aSourceArea
.aStart
.SetCol( aSourceArea
.aEnd
.Col() );
4373 ScDocument
* pUndoDoc
= nullptr;
4376 SCTAB nTabCount
= rDoc
.GetTableCount();
4377 SCTAB nDestStartTab
= aDestArea
.aStart
.Tab();
4379 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4380 pUndoDoc
->InitUndo( &rDoc
, nDestStartTab
, nDestStartTab
);
4381 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
4382 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
4383 if (*itr
!= nDestStartTab
)
4384 pUndoDoc
->AddUndoTab( *itr
, *itr
);
4386 ScRange aCopyRange
= aDestArea
;
4387 aCopyRange
.aStart
.SetTab(0);
4388 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
4389 rDoc
.CopyToDocument( aCopyRange
, InsertDeleteFlags::AUTOFILL
, false, pUndoDoc
, &aMark
);
4392 sal_uLong nProgCount
;
4393 if (eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
)
4394 nProgCount
= aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1;
4396 nProgCount
= aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1;
4397 nProgCount
*= nCount
;
4398 ScProgress
aProgress( rDoc
.GetDocumentShell(),
4399 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS
), nProgCount
, true );
4401 rDoc
.Fill( aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(),
4402 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), &aProgress
,
4403 aMark
, nCount
, eDir
, FILL_SIMPLE
);
4404 AdjustRowHeight(aRange
);
4406 if ( bRecord
) // Draw-Undo erst jetzt verfuegbar
4408 rDocShell
.GetUndoManager()->AddUndoAction(
4409 new ScUndoAutoFill( &rDocShell
, aDestArea
, aSourceArea
, pUndoDoc
, aMark
,
4410 eDir
, FILL_SIMPLE
, FILL_DAY
, MAXDOUBLE
, 1.0, 1e307
) );
4413 rDocShell
.PostPaintGridAll();
4414 aModificator
.SetDocumentModified();
4419 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4424 bool ScDocFunc::FillSeries( const ScRange
& rRange
, const ScMarkData
* pTabMark
,
4425 FillDir eDir
, FillCmd eCmd
, FillDateCmd eDateCmd
,
4426 double fStart
, double fStep
, double fMax
,
4429 ScDocShellModificator
aModificator( rDocShell
);
4431 bool bSuccess
= false;
4432 ScDocument
& rDoc
= rDocShell
.GetDocument();
4433 SCCOL nStartCol
= rRange
.aStart
.Col();
4434 SCROW nStartRow
= rRange
.aStart
.Row();
4435 SCTAB nStartTab
= rRange
.aStart
.Tab();
4436 SCCOL nEndCol
= rRange
.aEnd
.Col();
4437 SCROW nEndRow
= rRange
.aEnd
.Row();
4438 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4440 bool bRecord
= true;
4441 if (!rDoc
.IsUndoEnabled())
4449 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4450 aMark
.SelectTable( nTab
, true );
4453 ScEditableTester
aTester( &rDoc
, nStartCol
,nStartRow
, nEndCol
,nEndRow
, aMark
);
4454 if ( aTester
.IsEditable() )
4456 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4458 ScRange aSourceArea
= rRange
;
4459 ScRange aDestArea
= rRange
;
4461 SCSIZE nCount
= rDoc
.GetEmptyLinesInBlock(
4462 aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(), aSourceArea
.aStart
.Tab(),
4463 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), aSourceArea
.aEnd
.Tab(),
4464 DirFromFillDir(eDir
) );
4466 // mindestens eine Zeile/Spalte als Quellbereich behalten:
4467 SCSIZE nTotLines
= ( eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
) ?
4468 static_cast<SCSIZE
>( aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1 ) :
4469 static_cast<SCSIZE
>( aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1 );
4470 if ( nCount
>= nTotLines
)
4471 nCount
= nTotLines
- 1;
4475 case FILL_TO_BOTTOM
:
4476 aSourceArea
.aEnd
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aEnd
.Row() - nCount
) );
4479 aSourceArea
.aEnd
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aEnd
.Col() - nCount
) );
4482 aSourceArea
.aStart
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aStart
.Row() + nCount
) );
4485 aSourceArea
.aStart
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aStart
.Col() + nCount
) );
4489 ScDocument
* pUndoDoc
= nullptr;
4492 SCTAB nTabCount
= rDoc
.GetTableCount();
4493 SCTAB nDestStartTab
= aDestArea
.aStart
.Tab();
4495 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4496 pUndoDoc
->InitUndo( &rDoc
, nDestStartTab
, nDestStartTab
);
4497 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
4498 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
4499 if (*itr
!= nDestStartTab
)
4500 pUndoDoc
->AddUndoTab( *itr
, *itr
);
4502 rDoc
.CopyToDocument(
4503 aDestArea
.aStart
.Col(), aDestArea
.aStart
.Row(), 0,
4504 aDestArea
.aEnd
.Col(), aDestArea
.aEnd
.Row(), nTabCount
-1,
4505 InsertDeleteFlags::AUTOFILL
, false, pUndoDoc
, &aMark
);
4508 if (aDestArea
.aStart
.Col() <= aDestArea
.aEnd
.Col() &&
4509 aDestArea
.aStart
.Row() <= aDestArea
.aEnd
.Row())
4511 if ( fStart
!= MAXDOUBLE
)
4513 SCCOL nValX
= (eDir
== FILL_TO_LEFT
) ? aDestArea
.aEnd
.Col() : aDestArea
.aStart
.Col();
4514 SCROW nValY
= (eDir
== FILL_TO_TOP
) ? aDestArea
.aEnd
.Row() : aDestArea
.aStart
.Row();
4515 SCTAB nTab
= aDestArea
.aStart
.Tab();
4516 rDoc
.SetValue( nValX
, nValY
, nTab
, fStart
);
4519 sal_uLong nProgCount
;
4520 if (eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
)
4521 nProgCount
= aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1;
4523 nProgCount
= aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1;
4524 nProgCount
*= nCount
;
4525 ScProgress
aProgress( rDoc
.GetDocumentShell(),
4526 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS
), nProgCount
, true );
4528 rDoc
.Fill( aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(),
4529 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), &aProgress
,
4530 aMark
, nCount
, eDir
, eCmd
, eDateCmd
, fStep
, fMax
);
4531 AdjustRowHeight(rRange
);
4533 rDocShell
.PostPaintGridAll();
4534 aModificator
.SetDocumentModified();
4537 if ( bRecord
) // Draw-Undo erst jetzt verfuegbar
4539 rDocShell
.GetUndoManager()->AddUndoAction(
4540 new ScUndoAutoFill( &rDocShell
, aDestArea
, aSourceArea
, pUndoDoc
, aMark
,
4541 eDir
, eCmd
, eDateCmd
, fStart
, fStep
, fMax
) );
4547 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4552 bool ScDocFunc::FillAuto( ScRange
& rRange
, const ScMarkData
* pTabMark
,
4553 FillDir eDir
, sal_uLong nCount
, bool bApi
)
4556 double fMax
= MAXDOUBLE
;
4557 return FillAuto( rRange
, pTabMark
, eDir
, FILL_AUTO
, FILL_DAY
, nCount
, fStep
, fMax
, true/*bRecord*/, bApi
);
4560 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
)
4562 ScDocShellModificator
aModificator( rDocShell
);
4564 ScDocument
& rDoc
= rDocShell
.GetDocument();
4565 SCCOL nStartCol
= rRange
.aStart
.Col();
4566 SCROW nStartRow
= rRange
.aStart
.Row();
4567 SCTAB nStartTab
= rRange
.aStart
.Tab();
4568 SCCOL nEndCol
= rRange
.aEnd
.Col();
4569 SCROW nEndRow
= rRange
.aEnd
.Row();
4570 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4572 if (bRecord
&& !rDoc
.IsUndoEnabled())
4580 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4581 aMark
.SelectTable( nTab
, true );
4584 ScRange aSourceArea
= rRange
;
4585 ScRange aDestArea
= rRange
;
4589 case FILL_TO_BOTTOM
:
4590 aDestArea
.aEnd
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aEnd
.Row() + nCount
) );
4593 if (nCount
> sal::static_int_cast
<sal_uLong
>( aSourceArea
.aStart
.Row() ))
4595 OSL_FAIL("FillAuto: Row < 0");
4596 nCount
= aSourceArea
.aStart
.Row();
4598 aDestArea
.aStart
.SetRow( sal::static_int_cast
<SCROW
>( aSourceArea
.aStart
.Row() - nCount
) );
4601 aDestArea
.aEnd
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aEnd
.Col() + nCount
) );
4604 if (nCount
> sal::static_int_cast
<sal_uLong
>( aSourceArea
.aStart
.Col() ))
4606 OSL_FAIL("FillAuto: Col < 0");
4607 nCount
= aSourceArea
.aStart
.Col();
4609 aDestArea
.aStart
.SetCol( sal::static_int_cast
<SCCOL
>( aSourceArea
.aStart
.Col() - nCount
) );
4612 OSL_FAIL("Falsche Richtung bei FillAuto");
4616 // Zellschutz testen
4617 //! Quellbereich darf geschuetzt sein !!!
4618 //! aber kein Matrixfragment enthalten !!!
4620 ScEditableTester
aTester( &rDoc
, aDestArea
);
4621 if ( !aTester
.IsEditable() )
4624 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4628 if ( rDoc
.HasSelectedBlockMatrixFragment( nStartCol
, nStartRow
,
4629 nEndCol
, nEndRow
, aMark
) )
4632 rDocShell
.ErrorMessage(STR_MATRIXFRAGMENTERR
);
4636 // FID_FILL_... slots should already had been disabled, check here for API
4637 // calls, no message.
4638 if (ScViewData::SelectionFillDOOM( aDestArea
))
4641 WaitObject
aWait( ScDocShell::GetActiveDialogParent() );
4643 ScDocument
* pUndoDoc
= nullptr;
4646 SCTAB nTabCount
= rDoc
.GetTableCount();
4647 SCTAB nDestStartTab
= aDestArea
.aStart
.Tab();
4649 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4650 pUndoDoc
->InitUndo( &rDoc
, nDestStartTab
, nDestStartTab
);
4651 ScMarkData::iterator itr
= aMark
.begin(), itrEnd
= aMark
.end();
4652 for (; itr
!= itrEnd
&& nTabCount
; ++itr
)
4653 if (*itr
!= nDestStartTab
)
4654 pUndoDoc
->AddUndoTab( *itr
, *itr
);
4656 // do not clone note captions in undo document
4657 rDoc
.CopyToDocument(
4658 aDestArea
.aStart
.Col(), aDestArea
.aStart
.Row(), 0,
4659 aDestArea
.aEnd
.Col(), aDestArea
.aEnd
.Row(), nTabCount
-1,
4660 InsertDeleteFlags::AUTOFILL
, false, pUndoDoc
, &aMark
);
4663 sal_uLong nProgCount
;
4664 if (eDir
== FILL_TO_BOTTOM
|| eDir
== FILL_TO_TOP
)
4665 nProgCount
= aSourceArea
.aEnd
.Col() - aSourceArea
.aStart
.Col() + 1;
4667 nProgCount
= aSourceArea
.aEnd
.Row() - aSourceArea
.aStart
.Row() + 1;
4668 nProgCount
*= nCount
;
4669 ScProgress
aProgress( rDoc
.GetDocumentShell(),
4670 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS
), nProgCount
, true );
4672 rDoc
.Fill( aSourceArea
.aStart
.Col(), aSourceArea
.aStart
.Row(),
4673 aSourceArea
.aEnd
.Col(), aSourceArea
.aEnd
.Row(), &aProgress
,
4674 aMark
, nCount
, eDir
, eCmd
, eDateCmd
, fStep
, fMax
);
4676 AdjustRowHeight(aDestArea
);
4678 if ( bRecord
) // Draw-Undo erst jetzt verfuegbar
4680 rDocShell
.GetUndoManager()->AddUndoAction(
4681 new ScUndoAutoFill( &rDocShell
, aDestArea
, aSourceArea
, pUndoDoc
, aMark
,
4682 eDir
, eCmd
, eDateCmd
, MAXDOUBLE
, fStep
, fMax
) );
4685 rDocShell
.PostPaintGridAll();
4686 aModificator
.SetDocumentModified();
4688 rRange
= aDestArea
; // Zielbereich zurueckgeben (zum Markieren)
4692 bool ScDocFunc::MergeCells( const ScCellMergeOption
& rOption
, bool bContents
, bool bRecord
, bool bApi
)
4696 ScDocShellModificator
aModificator( rDocShell
);
4698 SCCOL nStartCol
= rOption
.mnStartCol
;
4699 SCROW nStartRow
= rOption
.mnStartRow
;
4700 SCCOL nEndCol
= rOption
.mnEndCol
;
4701 SCROW nEndRow
= rOption
.mnEndRow
;
4702 if ((nStartCol
== nEndCol
&& nStartRow
== nEndRow
) || rOption
.maTabs
.empty())
4704 // Nothing to do. Bail out quick.
4708 ScDocument
& rDoc
= rDocShell
.GetDocument();
4709 set
<SCTAB
>::const_iterator itrBeg
= rOption
.maTabs
.begin(), itrEnd
= rOption
.maTabs
.end();
4710 SCTAB nTab1
= *itrBeg
, nTab2
= *rOption
.maTabs
.rbegin();
4712 if (bRecord
&& !rDoc
.IsUndoEnabled())
4715 for (set
<SCTAB
>::const_iterator itr
= itrBeg
; itr
!= itrEnd
; ++itr
)
4717 ScEditableTester
aTester( &rDoc
, *itr
, nStartCol
, nStartRow
, nEndCol
, nEndRow
);
4718 if (!aTester
.IsEditable())
4721 rDocShell
.ErrorMessage(aTester
.GetMessageId());
4725 if ( rDoc
.HasAttrib( nStartCol
, nStartRow
, *itr
, nEndCol
, nEndRow
, *itr
,
4726 HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
4728 // "Zusammenfassen nicht verschachteln !"
4730 rDocShell
.ErrorMessage(STR_MSSG_MERGECELLS_0
);
4735 ScDocument
* pUndoDoc
= nullptr;
4736 bool bNeedContentsUndo
= false;
4737 for (set
<SCTAB
>::const_iterator itr
= itrBeg
; itr
!= itrEnd
; ++itr
)
4740 bool bNeedContents
= bContents
&&
4741 ( !rDoc
.IsBlockEmpty( nTab
, nStartCol
,nStartRow
+1, nStartCol
,nEndRow
, true ) ||
4742 !rDoc
.IsBlockEmpty( nTab
, nStartCol
+1,nStartRow
, nEndCol
,nEndRow
, true ) );
4746 // test if the range contains other notes which also implies that we need an undo document
4747 bool bHasNotes
= false;
4748 for( ScAddress
aPos( nStartCol
, nStartRow
, nTab
); !bHasNotes
&& (aPos
.Col() <= nEndCol
); aPos
.IncCol() )
4749 for( aPos
.SetRow( nStartRow
); !bHasNotes
&& (aPos
.Row() <= nEndRow
); aPos
.IncRow() )
4750 bHasNotes
= ((aPos
.Col() != nStartCol
) || (aPos
.Row() != nStartRow
)) && (rDoc
.HasNote(aPos
));
4754 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4755 pUndoDoc
->InitUndo(&rDoc
, nTab1
, nTab2
);
4757 // note captions are collected by drawing undo
4758 rDoc
.CopyToDocument( nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
,
4759 InsertDeleteFlags::ALL
|InsertDeleteFlags::NOCAPTIONS
, false, pUndoDoc
);
4761 rDoc
.BeginDrawUndo();
4765 rDoc
.DoMergeContents( nTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
);
4766 rDoc
.DoMerge( nTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
);
4768 if (rOption
.mbCenter
)
4770 rDoc
.ApplyAttr( nStartCol
, nStartRow
, nTab
, SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER
, ATTR_HOR_JUSTIFY
) );
4771 rDoc
.ApplyAttr( nStartCol
, nStartRow
, nTab
, SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER
, ATTR_VER_JUSTIFY
) );
4774 if ( !AdjustRowHeight( ScRange( 0,nStartRow
,nTab
, MAXCOL
,nEndRow
,nTab
) ) )
4775 rDocShell
.PostPaint( nStartCol
, nStartRow
, nTab
,
4776 nEndCol
, nEndRow
, nTab
, PAINT_GRID
);
4777 if (bNeedContents
|| rOption
.mbCenter
)
4779 ScRange
aRange(nStartCol
, nStartRow
, nTab
, nEndCol
, nEndRow
, nTab
);
4780 rDoc
.SetDirty(aRange
, true);
4783 bNeedContentsUndo
|= bNeedContents
;
4788 SdrUndoGroup
* pDrawUndo
= rDoc
.GetDrawLayer() ? rDoc
.GetDrawLayer()->GetCalcUndo() : nullptr;
4789 rDocShell
.GetUndoManager()->AddUndoAction(
4790 new ScUndoMerge(&rDocShell
, rOption
, bNeedContentsUndo
, pUndoDoc
, pDrawUndo
) );
4793 aModificator
.SetDocumentModified();
4795 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
4798 pBindings
->Invalidate( FID_MERGE_ON
);
4799 pBindings
->Invalidate( FID_MERGE_OFF
);
4800 pBindings
->Invalidate( FID_MERGE_TOGGLE
);
4806 bool ScDocFunc::UnmergeCells( const ScRange
& rRange
, bool bRecord
, ScUndoRemoveMerge
* pUndoRemoveMerge
)
4808 ScCellMergeOption
aOption(rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row());
4809 SCTAB nTab1
= rRange
.aStart
.Tab(), nTab2
= rRange
.aEnd
.Tab();
4810 for (SCTAB i
= nTab1
; i
<= nTab2
; ++i
)
4811 aOption
.maTabs
.insert(i
);
4813 return UnmergeCells(aOption
, bRecord
, pUndoRemoveMerge
);
4816 bool ScDocFunc::UnmergeCells( const ScCellMergeOption
& rOption
, bool bRecord
, ScUndoRemoveMerge
* pUndoRemoveMerge
)
4820 if (rOption
.maTabs
.empty())
4821 // Nothing to unmerge.
4824 ScDocShellModificator
aModificator( rDocShell
);
4825 ScDocument
& rDoc
= rDocShell
.GetDocument();
4827 if (bRecord
&& !rDoc
.IsUndoEnabled())
4830 ScDocument
* pUndoDoc
= (pUndoRemoveMerge
? pUndoRemoveMerge
->GetUndoDoc() : nullptr);
4831 assert( pUndoDoc
|| !pUndoRemoveMerge
);
4832 for (set
<SCTAB
>::const_iterator itr
= rOption
.maTabs
.begin(), itrEnd
= rOption
.maTabs
.end();
4833 itr
!= itrEnd
; ++itr
)
4836 ScRange aRange
= rOption
.getSingleRange(nTab
);
4837 if ( !rDoc
.HasAttrib(aRange
, HASATTR_MERGED
) )
4840 ScRange aExtended
= aRange
;
4841 rDoc
.ExtendMerge(aExtended
);
4842 ScRange aRefresh
= aExtended
;
4843 rDoc
.ExtendOverlapped(aRefresh
);
4849 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
4850 pUndoDoc
->InitUndo(&rDoc
, *rOption
.maTabs
.begin(), *rOption
.maTabs
.rbegin());
4852 rDoc
.CopyToDocument(aExtended
, InsertDeleteFlags::ATTRIB
, false, pUndoDoc
);
4855 const SfxPoolItem
& rDefAttr
= rDoc
.GetPool()->GetDefaultItem( ATTR_MERGE
);
4856 ScPatternAttr
aPattern( rDoc
.GetPool() );
4857 aPattern
.GetItemSet().Put( rDefAttr
);
4858 rDoc
.ApplyPatternAreaTab( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
4859 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), nTab
,
4862 rDoc
.RemoveFlagsTab( aExtended
.aStart
.Col(), aExtended
.aStart
.Row(),
4863 aExtended
.aEnd
.Col(), aExtended
.aEnd
.Row(), nTab
,
4864 ScMF::Hor
| ScMF::Ver
);
4866 rDoc
.ExtendMerge( aRefresh
, true );
4868 if ( !AdjustRowHeight( aExtended
) )
4869 rDocShell
.PostPaint( aExtended
, PAINT_GRID
);
4874 if (pUndoRemoveMerge
)
4876 // If pUndoRemoveMerge was passed, the caller is responsible for
4877 // adding it to Undo. Just add the current option.
4878 pUndoRemoveMerge
->AddCellMergeOption( rOption
);
4882 rDocShell
.GetUndoManager()->AddUndoAction(
4883 new ScUndoRemoveMerge( &rDocShell
, rOption
, pUndoDoc
) );
4886 aModificator
.SetDocumentModified();
4891 void ScDocFunc::ModifyRangeNames( const ScRangeName
& rNewRanges
, SCTAB nTab
)
4893 SetNewRangeNames( new ScRangeName(rNewRanges
), true, nTab
);
4896 void ScDocFunc::SetNewRangeNames( ScRangeName
* pNewRanges
, bool bModifyDoc
, SCTAB nTab
) // takes ownership of pNewRanges
4898 ScDocShellModificator
aModificator( rDocShell
);
4900 OSL_ENSURE( pNewRanges
, "pNewRanges is 0" );
4901 ScDocument
& rDoc
= rDocShell
.GetDocument();
4902 bool bUndo(rDoc
.IsUndoEnabled());
4909 pOld
= rDoc
.GetRangeName(nTab
);
4913 pOld
= rDoc
.GetRangeName();
4915 ScRangeName
* pUndoRanges
= new ScRangeName(*pOld
);
4916 ScRangeName
* pRedoRanges
= new ScRangeName(*pNewRanges
);
4917 rDocShell
.GetUndoManager()->AddUndoAction(
4918 new ScUndoRangeNames( &rDocShell
, pUndoRanges
, pRedoRanges
, nTab
) );
4921 // #i55926# While loading XML, formula cells only have a single string token,
4922 // so CompileNameFormula would never find any name (index) tokens, and would
4923 // unnecessarily loop through all cells.
4924 bool bCompile
= ( !rDoc
.IsImportingXML() && rDoc
.GetNamedRangesLockCount() == 0 );
4927 rDoc
.PreprocessRangeNameUpdate();
4929 rDoc
.SetRangeName( nTab
, pNewRanges
); // takes ownership
4931 rDoc
.SetRangeName( pNewRanges
); // takes ownership
4933 rDoc
.CompileHybridFormula();
4937 aModificator
.SetDocumentModified();
4938 SfxGetpApp()->Broadcast( SfxSimpleHint(SC_HINT_AREAS_CHANGED
) );
4942 void ScDocFunc::ModifyAllRangeNames(const std::map
<OUString
, std::unique_ptr
<ScRangeName
>>& rRangeMap
)
4944 ScDocShellModificator
aModificator(rDocShell
);
4945 ScDocument
& rDoc
= rDocShell
.GetDocument();
4947 if (rDoc
.IsUndoEnabled())
4949 std::map
<OUString
, ScRangeName
*> aOldRangeMap
;
4950 rDoc
.GetRangeNameMap(aOldRangeMap
);
4951 rDocShell
.GetUndoManager()->AddUndoAction(
4952 new ScUndoAllRangeNames(&rDocShell
, aOldRangeMap
, rRangeMap
));
4955 rDoc
.PreprocessRangeNameUpdate();
4956 rDoc
.SetAllRangeNames(rRangeMap
);
4957 rDoc
.CompileHybridFormula();
4959 aModificator
.SetDocumentModified();
4960 SfxGetpApp()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED
));
4963 void ScDocFunc::CreateOneName( ScRangeName
& rList
,
4964 SCCOL nPosX
, SCROW nPosY
, SCTAB nTab
,
4965 SCCOL nX1
, SCROW nY1
, SCCOL nX2
, SCROW nY2
,
4966 bool& rCancel
, bool bApi
)
4971 ScDocument
& rDoc
= rDocShell
.GetDocument();
4972 if (!rDoc
.HasValueData( nPosX
, nPosY
, nTab
))
4974 OUString aName
= rDoc
.GetString(nPosX
, nPosY
, nTab
);
4975 ScRangeData::MakeValidName(aName
);
4976 if (!aName
.isEmpty())
4978 OUString
aContent(ScRange( nX1
, nY1
, nTab
, nX2
, nY2
, nTab
).Format(ScRefFlags::RANGE_ABS_3D
, &rDoc
));
4980 bool bInsert
= false;
4981 ScRangeData
* pOld
= rList
.findByUpperName(ScGlobal::pCharClass
->uppercase(aName
));
4985 pOld
->GetSymbol( aOldStr
);
4986 if (aOldStr
!= aContent
)
4989 bInsert
= true; // per API nicht nachfragen
4992 OUString aTemplate
= ScGlobal::GetRscString( STR_CREATENAME_REPLACE
);
4994 OUString aMessage
= aTemplate
.getToken( 0, '#' );
4996 aMessage
+= aTemplate
.getToken( 1, '#' );
4998 short nResult
= ScopedVclPtrInstance
<QueryBox
>( ScDocShell::GetActiveDialogParent(),
4999 WinBits(WB_YES_NO_CANCEL
| WB_DEF_YES
),
5000 aMessage
)->Execute();
5001 if ( nResult
== RET_YES
)
5006 else if ( nResult
== RET_CANCEL
)
5016 ScRangeData
* pData
= new ScRangeData( &rDoc
, aName
, aContent
,
5017 ScAddress( nPosX
, nPosY
, nTab
));
5018 if (!rList
.insert(pData
))
5027 bool ScDocFunc::CreateNames( const ScRange
& rRange
, sal_uInt16 nFlags
, bool bApi
, SCTAB aTab
)
5030 return false; // war nix
5032 ScDocShellModificator
aModificator( rDocShell
);
5035 SCCOL nStartCol
= rRange
.aStart
.Col();
5036 SCROW nStartRow
= rRange
.aStart
.Row();
5037 SCCOL nEndCol
= rRange
.aEnd
.Col();
5038 SCROW nEndRow
= rRange
.aEnd
.Row();
5039 SCTAB nTab
= rRange
.aStart
.Tab();
5040 OSL_ENSURE(rRange
.aEnd
.Tab() == nTab
, "CreateNames: mehrere Tabellen geht nicht");
5043 if ( nFlags
& ( NAME_TOP
| NAME_BOTTOM
) )
5044 if ( nStartRow
== nEndRow
)
5046 if ( nFlags
& ( NAME_LEFT
| NAME_RIGHT
) )
5047 if ( nStartCol
== nEndCol
)
5052 ScDocument
& rDoc
= rDocShell
.GetDocument();
5053 ScRangeName
* pNames
;
5055 pNames
= rDoc
.GetRangeName(nTab
);
5057 pNames
= rDoc
.GetRangeName();
5060 return false; // soll nicht sein
5061 ScRangeName
aNewRanges( *pNames
);
5063 bool bTop
= ( ( nFlags
& NAME_TOP
) != 0 );
5064 bool bLeft
= ( ( nFlags
& NAME_LEFT
) != 0 );
5065 bool bBottom
= ( ( nFlags
& NAME_BOTTOM
) != 0 );
5066 bool bRight
= ( ( nFlags
& NAME_RIGHT
) != 0 );
5068 SCCOL nContX1
= nStartCol
;
5069 SCROW nContY1
= nStartRow
;
5070 SCCOL nContX2
= nEndCol
;
5071 SCROW nContY2
= nEndRow
;
5082 bool bCancel
= false;
5087 for (i
=nContX1
; i
<=nContX2
; i
++)
5088 CreateOneName( aNewRanges
, i
,nStartRow
,nTab
, i
,nContY1
,i
,nContY2
, bCancel
, bApi
);
5090 for (j
=nContY1
; j
<=nContY2
; j
++)
5091 CreateOneName( aNewRanges
, nStartCol
,j
,nTab
, nContX1
,j
,nContX2
,j
, bCancel
, bApi
);
5093 for (i
=nContX1
; i
<=nContX2
; i
++)
5094 CreateOneName( aNewRanges
, i
,nEndRow
,nTab
, i
,nContY1
,i
,nContY2
, bCancel
, bApi
);
5096 for (j
=nContY1
; j
<=nContY2
; j
++)
5097 CreateOneName( aNewRanges
, nEndCol
,j
,nTab
, nContX1
,j
,nContX2
,j
, bCancel
, bApi
);
5099 if ( bTop
&& bLeft
)
5100 CreateOneName( aNewRanges
, nStartCol
,nStartRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5101 if ( bTop
&& bRight
)
5102 CreateOneName( aNewRanges
, nEndCol
,nStartRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5103 if ( bBottom
&& bLeft
)
5104 CreateOneName( aNewRanges
, nStartCol
,nEndRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5105 if ( bBottom
&& bRight
)
5106 CreateOneName( aNewRanges
, nEndCol
,nEndRow
,nTab
, nContX1
,nContY1
,nContX2
,nContY2
, bCancel
, bApi
);
5108 ModifyRangeNames( aNewRanges
, aTab
);
5116 bool ScDocFunc::InsertNameList( const ScAddress
& rStartPos
, bool bApi
)
5118 ScDocShellModificator
aModificator( rDocShell
);
5121 ScDocument
& rDoc
= rDocShell
.GetDocument();
5122 const bool bRecord
= rDoc
.IsUndoEnabled();
5123 SCTAB nTab
= rStartPos
.Tab();
5125 //local names have higher priority than global names
5126 ScRangeName
* pLocalList
= rDoc
.GetRangeName(nTab
);
5127 sal_uInt16 nValidCount
= 0;
5128 ScRangeName::iterator itrLocalBeg
= pLocalList
->begin(), itrLocalEnd
= pLocalList
->end();
5129 for (ScRangeName::iterator itr
= itrLocalBeg
; itr
!= itrLocalEnd
; ++itr
)
5131 const ScRangeData
& r
= *itr
->second
;
5132 if (!r
.HasType(ScRangeData::Type::Database
))
5135 ScRangeName
* pList
= rDoc
.GetRangeName();
5136 ScRangeName::iterator itrBeg
= pList
->begin(), itrEnd
= pList
->end();
5137 for (ScRangeName::iterator itr
= itrBeg
; itr
!= itrEnd
; ++itr
)
5139 const ScRangeData
& r
= *itr
->second
;
5140 if (!r
.HasType(ScRangeData::Type::Database
) && !pLocalList
->findByUpperName(r
.GetUpperName()))
5146 SCCOL nStartCol
= rStartPos
.Col();
5147 SCROW nStartRow
= rStartPos
.Row();
5148 SCCOL nEndCol
= nStartCol
+ 1;
5149 SCROW nEndRow
= nStartRow
+ static_cast<SCROW
>(nValidCount
) - 1;
5151 ScEditableTester
aTester( &rDoc
, nTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
);
5152 if (aTester
.IsEditable())
5154 ScDocument
* pUndoDoc
= nullptr;
5158 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
5159 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
);
5160 rDoc
.CopyToDocument( nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
,
5161 InsertDeleteFlags::ALL
, false, pUndoDoc
);
5163 rDoc
.BeginDrawUndo(); // wegen Hoehenanpassung
5166 std::unique_ptr
<ScRangeData
*[]> ppSortArray(new ScRangeData
* [ nValidCount
]);
5168 for (ScRangeName::iterator itr
= itrLocalBeg
; itr
!= itrLocalEnd
; ++itr
)
5170 ScRangeData
& r
= *itr
->second
;
5171 if (!r
.HasType(ScRangeData::Type::Database
))
5172 ppSortArray
[j
++] = &r
;
5174 for (ScRangeName::iterator itr
= itrBeg
; itr
!= itrEnd
; ++itr
)
5176 ScRangeData
& r
= *itr
->second
;
5177 if (!r
.HasType(ScRangeData::Type::Database
) && !pLocalList
->findByUpperName(itr
->first
))
5178 ppSortArray
[j
++] = &r
;
5180 qsort( static_cast<void*>(ppSortArray
.get()), nValidCount
, sizeof(ScRangeData
*),
5181 &ScRangeData_QsortNameCompare
);
5183 OUStringBuffer aContent
;
5185 SCROW nOutRow
= nStartRow
;
5186 for (j
=0; j
<nValidCount
; j
++)
5188 ScRangeData
* pData
= ppSortArray
[j
];
5189 pData
->GetName(aName
);
5190 // relative Referenzen Excel-konform auf die linke Spalte anpassen:
5191 pData
->UpdateSymbol(aContent
, ScAddress( nStartCol
, nOutRow
, nTab
));
5192 aFormula
= "=" + aContent
.toString();
5193 ScSetStringParam aParam
;
5194 aParam
.setTextInput();
5195 rDoc
.SetString(ScAddress(nStartCol
,nOutRow
,nTab
), aName
, &aParam
);
5196 rDoc
.SetString(ScAddress(nEndCol
,nOutRow
,nTab
), aFormula
, &aParam
);
5200 ppSortArray
.reset();
5204 ScDocument
* pRedoDoc
= new ScDocument( SCDOCMODE_UNDO
);
5205 pRedoDoc
->InitUndo( &rDoc
, nTab
, nTab
);
5206 rDoc
.CopyToDocument( nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
,
5207 InsertDeleteFlags::ALL
, false, pRedoDoc
);
5209 rDocShell
.GetUndoManager()->AddUndoAction(
5210 new ScUndoListNames( &rDocShell
,
5211 ScRange( nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
),
5212 pUndoDoc
, pRedoDoc
) );
5215 if (!AdjustRowHeight(ScRange(0,nStartRow
,nTab
,MAXCOL
,nEndRow
,nTab
)))
5216 rDocShell
.PostPaint( nStartCol
,nStartRow
,nTab
, nEndCol
,nEndRow
,nTab
, PAINT_GRID
);
5218 aModificator
.SetDocumentModified();
5222 rDocShell
.ErrorMessage(aTester
.GetMessageId());
5227 void ScDocFunc::ResizeMatrix( const ScRange
& rOldRange
, const ScAddress
& rNewEnd
)
5229 ScDocument
& rDoc
= rDocShell
.GetDocument();
5230 SCCOL nStartCol
= rOldRange
.aStart
.Col();
5231 SCROW nStartRow
= rOldRange
.aStart
.Row();
5232 SCTAB nTab
= rOldRange
.aStart
.Tab();
5235 rDoc
.GetFormula( nStartCol
, nStartRow
, nTab
, aFormula
);
5236 if ( aFormula
.startsWith("{") && aFormula
.endsWith("}") )
5238 OUString aUndo
= ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX
);
5239 bool bUndo(rDoc
.IsUndoEnabled());
5241 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
);
5243 aFormula
= aFormula
.copy(1, aFormula
.getLength()-2);
5246 aMark
.SetMarkArea( rOldRange
);
5247 aMark
.SelectTable( nTab
, true );
5248 ScRange
aNewRange( rOldRange
.aStart
, rNewEnd
);
5250 if ( DeleteContents( aMark
, InsertDeleteFlags::CONTENTS
, true, false/*bApi*/ ) )
5252 // GRAM_PODF_A1 for API compatibility.
5253 if (!EnterMatrix( aNewRange
, &aMark
, nullptr, aFormula
, false/*bApi*/, false, EMPTY_OUSTRING
, formula::FormulaGrammar::GRAM_PODF_A1
))
5255 // versuchen, alten Zustand wiederherzustellen
5256 EnterMatrix( rOldRange
, &aMark
, nullptr, aFormula
, false/*bApi*/, false, EMPTY_OUSTRING
, formula::FormulaGrammar::GRAM_PODF_A1
);
5261 rDocShell
.GetUndoManager()->LeaveListAction();
5265 void ScDocFunc::InsertAreaLink( const OUString
& rFile
, const OUString
& rFilter
,
5266 const OUString
& rOptions
, const OUString
& rSource
,
5267 const ScRange
& rDestRange
, sal_uLong nRefresh
,
5268 bool bFitBlock
, bool bApi
)
5270 ScDocument
& rDoc
= rDocShell
.GetDocument();
5271 bool bUndo (rDoc
.IsUndoEnabled());
5273 sfx2::LinkManager
* pLinkManager
= rDoc
.GetLinkManager();
5275 // #i52120# if other area links exist at the same start position,
5276 // remove them first (file format specifies only one link definition
5279 sal_uInt16 nLinkCount
= pLinkManager
->GetLinks().size();
5280 sal_uInt16 nRemoved
= 0;
5281 sal_uInt16 nLinkPos
= 0;
5282 while (nLinkPos
<nLinkCount
)
5284 ::sfx2::SvBaseLink
* pBase
= pLinkManager
->GetLinks()[nLinkPos
].get();
5285 ScAreaLink
* pLink
= dynamic_cast<ScAreaLink
*>(pBase
);
5286 if (pLink
&& pLink
->GetDestArea().aStart
== rDestRange
.aStart
)
5292 // group all remove and the insert action
5293 OUString aUndo
= ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK
);
5294 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
);
5297 ScAreaLink
* pOldArea
= static_cast<ScAreaLink
*>(pBase
);
5298 rDocShell
.GetUndoManager()->AddUndoAction(
5299 new ScUndoRemoveAreaLink( &rDocShell
,
5300 pOldArea
->GetFile(), pOldArea
->GetFilter(), pOldArea
->GetOptions(),
5301 pOldArea
->GetSource(), pOldArea
->GetDestArea(), pOldArea
->GetRefreshDelay() ) );
5303 pLinkManager
->Remove( pBase
);
5304 nLinkCount
= pLinkManager
->GetLinks().size();
5311 OUString aFilterName
= rFilter
;
5312 OUString aNewOptions
= rOptions
;
5313 if (aFilterName
.isEmpty())
5314 ScDocumentLoader::GetFilterName( rFile
, aFilterName
, aNewOptions
, true, !bApi
);
5316 // remove application prefix from filter name here, so the filter options
5317 // aren't reset when the filter name is changed in ScAreaLink::DataChanged
5318 ScDocumentLoader::RemoveAppPrefix( aFilterName
);
5320 ScAreaLink
* pLink
= new ScAreaLink( &rDocShell
, rFile
, aFilterName
,
5321 aNewOptions
, rSource
, rDestRange
, nRefresh
);
5322 OUString aTmp
= aFilterName
;
5323 pLinkManager
->InsertFileLink( *pLink
, OBJECT_CLIENT_FILE
, rFile
, &aTmp
, &rSource
);
5325 // Undo fuer den leeren Link
5329 rDocShell
.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell
,
5330 rFile
, aFilterName
, aNewOptions
,
5331 rSource
, rDestRange
, nRefresh
) );
5333 rDocShell
.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
5336 // Update hat sein eigenes Undo
5337 if (rDoc
.IsExecuteLinkEnabled())
5339 pLink
->SetDoInsert(bFitBlock
); // beim ersten Update ggf. nichts einfuegen
5340 pLink
->Update(); // kein SetInCreate -> Update ausfuehren
5342 pLink
->SetDoInsert(true); // Default = true
5344 SfxBindings
* pBindings
= rDocShell
.GetViewBindings();
5346 pBindings
->Invalidate( SID_LINKS
);
5348 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED
) ); // Navigator
5351 void ScDocFunc::ReplaceConditionalFormat( sal_uLong nOldFormat
, ScConditionalFormat
* pFormat
, SCTAB nTab
, const ScRangeList
& rRanges
)
5353 ScDocShellModificator
aModificator(rDocShell
);
5354 ScDocument
& rDoc
= rDocShell
.GetDocument();
5355 if(rDoc
.IsTabProtected(nTab
))
5358 bool bUndo
= rDoc
.IsUndoEnabled();
5359 ScDocument
* pUndoDoc
= nullptr;
5360 ScRange aCombinedRange
= rRanges
.Combine();
5361 ScRange aCompleteRange
;
5364 pUndoDoc
= new ScDocument(SCDOCMODE_UNDO
);
5365 pUndoDoc
->InitUndo( &rDoc
, nTab
, nTab
);
5369 aCompleteRange
= aCombinedRange
;
5373 ScConditionalFormat
* pOldFormat
= rDoc
.GetCondFormList(nTab
)->GetFormat(nOldFormat
);
5375 aCompleteRange
.ExtendTo(pOldFormat
->GetRange().Combine());
5378 rDoc
.CopyToDocument( aCompleteRange
.aStart
.Col(),aCompleteRange
.aStart
.Row(),nTab
,
5379 aCompleteRange
.aEnd
.Col(),aCompleteRange
.aEnd
.Row(),nTab
,
5380 InsertDeleteFlags::ALL
, false, pUndoDoc
);
5383 std::unique_ptr
<ScRange
> pRepaintRange
;
5386 ScConditionalFormat
* pOldFormat
= rDoc
.GetCondFormList(nTab
)->GetFormat(nOldFormat
);
5389 pRepaintRange
.reset(new ScRange( pOldFormat
->GetRange().Combine() ));
5390 rDoc
.RemoveCondFormatData(pOldFormat
->GetRange(), nTab
, pOldFormat
->GetKey());
5393 rDoc
.DeleteConditionalFormat(nOldFormat
, nTab
);
5394 rDoc
.SetStreamValid(nTab
, false);
5399 pRepaintRange
->ExtendTo(aCombinedRange
);
5401 pRepaintRange
.reset(new ScRange(aCombinedRange
));
5403 sal_uLong nIndex
= rDoc
.AddCondFormat(pFormat
, nTab
);
5405 rDoc
.AddCondFormatData(rRanges
, nTab
, nIndex
);
5406 rDoc
.SetStreamValid(nTab
, false);
5411 ScDocument
* pRedoDoc
= new ScDocument(SCDOCMODE_UNDO
);
5412 pRedoDoc
->InitUndo( &rDoc
, nTab
, nTab
);
5413 rDoc
.CopyToDocument( aCompleteRange
.aStart
.Col(),aCompleteRange
.aStart
.Row(),nTab
,
5414 aCompleteRange
.aEnd
.Col(),aCompleteRange
.aEnd
.Row(),nTab
,
5415 InsertDeleteFlags::ALL
, false, pRedoDoc
);
5416 rDocShell
.GetUndoManager()->AddUndoAction(
5417 new ScUndoConditionalFormat(&rDocShell
, pUndoDoc
, pRedoDoc
, aCompleteRange
));
5421 rDocShell
.PostPaint(*pRepaintRange
, PAINT_GRID
);
5423 aModificator
.SetDocumentModified();
5424 SfxGetpApp()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED
));
5427 void ScDocFunc::SetConditionalFormatList( ScConditionalFormatList
* pList
, SCTAB nTab
)
5429 ScDocShellModificator
aModificator(rDocShell
);
5430 ScDocument
& rDoc
= rDocShell
.GetDocument();
5431 if(rDoc
.IsTabProtected(nTab
))
5434 // first remove all old entries
5435 ScConditionalFormatList
* pOldList
= rDoc
.GetCondFormList(nTab
);
5436 for(ScConditionalFormatList::const_iterator itr
= pOldList
->begin(), itrEnd
= pOldList
->end(); itr
!= itrEnd
; ++itr
)
5438 rDoc
.RemoveCondFormatData((*itr
)->GetRange(), nTab
, (*itr
)->GetKey());
5441 // then set new entries
5442 for(ScConditionalFormatList::iterator itr
= pList
->begin(); itr
!= pList
->end(); ++itr
)
5444 rDoc
.AddCondFormatData((*itr
)->GetRange(), nTab
, (*itr
)->GetKey());
5447 rDoc
.SetCondFormList(pList
, nTab
);
5448 rDocShell
.PostPaintGridAll();
5450 rDoc
.SetStreamValid(nTab
, false);
5451 aModificator
.SetDocumentModified();
5452 SfxGetpApp()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED
));
5455 void ScDocFunc::ConvertFormulaToValue( const ScRange
& rRange
, bool bInteraction
)
5457 ScDocShellModificator
aModificator(rDocShell
);
5458 ScDocument
& rDoc
= rDocShell
.GetDocument();
5459 bool bRecord
= true;
5460 if (!rDoc
.IsUndoEnabled())
5463 ScEditableTester
aTester(&rDoc
, rRange
);
5464 if (!aTester
.IsEditable())
5467 rDocShell
.ErrorMessage(aTester
.GetMessageId());
5471 sc::TableValues
aUndoVals(rRange
);
5472 sc::TableValues
* pUndoVals
= bRecord
? &aUndoVals
: nullptr;
5474 rDoc
.ConvertFormulaToValue(rRange
, pUndoVals
);
5476 if (bRecord
&& pUndoVals
)
5478 rDocShell
.GetUndoManager()->AddUndoAction(
5479 new sc::UndoFormulaToValue(&rDocShell
, *pUndoVals
));
5482 rDocShell
.PostPaint(rRange
, PAINT_GRID
);
5483 rDocShell
.PostDataChanged();
5484 rDoc
.BroadcastCells(rRange
, SC_HINT_DATACHANGED
);
5485 aModificator
.SetDocumentModified();
5488 void ScDocFunc::EnterListAction( sal_uInt16 nNameResId
)
5490 OUString
aUndo( ScGlobal::GetRscString( nNameResId
) );
5491 rDocShell
.GetUndoManager()->EnterListAction( aUndo
, aUndo
);
5494 void ScDocFunc::EndListAction()
5496 rDocShell
.GetUndoManager()->LeaveListAction();
5499 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */