Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / docshell / docfunc.cxx
blob72e7e469db6279a261889d274a462f08508e397e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
38 #include "sc.hrc"
40 #include "arealink.hxx"
41 #include "attrib.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"
49 #include "docsh.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"
71 #include "scmod.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"
87 #include <memory>
88 #include <basic/basmgr.hxx>
89 #include <boost/scoped_ptr.hpp>
90 #include <set>
91 #include <vector>
93 using namespace com::sun::star;
94 using ::com::sun::star::uno::Sequence;
95 using ::std::vector;
98 // STATIC DATA -----------------------------------------------------------
100 //========================================================================
102 IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction )
104 // #i101118# if drawing layer collects the undo actions, add it there
105 ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer();
106 if( pDrawLayer && pDrawLayer->IsRecording() )
107 pDrawLayer->AddCalcUndo( pUndoAction );
108 else
109 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) );
110 rDocShell.SetDrawModified();
112 // the affected sheet isn't known, so all stream positions are invalidated
113 ScDocument* pDoc = rDocShell.GetDocument();
114 SCTAB nTabCount = pDoc->GetTableCount();
115 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
116 if (pDoc->IsStreamValid(nTab))
117 pDoc->SetStreamValid(nTab, false);
119 return 0;
122 //------------------------------------------------------------------------
124 // Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
126 static void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
128 SCROW nRow = rRange.aStart.Row();
129 if ( nRow > 0 )
131 SCTAB nTab = rRange.aStart.Tab(); //! alle?
132 --nRow;
133 rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
137 //------------------------------------------------------------------------
139 sal_Bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, sal_Bool bPaint )
141 ScDocument* pDoc = rDocShell.GetDocument();
142 if ( pDoc->IsImportingXML() )
144 // for XML import, all row heights are updated together after importing
145 return false;
147 if ( !pDoc->IsAdjustHeightEnabled() )
149 return false;
152 SCTAB nTab = rRange.aStart.Tab();
153 SCROW nStartRow = rRange.aStart.Row();
154 SCROW nEndRow = rRange.aEnd.Row();
156 ScSizeDeviceProvider aProv( &rDocShell );
157 Fraction aOne(1,1);
159 sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
160 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, false );
162 if ( bPaint && bChanged )
163 rDocShell.PostPaint(ScRange(0, nStartRow, nTab, MAXCOL, MAXROW, nTab),
164 PAINT_GRID | PAINT_LEFT);
166 return bChanged;
170 //------------------------------------------------------------------------
172 sal_Bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
174 ScDocShellModificator aModificator( rDocShell );
176 rDocShell.MakeDrawLayer();
177 ScDocument* pDoc = rDocShell.GetDocument();
178 bool bUndo (pDoc->IsUndoEnabled());
179 ScDrawLayer* pModel = pDoc->GetDrawLayer();
180 SCCOL nCol = rPos.Col();
181 SCROW nRow = rPos.Row();
182 SCTAB nTab = rPos.Tab();
184 if (bUndo)
185 pModel->BeginCalcUndo(false);
186 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
187 SdrUndoGroup* pUndo = NULL;
188 if (bUndo)
189 pUndo = pModel->GetCalcUndo();
190 if (bDone)
192 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
193 pDoc->AddDetectiveOperation( aOperation );
194 if (bUndo)
196 rDocShell.GetUndoManager()->AddUndoAction(
197 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
199 aModificator.SetDocumentModified();
200 SfxBindings* pBindings = rDocShell.GetViewBindings();
201 if (pBindings)
202 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
204 else
205 delete pUndo;
207 return bDone;
210 sal_Bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
212 ScDocument* pDoc = rDocShell.GetDocument();
214 bool bUndo(pDoc->IsUndoEnabled());
215 ScDrawLayer* pModel = pDoc->GetDrawLayer();
216 if (!pModel)
217 return false;
219 ScDocShellModificator aModificator( rDocShell );
221 SCCOL nCol = rPos.Col();
222 SCROW nRow = rPos.Row();
223 SCTAB nTab = rPos.Tab();
225 if (bUndo)
226 pModel->BeginCalcUndo(false);
227 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
228 SdrUndoGroup* pUndo = NULL;
229 if (bUndo)
230 pUndo = pModel->GetCalcUndo();
231 if (bDone)
233 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
234 pDoc->AddDetectiveOperation( aOperation );
235 if (bUndo)
237 rDocShell.GetUndoManager()->AddUndoAction(
238 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
240 aModificator.SetDocumentModified();
241 SfxBindings* pBindings = rDocShell.GetViewBindings();
242 if (pBindings)
243 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
245 else
246 delete pUndo;
248 return bDone;
251 sal_Bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
253 ScDocShellModificator aModificator( rDocShell );
255 rDocShell.MakeDrawLayer();
256 ScDocument* pDoc = rDocShell.GetDocument();
258 bool bUndo(pDoc->IsUndoEnabled());
259 ScDrawLayer* pModel = pDoc->GetDrawLayer();
260 SCCOL nCol = rPos.Col();
261 SCROW nRow = rPos.Row();
262 SCTAB nTab = rPos.Tab();
264 if (bUndo)
265 pModel->BeginCalcUndo(false);
266 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow );
267 SdrUndoGroup* pUndo = NULL;
268 if (bUndo)
269 pUndo = pModel->GetCalcUndo();
270 if (bDone)
272 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
273 pDoc->AddDetectiveOperation( aOperation );
274 if (bUndo)
276 rDocShell.GetUndoManager()->AddUndoAction(
277 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
279 aModificator.SetDocumentModified();
280 SfxBindings* pBindings = rDocShell.GetViewBindings();
281 if (pBindings)
282 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
284 else
285 delete pUndo;
287 return bDone;
290 sal_Bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
292 ScDocument* pDoc = rDocShell.GetDocument();
294 bool bUndo (pDoc->IsUndoEnabled());
295 ScDrawLayer* pModel = pDoc->GetDrawLayer();
296 if (!pModel)
297 return false;
299 ScDocShellModificator aModificator( rDocShell );
301 SCCOL nCol = rPos.Col();
302 SCROW nRow = rPos.Row();
303 SCTAB nTab = rPos.Tab();
305 if (bUndo)
306 pModel->BeginCalcUndo(false);
307 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
308 SdrUndoGroup* pUndo = NULL;
309 if (bUndo)
310 pUndo = pModel->GetCalcUndo();
311 if (bDone)
313 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
314 pDoc->AddDetectiveOperation( aOperation );
315 if (bUndo)
317 rDocShell.GetUndoManager()->AddUndoAction(
318 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
320 aModificator.SetDocumentModified();
321 SfxBindings* pBindings = rDocShell.GetViewBindings();
322 if (pBindings)
323 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
325 else
326 delete pUndo;
328 return bDone;
331 sal_Bool ScDocFunc::DetectiveAddError(const ScAddress& rPos)
333 ScDocShellModificator aModificator( rDocShell );
335 rDocShell.MakeDrawLayer();
336 ScDocument* pDoc = rDocShell.GetDocument();
338 bool bUndo (pDoc->IsUndoEnabled());
339 ScDrawLayer* pModel = pDoc->GetDrawLayer();
340 SCCOL nCol = rPos.Col();
341 SCROW nRow = rPos.Row();
342 SCTAB nTab = rPos.Tab();
344 if (bUndo)
345 pModel->BeginCalcUndo(false);
346 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
347 SdrUndoGroup* pUndo = NULL;
348 if (bUndo)
349 pUndo = pModel->GetCalcUndo();
350 if (bDone)
352 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
353 pDoc->AddDetectiveOperation( aOperation );
354 if (bUndo)
356 rDocShell.GetUndoManager()->AddUndoAction(
357 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
359 aModificator.SetDocumentModified();
360 SfxBindings* pBindings = rDocShell.GetViewBindings();
361 if (pBindings)
362 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
364 else
365 delete pUndo;
367 return bDone;
370 sal_Bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
372 ScDocShellModificator aModificator( rDocShell );
374 rDocShell.MakeDrawLayer();
375 ScDocument* pDoc = rDocShell.GetDocument();
377 bool bUndo (pDoc->IsUndoEnabled());
378 ScDrawLayer* pModel = pDoc->GetDrawLayer();
380 Window* pWaitWin = rDocShell.GetActiveDialogParent();
381 if (pWaitWin)
382 pWaitWin->EnterWait();
383 if (bUndo)
384 pModel->BeginCalcUndo(false);
385 sal_Bool bOverflow;
386 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
387 SdrUndoGroup* pUndo = NULL;
388 if (bUndo)
389 pUndo = pModel->GetCalcUndo();
390 if (pWaitWin)
391 pWaitWin->LeaveWait();
392 if (bDone)
394 if (pUndo && bUndo)
396 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) );
397 rDocShell.GetUndoManager()->AddUndoAction( pUndo );
399 aModificator.SetDocumentModified();
400 if ( bOverflow )
402 InfoBox( NULL,
403 ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
406 else
407 delete pUndo;
409 return bDone;
412 sal_Bool ScDocFunc::DetectiveDelAll(SCTAB nTab)
414 ScDocument* pDoc = rDocShell.GetDocument();
416 bool bUndo (pDoc->IsUndoEnabled());
417 ScDrawLayer* pModel = pDoc->GetDrawLayer();
418 if (!pModel)
419 return false;
421 ScDocShellModificator aModificator( rDocShell );
423 if (bUndo)
424 pModel->BeginCalcUndo(false);
425 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
426 SdrUndoGroup* pUndo = NULL;
427 if (bUndo)
428 pUndo = pModel->GetCalcUndo();
429 if (bDone)
431 ScDetOpList* pOldList = pDoc->GetDetOpList();
432 ScDetOpList* pUndoList = NULL;
433 if (bUndo)
434 pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL;
436 pDoc->ClearDetectiveOperations();
438 if (bUndo)
440 rDocShell.GetUndoManager()->AddUndoAction(
441 new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) );
443 aModificator.SetDocumentModified();
444 SfxBindings* pBindings = rDocShell.GetViewBindings();
445 if (pBindings)
446 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
448 else
449 delete pUndo;
451 return bDone;
454 sal_Bool ScDocFunc::DetectiveRefresh( sal_Bool bAutomatic )
456 sal_Bool bDone = false;
457 ScDocument* pDoc = rDocShell.GetDocument();
459 bool bUndo (pDoc->IsUndoEnabled());
460 ScDetOpList* pList = pDoc->GetDetOpList();
461 if ( pList && pList->Count() )
463 rDocShell.MakeDrawLayer();
464 ScDrawLayer* pModel = pDoc->GetDrawLayer();
465 if (bUndo)
466 pModel->BeginCalcUndo(false);
468 // Loeschen auf allen Tabellen
470 SCTAB nTabCount = pDoc->GetTableCount();
471 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
472 ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles
474 // Wiederholen
476 size_t nCount = pList->Count();
477 for (size_t i=0; i < nCount; ++i)
479 const ScDetOpData* pData = pList->GetObject(i);
480 if (pData)
482 ScAddress aPos = pData->GetPos();
483 ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
484 SCCOL nCol = aPos.Col();
485 SCROW nRow = aPos.Row();
486 switch (pData->GetOperation())
488 case SCDETOP_ADDSUCC:
489 aFunc.ShowSucc( nCol, nRow );
490 break;
491 case SCDETOP_DELSUCC:
492 aFunc.DeleteSucc( nCol, nRow );
493 break;
494 case SCDETOP_ADDPRED:
495 aFunc.ShowPred( nCol, nRow );
496 break;
497 case SCDETOP_DELPRED:
498 aFunc.DeletePred( nCol, nRow );
499 break;
500 case SCDETOP_ADDERROR:
501 aFunc.ShowError( nCol, nRow );
502 break;
503 default:
504 OSL_FAIL("falsche Op bei DetectiveRefresh");
509 if (bUndo)
511 SdrUndoGroup* pUndo = pModel->GetCalcUndo();
512 if (pUndo)
514 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) );
515 // wenn automatisch, an letzte Aktion anhaengen
516 rDocShell.GetUndoManager()->AddUndoAction(
517 new ScUndoDraw( pUndo, &rDocShell ),
518 bAutomatic );
521 rDocShell.SetDrawModified();
522 bDone = sal_True;
524 return bDone;
527 static void lcl_collectAllPredOrSuccRanges(
528 const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens, ScDocShell& rDocShell,
529 bool bPred)
531 ScDocument* pDoc = rDocShell.GetDocument();
532 vector<ScTokenRef> aRefTokens;
533 ScRangeList aSrcRanges(rSrcRanges);
534 if (aSrcRanges.empty())
535 return;
536 ScRange* p = aSrcRanges.front();
537 ScDetectiveFunc aDetFunc(pDoc, p->aStart.Tab());
538 ScRangeList aDestRanges;
539 for (size_t i = 0, n = aSrcRanges.size(); i < n; ++i)
541 p = aSrcRanges[i];
542 if (bPred)
544 aDetFunc.GetAllPreds(
545 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
547 else
549 aDetFunc.GetAllSuccs(
550 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
553 rRefTokens.swap(aRefTokens);
556 void ScDocFunc::DetectiveCollectAllPreds(const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens)
558 lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, true);
561 void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens)
563 lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, false);
566 //------------------------------------------------------------------------
568 sal_Bool ScDocFunc::DeleteContents( const ScMarkData& rMark, sal_uInt16 nFlags,
569 sal_Bool bRecord, sal_Bool bApi )
571 ScDocShellModificator aModificator( rDocShell );
573 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
575 OSL_FAIL("ScDocFunc::DeleteContents ohne Markierung");
576 return false;
579 ScDocument* pDoc = rDocShell.GetDocument();
581 if (bRecord && !pDoc->IsUndoEnabled())
582 bRecord = false;
584 ScEditableTester aTester( pDoc, rMark );
585 if (!aTester.IsEditable())
587 if (!bApi)
588 rDocShell.ErrorMessage(aTester.GetMessageId());
589 return false;
592 ScRange aMarkRange;
593 sal_Bool bSimple = false;
595 ScMarkData aMultiMark = rMark;
596 aMultiMark.SetMarking(false); // fuer MarkToMulti
598 ScDocument* pUndoDoc = NULL;
599 sal_Bool bMulti = !bSimple && aMultiMark.IsMultiMarked();
600 if (!bSimple)
602 aMultiMark.MarkToMulti();
603 aMultiMark.GetMultiMarkArea( aMarkRange );
605 ScRange aExtendedRange(aMarkRange);
606 if (!bSimple)
608 if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) )
609 bMulti = false;
612 // keine Objekte auf geschuetzten Tabellen
613 sal_Bool bObjects = false;
614 if ( nFlags & IDF_OBJECTS )
616 bObjects = sal_True;
617 SCTAB nTabCount = pDoc->GetTableCount();
618 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
619 for (; itr != itrEnd && *itr < nTabCount; ++itr)
620 if (pDoc->IsTabProtected(*itr))
621 bObjects = false;
624 sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted
625 if ( nFlags & IDF_ATTRIB )
626 rDocShell.UpdatePaintExt( nExtFlags, aMarkRange );
628 // Reihenfolge:
629 // 1) BeginDrawUndo
630 // 2) Objekte loeschen (DrawUndo wird gefuellt)
631 // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
632 // 4) Inhalte loeschen
634 bool bDrawUndo = bObjects || (nFlags & IDF_NOTE);
635 if (bRecord && bDrawUndo)
636 pDoc->BeginDrawUndo();
638 if (bObjects)
640 if (bMulti)
641 pDoc->DeleteObjectsInSelection( aMultiMark );
642 else
643 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
644 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
645 aMultiMark );
648 if ( bRecord )
650 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
651 pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() );
653 // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
654 // nur mit IDF_HARDATTR zu langsam ist:
655 sal_uInt16 nUndoDocFlags = nFlags;
656 if (nFlags & IDF_ATTRIB)
657 nUndoDocFlags |= IDF_ATTRIB;
658 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
659 nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
660 if (nFlags & IDF_NOTE)
661 nUndoDocFlags |= IDF_CONTENTS; // copy all cells with their notes
662 // note captions are handled in drawing undo
663 nUndoDocFlags |= IDF_NOCAPTIONS;
664 pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark );
667 //! HideAllCursors(); // falls Zusammenfassung aufgehoben wird
668 if (bSimple)
669 pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
670 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
671 aMultiMark, nFlags );
672 else
674 pDoc->DeleteSelection( nFlags, aMultiMark );
677 // add undo action after drawing undo is complete (objects and note captions)
678 if( bRecord )
679 rDocShell.GetUndoManager()->AddUndoAction(
680 new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange,
681 pUndoDoc, bMulti, nFlags, bDrawUndo ) );
683 if (!AdjustRowHeight( aExtendedRange ))
684 rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
685 else if (nExtFlags & SC_PF_LINES)
686 lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich
688 aModificator.SetDocumentModified();
690 return sal_True;
693 //------------------------------------------------------------------------
695 sal_Bool ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
696 sal_Bool bRecord, sal_Bool bApi )
698 ScDocShellModificator aModificator( rDocShell );
700 ScDocument* pDoc = rDocShell.GetDocument();
701 if (bRecord && !pDoc->IsUndoEnabled())
702 bRecord = false;
704 ScEditableTester aTester( pDoc, rMark );
705 if (!aTester.IsEditable())
707 if (!bApi)
708 rDocShell.ErrorMessage(aTester.GetMessageId());
709 return false;
712 ScRange aMarkRange;
713 ScMarkData aMultiMark = rMark;
714 aMultiMark.SetMarking(false); // for MarkToMulti
715 aMultiMark.MarkToMulti();
716 aMultiMark.GetMultiMarkArea( aMarkRange );
718 if (bRecord)
720 SCTAB nStartTab = aMarkRange.aStart.Tab();
721 SCTAB nTabCount = pDoc->GetTableCount();
723 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
724 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
725 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
726 for (; itr != itrEnd && *itr < nTabCount; ++itr)
727 if (*itr != nStartTab)
728 pUndoDoc->AddUndoTab( *itr, *itr );
730 ScRange aCopyRange = aMarkRange;
731 aCopyRange.aStart.SetTab(0);
732 aCopyRange.aEnd.SetTab(nTabCount-1);
733 pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pUndoDoc, &aMultiMark );
735 rDocShell.GetUndoManager()->AddUndoAction(
736 new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) );
739 pDoc->TransliterateText( aMultiMark, nType );
741 if (!AdjustRowHeight( aMarkRange ))
742 rDocShell.PostPaint( aMarkRange, PAINT_GRID );
744 aModificator.SetDocumentModified();
746 return sal_True;
749 //------------------------------------------------------------------------
751 sal_Bool ScDocFunc::SetNormalString( bool& o_rbNumFmtSet, const ScAddress& rPos, const OUString& rText, sal_Bool bApi )
753 ScDocShellModificator aModificator( rDocShell );
754 ScDocument* pDoc = rDocShell.GetDocument();
756 bool bUndo(pDoc->IsUndoEnabled());
757 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
758 if (!aTester.IsEditable())
760 if (!bApi)
761 rDocShell.ErrorMessage(aTester.GetMessageId());
762 return false;
765 bool bEditDeleted = (pDoc->GetCellType(rPos) == CELLTYPE_EDIT);
766 ScUndoEnterData::ValuesType aOldValues;
768 if (bUndo)
770 ScUndoEnterData::Value aOldValue;
772 aOldValue.mnTab = rPos.Tab();
773 aOldValue.maCell.assign(*pDoc, rPos);
775 const SfxPoolItem* pItem;
776 const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() );
777 if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
778 ATTR_VALUE_FORMAT,false,&pItem) )
780 aOldValue.mbHasFormat = true;
781 aOldValue.mnFormat = ((const SfxUInt32Item*)pItem)->GetValue();
783 else
784 aOldValue.mbHasFormat = false;
786 aOldValues.push_back(aOldValue);
789 o_rbNumFmtSet = pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
791 if (bUndo)
793 // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
794 rDocShell.GetUndoManager()->AddUndoAction(
795 new ScUndoEnterData(&rDocShell, rPos, aOldValues, rText, NULL));
798 if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
799 AdjustRowHeight( ScRange(rPos) );
801 rDocShell.PostPaintCell( rPos );
802 aModificator.SetDocumentModified();
804 // notify input handler here the same way as in PutCell
805 if (bApi)
806 NotifyInputHandler( rPos );
808 return sal_True;
811 bool ScDocFunc::SetValueCell( const ScAddress& rPos, double fVal, bool bInteraction )
813 ScDocShellModificator aModificator( rDocShell );
814 ScDocument* pDoc = rDocShell.GetDocument();
815 bool bUndo = pDoc->IsUndoEnabled();
817 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
819 ScCellValue aOldVal;
820 if (bUndo)
821 aOldVal.assign(*pDoc, rPos);
823 pDoc->SetValue(rPos, fVal);
825 if (bUndo)
827 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
828 ScCellValue aNewVal;
829 aNewVal.assign(*pDoc, rPos);
830 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
833 if (bHeight)
834 AdjustRowHeight(rPos);
836 rDocShell.PostPaintCell( rPos );
837 aModificator.SetDocumentModified();
839 // #103934#; notify editline and cell in edit mode
840 if (!bInteraction)
841 NotifyInputHandler( rPos );
843 return true;
846 bool ScDocFunc::SetStringCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction )
848 ScDocShellModificator aModificator( rDocShell );
849 ScDocument* pDoc = rDocShell.GetDocument();
850 bool bUndo = pDoc->IsUndoEnabled();
852 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
854 ScCellValue aOldVal;
855 if (bUndo)
856 aOldVal.assign(*pDoc, rPos);
858 ScSetStringParam aParam;
859 aParam.setTextInput();
860 pDoc->SetString(rPos, rStr, &aParam);
862 if (bUndo)
864 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
865 ScCellValue aNewVal;
866 aNewVal.assign(*pDoc, rPos);
867 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
870 if (bHeight)
871 AdjustRowHeight(rPos);
873 rDocShell.PostPaintCell( rPos );
874 aModificator.SetDocumentModified();
876 // #103934#; notify editline and cell in edit mode
877 if (!bInteraction)
878 NotifyInputHandler( rPos );
880 return true;
883 bool ScDocFunc::SetEditCell( const ScAddress& rPos, const EditTextObject& rStr, bool bInteraction )
885 ScDocShellModificator aModificator( rDocShell );
886 ScDocument* pDoc = rDocShell.GetDocument();
887 bool bUndo = pDoc->IsUndoEnabled();
889 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
891 ScCellValue aOldVal;
892 if (bUndo)
893 aOldVal.assign(*pDoc, rPos);
895 pDoc->SetEditText(rPos, rStr.Clone());
897 if (bUndo)
899 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
900 ScCellValue aNewVal;
901 aNewVal.assign(*pDoc, rPos);
902 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
905 if (bHeight)
906 AdjustRowHeight(rPos);
908 rDocShell.PostPaintCell( rPos );
909 aModificator.SetDocumentModified();
911 // #103934#; notify editline and cell in edit mode
912 if (!bInteraction)
913 NotifyInputHandler( rPos );
915 return true;
918 bool ScDocFunc::SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction )
920 ScDocument* pDoc = rDocShell.GetDocument();
922 if (ScStringUtil::isMultiline(rStr))
924 ScFieldEditEngine& rEngine = pDoc->GetEditEngine();
925 rEngine.SetText(rStr);
926 boost::scoped_ptr<EditTextObject> pEditText(rEngine.CreateTextObject());
927 return SetEditCell(rPos, *pEditText, bInteraction);
929 else
930 return SetStringCell(rPos, rStr, bInteraction);
933 bool ScDocFunc::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction )
935 SAL_WNODEPRECATED_DECLARATIONS_PUSH
936 std::auto_ptr<ScFormulaCell> xCell(pCell);
937 SAL_WNODEPRECATED_DECLARATIONS_POP
939 ScDocShellModificator aModificator( rDocShell );
940 ScDocument* pDoc = rDocShell.GetDocument();
941 bool bUndo = pDoc->IsUndoEnabled();
943 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
945 ScCellValue aOldVal;
946 if (bUndo)
947 aOldVal.assign(*pDoc, rPos);
949 pCell = pDoc->SetFormulaCell(rPos, xCell.release());
951 // For performance reasons API calls may disable calculation while
952 // operating and recalculate once when done. If through user interaction
953 // and AutoCalc is disabled, calculate the formula (without its
954 // dependencies) once so the result matches the current document's content.
955 if (bInteraction && !pDoc->GetAutoCalc() && pCell)
957 // calculate just the cell once and set Dirty again
958 pCell->Interpret();
959 pCell->SetDirtyVar();
960 pDoc->PutInFormulaTree( pCell);
963 if (bUndo)
965 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
966 ScCellValue aNewVal;
967 aNewVal.assign(*pDoc, rPos);
968 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
971 if (bHeight)
972 AdjustRowHeight(rPos);
974 rDocShell.PostPaintCell( rPos );
975 aModificator.SetDocumentModified();
977 // #103934#; notify editline and cell in edit mode
978 if (!bInteraction)
979 NotifyInputHandler( rPos );
981 return true;
984 void ScDocFunc::NotifyInputHandler( const ScAddress& rPos )
986 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
987 if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell )
989 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
990 if ( pInputHdl && pInputHdl->GetCursorPos() == rPos )
992 sal_Bool bIsEditMode(pInputHdl->IsEditMode());
994 // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
995 // (the cell shows the same like the InputWindow)
996 if (bIsEditMode)
997 pInputHdl->SetModified();
998 pViewSh->UpdateInputHandler(false, !bIsEditMode);
1003 struct ScMyRememberItem
1005 sal_Int32 nIndex;
1006 SfxItemSet aItemSet;
1008 ScMyRememberItem(const SfxItemSet& rItemSet, sal_Int32 nTempIndex) :
1009 nIndex(nTempIndex), aItemSet(rItemSet) {}
1012 typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;
1014 bool ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, bool bApi )
1016 // PutData ruft PutCell oder SetNormalString
1018 sal_Bool bRet = false;
1019 ScDocument* pDoc = rDocShell.GetDocument();
1020 ScEditAttrTester aTester( &rEngine );
1021 sal_Bool bEditCell = aTester.NeedsObject();
1022 if ( bEditCell )
1024 // #i61702# With bLoseContent set, the content of rEngine isn't restored
1025 // (used in loading XML, where after the removeActionLock call the API obejct's
1026 // EditEngine isn't accessed again.
1027 sal_Bool bLoseContent = pDoc->IsImportingXML();
1029 sal_Bool bUpdateMode(rEngine.GetUpdateMode());
1030 if (bUpdateMode)
1031 rEngine.SetUpdateMode(false);
1033 ScMyRememberItemList aRememberItems;
1034 ScMyRememberItem* pRememberItem = NULL;
1036 // All paragraph attributes must be removed before calling CreateTextObject,
1037 // not only alignment, so the object doesn't contain the cell attributes as
1038 // paragraph attributes. Before remove the attributes store they in a list to
1039 // set they back to the EditEngine.
1040 sal_Int32 nCount = rEngine.GetParagraphCount();
1041 for (sal_Int32 i=0; i<nCount; i++)
1043 const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
1044 if ( rOld.Count() )
1046 if ( !bLoseContent )
1048 pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
1049 aRememberItems.push_back(pRememberItem);
1051 rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
1055 // A copy of pNewData will be stored in the cell.
1056 boost::scoped_ptr<EditTextObject> pNewData(rEngine.CreateTextObject());
1057 bRet = SetEditCell(rPos, *pNewData, !bApi);
1059 // Set the paragraph attributes back to the EditEngine.
1060 if (!aRememberItems.empty())
1062 ScMyRememberItemList::iterator aItr = aRememberItems.begin();
1063 while (aItr != aRememberItems.end())
1065 pRememberItem = *aItr;
1066 rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet);
1067 delete pRememberItem;
1068 aItr = aRememberItems.erase(aItr);
1072 // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
1073 if ( bUpdateMode && !bLoseContent )
1074 rEngine.SetUpdateMode(sal_True);
1076 else
1078 OUString aText = rEngine.GetText();
1079 if (aText.isEmpty())
1081 bool bNumFmtSet = false;
1082 bRet = SetNormalString( bNumFmtSet, rPos, aText, bApi );
1084 else
1085 bRet = SetStringCell(rPos, aText, !bApi);
1088 if ( bRet && aTester.NeedsCellAttr() )
1090 const SfxItemSet& rEditAttr = aTester.GetAttribs();
1091 ScPatternAttr aPattern( pDoc->GetPool() );
1092 aPattern.GetFromEditItemSet( &rEditAttr );
1093 aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
1094 aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object
1095 if ( aPattern.GetItemSet().Count() > 0 )
1097 ScMarkData aMark;
1098 aMark.SelectTable( rPos.Tab(), sal_True );
1099 aMark.SetMarkArea( ScRange( rPos ) );
1100 ApplyAttributes( aMark, aPattern, sal_True, bApi );
1104 return bRet;
1108 static ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const OUString& rText, const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
1110 ScTokenArray* pCode = new ScTokenArray;
1111 pCode->AddStringXML( rText );
1112 if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (!rFormulaNmsp.isEmpty()) )
1113 pCode->AddStringXML( rFormulaNmsp );
1114 return pCode;
1117 bool ScDocFunc::SetCellText(
1118 const ScAddress& rPos, const OUString& rText, bool bInterpret, bool bEnglish, bool bApi,
1119 const formula::FormulaGrammar::Grammar eGrammar )
1121 bool bSet = false;
1122 if ( bInterpret )
1124 if ( bEnglish )
1126 ScDocument* pDoc = rDocShell.GetDocument();
1128 ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
1129 if (bApi)
1130 pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
1132 ScInputStringType aRes =
1133 ScStringUtil::parseInputString(*pDoc->GetFormatTable(), rText, LANGUAGE_ENGLISH_US);
1135 switch (aRes.meType)
1137 case ScInputStringType::Formula:
1138 bSet = SetFormulaCell(rPos, new ScFormulaCell(pDoc, rPos, aRes.maText, eGrammar), !bApi);
1139 break;
1140 case ScInputStringType::Number:
1141 bSet = SetValueCell(rPos, aRes.mfValue, !bApi);
1142 break;
1143 case ScInputStringType::Text:
1144 bSet = SetStringOrEditCell(rPos, aRes.maText, !bApi);
1145 break;
1146 default:
1150 // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
1152 else if (!rText.isEmpty())
1154 bSet = SetStringOrEditCell(rPos, rText, !bApi);
1157 if (!bSet)
1159 bool bNumFmtSet = false;
1160 bSet = SetNormalString( bNumFmtSet, rPos, rText, bApi );
1162 return bSet;
1165 //------------------------------------------------------------------------
1167 bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
1169 ScDocument& rDoc = *rDocShell.GetDocument();
1170 ScPostIt* pNote = rDoc.GetNote( rPos );
1171 if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false;
1173 // move the caption to internal or hidden layer and create undo action
1174 pNote->ShowCaption( rPos, bShow );
1175 if( rDoc.IsUndoEnabled() )
1176 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) );
1178 if (rDoc.IsStreamValid(rPos.Tab()))
1179 rDoc.SetStreamValid(rPos.Tab(), false);
1181 rDocShell.SetDocumentModified();
1183 return true;
1186 //------------------------------------------------------------------------
1188 bool ScDocFunc::SetNoteText( const ScAddress& rPos, const OUString& rText, sal_Bool bApi )
1190 ScDocShellModificator aModificator( rDocShell );
1192 ScDocument* pDoc = rDocShell.GetDocument();
1193 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1194 if (!aTester.IsEditable())
1196 if (!bApi)
1197 rDocShell.ErrorMessage(aTester.GetMessageId());
1198 return false;
1201 OUString aNewText = convertLineEnd(rText, GetSystemLineEnd()); //! ist das noetig ???
1203 if( ScPostIt* pNote = (!aNewText.isEmpty()) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote(rPos) )
1204 pNote->SetText( rPos, aNewText );
1206 //! Undo !!!
1208 if (pDoc->IsStreamValid(rPos.Tab()))
1209 pDoc->SetStreamValid(rPos.Tab(), false);
1211 rDocShell.PostPaintCell( rPos );
1212 aModificator.SetDocumentModified();
1214 return true;
1217 //------------------------------------------------------------------------
1219 bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate, sal_Bool bApi )
1221 bool bDone = false;
1223 ScDocShellModificator aModificator( rDocShell );
1224 ScDocument& rDoc = *rDocShell.GetDocument();
1225 ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1226 if (aTester.IsEditable())
1228 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1229 ::svl::IUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0;
1231 ScNoteData aOldData;
1232 ScPostIt* pOldNote = rDoc.ReleaseNote( rPos );
1233 if( pOldNote )
1235 // ensure existing caption object before draw undo tracking starts
1236 pOldNote->GetOrCreateCaption( rPos );
1237 // rescue note data for undo
1238 aOldData = pOldNote->GetNoteData();
1241 // collect drawing undo actions for deleting/inserting caption obejcts
1242 if( pUndoMgr )
1243 pDrawLayer->BeginCalcUndo(false);
1245 // delete the note (creates drawing undo action for the caption object)
1246 delete pOldNote;
1248 // create new note (creates drawing undo action for the new caption object)
1249 ScNoteData aNewData;
1250 if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) )
1252 if( pAuthor ) pNewNote->SetAuthor( *pAuthor );
1253 if( pDate ) pNewNote->SetDate( *pDate );
1254 // rescue note data for undo
1255 aNewData = pNewNote->GetNoteData();
1258 // create the undo action
1259 if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) )
1260 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
1262 // repaint cell (to make note marker visible)
1263 rDocShell.PostPaintCell( rPos );
1265 if (rDoc.IsStreamValid(rPos.Tab()))
1266 rDoc.SetStreamValid(rPos.Tab(), false);
1268 aModificator.SetDocumentModified();
1269 bDone = true;
1271 else if (!bApi)
1273 rDocShell.ErrorMessage(aTester.GetMessageId());
1276 return bDone;
1279 //------------------------------------------------------------------------
1281 sal_Bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
1282 sal_Bool bRecord, sal_Bool bApi )
1284 ScDocument* pDoc = rDocShell.GetDocument();
1285 if ( bRecord && !pDoc->IsUndoEnabled() )
1286 bRecord = false;
1288 bool bImportingXML = pDoc->IsImportingXML();
1289 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1290 // #i62483# When loading XML, the check can be skipped altogether.
1291 bool bOnlyNotBecauseOfMatrix;
1292 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1293 && !bOnlyNotBecauseOfMatrix )
1295 if (!bApi)
1296 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1297 return false;
1300 ScDocShellModificator aModificator( rDocShell );
1302 //! Umrandung
1304 ScRange aMultiRange;
1305 sal_Bool bMulti = rMark.IsMultiMarked();
1306 if ( bMulti )
1307 rMark.GetMultiMarkArea( aMultiRange );
1308 else
1309 rMark.GetMarkArea( aMultiRange );
1311 if ( bRecord )
1313 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1314 pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() );
1315 pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1317 rDocShell.GetUndoManager()->AddUndoAction(
1318 new ScUndoSelectionAttr(
1319 &rDocShell, rMark,
1320 aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(),
1321 aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(),
1322 pUndoDoc, bMulti, &rPattern ) );
1325 // While loading XML it is not necessary to ask HasAttrib. It needs too much time.
1326 sal_uInt16 nExtFlags = 0;
1327 if ( !bImportingXML )
1328 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change
1329 pDoc->ApplySelectionPattern( rPattern, rMark );
1330 if ( !bImportingXML )
1331 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change
1333 if (!AdjustRowHeight( aMultiRange ))
1334 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1335 else if (nExtFlags & SC_PF_LINES)
1336 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
1338 aModificator.SetDocumentModified();
1340 return sal_True;
1344 sal_Bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const OUString& rStyleName,
1345 sal_Bool bRecord, sal_Bool bApi )
1347 ScDocument* pDoc = rDocShell.GetDocument();
1348 if ( bRecord && !pDoc->IsUndoEnabled() )
1349 bRecord = false;
1351 bool bImportingXML = pDoc->IsImportingXML();
1352 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1353 // #i62483# When loading XML, the check can be skipped altogether.
1354 bool bOnlyNotBecauseOfMatrix;
1355 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1356 && !bOnlyNotBecauseOfMatrix )
1358 if (!bApi)
1359 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1360 return false;
1363 ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
1364 rStyleName, SFX_STYLE_FAMILY_PARA );
1365 if (!pStyleSheet)
1366 return false;
1368 ScDocShellModificator aModificator( rDocShell );
1370 ScRange aMultiRange;
1371 sal_Bool bMulti = rMark.IsMultiMarked();
1372 if ( bMulti )
1373 rMark.GetMultiMarkArea( aMultiRange );
1374 else
1375 rMark.GetMarkArea( aMultiRange );
1377 if ( bRecord )
1379 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1380 SCTAB nStartTab = aMultiRange.aStart.Tab();
1381 SCTAB nTabCount = pDoc->GetTableCount();
1382 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1383 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1384 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1385 if (*itr != nStartTab)
1386 pUndoDoc->AddUndoTab( *itr, *itr );
1388 ScRange aCopyRange = aMultiRange;
1389 aCopyRange.aStart.SetTab(0);
1390 aCopyRange.aEnd.SetTab(nTabCount-1);
1391 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1393 rDocShell.GetUndoManager()->AddUndoAction(
1394 new ScUndoSelectionStyle(
1395 &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) );
1399 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
1401 sal_uInt16 nExtFlags = 0;
1402 if (!AdjustRowHeight( aMultiRange ))
1403 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1404 else if (nExtFlags & SC_PF_LINES)
1405 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
1407 aModificator.SetDocumentModified();
1409 return sal_True;
1412 namespace {
1415 * Check if this insertion attempt would end up cutting one or more pivot
1416 * tables in half, which is not desirable.
1418 * @return true if this insertion can be done safely without shearing any
1419 * existing pivot tables, false otherwise.
1421 bool canInsertCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, InsCellCmd eCmd, const ScDocument* pDoc)
1423 if (!pDoc->HasPivotTable())
1424 // This document has no pivot tables.
1425 return true;
1427 const ScDPCollection* pDPs = pDoc->GetDPCollection();
1428 ScMarkData::const_iterator itBeg = rMarkData.begin(), itEnd = rMarkData.end();
1430 ScRange aRange(rRange); // local copy
1431 switch (eCmd)
1433 case INS_INSROWS:
1435 aRange.aStart.SetCol(0);
1436 aRange.aEnd.SetCol(MAXCOL);
1437 // Continue below.
1439 case INS_CELLSDOWN:
1441 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1443 if (pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), aRange.aStart.Row(), *it))
1444 // This column range cuts through at least one pivot table. Not good.
1445 return false;
1448 // Start row must be either at the top or above any pivot tables.
1449 if (aRange.aStart.Row() < 0)
1450 // I don't know how to handle this case.
1451 return false;
1453 if (aRange.aStart.Row() == 0)
1454 // First row is always allowed.
1455 return true;
1457 ScRange aTest(aRange);
1458 aTest.aStart.IncRow(-1); // Test one row up.
1459 aTest.aEnd.SetRow(aTest.aStart.Row());
1460 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1462 aTest.aStart.SetTab(*it);
1463 aTest.aEnd.SetTab(*it);
1464 if (pDPs->HasTable(aTest))
1465 return false;
1468 break;
1469 case INS_INSCOLS:
1471 aRange.aStart.SetRow(0);
1472 aRange.aEnd.SetRow(MAXROW);
1473 // Continue below.
1475 case INS_CELLSRIGHT:
1477 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1479 if (pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Row(), *it))
1480 // This column range cuts through at least one pivot table. Not good.
1481 return false;
1484 // Start row must be either at the top or above any pivot tables.
1485 if (aRange.aStart.Col() < 0)
1486 // I don't know how to handle this case.
1487 return false;
1489 if (aRange.aStart.Col() == 0)
1490 // First row is always allowed.
1491 return true;
1493 ScRange aTest(aRange);
1494 aTest.aStart.IncCol(-1); // Test one column to the left.
1495 aTest.aEnd.SetCol(aTest.aStart.Col());
1496 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1498 aTest.aStart.SetTab(*it);
1499 aTest.aEnd.SetTab(*it);
1500 if (pDPs->HasTable(aTest))
1501 return false;
1504 break;
1505 default:
1508 return true;
1512 * Check if this deletion attempt would end up cutting one or more pivot
1513 * tables in half, which is not desirable.
1515 * @return true if this deletion can be done safely without shearing any
1516 * existing pivot tables, false otherwise.
1518 bool canDeleteCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, DelCellCmd eCmd, const ScDocument* pDoc)
1520 if (!pDoc->HasPivotTable())
1521 // This document has no pivot tables.
1522 return true;
1524 const ScDPCollection* pDPs = pDoc->GetDPCollection();
1525 ScMarkData::const_iterator itBeg = rMarkData.begin(), itEnd = rMarkData.end();
1527 ScRange aRange(rRange); // local copy
1529 switch (eCmd)
1531 case DEL_DELROWS:
1533 aRange.aStart.SetCol(0);
1534 aRange.aEnd.SetCol(MAXCOL);
1535 // Continue below.
1537 case DEL_CELLSUP:
1539 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1541 if (pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), aRange.aStart.Row(), *it))
1542 // This column range cuts through at least one pivot table. Not good.
1543 return false;
1546 ScRange aTest(aRange);
1547 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1549 aTest.aStart.SetTab(*it);
1550 aTest.aEnd.SetTab(*it);
1551 if (pDPs->HasTable(aTest))
1552 return false;
1555 break;
1556 case DEL_DELCOLS:
1558 aRange.aStart.SetRow(0);
1559 aRange.aEnd.SetRow(MAXROW);
1560 // Continue below.
1562 case DEL_CELLSLEFT:
1564 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1566 if (pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Row(), *it))
1567 // This column range cuts through at least one pivot table. Not good.
1568 return false;
1571 ScRange aTest(aRange);
1572 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1574 aTest.aStart.SetTab(*it);
1575 aTest.aEnd.SetTab(*it);
1576 if (pDPs->HasTable(aTest))
1577 return false;
1580 break;
1581 default:
1584 return true;
1589 bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
1590 bool bRecord, bool bApi, bool bPartOfPaste )
1592 ScDocShellModificator aModificator( rDocShell );
1594 SCCOL nStartCol = rRange.aStart.Col();
1595 SCROW nStartRow = rRange.aStart.Row();
1596 SCTAB nStartTab = rRange.aStart.Tab();
1597 SCCOL nEndCol = rRange.aEnd.Col();
1598 SCROW nEndRow = rRange.aEnd.Row();
1599 SCTAB nEndTab = rRange.aEnd.Tab();
1601 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1603 OSL_FAIL("invalid row in InsertCells");
1604 return false;
1607 ScDocument* pDoc = rDocShell.GetDocument();
1608 SCTAB nTabCount = pDoc->GetTableCount();
1609 SCCOL nPaintStartCol = nStartCol;
1610 SCROW nPaintStartRow = nStartRow;
1611 SCCOL nPaintEndCol = nEndCol;
1612 SCROW nPaintEndRow = nEndRow;
1613 sal_uInt16 nPaintFlags = PAINT_GRID;
1614 bool bSuccess;
1615 SCTAB i;
1617 ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position
1618 SCCOL nCursorCol = 0;
1619 SCROW nCursorRow = 0;
1620 if( pViewSh )
1622 nCursorCol = pViewSh->GetViewData()->GetCurX();
1623 nCursorRow = pViewSh->GetViewData()->GetCurY();
1626 if (bRecord && !pDoc->IsUndoEnabled())
1627 bRecord = false;
1629 ScMarkData aMark;
1630 if (pTabMark)
1631 aMark = *pTabMark;
1632 else
1634 SCTAB nCount = 0;
1635 for( i=0; i<nTabCount; i++ )
1637 if( !pDoc->IsScenario(i) )
1639 nCount++;
1640 if( nCount == nEndTab+1 )
1642 aMark.SelectTable( i, true );
1643 break;
1649 ScMarkData aFullMark( aMark ); // including scenario sheets
1650 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
1651 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1652 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1653 aFullMark.SelectTable( j, true );
1655 SCTAB nSelCount = aMark.GetSelectCount();
1657 // zugehoerige Szenarien auch anpassen
1658 // Test zusammengefasste
1660 SCCOL nMergeTestStartCol = nStartCol;
1661 SCROW nMergeTestStartRow = nStartRow;
1662 SCCOL nMergeTestEndCol = nEndCol;
1663 SCROW nMergeTestEndRow = nEndRow;
1665 ScRange aExtendMergeRange( rRange );
1667 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1669 pDoc->ExtendMerge( aExtendMergeRange );
1670 pDoc->ExtendOverlapped( aExtendMergeRange );
1671 nMergeTestEndCol = aExtendMergeRange.aEnd.Col();
1672 nMergeTestEndRow = aExtendMergeRange.aEnd.Row();
1673 nPaintEndCol = nMergeTestEndCol;
1674 nPaintEndRow = nMergeTestEndRow;
1677 if ( eCmd == INS_INSROWS )
1679 nMergeTestStartCol = 0;
1680 nMergeTestEndCol = MAXCOL;
1682 if ( eCmd == INS_INSCOLS )
1684 nMergeTestStartRow = 0;
1685 nMergeTestEndRow = MAXROW;
1687 if ( eCmd == INS_CELLSDOWN )
1688 nMergeTestEndRow = MAXROW;
1689 if ( eCmd == INS_CELLSRIGHT )
1690 nMergeTestEndCol = MAXCOL;
1692 bool bNeedRefresh = false;
1694 SCCOL nEditTestEndCol = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndCol;
1695 SCROW nEditTestEndRow = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndRow;
1696 ScEditableTester aTester( pDoc, nMergeTestStartCol, nMergeTestStartRow, nEditTestEndCol, nEditTestEndRow, aMark );
1697 if (!aTester.IsEditable())
1699 if (!bApi)
1700 rDocShell.ErrorMessage(aTester.GetMessageId());
1701 return false;
1704 // Check if this insertion is allowed with respect to pivot table.
1705 if (!canInsertCellsByPivot(rRange, aMark, eCmd, pDoc))
1707 if (!bApi)
1708 rDocShell.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE);
1709 return false;
1712 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
1714 ScDocument* pRefUndoDoc = NULL;
1715 ScRefUndoData* pUndoData = NULL;
1716 if ( bRecord )
1718 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1719 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
1721 // pRefUndoDoc is filled in InsertCol / InsertRow
1723 pUndoData = new ScRefUndoData( pDoc );
1725 pDoc->BeginDrawUndo();
1728 // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
1729 // the patch comes from mloiseleur and maoyg
1730 bool bInsertMerge = false;
1731 std::vector<ScRange> qIncreaseRange;
1732 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS );
1733 if (bRecord)
1734 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1736 itr = aMark.begin();
1737 for (; itr != itrEnd && nTabCount; ++itr)
1739 i = *itr;
1740 if( pDoc->HasAttrib( nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1742 if (eCmd==INS_CELLSRIGHT)
1743 bNeedRefresh = true;
1745 SCCOL nMergeStartCol = nMergeTestStartCol;
1746 SCROW nMergeStartRow = nMergeTestStartRow;
1747 SCCOL nMergeEndCol = nMergeTestEndCol;
1748 SCROW nMergeEndRow = nMergeTestEndRow;
1750 pDoc->ExtendMerge( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
1751 pDoc->ExtendOverlapped( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
1753 if(( eCmd == INS_CELLSDOWN && ( nMergeStartCol != nMergeTestStartCol || nMergeEndCol != nMergeTestEndCol )) ||
1754 (eCmd == INS_CELLSRIGHT && ( nMergeStartRow != nMergeTestStartRow || nMergeEndRow != nMergeTestEndRow )) )
1756 if (!bApi)
1757 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1758 rDocShell.GetUndoManager()->LeaveListAction();
1759 delete pUndoData;
1760 return false;
1763 SCCOL nTestCol = -1;
1764 SCROW nTestRow1 = -1;
1765 SCROW nTestRow2 = -1;
1767 ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow );
1768 ScRange aExtendRange( nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i );
1769 const ScPatternAttr* pPattern = NULL;
1770 const ScMergeAttr* pMergeFlag = NULL;
1771 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1772 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1774 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1775 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1776 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1777 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1779 ScRange aRange( nTestCol, nTestRow1, i );
1780 pDoc->ExtendOverlapped(aRange);
1781 pDoc->ExtendMerge(aRange, true);
1783 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1785 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1787 ScRange aTestRange( nTestCol, nTestRow, i );
1788 pDoc->ExtendOverlapped( aTestRange );
1789 pDoc->ExtendMerge( aTestRange, true);
1790 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1791 if( !aExtendRange.In( aMergeRange ) )
1793 qIncreaseRange.push_back( aTestRange );
1794 bInsertMerge = true;
1798 else
1800 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1801 if( !aExtendRange.In( aMergeRange ) )
1803 qIncreaseRange.push_back( aRange );
1805 bInsertMerge = true;
1810 if( bInsertMerge )
1812 if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN )
1814 nStartRow = aExtendMergeRange.aStart.Row();
1815 nEndRow = aExtendMergeRange.aEnd.Row();
1817 if( eCmd == INS_CELLSDOWN )
1818 nEndCol = nMergeTestEndCol;
1819 else
1821 nStartCol = 0;
1822 nEndCol = MAXCOL;
1825 else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS )
1828 nStartCol = aExtendMergeRange.aStart.Col();
1829 nEndCol = aExtendMergeRange.aEnd.Col();
1830 if( eCmd == INS_CELLSRIGHT )
1832 nEndRow = nMergeTestEndRow;
1834 else
1836 nStartRow = 0;
1837 nEndRow = MAXROW;
1841 if( !qIncreaseRange.empty() )
1843 for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); ++iIter )
1845 ScRange aRange( *iIter );
1846 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1848 UnmergeCells( aRange, true );
1853 else
1855 if (!bApi)
1856 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1857 rDocShell.GetUndoManager()->LeaveListAction();
1858 delete pUndoData;
1859 return false;
1864 switch (eCmd)
1866 case INS_CELLSDOWN:
1867 bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1868 nPaintEndRow = MAXROW;
1869 break;
1870 case INS_INSROWS:
1871 bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1872 nPaintStartCol = 0;
1873 nPaintEndCol = MAXCOL;
1874 nPaintEndRow = MAXROW;
1875 nPaintFlags |= PAINT_LEFT;
1876 break;
1877 case INS_CELLSRIGHT:
1878 bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1879 nPaintEndCol = MAXCOL;
1880 break;
1881 case INS_INSCOLS:
1882 bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1883 nPaintStartRow = 0;
1884 nPaintEndRow = MAXROW;
1885 nPaintEndCol = MAXCOL;
1886 nPaintFlags |= PAINT_TOP;
1887 break;
1888 default:
1889 OSL_FAIL("Falscher Code beim Einfuegen");
1890 bSuccess = false;
1891 break;
1894 if ( bSuccess )
1896 SCTAB* pTabs = NULL;
1897 SCTAB* pScenarios = NULL;
1898 SCTAB nUndoPos = 0;
1900 if ( bRecord )
1902 pTabs = new SCTAB[nSelCount];
1903 pScenarios = new SCTAB[nSelCount];
1904 nUndoPos = 0;
1905 itr = aMark.begin();
1906 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1908 SCTAB nCount = 0;
1909 for( SCTAB j=*itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1910 nCount ++;
1912 pScenarios[nUndoPos] = nCount;
1913 pTabs[nUndoPos] = *itr;
1914 nUndoPos ++;
1917 if( !bInsertMerge )
1919 rDocShell.GetUndoManager()->LeaveListAction();
1922 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
1923 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),
1924 nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) );
1927 // #i8302 : we remerge growing ranges, with the new part inserted
1929 while( !qIncreaseRange.empty() )
1931 ScRange aRange = qIncreaseRange.back();
1932 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1934 switch (eCmd)
1936 case INS_CELLSDOWN:
1937 case INS_INSROWS:
1938 aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1));
1939 break;
1940 case INS_CELLSRIGHT:
1941 case INS_INSCOLS:
1942 aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1));
1943 break;
1944 default:
1945 break;
1947 ScCellMergeOption aMergeOption(
1948 aRange.aStart.Col(), aRange.aStart.Row(),
1949 aRange.aEnd.Col(), aRange.aEnd.Row() );
1950 aMergeOption.maTabs.insert(aRange.aStart.Tab());
1951 MergeCells(aMergeOption, false, true, true);
1953 qIncreaseRange.pop_back();
1956 if( bInsertMerge )
1957 rDocShell.GetUndoManager()->LeaveListAction();
1959 itr = aMark.begin();
1960 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1962 i = *itr;
1963 pDoc->SetDrawPageSize(i);
1965 if (bNeedRefresh)
1966 pDoc->ExtendMerge( nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow, i, true );
1967 else
1968 pDoc->RefreshAutoFilter( nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow, i );
1970 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1971 pDoc->UpdatePageBreaks( i );
1973 sal_uInt16 nExtFlags = 0;
1974 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, i );
1976 SCTAB nScenarioCount = 0;
1978 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1979 nScenarioCount ++;
1981 bool bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) :
1982 AdjustRowHeight(ScRange(0, nPaintStartRow, i, MAXCOL, nPaintEndRow, i+nScenarioCount ));
1983 if (bAdjusted)
1985 // paint only what is not done by AdjustRowHeight
1986 if (nPaintFlags & PAINT_TOP)
1987 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, i+nScenarioCount, PAINT_TOP );
1989 else
1990 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, i+nScenarioCount, nPaintFlags, nExtFlags );
1993 else
1995 if( bInsertMerge )
1997 while( !qIncreaseRange.empty() )
1999 ScRange aRange = qIncreaseRange.back();
2000 ScCellMergeOption aMergeOption(
2001 aRange.aStart.Col(), aRange.aStart.Row(),
2002 aRange.aEnd.Col(), aRange.aEnd.Row() );
2003 MergeCells(aMergeOption, false, true, true);
2004 qIncreaseRange.pop_back();
2007 if( pViewSh )
2009 pViewSh->MarkRange( rRange, false );
2010 pViewSh->SetCursor( nCursorCol, nCursorRow );
2014 rDocShell.GetUndoManager()->LeaveListAction();
2015 rDocShell.GetUndoManager()->RemoveLastUndoAction();
2017 delete pRefUndoDoc;
2018 delete pUndoData;
2019 if (!bApi)
2020 rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll
2023 aModificator.SetDocumentModified();
2025 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2026 return bSuccess;
2029 bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
2030 bool bRecord, bool bApi )
2032 ScDocShellModificator aModificator( rDocShell );
2034 SCCOL nStartCol = rRange.aStart.Col();
2035 SCROW nStartRow = rRange.aStart.Row();
2036 SCTAB nStartTab = rRange.aStart.Tab();
2037 SCCOL nEndCol = rRange.aEnd.Col();
2038 SCROW nEndRow = rRange.aEnd.Row();
2039 SCTAB nEndTab = rRange.aEnd.Tab();
2041 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
2043 OSL_FAIL("invalid row in DeleteCells");
2044 return false;
2047 ScDocument* pDoc = rDocShell.GetDocument();
2048 SCTAB nTabCount = pDoc->GetTableCount();
2049 SCCOL nPaintStartCol = nStartCol;
2050 SCROW nPaintStartRow = nStartRow;
2051 SCCOL nPaintEndCol = nEndCol;
2052 SCROW nPaintEndRow = nEndRow;
2053 sal_uInt16 nPaintFlags = PAINT_GRID;
2055 if (bRecord && !pDoc->IsUndoEnabled())
2056 bRecord = false;
2058 ScMarkData aMark;
2059 if (pTabMark)
2060 aMark = *pTabMark;
2061 else
2063 SCTAB nCount = 0;
2064 for(SCTAB i=0; i<nTabCount; i++ )
2066 if( !pDoc->IsScenario(i) )
2068 nCount++;
2069 if( nCount == nEndTab+1 )
2071 aMark.SelectTable(i, true);
2072 break;
2078 ScMarkData aFullMark( aMark ); // including scenario sheets
2079 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
2080 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2081 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2082 aFullMark.SelectTable( j, true );
2084 SCTAB nSelCount = aMark.GetSelectCount();
2086 SCCOL nUndoStartCol = nStartCol;
2087 SCROW nUndoStartRow = nStartRow;
2088 SCCOL nUndoEndCol = nEndCol;
2089 SCROW nUndoEndRow = nEndRow;
2091 ScRange aExtendMergeRange( rRange );
2093 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
2095 pDoc->ExtendMerge( aExtendMergeRange );
2096 pDoc->ExtendOverlapped( aExtendMergeRange );
2097 nUndoEndCol = aExtendMergeRange.aEnd.Col();
2098 nUndoEndRow = aExtendMergeRange.aEnd.Row();
2099 nPaintEndCol = nUndoEndCol;
2100 nPaintEndRow = nUndoEndRow;
2103 if (eCmd==DEL_DELROWS)
2105 nUndoStartCol = 0;
2106 nUndoEndCol = MAXCOL;
2108 if (eCmd==DEL_DELCOLS)
2110 nUndoStartRow = 0;
2111 nUndoEndRow = MAXROW;
2113 // Test Zellschutz
2115 SCCOL nEditTestEndX = nUndoEndCol;
2116 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
2117 nEditTestEndX = MAXCOL;
2118 SCROW nEditTestEndY = nUndoEndRow;
2119 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
2120 nEditTestEndY = MAXROW;
2121 ScEditableTester aTester( pDoc, nUndoStartCol, nUndoStartRow, nEditTestEndX, nEditTestEndY, aMark );
2122 if (!aTester.IsEditable())
2124 if (!bApi)
2125 rDocShell.ErrorMessage(aTester.GetMessageId());
2126 return false;
2129 if (!canDeleteCellsByPivot(rRange, aMark, eCmd, pDoc))
2131 if (!bApi)
2132 rDocShell.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE);
2133 return false;
2135 // Test zusammengefasste
2137 SCCOL nMergeTestEndCol = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndCol;
2138 SCROW nMergeTestEndRow = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndRow;
2139 SCCOL nExtendStartCol = nUndoStartCol;
2140 SCROW nExtendStartRow = nUndoStartRow;
2141 bool bNeedRefresh = false;
2143 //Issue 8302 want to be able to insert into the middle of merged cells
2144 //the patch comes from maoyg
2145 ::std::vector<ScRange> qDecreaseRange;
2146 bool bDeletingMerge = false;
2147 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS );
2148 if (bRecord)
2149 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
2151 itr = aMark.begin();
2152 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2154 SCTAB i = *itr;
2155 if ( pDoc->HasAttrib( nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i, HASATTR_MERGED | HASATTR_OVERLAPPED ))
2157 SCCOL nMergeStartCol = nUndoStartCol;
2158 SCROW nMergeStartRow = nUndoStartRow;
2159 SCCOL nMergeEndCol = nMergeTestEndCol;
2160 SCROW nMergeEndRow = nMergeTestEndRow;
2162 pDoc->ExtendMerge( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
2163 pDoc->ExtendOverlapped( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
2164 if( ( eCmd == DEL_CELLSUP && ( nMergeStartCol != nUndoStartCol || nMergeEndCol != nMergeTestEndCol))||
2165 ( eCmd == DEL_CELLSLEFT && ( nMergeStartRow != nUndoStartRow || nMergeEndRow != nMergeTestEndRow)))
2167 if (!bApi)
2168 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
2169 rDocShell.GetUndoManager()->LeaveListAction();
2170 return false;
2173 nExtendStartCol = nMergeStartCol;
2174 nExtendStartRow = nMergeStartRow;
2175 SCCOL nTestCol = -1;
2176 SCROW nTestRow1 = -1;
2177 SCROW nTestRow2 = -1;
2179 ScDocAttrIterator aTestIter( pDoc, i, nUndoStartCol, nUndoStartRow, nMergeTestEndCol, nMergeTestEndRow );
2180 ScRange aExtendRange( nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i );
2181 const ScPatternAttr* pPattern = NULL;
2182 const ScMergeAttr* pMergeFlag = NULL;
2183 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
2184 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
2186 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
2187 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
2188 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
2189 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
2191 ScRange aRange( nTestCol, nTestRow1, i );
2192 pDoc->ExtendOverlapped( aRange );
2193 pDoc->ExtendMerge( aRange, true );
2195 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
2197 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
2199 ScRange aTestRange( nTestCol, nTestRow, i );
2200 pDoc->ExtendOverlapped( aTestRange );
2201 pDoc->ExtendMerge( aTestRange, true );
2202 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
2203 if( !aExtendRange.In( aMergeRange ) )
2205 qDecreaseRange.push_back( aTestRange );
2206 bDeletingMerge = true;
2210 else
2212 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
2213 if( !aExtendRange.In( aMergeRange ) )
2215 qDecreaseRange.push_back( aRange );
2217 bDeletingMerge = true;
2222 if( bDeletingMerge )
2225 if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP )
2227 nStartRow = aExtendMergeRange.aStart.Row();
2228 nEndRow = aExtendMergeRange.aEnd.Row();
2229 bNeedRefresh = true;
2231 if( eCmd == DEL_CELLSUP )
2233 nEndCol = aExtendMergeRange.aEnd.Col();
2235 else
2237 nStartCol = 0;
2238 nEndCol = MAXCOL;
2241 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2244 nStartCol = aExtendMergeRange.aStart.Col();
2245 nEndCol = aExtendMergeRange.aEnd.Col();
2246 if( eCmd == DEL_CELLSLEFT )
2248 nEndRow = aExtendMergeRange.aEnd.Row();
2249 bNeedRefresh = true;
2251 else
2253 nStartRow = 0;
2254 nEndRow = MAXROW;
2258 if( !qDecreaseRange.empty() )
2260 for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); ++iIter )
2262 ScRange aRange( *iIter );
2263 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2265 UnmergeCells( aRange, true );
2270 else
2272 if (!bApi)
2273 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
2274 rDocShell.GetUndoManager()->LeaveListAction();
2275 return false;
2281 // ausfuehren
2284 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
2286 ScDocument* pUndoDoc = NULL;
2287 ScDocument* pRefUndoDoc = NULL;
2288 ScRefUndoData* pUndoData = NULL;
2289 if ( bRecord )
2291 // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
2292 // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
2294 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2295 pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) );
2296 itr = aMark.begin();
2297 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2299 SCTAB nScenarioCount = 0;
2301 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2302 nScenarioCount ++;
2304 pDoc->CopyToDocument( nUndoStartCol, nUndoStartRow, *itr, nUndoEndCol, nUndoEndRow, *itr+nScenarioCount,
2305 IDF_ALL | IDF_NOCAPTIONS, false, pUndoDoc );
2308 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2309 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
2311 pUndoData = new ScRefUndoData( pDoc );
2313 pDoc->BeginDrawUndo();
2316 sal_uInt16 nExtFlags = 0;
2317 itr = aMark.begin();
2318 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2320 rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr );
2323 bool bUndoOutline = false;
2324 switch (eCmd)
2326 case DEL_CELLSUP:
2327 pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark );
2328 nPaintEndRow = MAXROW;
2329 break;
2330 case DEL_DELROWS:
2331 pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2332 nPaintStartCol = 0;
2333 nPaintEndCol = MAXCOL;
2334 nPaintEndRow = MAXROW;
2335 nPaintFlags |= PAINT_LEFT;
2336 break;
2337 case DEL_CELLSLEFT:
2338 pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark );
2339 nPaintEndCol = MAXCOL;
2340 break;
2341 case DEL_DELCOLS:
2342 pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2343 nPaintStartRow = 0;
2344 nPaintEndRow = MAXROW;
2345 nPaintEndCol = MAXCOL;
2346 nPaintFlags |= PAINT_TOP;
2347 break;
2348 default:
2349 OSL_FAIL("Falscher Code beim Loeschen");
2350 break;
2353 //! Test, ob Outline in Groesse geaendert
2355 if ( bRecord )
2357 itr = aFullMark.begin(), itrEnd = aFullMark.end();
2358 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2359 pRefUndoDoc->DeleteAreaTab(nUndoStartCol,nUndoStartRow,nUndoEndCol,nUndoEndRow, *itr, IDF_ALL);
2361 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2362 pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
2364 // kopieren mit bColRowFlags=false (#54194#)
2365 pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,false,pUndoDoc,NULL,false);
2366 delete pRefUndoDoc;
2368 SCTAB* pTabs = new SCTAB[nSelCount];
2369 SCTAB* pScenarios = new SCTAB[nSelCount];
2370 SCTAB nUndoPos = 0;
2372 itr = aMark.begin(), itrEnd = aMark.end();
2373 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2375 SCTAB nCount = 0;
2376 for( SCTAB j=*itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2377 nCount ++;
2379 pScenarios[nUndoPos] = nCount;
2380 pTabs[nUndoPos] = *itr;
2381 nUndoPos ++;
2384 if( !bDeletingMerge )
2386 rDocShell.GetUndoManager()->LeaveListAction();
2389 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
2390 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
2391 eCmd, pUndoDoc, pUndoData ) );
2394 // #i8302 want to be able to insert into the middle of merged cells
2395 // the patch comes from maoyg
2397 while( !qDecreaseRange.empty() )
2399 ScRange aRange = qDecreaseRange.back();
2401 long nDecreaseRowCount = 0;
2402 long nDecreaseColCount = 0;
2403 if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS )
2405 if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2406 nDecreaseRowCount = nEndRow-nStartRow+1;
2407 else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() )
2408 nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1;
2409 else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2410 nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1;
2412 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2414 if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2415 nDecreaseColCount = nEndCol-nStartCol+1;
2416 else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() )
2417 nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1;
2418 else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2419 nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1;
2422 switch (eCmd)
2424 case DEL_CELLSUP:
2425 case DEL_DELROWS:
2426 aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount));
2427 break;
2428 case DEL_CELLSLEFT:
2429 case DEL_DELCOLS:
2430 aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount));
2431 break;
2432 default:
2433 break;
2436 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2438 ScCellMergeOption aMergeOption(aRange);
2439 MergeCells( aMergeOption, false, true, true );
2441 qDecreaseRange.pop_back();
2444 if( bDeletingMerge )
2445 rDocShell.GetUndoManager()->LeaveListAction();
2447 if ( bNeedRefresh )
2449 // #i51445# old merge flag attributes must be deleted also for single cells,
2450 // not only for whole columns/rows
2452 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
2453 nMergeTestEndCol = MAXCOL;
2454 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
2455 nMergeTestEndRow = MAXROW;
2456 ScPatternAttr aPattern( pDoc->GetPool() );
2457 aPattern.GetItemSet().Put( ScMergeFlagAttr() );
2459 pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndCol, nMergeTestEndRow, aMark, aPattern );
2461 itr = aMark.begin(), itrEnd = aMark.end();
2462 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2464 SCTAB nScenarioCount = 0;
2466 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2467 nScenarioCount ++;
2469 ScRange aMergedRange( nExtendStartCol, nExtendStartRow, *itr, nMergeTestEndCol, nMergeTestEndRow, *itr+nScenarioCount );
2470 pDoc->ExtendMerge( aMergedRange, true );
2474 itr = aMark.begin(), itrEnd = aMark.end();
2475 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2477 pDoc->SetDrawPageSize(*itr);
2479 if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS )
2480 pDoc->UpdatePageBreaks( *itr );
2482 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr );
2484 SCTAB nScenarioCount = 0;
2486 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2487 nScenarioCount ++;
2489 // ganze Zeilen loeschen: nichts anpassen
2490 if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartRow, *itr, MAXCOL, nPaintEndRow, *itr+nScenarioCount )) )
2491 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr+nScenarioCount, nPaintFlags, nExtFlags );
2492 else
2494 // paint only what is not done by AdjustRowHeight
2495 if (nExtFlags & SC_PF_LINES)
2496 lcl_PaintAbove( rDocShell, ScRange( nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr+nScenarioCount) );
2497 if (nPaintFlags & PAINT_TOP)
2498 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr+nScenarioCount, PAINT_TOP );
2502 aModificator.SetDocumentModified();
2504 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2506 return true;
2509 sal_Bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
2510 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
2512 ScDocShellModificator aModificator( rDocShell );
2514 SCCOL nStartCol = rSource.aStart.Col();
2515 SCROW nStartRow = rSource.aStart.Row();
2516 SCTAB nStartTab = rSource.aStart.Tab();
2517 SCCOL nEndCol = rSource.aEnd.Col();
2518 SCROW nEndRow = rSource.aEnd.Row();
2519 SCTAB nEndTab = rSource.aEnd.Tab();
2520 SCCOL nDestCol = rDestPos.Col();
2521 SCROW nDestRow = rDestPos.Row();
2522 SCTAB nDestTab = rDestPos.Tab();
2524 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) )
2526 OSL_FAIL("invalid row in MoveBlock");
2527 return false;
2530 // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
2531 sal_Bool bScenariosAdded = false;
2532 ScDocument* pDoc = rDocShell.GetDocument();
2533 if (bRecord && !pDoc->IsUndoEnabled())
2534 bRecord = false;
2536 SCTAB nTabCount = pDoc->GetTableCount();
2537 if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) )
2538 while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) )
2540 ++nEndTab;
2541 bScenariosAdded = sal_True;
2544 SCTAB nSrcTabCount = nEndTab-nStartTab+1;
2545 SCTAB nDestEndTab = nDestTab+nSrcTabCount-1;
2546 SCTAB nTab;
2548 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
2550 ScMarkData aSourceMark;
2551 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2552 aSourceMark.SelectTable( nTab, sal_True ); // Source selektieren
2553 aSourceMark.SetMarkArea( rSource );
2555 ScDocShellRef aDragShellRef;
2556 if ( pDoc->HasOLEObjectsInArea( rSource ) )
2558 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
2559 aDragShellRef->DoInitNew(NULL);
2561 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
2563 ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut);
2564 pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
2566 ScDrawLayer::SetGlobalDrawPersist(NULL);
2568 SCCOL nOldEndCol = nEndCol;
2569 SCROW nOldEndRow = nEndRow;
2570 sal_Bool bClipOver = false;
2571 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2573 SCCOL nTmpEndCol = nOldEndCol;
2574 SCROW nTmpEndRow = nOldEndRow;
2575 if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab ))
2576 bClipOver = sal_True;
2577 if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol;
2578 if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow;
2581 SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol );
2582 SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow );
2584 SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock
2585 SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow );
2587 sal_Bool bIncludeFiltered = bCut;
2588 if ( !bIncludeFiltered )
2590 // adjust sizes to include only non-filtered rows
2592 SCCOL nClipX;
2593 SCROW nClipY;
2594 pClipDoc->GetClipArea( nClipX, nClipY, false );
2595 SCROW nUndoAdd = nUndoEndRow - nDestEndRow;
2596 nDestEndRow = nDestRow + nClipY;
2597 nUndoEndRow = nDestEndRow + nUndoAdd;
2600 if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow))
2602 if (!bApi)
2603 rDocShell.ErrorMessage(STR_PASTE_FULL);
2604 delete pClipDoc;
2605 return false;
2608 // Test auf Zellschutz
2610 ScEditableTester aTester;
2611 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2612 aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow );
2613 if (bCut)
2614 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2615 aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
2617 if (!aTester.IsEditable())
2619 if (!bApi)
2620 rDocShell.ErrorMessage(aTester.GetMessageId());
2621 delete pClipDoc;
2622 return false;
2625 // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
2627 if (bClipOver && !bCut)
2628 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab,
2629 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2630 { // "Zusammenfassen nicht verschachteln !"
2631 if (!bApi)
2632 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2633 delete pClipDoc;
2634 return false;
2637 // Are there borders in the cells? (for painting)
2639 sal_uInt16 nSourceExt = 0;
2640 rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab );
2641 sal_uInt16 nDestExt = 0;
2642 rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab );
2645 // ausfuehren
2648 ScDocument* pUndoDoc = NULL;
2649 ScDocument* pRefUndoDoc = NULL;
2650 ScRefUndoData* pUndoData = NULL;
2651 if (bRecord)
2653 sal_Bool bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW );
2654 sal_Bool bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL );
2655 sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
2657 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2658 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows );
2660 if (bCut)
2662 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
2663 nUndoFlags, false, pUndoDoc );
2664 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2665 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
2668 if ( nDestTab != nStartTab )
2669 pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows );
2670 pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab,
2671 nDestEndCol, nDestEndRow, nDestEndTab,
2672 nUndoFlags, false, pUndoDoc );
2674 pUndoData = new ScRefUndoData( pDoc );
2676 pDoc->BeginDrawUndo();
2679 sal_Bool bSourceHeight = false; // Hoehen angepasst?
2680 if (bCut)
2682 ScMarkData aDelMark; // only for tables
2683 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2685 pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL );
2686 aDelMark.SelectTable( nTab, sal_True );
2688 pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark );
2690 // Test auf zusammengefasste
2692 if (bClipOver)
2693 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab,
2694 nUndoEndCol,nUndoEndRow,nDestEndTab,
2695 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2697 pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc );
2698 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2700 SCCOL nTmpEndCol = nEndCol;
2701 SCROW nTmpEndRow = nEndRow;
2702 pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
2705 // Fehlermeldung erst nach dem Wiederherstellen des Inhalts
2706 if (!bApi) // "Zusammenfassen nicht verschachteln !"
2707 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2709 delete pUndoDoc;
2710 delete pRefUndoDoc;
2711 delete pUndoData;
2712 delete pClipDoc;
2713 return false;
2716 bSourceHeight = AdjustRowHeight( rSource, false );
2719 ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab );
2721 ScMarkData aDestMark;
2722 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2723 aDestMark.SelectTable( nTab, sal_True ); // Destination selektieren
2724 aDestMark.SetMarkArea( aPasteDest );
2726 /* Do not drawing objects here. While pasting, the
2727 function ScDocument::UpdateReference() is called which calls
2728 ScDrawLayer::MoveCells() which may move away inserted objects to wrong
2729 positions (e.g. if source and destination range overlaps).*/
2730 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_OBJECTS),
2731 pRefUndoDoc, pClipDoc, sal_True, false, bIncludeFiltered );
2734 // skipped rows and merged cells don't mix
2735 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
2736 UnmergeCells( aPasteDest, false );
2738 VirtualDevice aVirtDev;
2739 sal_Bool bDestHeight = AdjustRowHeight(
2740 ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ),
2741 false );
2743 /* Paste drawing objects after adjusting formula references
2744 and row heights. There are no cell notes or drawing objects, if the
2745 clipdoc does not contain a drawing layer.*/
2746 if ( pClipDoc->GetDrawLayer() )
2747 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_OBJECTS,
2748 pRefUndoDoc, pClipDoc, sal_True, false, bIncludeFiltered );
2750 if (bRecord)
2752 if (pRefUndoDoc)
2754 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2755 pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
2757 pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL );
2758 // kopieren mit bColRowFlags=sal_False (#54194#)
2759 pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB,
2760 IDF_FORMULA, false, pUndoDoc, NULL, false );
2761 delete pRefUndoDoc;
2764 rDocShell.GetUndoManager()->AddUndoAction(
2765 new ScUndoDragDrop( &rDocShell, ScRange(
2766 nStartCol, nStartRow, nStartTab,
2767 nOldEndCol, nOldEndRow, nEndTab ),
2768 ScAddress( nDestCol, nDestRow, nDestTab ),
2769 bCut, pUndoDoc, pUndoData, bScenariosAdded ) );
2772 SCCOL nDestPaintEndCol = nDestEndCol;
2773 SCROW nDestPaintEndRow = nDestEndRow;
2774 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2776 SCCOL nTmpEndCol = nDestEndCol;
2777 SCROW nTmpEndRow = nDestEndRow;
2778 pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
2779 if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol;
2780 if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow;
2783 if (bCut)
2784 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2785 pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
2787 if (bPaint)
2789 // Zielbereich:
2791 SCCOL nPaintStartX = nDestCol;
2792 SCROW nPaintStartY = nDestRow;
2793 SCCOL nPaintEndX = nDestPaintEndCol;
2794 SCROW nPaintEndY = nDestPaintEndRow;
2795 sal_uInt16 nFlags = PAINT_GRID;
2797 if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert?
2799 nPaintEndX = MAXCOL;
2800 nPaintStartY = 0;
2801 nPaintEndY = MAXROW;
2802 nFlags |= PAINT_TOP;
2804 if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) )
2806 nPaintEndY = MAXROW;
2807 nPaintStartX = 0;
2808 nPaintEndX = MAXCOL;
2809 nFlags |= PAINT_LEFT;
2811 if ( bScenariosAdded )
2813 nPaintStartX = 0;
2814 nPaintStartY = 0;
2815 nPaintEndX = MAXCOL;
2816 nPaintEndY = MAXROW;
2819 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab,
2820 nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt );
2822 if ( bCut )
2824 // Quellbereich:
2826 nPaintStartX = nStartCol;
2827 nPaintStartY = nStartRow;
2828 nPaintEndX = nEndCol;
2829 nPaintEndY = nEndRow;
2830 nFlags = PAINT_GRID;
2832 if ( bSourceHeight )
2834 nPaintEndY = MAXROW;
2835 nPaintStartX = 0;
2836 nPaintEndX = MAXCOL;
2837 nFlags |= PAINT_LEFT;
2839 if ( bScenariosAdded )
2841 nPaintStartX = 0;
2842 nPaintStartY = 0;
2843 nPaintEndX = MAXCOL;
2844 nPaintEndY = MAXROW;
2847 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab,
2848 nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt );
2852 aModificator.SetDocumentModified();
2854 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2856 delete pClipDoc;
2857 return sal_True;
2860 //------------------------------------------------------------------------
2861 uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, OUString& sCodeName )
2863 uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY);
2864 uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess;
2865 uno::Reference< uno::XInterface > xDocModuleApiObject;
2866 if ( xSF.is() )
2868 xVBACodeNamedObjectAccess.set( xSF->createInstance("ooo.vba.VBAObjectModuleObjectProvider"), uno::UNO_QUERY );
2869 xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY );
2871 return xDocModuleApiObject;
2875 static script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, OUString& sModule )
2877 script::ModuleInfo sModuleInfo;
2878 sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
2879 sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule );
2880 return sModuleInfo;
2883 void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, const OUString& sModuleName, const OUString& sSource )
2885 SfxObjectShell& rDocSh = *rDoc.GetDocumentShell();
2886 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2887 OSL_ENSURE( xLibContainer.is(), "No BasicContainer!" );
2889 uno::Reference< container::XNameContainer > xLib;
2890 if( xLibContainer.is() )
2892 OUString aLibName( "Standard" );
2893 if ( rDocSh.GetBasicManager() && !rDocSh.GetBasicManager()->GetName().isEmpty() )
2895 aLibName = rDocSh.GetBasicManager()->GetName();
2897 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2898 aLibAny >>= xLib;
2900 if( xLib.is() )
2902 // if the Module with codename exists then find a new name
2903 sal_Int32 nNum = 0;
2904 OUString genModuleName;
2905 if ( !sModuleName.isEmpty() )
2906 genModuleName = sModuleName;
2907 else
2909 genModuleName = "Sheet1";
2910 nNum = 1;
2912 while( xLib->hasByName( genModuleName ) )
2913 genModuleName = "Sheet" + OUString::number( ++nNum );
2915 uno::Any aSourceAny;
2916 OUString sTmpSource = sSource;
2917 if ( sTmpSource.isEmpty() )
2918 sTmpSource = "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n";
2919 aSourceAny <<= sTmpSource;
2920 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2921 if ( xVBAModuleInfo.is() )
2923 rDoc.SetCodeName( nTab, genModuleName );
2924 script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, genModuleName );
2925 xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo );
2926 xLib->insertByName( genModuleName, aSourceAny );
2932 void VBA_DeleteModule( ScDocShell& rDocSh, const OUString& sModuleName )
2934 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2935 OSL_ENSURE( xLibContainer.is(), "No BasicContainer!" );
2937 uno::Reference< container::XNameContainer > xLib;
2938 if( xLibContainer.is() )
2940 OUString aLibName( "Standard" );
2941 if ( rDocSh.GetBasicManager() && !rDocSh.GetBasicManager()->GetName().isEmpty() )
2943 aLibName = rDocSh.GetBasicManager()->GetName();
2945 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2946 aLibAny >>= xLib;
2948 if( xLib.is() )
2950 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2951 if( xLib->hasByName( sModuleName ) )
2952 xLib->removeByName( sModuleName );
2953 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo(sModuleName) )
2954 xVBAModuleInfo->removeModuleInfo( sModuleName );
2960 sal_Bool ScDocFunc::InsertTable( SCTAB nTab, const OUString& rName, sal_Bool bRecord, sal_Bool bApi )
2962 sal_Bool bSuccess = false;
2963 WaitObject aWait( rDocShell.GetActiveDialogParent() );
2965 ScDocShellModificator aModificator( rDocShell );
2967 ScDocument* pDoc = rDocShell.GetDocument();
2970 // Strange loop, also basic is loaded too early ( InsertTable )
2971 // is called via the xml import for sheets in described in ODF
2972 sal_Bool bInsertDocModule = false;
2974 if( !rDocShell.GetDocument()->IsImportingXML() )
2976 bInsertDocModule = pDoc ? pDoc->IsInVBAMode() : false;
2978 if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) )
2979 bRecord = false;
2981 if (bRecord)
2982 pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage
2984 SCTAB nTabCount = pDoc->GetTableCount();
2985 sal_Bool bAppend = ( nTab >= nTabCount );
2986 if ( bAppend )
2987 nTab = nTabCount; // wichtig fuer Undo
2989 if (pDoc->InsertTab( nTab, rName ))
2991 if (bRecord)
2992 rDocShell.GetUndoManager()->AddUndoAction(
2993 new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName));
2994 // Views updaten:
2995 // Only insert vba modules if vba mode ( and not currently importing XML )
2996 if( bInsertDocModule )
2998 OUString sSource, sCodeName;
2999 VBA_InsertModule( *pDoc, nTab, sCodeName, sSource );
3001 rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
3003 rDocShell.PostPaintExtras();
3004 aModificator.SetDocumentModified();
3005 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3006 bSuccess = sal_True;
3008 else if (!bApi)
3009 rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
3011 return bSuccess;
3014 sal_Bool ScDocFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord, sal_Bool /* bApi */ )
3016 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3018 ScDocShellModificator aModificator( rDocShell );
3020 sal_Bool bSuccess = false;
3021 ScDocument* pDoc = rDocShell.GetDocument();
3022 sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false;
3023 if (bRecord && !pDoc->IsUndoEnabled())
3024 bRecord = false;
3025 if ( bVbaEnabled )
3026 bRecord = false;
3027 sal_Bool bWasLinked = pDoc->IsLinked(nTab);
3028 ScDocument* pUndoDoc = NULL;
3029 ScRefUndoData* pUndoData = NULL;
3030 if (bRecord)
3032 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3033 SCTAB nCount = pDoc->GetTableCount();
3035 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); // nur nTab mit Flags
3036 pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen
3038 pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pUndoDoc );
3039 OUString aOldName;
3040 pDoc->GetName( nTab, aOldName );
3041 pUndoDoc->RenameTab( nTab, aOldName, false );
3042 if (bWasLinked)
3043 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
3044 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
3045 pDoc->GetLinkTab(nTab),
3046 pDoc->GetLinkRefreshDelay(nTab) );
3048 if ( pDoc->IsScenario(nTab) )
3050 pUndoDoc->SetScenario( nTab, sal_True );
3051 OUString aComment;
3052 Color aColor;
3053 sal_uInt16 nScenFlags;
3054 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
3055 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
3056 sal_Bool bActive = pDoc->IsActiveScenario( nTab );
3057 pUndoDoc->SetActiveScenario( nTab, bActive );
3059 pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
3060 pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
3061 pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
3063 // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
3064 pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage
3066 pUndoData = new ScRefUndoData( pDoc );
3069 if (pDoc->DeleteTab(nTab))
3071 if (bRecord)
3073 vector<SCTAB> theTabs;
3074 theTabs.push_back(nTab);
3075 rDocShell.GetUndoManager()->AddUndoAction(
3076 new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData ));
3078 // Views updaten:
3079 if( bVbaEnabled )
3081 OUString sCodeName;
3082 if( pDoc->GetCodeName( nTab, sCodeName ) )
3084 VBA_DeleteModule( rDocShell, sCodeName );
3087 rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
3089 if (bWasLinked)
3091 rDocShell.UpdateLinks(); // Link-Manager updaten
3092 SfxBindings* pBindings = rDocShell.GetViewBindings();
3093 if (pBindings)
3094 pBindings->Invalidate(SID_LINKS);
3097 rDocShell.PostPaintExtras();
3098 aModificator.SetDocumentModified();
3100 SfxApplication* pSfxApp = SFX_APP(); // Navigator
3101 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3102 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
3103 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
3105 bSuccess = sal_True;
3107 else
3109 delete pUndoDoc;
3110 delete pUndoData;
3112 return bSuccess;
3115 sal_Bool ScDocFunc::SetTableVisible( SCTAB nTab, bool bVisible, sal_Bool bApi )
3117 ScDocument* pDoc = rDocShell.GetDocument();
3118 bool bUndo(pDoc->IsUndoEnabled());
3119 if ( pDoc->IsVisible( nTab ) == bVisible )
3120 return sal_True; // nichts zu tun - ok
3122 if ( !pDoc->IsDocEditable() )
3124 if (!bApi)
3125 rDocShell.ErrorMessage(STR_PROTECTIONERR);
3126 return false;
3129 ScDocShellModificator aModificator( rDocShell );
3131 if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading
3133 // nicht alle Tabellen ausblenden
3135 sal_uInt16 nVisCount = 0;
3136 SCTAB nCount = pDoc->GetTableCount();
3137 for (SCTAB i=0; i<nCount && nVisCount<2; i++)
3138 if (pDoc->IsVisible(i))
3139 ++nVisCount;
3141 if (nVisCount <= 1)
3143 if (!bApi)
3144 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
3145 return false;
3149 pDoc->SetVisible( nTab, bVisible );
3150 if (bUndo)
3152 std::vector<SCTAB> undoTabs;
3153 undoTabs.push_back(nTab);
3154 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, undoTabs, bVisible ) );
3157 // Views updaten:
3158 if (!bVisible)
3159 rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
3161 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3162 rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
3163 aModificator.SetDocumentModified();
3165 return sal_True;
3168 sal_Bool ScDocFunc::SetLayoutRTL( SCTAB nTab, bool bRTL, sal_Bool /* bApi */ )
3170 ScDocument* pDoc = rDocShell.GetDocument();
3171 bool bUndo(pDoc->IsUndoEnabled());
3172 if ( pDoc->IsLayoutRTL( nTab ) == bRTL )
3173 return sal_True; // nothing to do - ok
3175 //! protection (sheet or document?)
3177 ScDocShellModificator aModificator( rDocShell );
3179 pDoc->SetLayoutRTL( nTab, bRTL );
3181 if (bUndo)
3183 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) );
3186 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
3187 aModificator.SetDocumentModified();
3189 SfxBindings* pBindings = rDocShell.GetViewBindings();
3190 if (pBindings)
3192 pBindings->Invalidate( FID_TAB_RTL );
3193 pBindings->Invalidate( SID_ATTR_SIZE );
3196 return sal_True;
3199 sal_Bool ScDocFunc::RenameTable( SCTAB nTab, const OUString& rName, sal_Bool bRecord, sal_Bool bApi )
3201 ScDocument* pDoc = rDocShell.GetDocument();
3202 if (bRecord && !pDoc->IsUndoEnabled())
3203 bRecord = false;
3204 if ( !pDoc->IsDocEditable() )
3206 if (!bApi)
3207 rDocShell.ErrorMessage(STR_PROTECTIONERR);
3208 return false;
3211 ScDocShellModificator aModificator( rDocShell );
3213 sal_Bool bSuccess = false;
3214 OUString sOldName;
3215 pDoc->GetName(nTab, sOldName);
3216 if (pDoc->RenameTab( nTab, rName ))
3218 if (bRecord)
3220 rDocShell.GetUndoManager()->AddUndoAction(
3221 new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName));
3223 rDocShell.PostPaintExtras();
3224 aModificator.SetDocumentModified();
3225 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3227 bSuccess = sal_True;
3229 return bSuccess;
3232 bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi )
3235 ScDocument* pDoc = rDocShell.GetDocument();
3236 if (bRecord && !pDoc->IsUndoEnabled())
3237 bRecord = false;
3238 if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) )
3240 if (!bApi)
3241 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is...
3242 return false;
3245 Color aOldTabBgColor;
3246 aOldTabBgColor = pDoc->GetTabBgColor(nTab);
3248 bool bSuccess = false;
3249 pDoc->SetTabBgColor(nTab, rColor);
3250 if ( pDoc->GetTabBgColor(nTab) == rColor)
3251 bSuccess = true;
3252 if (bSuccess)
3254 if (bRecord)
3256 rDocShell.GetUndoManager()->AddUndoAction(
3257 new ScUndoTabColor( &rDocShell, nTab, aOldTabBgColor, rColor));
3259 rDocShell.PostPaintExtras();
3260 ScDocShellModificator aModificator( rDocShell );
3261 aModificator.SetDocumentModified();
3262 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3264 bSuccess = true;
3266 return bSuccess;
3269 bool ScDocFunc::SetTabBgColor(
3270 ScUndoTabColorInfo::List& rUndoTabColorList, bool bRecord, bool bApi )
3272 ScDocument* pDoc = rDocShell.GetDocument();
3273 if (bRecord && !pDoc->IsUndoEnabled())
3274 bRecord = false;
3276 if ( !pDoc->IsDocEditable() )
3278 if (!bApi)
3279 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3280 return false;
3283 sal_uInt16 nTab;
3284 Color aNewTabBgColor;
3285 bool bSuccess = true;
3286 size_t nTabProtectCount = 0;
3287 size_t nTabListCount = rUndoTabColorList.size();
3288 for ( size_t i = 0; i < nTabListCount; ++i )
3290 ScUndoTabColorInfo& rInfo = rUndoTabColorList[i];
3291 nTab = rInfo.mnTabId;
3292 if ( !pDoc->IsTabProtected(nTab) )
3294 aNewTabBgColor = rInfo.maNewTabBgColor;
3295 rInfo.maOldTabBgColor = pDoc->GetTabBgColor(nTab);
3296 pDoc->SetTabBgColor(nTab, aNewTabBgColor);
3297 if ( pDoc->GetTabBgColor(nTab) != aNewTabBgColor)
3299 bSuccess = false;
3300 break;
3303 else
3305 nTabProtectCount++;
3309 if ( nTabProtectCount == nTabListCount )
3311 if (!bApi)
3312 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3313 return false;
3316 if (bSuccess)
3318 if (bRecord)
3320 rDocShell.GetUndoManager()->AddUndoAction(
3321 new ScUndoTabColor( &rDocShell, rUndoTabColorList));
3323 rDocShell.PostPaintExtras();
3324 ScDocShellModificator aModificator( rDocShell );
3325 aModificator.SetDocumentModified();
3327 return bSuccess;
3330 //------------------------------------------------------------------------
3332 //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
3333 //! Probleme:
3334 //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
3335 //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
3337 static sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, sal_Bool bFormula )
3339 ScSizeDeviceProvider aProv(&rDocShell);
3340 OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode
3341 double nPPTX = aProv.GetPPTX();
3342 double nPPTY = aProv.GetPPTY();
3344 ScDocument* pDoc = rDocShell.GetDocument();
3345 Fraction aOne(1,1);
3346 sal_uInt16 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
3347 bFormula, NULL );
3349 return nTwips;
3352 sal_Bool ScDocFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab,
3353 ScSizeMode eMode, sal_uInt16 nSizeTwips,
3354 sal_Bool bRecord, sal_Bool bApi )
3356 ScDocShellModificator aModificator( rDocShell );
3358 if (!nRangeCnt)
3359 return sal_True;
3361 ScDocument* pDoc = rDocShell.GetDocument();
3362 if ( bRecord && !pDoc->IsUndoEnabled() )
3363 bRecord = false;
3365 // import into read-only document is possible
3366 if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
3368 if (!bApi)
3369 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
3370 return false;
3373 sal_Bool bSuccess = false;
3374 SCCOLROW nStart = pRanges[0];
3375 SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
3377 sal_Bool bFormula = false;
3378 if ( eMode == SC_SIZE_OPTIMAL )
3380 //! Option "Formeln anzeigen" - woher nehmen?
3383 ScDocument* pUndoDoc = NULL;
3384 ScOutlineTable* pUndoTab = NULL;
3385 SCCOLROW* pUndoRanges = NULL;
3387 if ( bRecord )
3389 pDoc->BeginDrawUndo(); // Drawing Updates
3391 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3392 if (bWidth)
3394 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, false );
3395 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, false, pUndoDoc );
3397 else
3399 pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
3400 pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, false, pUndoDoc );
3403 pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
3404 memcpy( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
3406 ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
3407 if (pTable)
3408 pUndoTab = new ScOutlineTable( *pTable );
3411 sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
3412 sal_Bool bOutline = false;
3414 for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
3416 SCCOLROW nStartNo = *(pRanges++);
3417 SCCOLROW nEndNo = *(pRanges++);
3419 if ( !bWidth ) // Hoehen immer blockweise
3421 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3423 sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL );
3424 if (!bAll)
3426 // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
3427 // dann SetOptimalHeight mit bShrink = FALSE
3428 for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
3430 sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab);
3431 SCROW nLastRow = -1;
3432 bool bHidden = pDoc->RowHidden(nRow, nTab, NULL, &nLastRow);
3433 if ( !bHidden && ( nOld & CR_MANUALSIZE ) )
3434 pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
3438 ScSizeDeviceProvider aProv( &rDocShell );
3439 Fraction aOne(1,1);
3440 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
3441 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll );
3443 if (bAll)
3444 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
3446 // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt
3447 // (an bei Extra-Height, sonst aus).
3449 else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
3451 if (nSizeTwips)
3453 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
3454 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True ); // height was set manually
3456 if ( eMode != SC_SIZE_ORIGINAL )
3457 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
3459 else if ( eMode==SC_SIZE_SHOW )
3461 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
3464 else // Spaltenbreiten
3466 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
3468 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) )
3470 sal_uInt16 nThisSize = nSizeTwips;
3472 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3473 nThisSize = nSizeTwips +
3474 lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
3475 if ( nThisSize )
3476 pDoc->SetColWidth( nCol, nTab, nThisSize );
3478 if ( eMode != SC_SIZE_ORIGINAL )
3479 pDoc->ShowCol( nCol, nTab, bShow );
3484 // adjust outlines
3486 if ( eMode != SC_SIZE_ORIGINAL )
3488 if (bWidth)
3489 bOutline = bOutline || pDoc->UpdateOutlineCol(
3490 static_cast<SCCOL>(nStartNo),
3491 static_cast<SCCOL>(nEndNo), nTab, bShow );
3492 else
3493 bOutline = bOutline || pDoc->UpdateOutlineRow(
3494 static_cast<SCROW>(nStartNo),
3495 static_cast<SCROW>(nEndNo), nTab, bShow );
3498 pDoc->SetDrawPageSize(nTab);
3500 if (!bOutline)
3501 DELETEZ(pUndoTab);
3503 if (bRecord)
3505 ScMarkData aMark;
3506 aMark.SelectOneTable( nTab );
3507 rDocShell.GetUndoManager()->AddUndoAction(
3508 new ScUndoWidthOrHeight( &rDocShell, aMark,
3509 nStart, nTab, nEnd, nTab,
3510 pUndoDoc, nRangeCnt, pUndoRanges,
3511 pUndoTab, eMode, nSizeTwips, bWidth ) );
3514 pDoc->UpdatePageBreaks( nTab );
3516 rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
3517 aModificator.SetDocumentModified();
3519 return bSuccess;
3523 sal_Bool ScDocFunc::InsertPageBreak( sal_Bool bColumn, const ScAddress& rPos,
3524 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
3526 ScDocShellModificator aModificator( rDocShell );
3528 ScDocument* pDoc = rDocShell.GetDocument();
3529 if (bRecord && !pDoc->IsUndoEnabled())
3530 bRecord = false;
3531 SCTAB nTab = rPos.Tab();
3532 SfxBindings* pBindings = rDocShell.GetViewBindings();
3534 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3535 static_cast<SCCOLROW>(rPos.Row());
3536 if (nPos == 0)
3537 return false; // erste Spalte / Zeile
3539 ScBreakType nBreak = bColumn ?
3540 pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) :
3541 pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3542 if (nBreak & BREAK_MANUAL)
3543 return true;
3545 if (bRecord)
3546 rDocShell.GetUndoManager()->AddUndoAction(
3547 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_True ) );
3549 if (bColumn)
3550 pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3551 else
3552 pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3554 pDoc->InvalidatePageBreaks(nTab);
3555 pDoc->UpdatePageBreaks( nTab );
3557 if (pDoc->IsStreamValid(nTab))
3558 pDoc->SetStreamValid(nTab, false);
3560 if (bColumn)
3562 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3563 if (pBindings)
3565 pBindings->Invalidate( FID_INS_COLBRK );
3566 pBindings->Invalidate( FID_DEL_COLBRK );
3569 else
3571 rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3572 if (pBindings)
3574 pBindings->Invalidate( FID_INS_ROWBRK );
3575 pBindings->Invalidate( FID_DEL_ROWBRK );
3578 if (pBindings)
3579 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3581 if (bSetModified)
3582 aModificator.SetDocumentModified();
3584 return sal_True;
3587 sal_Bool ScDocFunc::RemovePageBreak( sal_Bool bColumn, const ScAddress& rPos,
3588 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
3590 ScDocShellModificator aModificator( rDocShell );
3592 ScDocument* pDoc = rDocShell.GetDocument();
3593 if (bRecord && !pDoc->IsUndoEnabled())
3594 bRecord = false;
3595 SCTAB nTab = rPos.Tab();
3596 SfxBindings* pBindings = rDocShell.GetViewBindings();
3598 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3599 static_cast<SCCOLROW>(rPos.Row());
3601 ScBreakType nBreak;
3602 if (bColumn)
3603 nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab);
3604 else
3605 nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3606 if ((nBreak & BREAK_MANUAL) == 0)
3607 // There is no manual break.
3608 return false;
3610 if (bRecord)
3611 rDocShell.GetUndoManager()->AddUndoAction(
3612 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, false ) );
3614 if (bColumn)
3615 pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3616 else
3617 pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3619 pDoc->UpdatePageBreaks( nTab );
3621 if (pDoc->IsStreamValid(nTab))
3622 pDoc->SetStreamValid(nTab, false);
3624 if (bColumn)
3626 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3627 if (pBindings)
3629 pBindings->Invalidate( FID_INS_COLBRK );
3630 pBindings->Invalidate( FID_DEL_COLBRK );
3633 else
3635 rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3636 if (pBindings)
3638 pBindings->Invalidate( FID_INS_ROWBRK );
3639 pBindings->Invalidate( FID_DEL_ROWBRK );
3642 if (pBindings)
3643 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3645 if (bSetModified)
3646 aModificator.SetDocumentModified();
3648 return sal_True;
3651 //------------------------------------------------------------------------
3653 void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
3655 ScDocument* pDoc = rDocShell.GetDocument();
3657 pDoc->SetTabProtection(nTab, &rProtect);
3658 if (pDoc->IsUndoEnabled())
3660 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3661 OSL_ENSURE(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3662 if (pProtect)
3664 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3665 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3666 SAL_WNODEPRECATED_DECLARATIONS_POP
3667 p->setProtected(true); // just in case ...
3668 rDocShell.GetUndoManager()->AddUndoAction(
3669 new ScUndoTabProtect(&rDocShell, nTab, p) );
3671 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3675 rDocShell.PostPaintGridAll();
3676 ScDocShellModificator aModificator(rDocShell);
3677 aModificator.SetDocumentModified();
3680 sal_Bool ScDocFunc::Protect( SCTAB nTab, const OUString& rPassword, sal_Bool /*bApi*/ )
3682 ScDocument* pDoc = rDocShell.GetDocument();
3683 if (nTab == TABLEID_DOC)
3685 // document protection
3686 ScDocProtection aProtection;
3687 aProtection.setProtected(true);
3688 aProtection.setPassword(rPassword);
3689 pDoc->SetDocProtection(&aProtection);
3690 if (pDoc->IsUndoEnabled())
3692 ScDocProtection* pProtect = pDoc->GetDocProtection();
3693 OSL_ENSURE(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
3694 if (pProtect)
3696 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3697 ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
3698 SAL_WNODEPRECATED_DECLARATIONS_POP
3699 p->setProtected(true); // just in case ...
3700 rDocShell.GetUndoManager()->AddUndoAction(
3701 new ScUndoDocProtect(&rDocShell, p) );
3702 // ownership of auto_ptr is transferred to ScUndoDocProtect.
3706 else
3708 // sheet protection
3710 ScTableProtection aProtection;
3711 aProtection.setProtected(true);
3712 aProtection.setPassword(rPassword);
3713 pDoc->SetTabProtection(nTab, &aProtection);
3714 if (pDoc->IsUndoEnabled())
3716 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3717 OSL_ENSURE(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3718 if (pProtect)
3720 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3721 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3722 SAL_WNODEPRECATED_DECLARATIONS_POP
3723 p->setProtected(true); // just in case ...
3724 rDocShell.GetUndoManager()->AddUndoAction(
3725 new ScUndoTabProtect(&rDocShell, nTab, p) );
3726 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3731 rDocShell.PostPaintGridAll();
3732 ScDocShellModificator aModificator( rDocShell );
3733 aModificator.SetDocumentModified();
3735 return true;
3738 sal_Bool ScDocFunc::Unprotect( SCTAB nTab, const OUString& rPassword, sal_Bool bApi )
3740 ScDocument* pDoc = rDocShell.GetDocument();
3742 if (nTab == TABLEID_DOC)
3744 // document protection
3746 ScDocProtection* pDocProtect = pDoc->GetDocProtection();
3747 if (!pDocProtect || !pDocProtect->isProtected())
3748 // already unprotected (should not happen)!
3749 return true;
3751 // save the protection state before unprotect (for undo).
3752 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3753 ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
3754 SAL_WNODEPRECATED_DECLARATIONS_POP
3756 if (!pDocProtect->verifyPassword(rPassword))
3758 if (!bApi)
3760 InfoBox aBox( rDocShell.GetActiveDialogParent(), OUString( ScResId( SCSTR_WRONGPASSWORD ) ) );
3761 aBox.Execute();
3763 return false;
3766 pDoc->SetDocProtection(NULL);
3767 if (pDoc->IsUndoEnabled())
3769 pProtectCopy->setProtected(false);
3770 rDocShell.GetUndoManager()->AddUndoAction(
3771 new ScUndoDocProtect(&rDocShell, pProtectCopy) );
3772 // ownership of auto_ptr now transferred to ScUndoDocProtect.
3775 else
3777 // sheet protection
3779 ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
3780 if (!pTabProtect || !pTabProtect->isProtected())
3781 // already unprotected (should not happen)!
3782 return true;
3784 // save the protection state before unprotect (for undo).
3785 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3786 ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
3787 SAL_WNODEPRECATED_DECLARATIONS_POP
3788 if (!pTabProtect->verifyPassword(rPassword))
3790 if (!bApi)
3792 InfoBox aBox( rDocShell.GetActiveDialogParent(), OUString( ScResId( SCSTR_WRONGPASSWORD ) ) );
3793 aBox.Execute();
3795 return false;
3798 pDoc->SetTabProtection(nTab, NULL);
3799 if (pDoc->IsUndoEnabled())
3801 pProtectCopy->setProtected(false);
3802 rDocShell.GetUndoManager()->AddUndoAction(
3803 new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
3804 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3808 rDocShell.PostPaintGridAll();
3809 ScDocShellModificator aModificator( rDocShell );
3810 aModificator.SetDocumentModified();
3812 return true;
3815 //------------------------------------------------------------------------
3817 sal_Bool ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, sal_Bool bApi )
3819 ScDocShellModificator aModificator( rDocShell );
3821 ScDocument* pDoc = rDocShell.GetDocument();
3822 bool bUndo (pDoc->IsUndoEnabled());
3823 ScEditableTester aTester( pDoc, rMark );
3824 if (!aTester.IsEditable())
3826 if (!bApi)
3827 rDocShell.ErrorMessage(aTester.GetMessageId());
3828 return false;
3831 // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
3832 // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
3833 // here.
3835 ScRange aMarkRange;
3836 ScMarkData aMultiMark = rMark;
3837 aMultiMark.SetMarking(false); // for MarkToMulti
3838 aMultiMark.MarkToMulti();
3839 aMultiMark.GetMultiMarkArea( aMarkRange );
3841 if (bUndo)
3843 SCTAB nStartTab = aMarkRange.aStart.Tab();
3844 SCTAB nEndTab = aMarkRange.aEnd.Tab();
3846 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3847 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3848 pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&aMultiMark );
3850 rDocShell.GetUndoManager()->AddUndoAction(
3851 new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) );
3854 pDoc->ClearSelectionItems( pWhich, aMultiMark );
3856 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3857 aModificator.SetDocumentModified();
3859 //! Bindings-Invalidate etc.?
3861 return sal_True;
3864 sal_Bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, sal_Bool bIncrement, sal_Bool bApi )
3866 ScDocShellModificator aModificator( rDocShell );
3868 ScDocument* pDoc = rDocShell.GetDocument();
3869 bool bUndo(pDoc->IsUndoEnabled());
3870 ScEditableTester aTester( pDoc, rMark );
3871 if (!aTester.IsEditable())
3873 if (!bApi)
3874 rDocShell.ErrorMessage(aTester.GetMessageId());
3875 return false;
3878 ScRange aMarkRange;
3879 rMark.GetMultiMarkArea( aMarkRange );
3881 if (bUndo)
3883 SCTAB nStartTab = aMarkRange.aStart.Tab();
3884 SCTAB nTabCount = pDoc->GetTableCount();
3886 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3887 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
3888 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
3889 for (; itr != itrEnd && *itr < nTabCount; ++itr)
3890 if (*itr != nStartTab)
3891 pUndoDoc->AddUndoTab( *itr, *itr );
3893 ScRange aCopyRange = aMarkRange;
3894 aCopyRange.aStart.SetTab(0);
3895 aCopyRange.aEnd.SetTab(nTabCount-1);
3896 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&rMark );
3898 rDocShell.GetUndoManager()->AddUndoAction(
3899 new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) );
3902 pDoc->ChangeSelectionIndent( bIncrement, rMark );
3904 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3905 aModificator.SetDocumentModified();
3907 SfxBindings* pBindings = rDocShell.GetViewBindings();
3908 if (pBindings)
3910 pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links
3911 pBindings->Invalidate( SID_ALIGNRIGHT );
3912 pBindings->Invalidate( SID_ALIGNBLOCK );
3913 pBindings->Invalidate( SID_ALIGNCENTERHOR );
3914 pBindings->Invalidate( SID_ATTR_LRSPACE );
3915 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_LEFT );
3916 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT );
3917 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK );
3918 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_CENTER);
3919 // pseudo slots for Format menu
3920 pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT );
3921 pBindings->Invalidate( SID_ALIGN_ANY_LEFT );
3922 pBindings->Invalidate( SID_ALIGN_ANY_HCENTER );
3923 pBindings->Invalidate( SID_ALIGN_ANY_RIGHT );
3924 pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED );
3927 return sal_True;
3930 bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
3931 sal_uInt16 nFormatNo, bool bRecord, bool bApi )
3933 ScDocShellModificator aModificator( rDocShell );
3935 sal_Bool bSuccess = false;
3936 ScDocument* pDoc = rDocShell.GetDocument();
3937 SCCOL nStartCol = rRange.aStart.Col();
3938 SCROW nStartRow = rRange.aStart.Row();
3939 SCTAB nStartTab = rRange.aStart.Tab();
3940 SCCOL nEndCol = rRange.aEnd.Col();
3941 SCROW nEndRow = rRange.aEnd.Row();
3942 SCTAB nEndTab = rRange.aEnd.Tab();
3944 if (bRecord && !pDoc->IsUndoEnabled())
3945 bRecord = false;
3946 ScMarkData aMark;
3947 if (pTabMark)
3948 aMark = *pTabMark;
3949 else
3951 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3952 aMark.SelectTable( nTab, sal_True );
3955 ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat();
3956 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3957 if ( nFormatNo < pAutoFormat->size() && aTester.IsEditable() )
3959 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3961 bool bSize = pAutoFormat->findByIndex(nFormatNo)->GetIncludeWidthHeight();
3963 SCTAB nTabCount = pDoc->GetTableCount();
3964 ScDocument* pUndoDoc = NULL;
3965 if ( bRecord )
3967 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3968 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize );
3969 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
3970 for (; itr != itrEnd && *itr < nTabCount; ++itr)
3971 if (*itr != nStartTab)
3972 pUndoDoc->AddUndoTab( *itr, *itr, bSize, bSize );
3974 ScRange aCopyRange = rRange;
3975 aCopyRange.aStart.SetTab(0);
3976 aCopyRange.aStart.SetTab(nTabCount-1);
3977 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, false, pUndoDoc, &aMark );
3978 if (bSize)
3980 pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1,
3981 IDF_NONE, false, pUndoDoc, &aMark );
3982 pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1,
3983 IDF_NONE, false, pUndoDoc, &aMark );
3985 pDoc->BeginDrawUndo();
3988 pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark );
3990 if (bSize)
3992 SCCOLROW nCols[2] = { nStartCol, nEndCol };
3993 SCCOLROW nRows[2] = { nStartRow, nEndRow };
3995 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
3996 for (; itr != itrEnd && *itr < nTabCount; ++itr)
3998 SetWidthOrHeight( sal_True, 1,nCols, *itr, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, false, sal_True);
3999 SetWidthOrHeight( false,1,nRows, *itr, SC_SIZE_VISOPT, 0, false, false);
4000 rDocShell.PostPaint( 0,0,*itr, MAXCOL,MAXROW,*itr,
4001 PAINT_GRID | PAINT_LEFT | PAINT_TOP );
4004 else
4006 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
4007 for (; itr != itrEnd && *itr < nTabCount; ++itr)
4009 sal_Bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, *itr,
4010 nEndCol, nEndRow, *itr), false );
4011 if (bAdj)
4012 rDocShell.PostPaint( 0,nStartRow,*itr, MAXCOL,MAXROW,*itr,
4013 PAINT_GRID | PAINT_LEFT );
4014 else
4015 rDocShell.PostPaint( nStartCol, nStartRow, *itr,
4016 nEndCol, nEndRow, *itr, PAINT_GRID );
4020 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4022 rDocShell.GetUndoManager()->AddUndoAction(
4023 new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) );
4026 aModificator.SetDocumentModified();
4028 else if (!bApi)
4029 rDocShell.ErrorMessage(aTester.GetMessageId());
4031 return bSuccess;
4034 //------------------------------------------------------------------------
4036 sal_Bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
4037 const ScTokenArray* pTokenArray, const OUString& rString, sal_Bool bApi, sal_Bool bEnglish,
4038 const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
4040 ScDocShellModificator aModificator( rDocShell );
4042 sal_Bool bSuccess = false;
4043 ScDocument* pDoc = rDocShell.GetDocument();
4044 SCCOL nStartCol = rRange.aStart.Col();
4045 SCROW nStartRow = rRange.aStart.Row();
4046 SCTAB nStartTab = rRange.aStart.Tab();
4047 SCCOL nEndCol = rRange.aEnd.Col();
4048 SCROW nEndRow = rRange.aEnd.Row();
4049 SCTAB nEndTab = rRange.aEnd.Tab();
4051 bool bUndo(pDoc->IsUndoEnabled());
4053 ScMarkData aMark;
4054 if (pTabMark)
4055 aMark = *pTabMark;
4056 else
4058 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4059 aMark.SelectTable( nTab, sal_True );
4062 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4063 if ( aTester.IsEditable() )
4065 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4067 ScDocument* pUndoDoc = NULL;
4069 if (bUndo)
4071 //! auch bei Undo selektierte Tabellen beruecksichtigen
4072 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4073 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
4074 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, false, pUndoDoc );
4077 // use TokenArray if given, string (and flags) otherwise
4078 if ( pTokenArray )
4080 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4081 aMark, EMPTY_OUSTRING, pTokenArray, eGrammar);
4083 else if ( pDoc->IsImportingXML() )
4085 ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
4086 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4087 aMark, EMPTY_OUSTRING, pCode, eGrammar);
4088 delete pCode;
4089 pDoc->IncXMLImportedFormulaCount( rString.getLength() );
4091 else if (bEnglish)
4093 ScCompiler aComp( pDoc, rRange.aStart);
4094 aComp.SetGrammar(eGrammar);
4095 ScTokenArray* pCode = aComp.CompileString( rString );
4096 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4097 aMark, EMPTY_OUSTRING, pCode, eGrammar);
4098 delete pCode;
4100 else
4101 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4102 aMark, rString, NULL, eGrammar);
4104 if (bUndo)
4106 //! auch bei Undo selektierte Tabellen beruecksichtigen
4107 rDocShell.GetUndoManager()->AddUndoAction(
4108 new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) );
4111 // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
4112 rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
4113 aModificator.SetDocumentModified();
4115 bSuccess = sal_True;
4117 else if (!bApi)
4118 rDocShell.ErrorMessage(aTester.GetMessageId());
4120 return bSuccess;
4123 //------------------------------------------------------------------------
4125 sal_Bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
4126 const ScTabOpParam& rParam, sal_Bool bRecord, sal_Bool bApi )
4128 ScDocShellModificator aModificator( rDocShell );
4130 sal_Bool bSuccess = false;
4131 ScDocument* pDoc = rDocShell.GetDocument();
4132 SCCOL nStartCol = rRange.aStart.Col();
4133 SCROW nStartRow = rRange.aStart.Row();
4134 SCTAB nStartTab = rRange.aStart.Tab();
4135 SCCOL nEndCol = rRange.aEnd.Col();
4136 SCROW nEndRow = rRange.aEnd.Row();
4137 SCTAB nEndTab = rRange.aEnd.Tab();
4139 if (bRecord && !pDoc->IsUndoEnabled())
4140 bRecord = false;
4142 ScMarkData aMark;
4143 if (pTabMark)
4144 aMark = *pTabMark;
4145 else
4147 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4148 aMark.SelectTable( nTab, sal_True );
4151 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4152 if ( aTester.IsEditable() )
4154 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4155 pDoc->SetDirty( rRange );
4156 if ( bRecord )
4158 //! auch bei Undo selektierte Tabellen beruecksichtigen
4159 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4160 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
4161 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, false, pUndoDoc );
4163 rDocShell.GetUndoManager()->AddUndoAction(
4164 new ScUndoTabOp( &rDocShell,
4165 nStartCol, nStartRow, nStartTab,
4166 nEndCol, nEndRow, nEndTab, pUndoDoc,
4167 rParam.aRefFormulaCell,
4168 rParam.aRefFormulaEnd,
4169 rParam.aRefRowCell,
4170 rParam.aRefColCell,
4171 rParam.meMode) );
4173 pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
4174 rDocShell.PostPaintGridAll();
4175 aModificator.SetDocumentModified();
4176 bSuccess = sal_True;
4178 else if (!bApi)
4179 rDocShell.ErrorMessage(aTester.GetMessageId());
4181 return bSuccess;
4184 //------------------------------------------------------------------------
4186 inline ScDirection DirFromFillDir( FillDir eDir )
4188 if (eDir==FILL_TO_BOTTOM)
4189 return DIR_BOTTOM;
4190 else if (eDir==FILL_TO_RIGHT)
4191 return DIR_RIGHT;
4192 else if (eDir==FILL_TO_TOP)
4193 return DIR_TOP;
4194 else // if (eDir==FILL_TO_LEFT)
4195 return DIR_LEFT;
4198 namespace {
4201 * Expand the fill range as necessary, to allow copying of adjacent cell(s)
4202 * even when those cells are not in the original range.
4204 void adjustFillRangeForAdjacentCopy(ScRange& rRange, FillDir eDir)
4206 switch (eDir)
4208 case FILL_TO_BOTTOM:
4210 if (rRange.aStart.Row() == 0)
4211 return;
4213 if (rRange.aStart.Row() != rRange.aEnd.Row())
4214 return;
4216 // Include the above row.
4217 ScAddress& s = rRange.aStart;
4218 s.SetRow(s.Row()-1);
4220 break;
4221 case FILL_TO_TOP:
4223 if (rRange.aStart.Row() == MAXROW)
4224 return;
4226 if (rRange.aStart.Row() != rRange.aEnd.Row())
4227 return;
4229 // Include the row below.
4230 ScAddress& e = rRange.aEnd;
4231 e.SetRow(e.Row()+1);
4233 break;
4234 case FILL_TO_LEFT:
4236 if (rRange.aStart.Col() == MAXCOL)
4237 return;
4239 if (rRange.aStart.Col() != rRange.aEnd.Col())
4240 return;
4242 // Include the column to the right.
4243 ScAddress& e = rRange.aEnd;
4244 e.SetCol(e.Col()+1);
4246 break;
4247 case FILL_TO_RIGHT:
4249 if (rRange.aStart.Col() == 0)
4250 return;
4252 if (rRange.aStart.Col() != rRange.aEnd.Col())
4253 return;
4255 // Include the column to the left.
4256 ScAddress& s = rRange.aStart;
4257 s.SetCol(s.Col()-1);
4259 break;
4260 default:
4267 bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
4268 FillDir eDir, bool bRecord, bool bApi )
4270 ScDocShellModificator aModificator( rDocShell );
4271 ScDocument* pDoc = rDocShell.GetDocument();
4273 bool bSuccess = false;
4274 ScRange aRange = rRange;
4275 adjustFillRangeForAdjacentCopy(aRange, eDir);
4277 SCCOL nStartCol = aRange.aStart.Col();
4278 SCROW nStartRow = aRange.aStart.Row();
4279 SCTAB nStartTab = aRange.aStart.Tab();
4280 SCCOL nEndCol = aRange.aEnd.Col();
4281 SCROW nEndRow = aRange.aEnd.Row();
4282 SCTAB nEndTab = aRange.aEnd.Tab();
4284 if (bRecord && !pDoc->IsUndoEnabled())
4285 bRecord = false;
4287 ScMarkData aMark;
4288 if (pTabMark)
4289 aMark = *pTabMark;
4290 else
4292 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4293 aMark.SelectTable( nTab, sal_True );
4296 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4297 if ( aTester.IsEditable() )
4299 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4301 ScRange aSourceArea = aRange;
4302 ScRange aDestArea = aRange;
4304 SCCOLROW nCount = 0;
4305 switch (eDir)
4307 case FILL_TO_BOTTOM:
4308 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4309 aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() );
4310 break;
4311 case FILL_TO_RIGHT:
4312 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4313 aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() );
4314 break;
4315 case FILL_TO_TOP:
4316 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4317 aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() );
4318 break;
4319 case FILL_TO_LEFT:
4320 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4321 aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() );
4322 break;
4325 ScDocument* pUndoDoc = NULL;
4326 if ( bRecord )
4328 SCTAB nTabCount = pDoc->GetTableCount();
4329 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4331 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4332 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4333 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
4334 for (; itr != itrEnd && *itr < nTabCount; ++itr)
4335 if (*itr != nDestStartTab)
4336 pUndoDoc->AddUndoTab( *itr, *itr );
4338 ScRange aCopyRange = aDestArea;
4339 aCopyRange.aStart.SetTab(0);
4340 aCopyRange.aEnd.SetTab(nTabCount-1);
4341 pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, false, pUndoDoc, &aMark );
4344 sal_uLong nProgCount;
4345 if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP)
4346 nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1;
4347 else
4348 nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1;
4349 nProgCount *= nCount;
4350 ScProgress aProgress( pDoc->GetDocumentShell(),
4351 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
4353 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4354 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress,
4355 aMark, nCount, eDir, FILL_SIMPLE );
4356 AdjustRowHeight(aRange);
4358 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4360 rDocShell.GetUndoManager()->AddUndoAction(
4361 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4362 eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307) );
4365 rDocShell.PostPaintGridAll();
4366 aModificator.SetDocumentModified();
4368 bSuccess = true;
4370 else if (!bApi)
4371 rDocShell.ErrorMessage(aTester.GetMessageId());
4373 return bSuccess;
4376 sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
4377 FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
4378 double fStart, double fStep, double fMax,
4379 sal_Bool bRecord, sal_Bool bApi )
4381 ScDocShellModificator aModificator( rDocShell );
4383 sal_Bool bSuccess = false;
4384 ScDocument* pDoc = rDocShell.GetDocument();
4385 SCCOL nStartCol = rRange.aStart.Col();
4386 SCROW nStartRow = rRange.aStart.Row();
4387 SCTAB nStartTab = rRange.aStart.Tab();
4388 SCCOL nEndCol = rRange.aEnd.Col();
4389 SCROW nEndRow = rRange.aEnd.Row();
4390 SCTAB nEndTab = rRange.aEnd.Tab();
4392 if (bRecord && !pDoc->IsUndoEnabled())
4393 bRecord = false;
4395 ScMarkData aMark;
4396 if (pTabMark)
4397 aMark = *pTabMark;
4398 else
4400 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4401 aMark.SelectTable( nTab, sal_True );
4404 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4405 if ( aTester.IsEditable() )
4407 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4409 ScRange aSourceArea = rRange;
4410 ScRange aDestArea = rRange;
4412 SCSIZE nCount = pDoc->GetEmptyLinesInBlock(
4413 aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(),
4414 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(),
4415 DirFromFillDir(eDir) );
4417 // mindestens eine Zeile/Spalte als Quellbereich behalten:
4418 SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ?
4419 static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) :
4420 static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 );
4421 if ( nCount >= nTotLines )
4422 nCount = nTotLines - 1;
4424 switch (eDir)
4426 case FILL_TO_BOTTOM:
4427 aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) );
4428 break;
4429 case FILL_TO_RIGHT:
4430 aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) );
4431 break;
4432 case FILL_TO_TOP:
4433 aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) );
4434 break;
4435 case FILL_TO_LEFT:
4436 aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) );
4437 break;
4440 ScDocument* pUndoDoc = NULL;
4441 if ( bRecord )
4443 SCTAB nTabCount = pDoc->GetTableCount();
4444 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4446 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4447 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4448 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
4449 for (; itr != itrEnd && *itr < nTabCount; ++itr)
4450 if (*itr != nDestStartTab)
4451 pUndoDoc->AddUndoTab( *itr, *itr );
4453 pDoc->CopyToDocument(
4454 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4455 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4456 IDF_AUTOFILL, false, pUndoDoc, &aMark );
4459 if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() &&
4460 aDestArea.aStart.Row() <= aDestArea.aEnd.Row())
4462 if ( fStart != MAXDOUBLE )
4464 SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col();
4465 SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row();
4466 SCTAB nTab = aDestArea.aStart.Tab();
4467 pDoc->SetValue( nValX, nValY, nTab, fStart );
4470 sal_uLong nProgCount;
4471 if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP)
4472 nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1;
4473 else
4474 nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1;
4475 nProgCount *= nCount;
4476 ScProgress aProgress( pDoc->GetDocumentShell(),
4477 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
4479 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4480 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress,
4481 aMark, nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4482 AdjustRowHeight(rRange);
4484 rDocShell.PostPaintGridAll();
4485 aModificator.SetDocumentModified();
4488 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4490 rDocShell.GetUndoManager()->AddUndoAction(
4491 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4492 eDir, eCmd, eDateCmd, fStart, fStep, fMax) );
4495 bSuccess = sal_True;
4497 else if (!bApi)
4498 rDocShell.ErrorMessage(aTester.GetMessageId());
4500 return bSuccess;
4503 sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
4504 FillDir eDir, sal_uLong nCount, sal_Bool bRecord, sal_Bool bApi )
4506 double fStep = 1.0;
4507 double fMax = MAXDOUBLE;
4508 return FillAuto( rRange, pTabMark, eDir, FILL_AUTO, FILL_DAY, nCount, fStep, fMax, bRecord, bApi );
4511 sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, sal_uLong nCount, double fStep, double fMax, sal_Bool bRecord, sal_Bool bApi )
4513 ScDocShellModificator aModificator( rDocShell );
4515 ScDocument* pDoc = rDocShell.GetDocument();
4516 SCCOL nStartCol = rRange.aStart.Col();
4517 SCROW nStartRow = rRange.aStart.Row();
4518 SCTAB nStartTab = rRange.aStart.Tab();
4519 SCCOL nEndCol = rRange.aEnd.Col();
4520 SCROW nEndRow = rRange.aEnd.Row();
4521 SCTAB nEndTab = rRange.aEnd.Tab();
4523 if (bRecord && !pDoc->IsUndoEnabled())
4524 bRecord = false;
4526 ScMarkData aMark;
4527 if (pTabMark)
4528 aMark = *pTabMark;
4529 else
4531 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4532 aMark.SelectTable( nTab, sal_True );
4535 ScRange aSourceArea = rRange;
4536 ScRange aDestArea = rRange;
4539 switch (eDir)
4541 case FILL_TO_BOTTOM:
4542 aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) );
4543 break;
4544 case FILL_TO_TOP:
4545 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() ))
4547 OSL_FAIL("FillAuto: Row < 0");
4548 nCount = aSourceArea.aStart.Row();
4550 aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) );
4551 break;
4552 case FILL_TO_RIGHT:
4553 aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) );
4554 break;
4555 case FILL_TO_LEFT:
4556 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() ))
4558 OSL_FAIL("FillAuto: Col < 0");
4559 nCount = aSourceArea.aStart.Col();
4561 aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) );
4562 break;
4563 default:
4564 OSL_FAIL("Falsche Richtung bei FillAuto");
4565 break;
4568 // Zellschutz testen
4569 //! Quellbereich darf geschuetzt sein !!!
4570 //! aber kein Matrixfragment enthalten !!!
4572 ScEditableTester aTester( pDoc, aDestArea );
4573 if ( !aTester.IsEditable() )
4575 if (!bApi)
4576 rDocShell.ErrorMessage(aTester.GetMessageId());
4577 return false;
4580 if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow,
4581 nEndCol, nEndRow, aMark ) )
4583 if (!bApi)
4584 rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR);
4585 return false;
4588 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4590 ScDocument* pUndoDoc = NULL;
4591 if ( bRecord )
4593 SCTAB nTabCount = pDoc->GetTableCount();
4594 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4596 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4597 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4598 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
4599 for (; itr != itrEnd && nTabCount; ++itr)
4600 if (*itr != nDestStartTab)
4601 pUndoDoc->AddUndoTab( *itr, *itr );
4603 // do not clone note captions in undo document
4604 pDoc->CopyToDocument(
4605 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4606 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4607 IDF_AUTOFILL, false, pUndoDoc, &aMark );
4610 sal_uLong nProgCount;
4611 if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP)
4612 nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1;
4613 else
4614 nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1;
4615 nProgCount *= nCount;
4616 ScProgress aProgress( pDoc->GetDocumentShell(),
4617 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
4619 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4620 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress,
4621 aMark, nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4623 AdjustRowHeight(aDestArea);
4625 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4627 rDocShell.GetUndoManager()->AddUndoAction(
4628 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4629 eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax) );
4632 rDocShell.PostPaintGridAll();
4633 aModificator.SetDocumentModified();
4635 rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren)
4636 return sal_True;
4639 //------------------------------------------------------------------------
4641 sal_Bool ScDocFunc::MergeCells( const ScCellMergeOption& rOption, sal_Bool bContents, sal_Bool bRecord, sal_Bool bApi )
4643 using ::std::set;
4645 ScDocShellModificator aModificator( rDocShell );
4647 SCCOL nStartCol = rOption.mnStartCol;
4648 SCROW nStartRow = rOption.mnStartRow;
4649 SCCOL nEndCol = rOption.mnEndCol;
4650 SCROW nEndRow = rOption.mnEndRow;
4651 if ((nStartCol == nEndCol && nStartRow == nEndRow) || rOption.maTabs.empty())
4653 // Nothing to do. Bail out quick.
4654 return true;
4657 ScDocument* pDoc = rDocShell.GetDocument();
4658 set<SCTAB>::const_iterator itrBeg = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
4659 SCTAB nTab1 = *itrBeg, nTab2 = *rOption.maTabs.rbegin();
4661 if (bRecord && !pDoc->IsUndoEnabled())
4662 bRecord = false;
4664 for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
4666 ScEditableTester aTester( pDoc, *itr, nStartCol, nStartRow, nEndCol, nEndRow );
4667 if (!aTester.IsEditable())
4669 if (!bApi)
4670 rDocShell.ErrorMessage(aTester.GetMessageId());
4671 return false;
4674 if ( pDoc->HasAttrib( nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr,
4675 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
4677 // "Zusammenfassen nicht verschachteln !"
4678 if (!bApi)
4679 rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
4680 return false;
4684 ScDocument* pUndoDoc = NULL;
4685 bool bNeedContentsUndo = false;
4686 for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
4688 SCTAB nTab = *itr;
4689 bool bNeedContents = bContents &&
4690 ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
4691 !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
4693 if (bRecord)
4695 // test if the range contains other notes which also implies that we need an undo document
4696 bool bHasNotes = false;
4697 for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
4698 for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
4699 bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->HasNote(aPos));
4701 if (!pUndoDoc)
4703 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4704 pUndoDoc->InitUndo(pDoc, nTab1, nTab2);
4706 // note captions are collected by drawing undo
4707 pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
4708 IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
4709 if( bHasNotes )
4710 pDoc->BeginDrawUndo();
4713 if (bNeedContents)
4714 pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4715 pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4717 if (rOption.mbCenter)
4719 pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
4720 pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) );
4723 if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
4724 rDocShell.PostPaint( nStartCol, nStartRow, nTab,
4725 nEndCol, nEndRow, nTab, PAINT_GRID );
4726 if (bNeedContents || rOption.mbCenter)
4728 ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab);
4729 pDoc->SetDirty(aRange);
4732 bNeedContentsUndo |= bNeedContents;
4735 if (pUndoDoc)
4737 SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : NULL;
4738 rDocShell.GetUndoManager()->AddUndoAction(
4739 new ScUndoMerge(&rDocShell, rOption, bNeedContentsUndo, pUndoDoc, pDrawUndo) );
4742 aModificator.SetDocumentModified();
4744 SfxBindings* pBindings = rDocShell.GetViewBindings();
4745 if (pBindings)
4747 pBindings->Invalidate( FID_MERGE_ON );
4748 pBindings->Invalidate( FID_MERGE_OFF );
4749 pBindings->Invalidate( FID_MERGE_TOGGLE );
4752 return sal_True;
4755 sal_Bool ScDocFunc::UnmergeCells( const ScRange& rRange, sal_Bool bRecord )
4757 ScCellMergeOption aOption(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
4758 SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
4759 for (SCTAB i = nTab1; i <= nTab2; ++i)
4760 aOption.maTabs.insert(i);
4762 return UnmergeCells(aOption, bRecord);
4765 bool ScDocFunc::UnmergeCells( const ScCellMergeOption& rOption, sal_Bool bRecord )
4767 using ::std::set;
4769 if (rOption.maTabs.empty())
4770 // Nothing to unmerge.
4771 return true;
4773 ScDocShellModificator aModificator( rDocShell );
4774 ScDocument* pDoc = rDocShell.GetDocument();
4776 if (bRecord && !pDoc->IsUndoEnabled())
4777 bRecord = false;
4779 ScDocument* pUndoDoc = NULL;
4780 for (set<SCTAB>::const_iterator itr = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
4781 itr != itrEnd; ++itr)
4783 SCTAB nTab = *itr;
4784 ScRange aRange = rOption.getSingleRange(nTab);
4785 if ( !pDoc->HasAttrib(aRange, HASATTR_MERGED) )
4786 continue;
4788 ScRange aExtended = aRange;
4789 pDoc->ExtendMerge(aExtended);
4790 ScRange aRefresh = aExtended;
4791 pDoc->ExtendOverlapped(aRefresh);
4793 if (bRecord)
4795 if (!pUndoDoc)
4797 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4798 pUndoDoc->InitUndo(pDoc, *rOption.maTabs.begin(), *rOption.maTabs.rbegin());
4800 pDoc->CopyToDocument(aExtended, IDF_ATTRIB, false, pUndoDoc);
4803 const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
4804 ScPatternAttr aPattern( pDoc->GetPool() );
4805 aPattern.GetItemSet().Put( rDefAttr );
4806 pDoc->ApplyPatternAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
4807 aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
4808 aPattern );
4810 pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
4811 aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
4812 SC_MF_HOR | SC_MF_VER );
4814 pDoc->ExtendMerge( aRefresh, sal_True );
4816 if ( !AdjustRowHeight( aExtended ) )
4817 rDocShell.PostPaint( aExtended, PAINT_GRID );
4820 if (bRecord)
4822 rDocShell.GetUndoManager()->AddUndoAction(
4823 new ScUndoRemoveMerge( &rDocShell, rOption, pUndoDoc ) );
4825 aModificator.SetDocumentModified();
4827 return sal_True;
4830 //------------------------------------------------------------------------
4832 bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, SCTAB nTab )
4834 return SetNewRangeNames( new ScRangeName(rNewRanges), true, nTab );
4837 bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, bool bModifyDoc, SCTAB nTab ) // takes ownership of pNewRanges
4839 ScDocShellModificator aModificator( rDocShell );
4841 OSL_ENSURE( pNewRanges, "pNewRanges is 0" );
4842 ScDocument* pDoc = rDocShell.GetDocument();
4843 bool bUndo(pDoc->IsUndoEnabled());
4845 if (bUndo)
4847 ScRangeName* pOld;
4848 if (nTab >=0)
4850 pOld = pDoc->GetRangeName(nTab);
4852 else
4854 pOld = pDoc->GetRangeName();
4856 ScRangeName* pUndoRanges = new ScRangeName(*pOld);
4857 ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges);
4858 rDocShell.GetUndoManager()->AddUndoAction(
4859 new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges, nTab ) );
4862 // #i55926# While loading XML, formula cells only have a single string token,
4863 // so CompileNameFormula would never find any name (index) tokens, and would
4864 // unnecessarily loop through all cells.
4865 sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
4867 if ( bCompile )
4868 pDoc->CompileNameFormula( sal_True ); // CreateFormulaString
4869 if (nTab >= 0)
4870 pDoc->SetRangeName( nTab, pNewRanges ); // takes ownership
4871 else
4872 pDoc->SetRangeName( pNewRanges ); // takes ownership
4873 if ( bCompile )
4874 pDoc->CompileNameFormula( false ); // CompileFormulaString
4876 if (bModifyDoc)
4878 aModificator.SetDocumentModified();
4879 SFX_APP()->Broadcast( SfxSimpleHint(SC_HINT_AREAS_CHANGED) );
4882 return true;
4885 void ScDocFunc::ModifyAllRangeNames( const boost::ptr_map<OUString, ScRangeName>& rRangeMap )
4887 ScDocShellModificator aModificator(rDocShell);
4888 ScDocument* pDoc = rDocShell.GetDocument();
4890 if (pDoc->IsUndoEnabled())
4892 std::map<OUString, ScRangeName*> aOldRangeMap;
4893 pDoc->GetRangeNameMap(aOldRangeMap);
4894 rDocShell.GetUndoManager()->AddUndoAction(
4895 new ScUndoAllRangeNames(&rDocShell, aOldRangeMap, rRangeMap));
4898 pDoc->CompileNameFormula(true);
4900 // set all range names
4901 pDoc->SetAllRangeNames(rRangeMap);
4903 pDoc->CompileNameFormula(false);
4905 aModificator.SetDocumentModified();
4906 SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
4909 //------------------------------------------------------------------------
4911 void ScDocFunc::CreateOneName( ScRangeName& rList,
4912 SCCOL nPosX, SCROW nPosY, SCTAB nTab,
4913 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
4914 sal_Bool& rCancel, sal_Bool bApi )
4916 if (rCancel)
4917 return;
4919 ScDocument* pDoc = rDocShell.GetDocument();
4920 if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
4922 OUString aName = pDoc->GetString(nPosX, nPosY, nTab);
4923 ScRangeData::MakeValidName(aName);
4924 if (!aName.isEmpty())
4926 OUString aContent(ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format(SCR_ABS_3D, pDoc));
4928 bool bInsert = false;
4929 ScRangeData* pOld = rList.findByUpperName(ScGlobal::pCharClass->uppercase(aName));
4930 if (pOld)
4932 OUString aOldStr;
4933 pOld->GetSymbol( aOldStr );
4934 if (aOldStr != aContent)
4936 if (bApi)
4937 bInsert = sal_True; // per API nicht nachfragen
4938 else
4940 OUString aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
4942 OUString aMessage = aTemplate.getToken( 0, '#' );
4943 aMessage += aName;
4944 aMessage += aTemplate.getToken( 1, '#' );
4946 short nResult = QueryBox( rDocShell.GetActiveDialogParent(),
4947 WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
4948 aMessage ).Execute();
4949 if ( nResult == RET_YES )
4951 rList.erase(*pOld);
4952 bInsert = true;
4954 else if ( nResult == RET_CANCEL )
4955 rCancel = sal_True;
4959 else
4960 bInsert = true;
4962 if (bInsert)
4964 ScRangeData* pData = new ScRangeData( pDoc, aName, aContent,
4965 ScAddress( nPosX, nPosY, nTab));
4966 if (!rList.insert(pData))
4968 OSL_FAIL("nanu?");
4975 sal_Bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, sal_Bool bApi, SCTAB aTab )
4977 if (!nFlags)
4978 return false; // war nix
4980 ScDocShellModificator aModificator( rDocShell );
4982 sal_Bool bDone = false;
4983 SCCOL nStartCol = rRange.aStart.Col();
4984 SCROW nStartRow = rRange.aStart.Row();
4985 SCCOL nEndCol = rRange.aEnd.Col();
4986 SCROW nEndRow = rRange.aEnd.Row();
4987 SCTAB nTab = rRange.aStart.Tab();
4988 OSL_ENSURE(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
4990 sal_Bool bValid = sal_True;
4991 if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
4992 if ( nStartRow == nEndRow )
4993 bValid = false;
4994 if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
4995 if ( nStartCol == nEndCol )
4996 bValid = false;
4998 if (bValid)
5000 ScDocument* pDoc = rDocShell.GetDocument();
5001 ScRangeName* pNames;
5002 if (aTab >=0)
5003 pNames = pDoc->GetRangeName(nTab);
5004 else
5005 pNames = pDoc->GetRangeName();
5007 if (!pNames)
5008 return false; // soll nicht sein
5009 ScRangeName aNewRanges( *pNames );
5011 sal_Bool bTop = ( ( nFlags & NAME_TOP ) != 0 );
5012 sal_Bool bLeft = ( ( nFlags & NAME_LEFT ) != 0 );
5013 sal_Bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
5014 sal_Bool bRight = ( ( nFlags & NAME_RIGHT ) != 0 );
5016 SCCOL nContX1 = nStartCol;
5017 SCROW nContY1 = nStartRow;
5018 SCCOL nContX2 = nEndCol;
5019 SCROW nContY2 = nEndRow;
5021 if ( bTop )
5022 ++nContY1;
5023 if ( bLeft )
5024 ++nContX1;
5025 if ( bBottom )
5026 --nContY2;
5027 if ( bRight )
5028 --nContX2;
5030 sal_Bool bCancel = false;
5031 SCCOL i;
5032 SCROW j;
5034 if ( bTop )
5035 for (i=nContX1; i<=nContX2; i++)
5036 CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
5037 if ( bLeft )
5038 for (j=nContY1; j<=nContY2; j++)
5039 CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
5040 if ( bBottom )
5041 for (i=nContX1; i<=nContX2; i++)
5042 CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
5043 if ( bRight )
5044 for (j=nContY1; j<=nContY2; j++)
5045 CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
5047 if ( bTop && bLeft )
5048 CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5049 if ( bTop && bRight )
5050 CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5051 if ( bBottom && bLeft )
5052 CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5053 if ( bBottom && bRight )
5054 CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5056 bDone = ModifyRangeNames( aNewRanges, aTab );
5058 aModificator.SetDocumentModified();
5059 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
5062 return bDone;
5065 //------------------------------------------------------------------------
5067 sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi )
5069 ScDocShellModificator aModificator( rDocShell );
5071 sal_Bool bDone = false;
5072 ScDocument* pDoc = rDocShell.GetDocument();
5073 const bool bRecord = pDoc->IsUndoEnabled();
5074 SCTAB nTab = rStartPos.Tab();
5075 ScDocument* pUndoDoc = NULL;
5077 //local names have higher priority than global names
5078 ScRangeName* pLocalList = pDoc->GetRangeName(nTab);
5079 sal_uInt16 nValidCount = 0;
5080 ScRangeName::iterator itrLocalBeg = pLocalList->begin(), itrLocalEnd = pLocalList->end();
5081 for (ScRangeName::iterator itr = itrLocalBeg; itr != itrLocalEnd; ++itr)
5083 const ScRangeData& r = *itr->second;
5084 if (!r.HasType(RT_DATABASE))
5085 ++nValidCount;
5087 ScRangeName* pList = pDoc->GetRangeName();
5088 ScRangeName::iterator itrBeg = pList->begin(), itrEnd = pList->end();
5089 for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
5091 const ScRangeData& r = *itr->second;
5092 if (!r.HasType(RT_DATABASE) && !pLocalList->findByUpperName(r.GetUpperName()))
5093 ++nValidCount;
5096 if (nValidCount)
5098 SCCOL nStartCol = rStartPos.Col();
5099 SCROW nStartRow = rStartPos.Row();
5100 SCCOL nEndCol = nStartCol + 1;
5101 SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1;
5103 ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
5104 if (aTester.IsEditable())
5106 if (bRecord)
5108 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
5109 pUndoDoc->InitUndo( pDoc, nTab, nTab );
5110 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
5111 IDF_ALL, false, pUndoDoc );
5113 pDoc->BeginDrawUndo(); // wegen Hoehenanpassung
5116 ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
5117 sal_uInt16 j = 0;
5118 for (ScRangeName::iterator itr = itrLocalBeg; itr != itrLocalEnd; ++itr)
5120 ScRangeData& r = *itr->second;
5121 if (!r.HasType(RT_DATABASE))
5122 ppSortArray[j++] = &r;
5124 for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
5126 ScRangeData& r = *itr->second;
5127 if (!r.HasType(RT_DATABASE) && !pLocalList->findByUpperName(itr->first))
5128 ppSortArray[j++] = &r;
5130 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
5131 &ScRangeData_QsortNameCompare );
5132 OUString aName;
5133 OUStringBuffer aContent;
5134 OUString aFormula;
5135 SCROW nOutRow = nStartRow;
5136 for (j=0; j<nValidCount; j++)
5138 ScRangeData* pData = ppSortArray[j];
5139 pData->GetName(aName);
5140 // relative Referenzen Excel-konform auf die linke Spalte anpassen:
5141 pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
5142 aFormula = "=" + aContent.toString();
5143 ScSetStringParam aParam;
5144 aParam.setTextInput();
5145 pDoc->SetString(ScAddress(nStartCol,nOutRow,nTab), aName, &aParam);
5146 pDoc->SetString(ScAddress(nEndCol,nOutRow,nTab), aFormula, &aParam);
5147 ++nOutRow;
5150 delete [] ppSortArray;
5152 if (bRecord)
5154 ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
5155 pRedoDoc->InitUndo( pDoc, nTab, nTab );
5156 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
5157 IDF_ALL, false, pRedoDoc );
5159 rDocShell.GetUndoManager()->AddUndoAction(
5160 new ScUndoListNames( &rDocShell,
5161 ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ),
5162 pUndoDoc, pRedoDoc ) );
5165 if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
5166 rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
5168 aModificator.SetDocumentModified();
5169 bDone = sal_True;
5171 else if (!bApi)
5172 rDocShell.ErrorMessage(aTester.GetMessageId());
5174 return bDone;
5177 //------------------------------------------------------------------------
5179 sal_Bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, sal_Bool bApi )
5181 ScDocument* pDoc = rDocShell.GetDocument();
5182 SCCOL nStartCol = rOldRange.aStart.Col();
5183 SCROW nStartRow = rOldRange.aStart.Row();
5184 SCTAB nTab = rOldRange.aStart.Tab();
5186 bool bUndo(pDoc->IsUndoEnabled());
5188 sal_Bool bRet = false;
5190 OUString aFormula;
5191 pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula );
5192 if ( aFormula.startsWith("{") && aFormula.endsWith("}") )
5194 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX );
5195 if (bUndo)
5196 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
5198 aFormula = aFormula.copy(1, aFormula.getLength()-2);
5200 ScMarkData aMark;
5201 aMark.SetMarkArea( rOldRange );
5202 aMark.SelectTable( nTab, sal_True );
5203 ScRange aNewRange( rOldRange.aStart, rNewEnd );
5205 if ( DeleteContents( aMark, IDF_CONTENTS, sal_True, bApi ) )
5207 // GRAM_PODF_A1 for API compatibility.
5208 bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, false, EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_PODF_A1 );
5209 if (!bRet)
5211 // versuchen, alten Zustand wiederherzustellen
5212 EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, false, EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_PODF_A1 );
5216 if (bUndo)
5217 rDocShell.GetUndoManager()->LeaveListAction();
5220 return bRet;
5223 //------------------------------------------------------------------------
5225 sal_Bool ScDocFunc::InsertAreaLink( const OUString& rFile, const OUString& rFilter,
5226 const OUString& rOptions, const OUString& rSource,
5227 const ScRange& rDestRange, sal_uLong nRefresh,
5228 sal_Bool bFitBlock, sal_Bool bApi )
5230 ScDocument* pDoc = rDocShell.GetDocument();
5231 sal_Bool bUndo (pDoc->IsUndoEnabled());
5233 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
5235 // #i52120# if other area links exist at the same start position,
5236 // remove them first (file format specifies only one link definition
5237 // for a cell)
5239 sal_uInt16 nLinkCount = pLinkManager->GetLinks().size();
5240 sal_uInt16 nRemoved = 0;
5241 sal_uInt16 nLinkPos = 0;
5242 while (nLinkPos<nLinkCount)
5244 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
5245 if ( pBase->ISA(ScAreaLink) &&
5246 static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart )
5248 if ( bUndo )
5250 if ( !nRemoved )
5252 // group all remove and the insert action
5253 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK );
5254 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
5257 ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
5258 rDocShell.GetUndoManager()->AddUndoAction(
5259 new ScUndoRemoveAreaLink( &rDocShell,
5260 pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
5261 pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) );
5263 pLinkManager->Remove( pBase );
5264 nLinkCount = pLinkManager->GetLinks().size();
5265 ++nRemoved;
5267 else
5268 ++nLinkPos;
5271 OUString aFilterName = rFilter;
5272 OUString aNewOptions = rOptions;
5273 if (aFilterName.isEmpty())
5274 ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, true, !bApi );
5276 // remove application prefix from filter name here, so the filter options
5277 // aren't reset when the filter name is changed in ScAreaLink::DataChanged
5278 ScDocumentLoader::RemoveAppPrefix( aFilterName );
5280 ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
5281 aNewOptions, rSource, rDestRange, nRefresh );
5282 OUString aTmp = aFilterName;
5283 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aTmp, &rSource );
5285 // Undo fuer den leeren Link
5287 if (bUndo)
5289 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell,
5290 rFile, aFilterName, aNewOptions,
5291 rSource, rDestRange, nRefresh ) );
5292 if ( nRemoved )
5293 rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
5296 // Update hat sein eigenes Undo
5297 if (pDoc->IsExecuteLinkEnabled())
5299 pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen
5300 pLink->Update(); // kein SetInCreate -> Update ausfuehren
5302 pLink->SetDoInsert(sal_True); // Default = sal_True
5304 SfxBindings* pBindings = rDocShell.GetViewBindings();
5305 if (pBindings)
5306 pBindings->Invalidate( SID_LINKS );
5308 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator
5310 return sal_True;
5313 namespace {
5315 void RemoveCondFormatAttributes(ScDocument* pDoc, const ScConditionalFormat* pFormat, SCTAB nTab)
5317 const ScRangeList& rRangeList = pFormat->GetRange();
5318 pDoc->RemoveCondFormatData( rRangeList, nTab, pFormat->GetKey() );
5321 void SetConditionalFormatAttributes(ScDocument* pDoc, const ScRangeList& rRanges, sal_uLong nIndex, SCTAB nTab)
5323 pDoc->AddCondFormatData( rRanges, nTab, nIndex );
5328 void ScDocFunc::ReplaceConditionalFormat( sal_uLong nOldFormat, ScConditionalFormat* pFormat, SCTAB nTab, const ScRangeList& rRanges )
5330 ScDocShellModificator aModificator(rDocShell);
5331 ScDocument* pDoc = rDocShell.GetDocument();
5332 if(pDoc->IsTabProtected(nTab))
5333 return;
5335 boost::scoped_ptr<ScRange> pRepaintRange;
5336 if(nOldFormat)
5338 ScConditionalFormat* pOldFormat = pDoc->GetCondFormList(nTab)->GetFormat(nOldFormat);
5339 if(pOldFormat)
5341 pRepaintRange.reset(new ScRange( pOldFormat->GetRange().Combine() ));
5342 RemoveCondFormatAttributes(pDoc, pOldFormat, nTab);
5345 pDoc->DeleteConditionalFormat(nOldFormat, nTab);
5346 pDoc->SetStreamValid(nTab, false);
5348 if(pFormat)
5350 if(pRepaintRange)
5351 pRepaintRange->ExtendTo(rRanges.Combine());
5352 else
5353 pRepaintRange.reset(new ScRange(rRanges.Combine()));
5355 sal_uLong nIndex = pDoc->AddCondFormat(pFormat, nTab);
5357 SetConditionalFormatAttributes(pDoc, rRanges, nIndex, nTab);
5358 pDoc->SetStreamValid(nTab, false);
5361 if(pRepaintRange)
5362 rDocShell.PostPaint(*pRepaintRange, PAINT_GRID);
5364 aModificator.SetDocumentModified();
5365 SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
5368 void ScDocFunc::SetConditionalFormatList( ScConditionalFormatList* pList, SCTAB nTab )
5370 ScDocShellModificator aModificator(rDocShell);
5371 ScDocument* pDoc = rDocShell.GetDocument();
5372 if(pDoc->IsTabProtected(nTab))
5373 return;
5375 // first remove all old entries
5376 ScConditionalFormatList* pOldList = pDoc->GetCondFormList(nTab);
5377 for(ScConditionalFormatList::const_iterator itr = pOldList->begin(), itrEnd = pOldList->end(); itr != itrEnd; ++itr)
5379 RemoveCondFormatAttributes(pDoc, &(*itr), nTab);
5382 // then set new entries
5383 for(ScConditionalFormatList::iterator itr = pList->begin(); itr != pList->end(); ++itr)
5385 sal_uLong nIndex = itr->GetKey();
5386 const ScRangeList& rRange = itr->GetRange();
5387 SetConditionalFormatAttributes(pDoc, rRange, nIndex, nTab);
5390 pDoc->SetCondFormList(pList, nTab);
5391 rDocShell.PostPaintGridAll();
5393 pDoc->SetStreamValid(nTab, false);
5394 aModificator.SetDocumentModified();
5395 SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
5398 void ScDocFunc::EnterListAction( sal_uInt16 nNameResId )
5400 OUString aUndo( ScGlobal::GetRscString( nNameResId ) );
5401 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
5404 void ScDocFunc::EndListAction()
5406 rDocShell.GetUndoManager()->LeaveListAction();
5409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */