Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / docshell / docfunc.cxx
bloba52c3bd7c05399e583b2ba938f3ab770286a4fba
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"
86 #include <rowheightcontext.hxx>
88 #include <memory>
89 #include <basic/basmgr.hxx>
90 #include <boost/scoped_array.hpp>
91 #include <boost/scoped_ptr.hpp>
92 #include <set>
93 #include <vector>
95 using namespace com::sun::star;
96 using ::com::sun::star::uno::Sequence;
97 using ::std::vector;
100 // STATIC DATA -----------------------------------------------------------
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 // Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
124 static void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
126 SCROW nRow = rRange.aStart.Row();
127 if ( nRow > 0 )
129 SCTAB nTab = rRange.aStart.Tab(); //! alle?
130 --nRow;
131 rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
135 bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, bool bPaint )
137 ScDocument* pDoc = rDocShell.GetDocument();
138 if ( pDoc->IsImportingXML() )
140 // for XML import, all row heights are updated together after importing
141 return false;
143 if ( !pDoc->IsAdjustHeightEnabled() )
145 return false;
148 SCTAB nTab = rRange.aStart.Tab();
149 SCROW nStartRow = rRange.aStart.Row();
150 SCROW nEndRow = rRange.aEnd.Row();
152 ScSizeDeviceProvider aProv( &rDocShell );
153 Fraction aOne(1,1);
155 sc::RowHeightContext aCxt(aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, aProv.GetDevice());
156 bool bChanged = pDoc->SetOptimalHeight(aCxt, nStartRow, nEndRow, nTab);
158 if ( bPaint && bChanged )
159 rDocShell.PostPaint(ScRange(0, nStartRow, nTab, MAXCOL, MAXROW, nTab),
160 PAINT_GRID | PAINT_LEFT);
162 return bChanged;
166 bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
168 ScDocShellModificator aModificator( rDocShell );
170 rDocShell.MakeDrawLayer();
171 ScDocument* pDoc = rDocShell.GetDocument();
172 bool bUndo (pDoc->IsUndoEnabled());
173 ScDrawLayer* pModel = pDoc->GetDrawLayer();
174 SCCOL nCol = rPos.Col();
175 SCROW nRow = rPos.Row();
176 SCTAB nTab = rPos.Tab();
178 if (bUndo)
179 pModel->BeginCalcUndo(false);
180 bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
181 SdrUndoGroup* pUndo = NULL;
182 if (bUndo)
183 pUndo = pModel->GetCalcUndo();
184 if (bDone)
186 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
187 pDoc->AddDetectiveOperation( aOperation );
188 if (bUndo)
190 rDocShell.GetUndoManager()->AddUndoAction(
191 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
193 aModificator.SetDocumentModified();
194 SfxBindings* pBindings = rDocShell.GetViewBindings();
195 if (pBindings)
196 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
198 else
199 delete pUndo;
201 return bDone;
204 bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
206 ScDocument* pDoc = rDocShell.GetDocument();
208 bool bUndo(pDoc->IsUndoEnabled());
209 ScDrawLayer* pModel = pDoc->GetDrawLayer();
210 if (!pModel)
211 return false;
213 ScDocShellModificator aModificator( rDocShell );
215 SCCOL nCol = rPos.Col();
216 SCROW nRow = rPos.Row();
217 SCTAB nTab = rPos.Tab();
219 if (bUndo)
220 pModel->BeginCalcUndo(false);
221 bool bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
222 SdrUndoGroup* pUndo = NULL;
223 if (bUndo)
224 pUndo = pModel->GetCalcUndo();
225 if (bDone)
227 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
228 pDoc->AddDetectiveOperation( aOperation );
229 if (bUndo)
231 rDocShell.GetUndoManager()->AddUndoAction(
232 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
234 aModificator.SetDocumentModified();
235 SfxBindings* pBindings = rDocShell.GetViewBindings();
236 if (pBindings)
237 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
239 else
240 delete pUndo;
242 return bDone;
245 bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
247 ScDocShellModificator aModificator( rDocShell );
249 rDocShell.MakeDrawLayer();
250 ScDocument* pDoc = rDocShell.GetDocument();
252 bool bUndo(pDoc->IsUndoEnabled());
253 ScDrawLayer* pModel = pDoc->GetDrawLayer();
254 SCCOL nCol = rPos.Col();
255 SCROW nRow = rPos.Row();
256 SCTAB nTab = rPos.Tab();
258 if (bUndo)
259 pModel->BeginCalcUndo(false);
260 bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow );
261 SdrUndoGroup* pUndo = NULL;
262 if (bUndo)
263 pUndo = pModel->GetCalcUndo();
264 if (bDone)
266 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
267 pDoc->AddDetectiveOperation( aOperation );
268 if (bUndo)
270 rDocShell.GetUndoManager()->AddUndoAction(
271 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
273 aModificator.SetDocumentModified();
274 SfxBindings* pBindings = rDocShell.GetViewBindings();
275 if (pBindings)
276 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
278 else
279 delete pUndo;
281 return bDone;
284 bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
286 ScDocument* pDoc = rDocShell.GetDocument();
288 bool bUndo (pDoc->IsUndoEnabled());
289 ScDrawLayer* pModel = pDoc->GetDrawLayer();
290 if (!pModel)
291 return false;
293 ScDocShellModificator aModificator( rDocShell );
295 SCCOL nCol = rPos.Col();
296 SCROW nRow = rPos.Row();
297 SCTAB nTab = rPos.Tab();
299 if (bUndo)
300 pModel->BeginCalcUndo(false);
301 bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
302 SdrUndoGroup* pUndo = NULL;
303 if (bUndo)
304 pUndo = pModel->GetCalcUndo();
305 if (bDone)
307 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
308 pDoc->AddDetectiveOperation( aOperation );
309 if (bUndo)
311 rDocShell.GetUndoManager()->AddUndoAction(
312 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
314 aModificator.SetDocumentModified();
315 SfxBindings* pBindings = rDocShell.GetViewBindings();
316 if (pBindings)
317 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
319 else
320 delete pUndo;
322 return bDone;
325 bool ScDocFunc::DetectiveAddError(const ScAddress& rPos)
327 ScDocShellModificator aModificator( rDocShell );
329 rDocShell.MakeDrawLayer();
330 ScDocument* pDoc = rDocShell.GetDocument();
332 bool bUndo (pDoc->IsUndoEnabled());
333 ScDrawLayer* pModel = pDoc->GetDrawLayer();
334 SCCOL nCol = rPos.Col();
335 SCROW nRow = rPos.Row();
336 SCTAB nTab = rPos.Tab();
338 if (bUndo)
339 pModel->BeginCalcUndo(false);
340 bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
341 SdrUndoGroup* pUndo = NULL;
342 if (bUndo)
343 pUndo = pModel->GetCalcUndo();
344 if (bDone)
346 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
347 pDoc->AddDetectiveOperation( aOperation );
348 if (bUndo)
350 rDocShell.GetUndoManager()->AddUndoAction(
351 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
353 aModificator.SetDocumentModified();
354 SfxBindings* pBindings = rDocShell.GetViewBindings();
355 if (pBindings)
356 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
358 else
359 delete pUndo;
361 return bDone;
364 bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
366 ScDocShellModificator aModificator( rDocShell );
368 rDocShell.MakeDrawLayer();
369 ScDocument* pDoc = rDocShell.GetDocument();
371 bool bUndo (pDoc->IsUndoEnabled());
372 ScDrawLayer* pModel = pDoc->GetDrawLayer();
374 Window* pWaitWin = rDocShell.GetActiveDialogParent();
375 if (pWaitWin)
376 pWaitWin->EnterWait();
377 if (bUndo)
378 pModel->BeginCalcUndo(false);
379 bool bOverflow;
380 bool bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
381 SdrUndoGroup* pUndo = NULL;
382 if (bUndo)
383 pUndo = pModel->GetCalcUndo();
384 if (pWaitWin)
385 pWaitWin->LeaveWait();
386 if (bDone)
388 if (pUndo && bUndo)
390 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) );
391 rDocShell.GetUndoManager()->AddUndoAction( pUndo );
393 aModificator.SetDocumentModified();
394 if ( bOverflow )
396 InfoBox( NULL,
397 ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
400 else
401 delete pUndo;
403 return bDone;
406 bool ScDocFunc::DetectiveDelAll(SCTAB nTab)
408 ScDocument* pDoc = rDocShell.GetDocument();
410 bool bUndo (pDoc->IsUndoEnabled());
411 ScDrawLayer* pModel = pDoc->GetDrawLayer();
412 if (!pModel)
413 return false;
415 ScDocShellModificator aModificator( rDocShell );
417 if (bUndo)
418 pModel->BeginCalcUndo(false);
419 bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
420 SdrUndoGroup* pUndo = NULL;
421 if (bUndo)
422 pUndo = pModel->GetCalcUndo();
423 if (bDone)
425 ScDetOpList* pOldList = pDoc->GetDetOpList();
426 ScDetOpList* pUndoList = NULL;
427 if (bUndo)
428 pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL;
430 pDoc->ClearDetectiveOperations();
432 if (bUndo)
434 rDocShell.GetUndoManager()->AddUndoAction(
435 new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) );
437 aModificator.SetDocumentModified();
438 SfxBindings* pBindings = rDocShell.GetViewBindings();
439 if (pBindings)
440 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
442 else
443 delete pUndo;
445 return bDone;
448 bool ScDocFunc::DetectiveRefresh( bool bAutomatic )
450 bool bDone = false;
451 ScDocument* pDoc = rDocShell.GetDocument();
453 bool bUndo (pDoc->IsUndoEnabled());
454 ScDetOpList* pList = pDoc->GetDetOpList();
455 if ( pList && pList->Count() )
457 rDocShell.MakeDrawLayer();
458 ScDrawLayer* pModel = pDoc->GetDrawLayer();
459 if (bUndo)
460 pModel->BeginCalcUndo(false);
462 // Loeschen auf allen Tabellen
464 SCTAB nTabCount = pDoc->GetTableCount();
465 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
466 ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles
468 // Wiederholen
470 size_t nCount = pList->Count();
471 for (size_t i=0; i < nCount; ++i)
473 const ScDetOpData* pData = pList->GetObject(i);
474 if (pData)
476 ScAddress aPos = pData->GetPos();
477 ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
478 SCCOL nCol = aPos.Col();
479 SCROW nRow = aPos.Row();
480 switch (pData->GetOperation())
482 case SCDETOP_ADDSUCC:
483 aFunc.ShowSucc( nCol, nRow );
484 break;
485 case SCDETOP_DELSUCC:
486 aFunc.DeleteSucc( nCol, nRow );
487 break;
488 case SCDETOP_ADDPRED:
489 aFunc.ShowPred( nCol, nRow );
490 break;
491 case SCDETOP_DELPRED:
492 aFunc.DeletePred( nCol, nRow );
493 break;
494 case SCDETOP_ADDERROR:
495 aFunc.ShowError( nCol, nRow );
496 break;
497 default:
498 OSL_FAIL("falsche Op bei DetectiveRefresh");
503 if (bUndo)
505 SdrUndoGroup* pUndo = pModel->GetCalcUndo();
506 if (pUndo)
508 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) );
509 // wenn automatisch, an letzte Aktion anhaengen
510 rDocShell.GetUndoManager()->AddUndoAction(
511 new ScUndoDraw( pUndo, &rDocShell ),
512 bAutomatic );
515 rDocShell.SetDrawModified();
516 bDone = true;
518 return bDone;
521 static void lcl_collectAllPredOrSuccRanges(
522 const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens, ScDocShell& rDocShell,
523 bool bPred)
525 ScDocument* pDoc = rDocShell.GetDocument();
526 vector<ScTokenRef> aRefTokens;
527 ScRangeList aSrcRanges(rSrcRanges);
528 if (aSrcRanges.empty())
529 return;
530 ScRange* p = aSrcRanges.front();
531 ScDetectiveFunc aDetFunc(pDoc, p->aStart.Tab());
532 ScRangeList aDestRanges;
533 for (size_t i = 0, n = aSrcRanges.size(); i < n; ++i)
535 p = aSrcRanges[i];
536 if (bPred)
538 aDetFunc.GetAllPreds(
539 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
541 else
543 aDetFunc.GetAllSuccs(
544 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
547 rRefTokens.swap(aRefTokens);
550 void ScDocFunc::DetectiveCollectAllPreds(const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens)
552 lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, true);
555 void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList& rSrcRanges, vector<ScTokenRef>& rRefTokens)
557 lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, false);
560 bool ScDocFunc::DeleteContents( const ScMarkData& rMark, sal_uInt16 nFlags,
561 bool bRecord, bool bApi )
563 ScDocShellModificator aModificator( rDocShell );
565 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
567 OSL_FAIL("ScDocFunc::DeleteContents ohne Markierung");
568 return false;
571 ScDocument* pDoc = rDocShell.GetDocument();
573 if (bRecord && !pDoc->IsUndoEnabled())
574 bRecord = false;
576 ScEditableTester aTester( pDoc, rMark );
577 if (!aTester.IsEditable())
579 if (!bApi)
580 rDocShell.ErrorMessage(aTester.GetMessageId());
581 return false;
584 ScRange aMarkRange;
586 ScMarkData aMultiMark = rMark;
587 aMultiMark.SetMarking(false); // fuer MarkToMulti
589 ScDocument* pUndoDoc = NULL;
590 bool bMulti = aMultiMark.IsMultiMarked();
591 aMultiMark.MarkToMulti();
592 aMultiMark.GetMultiMarkArea( aMarkRange );
593 ScRange aExtendedRange(aMarkRange);
594 if ( pDoc->ExtendMerge( aExtendedRange, true ) )
595 bMulti = false;
597 // keine Objekte auf geschuetzten Tabellen
598 bool bObjects = false;
599 if ( nFlags & IDF_OBJECTS )
601 bObjects = true;
602 SCTAB nTabCount = pDoc->GetTableCount();
603 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
604 for (; itr != itrEnd && *itr < nTabCount; ++itr)
605 if (pDoc->IsTabProtected(*itr))
606 bObjects = false;
609 sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted
610 if ( nFlags & IDF_ATTRIB )
611 rDocShell.UpdatePaintExt( nExtFlags, aMarkRange );
613 // Reihenfolge:
614 // 1) BeginDrawUndo
615 // 2) Objekte loeschen (DrawUndo wird gefuellt)
616 // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
617 // 4) Inhalte loeschen
619 bool bDrawUndo = bObjects || (nFlags & IDF_NOTE);
620 if (bRecord && bDrawUndo)
621 pDoc->BeginDrawUndo();
623 if (bObjects)
625 if (bMulti)
626 pDoc->DeleteObjectsInSelection( aMultiMark );
627 else
628 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
629 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
630 aMultiMark );
633 if ( bRecord )
635 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
636 pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() );
638 // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
639 // nur mit IDF_HARDATTR zu langsam ist:
640 sal_uInt16 nUndoDocFlags = nFlags;
641 if (nFlags & IDF_ATTRIB)
642 nUndoDocFlags |= IDF_ATTRIB;
643 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
644 nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
645 if (nFlags & IDF_NOTE)
646 nUndoDocFlags |= IDF_CONTENTS; // copy all cells with their notes
647 // note captions are handled in drawing undo
648 nUndoDocFlags |= IDF_NOCAPTIONS;
649 pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark );
652 //! HideAllCursors(); // falls Zusammenfassung aufgehoben wird
653 pDoc->DeleteSelection( nFlags, aMultiMark );
655 // add undo action after drawing undo is complete (objects and note captions)
656 if( bRecord )
657 rDocShell.GetUndoManager()->AddUndoAction(
658 new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange,
659 pUndoDoc, bMulti, nFlags, bDrawUndo ) );
661 if (!AdjustRowHeight( aExtendedRange ))
662 rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
663 else if (nExtFlags & SC_PF_LINES)
664 lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich
666 aModificator.SetDocumentModified();
668 return true;
671 bool ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
672 bool bRecord, bool bApi )
674 ScDocShellModificator aModificator( rDocShell );
676 ScDocument* pDoc = rDocShell.GetDocument();
677 if (bRecord && !pDoc->IsUndoEnabled())
678 bRecord = false;
680 ScEditableTester aTester( pDoc, rMark );
681 if (!aTester.IsEditable())
683 if (!bApi)
684 rDocShell.ErrorMessage(aTester.GetMessageId());
685 return false;
688 ScRange aMarkRange;
689 ScMarkData aMultiMark = rMark;
690 aMultiMark.SetMarking(false); // for MarkToMulti
691 aMultiMark.MarkToMulti();
692 aMultiMark.GetMultiMarkArea( aMarkRange );
694 if (bRecord)
696 SCTAB nStartTab = aMarkRange.aStart.Tab();
697 SCTAB nTabCount = pDoc->GetTableCount();
699 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
700 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
701 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
702 for (; itr != itrEnd && *itr < nTabCount; ++itr)
703 if (*itr != nStartTab)
704 pUndoDoc->AddUndoTab( *itr, *itr );
706 ScRange aCopyRange = aMarkRange;
707 aCopyRange.aStart.SetTab(0);
708 aCopyRange.aEnd.SetTab(nTabCount-1);
709 pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, true, pUndoDoc, &aMultiMark );
711 rDocShell.GetUndoManager()->AddUndoAction(
712 new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) );
715 pDoc->TransliterateText( aMultiMark, nType );
717 if (!AdjustRowHeight( aMarkRange ))
718 rDocShell.PostPaint( aMarkRange, PAINT_GRID );
720 aModificator.SetDocumentModified();
722 return true;
725 bool ScDocFunc::SetNormalString( bool& o_rbNumFmtSet, const ScAddress& rPos, const OUString& rText, bool bApi )
727 ScDocShellModificator aModificator( rDocShell );
728 ScDocument* pDoc = rDocShell.GetDocument();
730 bool bUndo(pDoc->IsUndoEnabled());
731 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
732 if (!aTester.IsEditable())
734 if (!bApi)
735 rDocShell.ErrorMessage(aTester.GetMessageId());
736 return false;
739 bool bEditDeleted = (pDoc->GetCellType(rPos) == CELLTYPE_EDIT);
740 ScUndoEnterData::ValuesType aOldValues;
742 if (bUndo)
744 ScUndoEnterData::Value aOldValue;
746 aOldValue.mnTab = rPos.Tab();
747 aOldValue.maCell.assign(*pDoc, rPos);
749 const SfxPoolItem* pItem;
750 const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() );
751 if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
752 ATTR_VALUE_FORMAT,false,&pItem) )
754 aOldValue.mbHasFormat = true;
755 aOldValue.mnFormat = ((const SfxUInt32Item*)pItem)->GetValue();
757 else
758 aOldValue.mbHasFormat = false;
760 aOldValues.push_back(aOldValue);
763 o_rbNumFmtSet = pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
765 if (bUndo)
767 // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
768 rDocShell.GetUndoManager()->AddUndoAction(
769 new ScUndoEnterData(&rDocShell, rPos, aOldValues, rText, NULL));
772 if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
773 AdjustRowHeight( ScRange(rPos) );
775 rDocShell.PostPaintCell( rPos );
776 aModificator.SetDocumentModified();
778 // notify input handler here the same way as in PutCell
779 if (bApi)
780 NotifyInputHandler( rPos );
782 return true;
785 bool ScDocFunc::SetValueCell( const ScAddress& rPos, double fVal, bool bInteraction )
787 ScDocShellModificator aModificator( rDocShell );
788 ScDocument* pDoc = rDocShell.GetDocument();
789 bool bUndo = pDoc->IsUndoEnabled();
791 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
793 ScCellValue aOldVal;
794 if (bUndo)
795 aOldVal.assign(*pDoc, rPos);
797 pDoc->SetValue(rPos, fVal);
799 if (bUndo)
801 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
802 ScCellValue aNewVal;
803 aNewVal.assign(*pDoc, rPos);
804 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
807 if (bHeight)
808 AdjustRowHeight(rPos);
810 rDocShell.PostPaintCell( rPos );
811 aModificator.SetDocumentModified();
813 // #103934#; notify editline and cell in edit mode
814 if (!bInteraction)
815 NotifyInputHandler( rPos );
817 return true;
820 bool ScDocFunc::SetValueCells( const ScAddress& rPos, const std::vector<double>& aVals, bool bInteraction )
822 // Check for invalid range.
823 SCROW nLastRow = rPos.Row() + aVals.size() - 1;
824 if (nLastRow > MAXROW)
825 // out of bound.
826 return false;
828 ScRange aRange(rPos);
829 aRange.aEnd.SetRow(nLastRow);
831 ScDocShellModificator aModificator(rDocShell);
832 ScDocument* pDoc = rDocShell.GetDocument();
834 if (pDoc->IsUndoEnabled())
836 sc::UndoSetCells* pUndoObj = new sc::UndoSetCells(&rDocShell, rPos);
837 pDoc->TransferCellValuesTo(rPos, aVals.size(), pUndoObj->GetOldValues());
838 pUndoObj->SetNewValues(aVals);
839 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
840 pUndoMgr->AddUndoAction(pUndoObj);
843 pDoc->SetValues(rPos, aVals);
845 rDocShell.PostPaint(aRange, PAINT_GRID);
846 aModificator.SetDocumentModified();
848 // #103934#; notify editline and cell in edit mode
849 if (!bInteraction)
850 NotifyInputHandler(rPos);
852 return true;
855 bool ScDocFunc::SetStringCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction )
857 ScDocShellModificator aModificator( rDocShell );
858 ScDocument* pDoc = rDocShell.GetDocument();
859 bool bUndo = pDoc->IsUndoEnabled();
861 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
863 ScCellValue aOldVal;
864 if (bUndo)
865 aOldVal.assign(*pDoc, rPos);
867 ScSetStringParam aParam;
868 aParam.setTextInput();
869 pDoc->SetString(rPos, rStr, &aParam);
871 if (bUndo)
873 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
874 ScCellValue aNewVal;
875 aNewVal.assign(*pDoc, rPos);
876 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
879 if (bHeight)
880 AdjustRowHeight(rPos);
882 rDocShell.PostPaintCell( rPos );
883 aModificator.SetDocumentModified();
885 // #103934#; notify editline and cell in edit mode
886 if (!bInteraction)
887 NotifyInputHandler( rPos );
889 return true;
892 bool ScDocFunc::SetEditCell( const ScAddress& rPos, const EditTextObject& rStr, bool bInteraction )
894 ScDocShellModificator aModificator( rDocShell );
895 ScDocument* pDoc = rDocShell.GetDocument();
896 bool bUndo = pDoc->IsUndoEnabled();
898 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
900 ScCellValue aOldVal;
901 if (bUndo)
902 aOldVal.assign(*pDoc, rPos);
904 pDoc->SetEditText(rPos, rStr.Clone());
906 if (bUndo)
908 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
909 ScCellValue aNewVal;
910 aNewVal.assign(*pDoc, rPos);
911 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
914 if (bHeight)
915 AdjustRowHeight(rPos);
917 rDocShell.PostPaintCell( rPos );
918 aModificator.SetDocumentModified();
920 // #103934#; notify editline and cell in edit mode
921 if (!bInteraction)
922 NotifyInputHandler( rPos );
924 return true;
927 bool ScDocFunc::SetStringOrEditCell( const ScAddress& rPos, const OUString& rStr, bool bInteraction )
929 ScDocument* pDoc = rDocShell.GetDocument();
931 if (ScStringUtil::isMultiline(rStr))
933 ScFieldEditEngine& rEngine = pDoc->GetEditEngine();
934 rEngine.SetText(rStr);
935 boost::scoped_ptr<EditTextObject> pEditText(rEngine.CreateTextObject());
936 return SetEditCell(rPos, *pEditText, bInteraction);
938 else
939 return SetStringCell(rPos, rStr, bInteraction);
942 bool ScDocFunc::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell, bool bInteraction )
944 SAL_WNODEPRECATED_DECLARATIONS_PUSH
945 std::auto_ptr<ScFormulaCell> xCell(pCell);
946 SAL_WNODEPRECATED_DECLARATIONS_POP
948 ScDocShellModificator aModificator( rDocShell );
949 ScDocument* pDoc = rDocShell.GetDocument();
950 bool bUndo = pDoc->IsUndoEnabled();
952 bool bHeight = pDoc->HasAttrib(rPos, HASATTR_NEEDHEIGHT);
954 ScCellValue aOldVal;
955 if (bUndo)
956 aOldVal.assign(*pDoc, rPos);
958 pCell = pDoc->SetFormulaCell(rPos, xCell.release());
960 // For performance reasons API calls may disable calculation while
961 // operating and recalculate once when done. If through user interaction
962 // and AutoCalc is disabled, calculate the formula (without its
963 // dependencies) once so the result matches the current document's content.
964 if (bInteraction && !pDoc->GetAutoCalc() && pCell)
966 // calculate just the cell once and set Dirty again
967 pCell->Interpret();
968 pCell->SetDirtyVar();
969 pDoc->PutInFormulaTree( pCell);
972 if (bUndo)
974 svl::IUndoManager* pUndoMgr = rDocShell.GetUndoManager();
975 ScCellValue aNewVal;
976 aNewVal.assign(*pDoc, rPos);
977 pUndoMgr->AddUndoAction(new ScUndoSetCell(&rDocShell, rPos, aOldVal, aNewVal));
980 if (bHeight)
981 AdjustRowHeight(rPos);
983 rDocShell.PostPaintCell( rPos );
984 aModificator.SetDocumentModified();
986 // #103934#; notify editline and cell in edit mode
987 if (!bInteraction)
988 NotifyInputHandler( rPos );
990 return true;
993 void ScDocFunc::NotifyInputHandler( const ScAddress& rPos )
995 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
996 if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell )
998 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
999 if ( pInputHdl && pInputHdl->GetCursorPos() == rPos )
1001 bool bIsEditMode(pInputHdl->IsEditMode());
1003 // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
1004 // (the cell shows the same like the InputWindow)
1005 if (bIsEditMode)
1006 pInputHdl->SetModified();
1007 pViewSh->UpdateInputHandler(false, !bIsEditMode);
1012 struct ScMyRememberItem
1014 sal_Int32 nIndex;
1015 SfxItemSet aItemSet;
1017 ScMyRememberItem(const SfxItemSet& rItemSet, sal_Int32 nTempIndex) :
1018 nIndex(nTempIndex), aItemSet(rItemSet) {}
1021 typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;
1023 bool ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, bool bApi )
1025 // PutData ruft PutCell oder SetNormalString
1027 bool bRet = false;
1028 ScDocument* pDoc = rDocShell.GetDocument();
1029 ScEditAttrTester aTester( &rEngine );
1030 bool bEditCell = aTester.NeedsObject();
1031 if ( bEditCell )
1033 // #i61702# With bLoseContent set, the content of rEngine isn't restored
1034 // (used in loading XML, where after the removeActionLock call the API object's
1035 // EditEngine isn't accessed again.
1036 bool bLoseContent = pDoc->IsImportingXML();
1038 bool bUpdateMode(rEngine.GetUpdateMode());
1039 if (bUpdateMode)
1040 rEngine.SetUpdateMode(false);
1042 ScMyRememberItemList aRememberItems;
1043 ScMyRememberItem* pRememberItem = NULL;
1045 // All paragraph attributes must be removed before calling CreateTextObject,
1046 // not only alignment, so the object doesn't contain the cell attributes as
1047 // paragraph attributes. Before remove the attributes store they in a list to
1048 // set they back to the EditEngine.
1049 sal_Int32 nCount = rEngine.GetParagraphCount();
1050 for (sal_Int32 i=0; i<nCount; i++)
1052 const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
1053 if ( rOld.Count() )
1055 if ( !bLoseContent )
1057 pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
1058 aRememberItems.push_back(pRememberItem);
1060 rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
1064 // A copy of pNewData will be stored in the cell.
1065 boost::scoped_ptr<EditTextObject> pNewData(rEngine.CreateTextObject());
1066 bRet = SetEditCell(rPos, *pNewData, !bApi);
1068 // Set the paragraph attributes back to the EditEngine.
1069 if (!aRememberItems.empty())
1071 ScMyRememberItemList::iterator aItr = aRememberItems.begin();
1072 while (aItr != aRememberItems.end())
1074 pRememberItem = *aItr;
1075 rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet);
1076 delete pRememberItem;
1077 aItr = aRememberItems.erase(aItr);
1081 // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
1082 if ( bUpdateMode && !bLoseContent )
1083 rEngine.SetUpdateMode(true);
1085 else
1087 OUString aText = rEngine.GetText();
1088 if (aText.isEmpty())
1090 bool bNumFmtSet = false;
1091 bRet = SetNormalString( bNumFmtSet, rPos, aText, bApi );
1093 else
1094 bRet = SetStringCell(rPos, aText, !bApi);
1097 if ( bRet && aTester.NeedsCellAttr() )
1099 const SfxItemSet& rEditAttr = aTester.GetAttribs();
1100 ScPatternAttr aPattern( pDoc->GetPool() );
1101 aPattern.GetFromEditItemSet( &rEditAttr );
1102 aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
1103 aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object
1104 if ( aPattern.GetItemSet().Count() > 0 )
1106 ScMarkData aMark;
1107 aMark.SelectTable( rPos.Tab(), true );
1108 aMark.SetMarkArea( ScRange( rPos ) );
1109 ApplyAttributes( aMark, aPattern, true, bApi );
1113 return bRet;
1117 static ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const OUString& rText, const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
1119 ScTokenArray* pCode = new ScTokenArray;
1120 pCode->AddStringXML( rText );
1121 if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (!rFormulaNmsp.isEmpty()) )
1122 pCode->AddStringXML( rFormulaNmsp );
1123 return pCode;
1126 bool ScDocFunc::SetCellText(
1127 const ScAddress& rPos, const OUString& rText, bool bInterpret, bool bEnglish, bool bApi,
1128 const formula::FormulaGrammar::Grammar eGrammar )
1130 bool bSet = false;
1131 if ( bInterpret )
1133 if ( bEnglish )
1135 ScDocument* pDoc = rDocShell.GetDocument();
1137 ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
1138 if (bApi)
1139 pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
1141 ScInputStringType aRes =
1142 ScStringUtil::parseInputString(*pDoc->GetFormatTable(), rText, LANGUAGE_ENGLISH_US);
1144 switch (aRes.meType)
1146 case ScInputStringType::Formula:
1147 bSet = SetFormulaCell(rPos, new ScFormulaCell(pDoc, rPos, aRes.maText, eGrammar), !bApi);
1148 break;
1149 case ScInputStringType::Number:
1150 bSet = SetValueCell(rPos, aRes.mfValue, !bApi);
1151 break;
1152 case ScInputStringType::Text:
1153 bSet = SetStringOrEditCell(rPos, aRes.maText, !bApi);
1154 break;
1155 default:
1159 // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
1161 else if (!rText.isEmpty())
1163 bSet = SetStringOrEditCell(rPos, rText, !bApi);
1166 if (!bSet)
1168 bool bNumFmtSet = false;
1169 bSet = SetNormalString( bNumFmtSet, rPos, rText, bApi );
1171 return bSet;
1174 bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
1176 ScDocument& rDoc = *rDocShell.GetDocument();
1177 ScPostIt* pNote = rDoc.GetNote( rPos );
1178 if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false;
1180 // move the caption to internal or hidden layer and create undo action
1181 pNote->ShowCaption( rPos, bShow );
1182 if( rDoc.IsUndoEnabled() )
1183 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) );
1185 if (rDoc.IsStreamValid(rPos.Tab()))
1186 rDoc.SetStreamValid(rPos.Tab(), false);
1188 rDocShell.SetDocumentModified();
1190 return true;
1193 bool ScDocFunc::SetNoteText( const ScAddress& rPos, const OUString& rText, bool bApi )
1195 ScDocShellModificator aModificator( rDocShell );
1197 ScDocument* pDoc = rDocShell.GetDocument();
1198 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1199 if (!aTester.IsEditable())
1201 if (!bApi)
1202 rDocShell.ErrorMessage(aTester.GetMessageId());
1203 return false;
1206 OUString aNewText = convertLineEnd(rText, GetSystemLineEnd()); //! ist das noetig ???
1208 if( ScPostIt* pNote = (!aNewText.isEmpty()) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote(rPos) )
1209 pNote->SetText( rPos, aNewText );
1211 //! Undo !!!
1213 if (pDoc->IsStreamValid(rPos.Tab()))
1214 pDoc->SetStreamValid(rPos.Tab(), false);
1216 rDocShell.PostPaintCell( rPos );
1217 aModificator.SetDocumentModified();
1219 return true;
1222 bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const OUString& rNoteText, const OUString* pAuthor, const OUString* pDate, bool bApi )
1224 bool bDone = false;
1226 ScDocShellModificator aModificator( rDocShell );
1227 ScDocument& rDoc = *rDocShell.GetDocument();
1228 ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1229 if (aTester.IsEditable())
1231 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1232 ::svl::IUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0;
1234 ScNoteData aOldData;
1235 ScPostIt* pOldNote = rDoc.ReleaseNote( rPos );
1236 if( pOldNote )
1238 // ensure existing caption object before draw undo tracking starts
1239 pOldNote->GetOrCreateCaption( rPos );
1240 // rescue note data for undo
1241 aOldData = pOldNote->GetNoteData();
1244 // collect drawing undo actions for deleting/inserting caption objects
1245 if( pUndoMgr )
1246 pDrawLayer->BeginCalcUndo(false);
1248 // delete the note (creates drawing undo action for the caption object)
1249 delete pOldNote;
1251 // create new note (creates drawing undo action for the new caption object)
1252 ScNoteData aNewData;
1253 if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) )
1255 if( pAuthor ) pNewNote->SetAuthor( *pAuthor );
1256 if( pDate ) pNewNote->SetDate( *pDate );
1257 // rescue note data for undo
1258 aNewData = pNewNote->GetNoteData();
1261 // create the undo action
1262 if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) )
1263 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
1265 // repaint cell (to make note marker visible)
1266 rDocShell.PostPaintCell( rPos );
1268 if (rDoc.IsStreamValid(rPos.Tab()))
1269 rDoc.SetStreamValid(rPos.Tab(), false);
1271 aModificator.SetDocumentModified();
1272 bDone = true;
1274 else if (!bApi)
1276 rDocShell.ErrorMessage(aTester.GetMessageId());
1279 return bDone;
1282 bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
1283 bool bRecord, bool bApi )
1285 ScDocument* pDoc = rDocShell.GetDocument();
1286 if ( bRecord && !pDoc->IsUndoEnabled() )
1287 bRecord = false;
1289 bool bImportingXML = pDoc->IsImportingXML();
1290 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1291 // #i62483# When loading XML, the check can be skipped altogether.
1292 bool bOnlyNotBecauseOfMatrix;
1293 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1294 && !bOnlyNotBecauseOfMatrix )
1296 if (!bApi)
1297 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1298 return false;
1301 ScDocShellModificator aModificator( rDocShell );
1303 //! Umrandung
1305 ScRange aMultiRange;
1306 bool bMulti = rMark.IsMultiMarked();
1307 if ( bMulti )
1308 rMark.GetMultiMarkArea( aMultiRange );
1309 else
1310 rMark.GetMarkArea( aMultiRange );
1312 if ( bRecord )
1314 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1315 pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() );
1316 pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1318 rDocShell.GetUndoManager()->AddUndoAction(
1319 new ScUndoSelectionAttr(
1320 &rDocShell, rMark,
1321 aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(),
1322 aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(),
1323 pUndoDoc, bMulti, &rPattern ) );
1326 // While loading XML it is not necessary to ask HasAttrib. It needs too much time.
1327 sal_uInt16 nExtFlags = 0;
1328 if ( !bImportingXML )
1329 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change
1330 pDoc->ApplySelectionPattern( rPattern, rMark );
1331 if ( !bImportingXML )
1332 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change
1334 if (!AdjustRowHeight( aMultiRange ))
1335 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1336 else if (nExtFlags & SC_PF_LINES)
1337 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
1339 aModificator.SetDocumentModified();
1341 return true;
1345 bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const OUString& rStyleName,
1346 bool bRecord, bool bApi )
1348 ScDocument* pDoc = rDocShell.GetDocument();
1349 if ( bRecord && !pDoc->IsUndoEnabled() )
1350 bRecord = false;
1352 bool bImportingXML = pDoc->IsImportingXML();
1353 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1354 // #i62483# When loading XML, the check can be skipped altogether.
1355 bool bOnlyNotBecauseOfMatrix;
1356 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1357 && !bOnlyNotBecauseOfMatrix )
1359 if (!bApi)
1360 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1361 return false;
1364 ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
1365 rStyleName, SFX_STYLE_FAMILY_PARA );
1366 if (!pStyleSheet)
1367 return false;
1369 ScDocShellModificator aModificator( rDocShell );
1371 ScRange aMultiRange;
1372 bool bMulti = rMark.IsMultiMarked();
1373 if ( bMulti )
1374 rMark.GetMultiMarkArea( aMultiRange );
1375 else
1376 rMark.GetMarkArea( aMultiRange );
1378 if ( bRecord )
1380 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1381 SCTAB nStartTab = aMultiRange.aStart.Tab();
1382 SCTAB nTabCount = pDoc->GetTableCount();
1383 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1384 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1385 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1386 if (*itr != nStartTab)
1387 pUndoDoc->AddUndoTab( *itr, *itr );
1389 ScRange aCopyRange = aMultiRange;
1390 aCopyRange.aStart.SetTab(0);
1391 aCopyRange.aEnd.SetTab(nTabCount-1);
1392 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1394 rDocShell.GetUndoManager()->AddUndoAction(
1395 new ScUndoSelectionStyle(
1396 &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) );
1400 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
1402 if (!AdjustRowHeight( aMultiRange ))
1403 rDocShell.PostPaint( aMultiRange, PAINT_GRID, 0 );
1405 aModificator.SetDocumentModified();
1407 return true;
1410 namespace {
1413 * Check if this insertion attempt would end up cutting one or more pivot
1414 * tables in half, which is not desirable.
1416 * @return true if this insertion can be done safely without shearing any
1417 * existing pivot tables, false otherwise.
1419 bool canInsertCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, InsCellCmd eCmd, const ScDocument* pDoc)
1421 if (!pDoc->HasPivotTable())
1422 // This document has no pivot tables.
1423 return true;
1425 const ScDPCollection* pDPs = pDoc->GetDPCollection();
1426 ScMarkData::const_iterator itBeg = rMarkData.begin(), itEnd = rMarkData.end();
1428 ScRange aRange(rRange); // local copy
1429 switch (eCmd)
1431 case INS_INSROWS:
1433 aRange.aStart.SetCol(0);
1434 aRange.aEnd.SetCol(MAXCOL);
1435 // Continue below.
1437 case INS_CELLSDOWN:
1439 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1441 if (pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), aRange.aStart.Row(), *it))
1442 // This column range cuts through at least one pivot table. Not good.
1443 return false;
1446 // Start row must be either at the top or above any pivot tables.
1447 if (aRange.aStart.Row() < 0)
1448 // I don't know how to handle this case.
1449 return false;
1451 if (aRange.aStart.Row() == 0)
1452 // First row is always allowed.
1453 return true;
1455 ScRange aTest(aRange);
1456 aTest.aStart.IncRow(-1); // Test one row up.
1457 aTest.aEnd.SetRow(aTest.aStart.Row());
1458 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1460 aTest.aStart.SetTab(*it);
1461 aTest.aEnd.SetTab(*it);
1462 if (pDPs->HasTable(aTest))
1463 return false;
1466 break;
1467 case INS_INSCOLS:
1469 aRange.aStart.SetRow(0);
1470 aRange.aEnd.SetRow(MAXROW);
1471 // Continue below.
1473 case INS_CELLSRIGHT:
1475 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1477 if (pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Row(), *it))
1478 // This column range cuts through at least one pivot table. Not good.
1479 return false;
1482 // Start row must be either at the top or above any pivot tables.
1483 if (aRange.aStart.Col() < 0)
1484 // I don't know how to handle this case.
1485 return false;
1487 if (aRange.aStart.Col() == 0)
1488 // First row is always allowed.
1489 return true;
1491 ScRange aTest(aRange);
1492 aTest.aStart.IncCol(-1); // Test one column to the left.
1493 aTest.aEnd.SetCol(aTest.aStart.Col());
1494 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1496 aTest.aStart.SetTab(*it);
1497 aTest.aEnd.SetTab(*it);
1498 if (pDPs->HasTable(aTest))
1499 return false;
1502 break;
1503 default:
1506 return true;
1510 * Check if this deletion attempt would end up cutting one or more pivot
1511 * tables in half, which is not desirable.
1513 * @return true if this deletion can be done safely without shearing any
1514 * existing pivot tables, false otherwise.
1516 bool canDeleteCellsByPivot(const ScRange& rRange, const ScMarkData& rMarkData, DelCellCmd eCmd, const ScDocument* pDoc)
1518 if (!pDoc->HasPivotTable())
1519 // This document has no pivot tables.
1520 return true;
1522 const ScDPCollection* pDPs = pDoc->GetDPCollection();
1523 ScMarkData::const_iterator itBeg = rMarkData.begin(), itEnd = rMarkData.end();
1525 ScRange aRange(rRange); // local copy
1527 switch (eCmd)
1529 case DEL_DELROWS:
1531 aRange.aStart.SetCol(0);
1532 aRange.aEnd.SetCol(MAXCOL);
1533 // Continue below.
1535 case DEL_CELLSUP:
1537 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1539 if (pDPs->IntersectsTableByColumns(aRange.aStart.Col(), aRange.aEnd.Col(), aRange.aStart.Row(), *it))
1540 // This column range cuts through at least one pivot table. Not good.
1541 return false;
1544 ScRange aTest(aRange);
1545 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1547 aTest.aStart.SetTab(*it);
1548 aTest.aEnd.SetTab(*it);
1549 if (pDPs->HasTable(aTest))
1550 return false;
1553 break;
1554 case DEL_DELCOLS:
1556 aRange.aStart.SetRow(0);
1557 aRange.aEnd.SetRow(MAXROW);
1558 // Continue below.
1560 case DEL_CELLSLEFT:
1562 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1564 if (pDPs->IntersectsTableByRows(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Row(), *it))
1565 // This column range cuts through at least one pivot table. Not good.
1566 return false;
1569 ScRange aTest(aRange);
1570 for (ScMarkData::const_iterator it = itBeg; it != itEnd; ++it)
1572 aTest.aStart.SetTab(*it);
1573 aTest.aEnd.SetTab(*it);
1574 if (pDPs->HasTable(aTest))
1575 return false;
1578 break;
1579 default:
1582 return true;
1587 bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
1588 bool bRecord, bool bApi, bool bPartOfPaste )
1590 ScDocShellModificator aModificator( rDocShell );
1592 SCCOL nStartCol = rRange.aStart.Col();
1593 SCROW nStartRow = rRange.aStart.Row();
1594 SCTAB nStartTab = rRange.aStart.Tab();
1595 SCCOL nEndCol = rRange.aEnd.Col();
1596 SCROW nEndRow = rRange.aEnd.Row();
1597 SCTAB nEndTab = rRange.aEnd.Tab();
1599 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1601 OSL_FAIL("invalid row in InsertCells");
1602 return false;
1605 ScDocument* pDoc = rDocShell.GetDocument();
1606 SCTAB nTabCount = pDoc->GetTableCount();
1607 SCCOL nPaintStartCol = nStartCol;
1608 SCROW nPaintStartRow = nStartRow;
1609 SCCOL nPaintEndCol = nEndCol;
1610 SCROW nPaintEndRow = nEndRow;
1611 sal_uInt16 nPaintFlags = PAINT_GRID;
1612 bool bSuccess;
1613 SCTAB i;
1615 ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position
1616 SCCOL nCursorCol = 0;
1617 SCROW nCursorRow = 0;
1618 if( pViewSh )
1620 nCursorCol = pViewSh->GetViewData()->GetCurX();
1621 nCursorRow = pViewSh->GetViewData()->GetCurY();
1624 if (bRecord && !pDoc->IsUndoEnabled())
1625 bRecord = false;
1627 ScMarkData aMark;
1628 if (pTabMark)
1629 aMark = *pTabMark;
1630 else
1632 SCTAB nCount = 0;
1633 for( i=0; i<nTabCount; i++ )
1635 if( !pDoc->IsScenario(i) )
1637 nCount++;
1638 if( nCount == nEndTab+1 )
1640 aMark.SelectTable( i, true );
1641 break;
1647 ScMarkData aFullMark( aMark ); // including scenario sheets
1648 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
1649 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1650 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1651 aFullMark.SelectTable( j, true );
1653 SCTAB nSelCount = aMark.GetSelectCount();
1655 // zugehoerige Szenarien auch anpassen
1656 // Test zusammengefasste
1658 SCCOL nMergeTestStartCol = nStartCol;
1659 SCROW nMergeTestStartRow = nStartRow;
1660 SCCOL nMergeTestEndCol = nEndCol;
1661 SCROW nMergeTestEndRow = nEndRow;
1663 ScRange aExtendMergeRange( rRange );
1665 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1667 pDoc->ExtendMerge( aExtendMergeRange );
1668 pDoc->ExtendOverlapped( aExtendMergeRange );
1669 nMergeTestEndCol = aExtendMergeRange.aEnd.Col();
1670 nMergeTestEndRow = aExtendMergeRange.aEnd.Row();
1671 nPaintEndCol = nMergeTestEndCol;
1672 nPaintEndRow = nMergeTestEndRow;
1675 if ( eCmd == INS_INSROWS )
1677 nMergeTestStartCol = 0;
1678 nMergeTestEndCol = MAXCOL;
1680 if ( eCmd == INS_INSCOLS )
1682 nMergeTestStartRow = 0;
1683 nMergeTestEndRow = MAXROW;
1685 if ( eCmd == INS_CELLSDOWN )
1686 nMergeTestEndRow = MAXROW;
1687 if ( eCmd == INS_CELLSRIGHT )
1688 nMergeTestEndCol = MAXCOL;
1690 bool bNeedRefresh = false;
1692 SCCOL nEditTestEndCol = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndCol;
1693 SCROW nEditTestEndRow = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndRow;
1694 ScEditableTester aTester( pDoc, nMergeTestStartCol, nMergeTestStartRow, nEditTestEndCol, nEditTestEndRow, aMark );
1695 if (!aTester.IsEditable())
1697 if (!bApi)
1698 rDocShell.ErrorMessage(aTester.GetMessageId());
1699 return false;
1702 // Check if this insertion is allowed with respect to pivot table.
1703 if (!canInsertCellsByPivot(rRange, aMark, eCmd, pDoc))
1705 if (!bApi)
1706 rDocShell.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE);
1707 return false;
1710 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
1712 ScDocument* pRefUndoDoc = NULL;
1713 ScRefUndoData* pUndoData = NULL;
1714 if ( bRecord )
1716 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1717 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
1719 // pRefUndoDoc is filled in InsertCol / InsertRow
1721 pUndoData = new ScRefUndoData( pDoc );
1723 pDoc->BeginDrawUndo();
1726 // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
1727 // the patch comes from mloiseleur and maoyg
1728 bool bInsertMerge = false;
1729 std::vector<ScRange> qIncreaseRange;
1730 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS );
1731 if (bRecord)
1732 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1734 itr = aMark.begin();
1735 for (; itr != itrEnd && nTabCount; ++itr)
1737 i = *itr;
1738 if( pDoc->HasAttrib( nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1740 if (eCmd==INS_CELLSRIGHT)
1741 bNeedRefresh = true;
1743 SCCOL nMergeStartCol = nMergeTestStartCol;
1744 SCROW nMergeStartRow = nMergeTestStartRow;
1745 SCCOL nMergeEndCol = nMergeTestEndCol;
1746 SCROW nMergeEndRow = nMergeTestEndRow;
1748 pDoc->ExtendMerge( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
1749 pDoc->ExtendOverlapped( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
1751 if(( eCmd == INS_CELLSDOWN && ( nMergeStartCol != nMergeTestStartCol || nMergeEndCol != nMergeTestEndCol )) ||
1752 (eCmd == INS_CELLSRIGHT && ( nMergeStartRow != nMergeTestStartRow || nMergeEndRow != nMergeTestEndRow )) )
1754 if (!bApi)
1755 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1756 rDocShell.GetUndoManager()->LeaveListAction();
1757 delete pUndoData;
1758 return false;
1761 SCCOL nTestCol = -1;
1762 SCROW nTestRow1 = -1;
1763 SCROW nTestRow2 = -1;
1765 ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow );
1766 ScRange aExtendRange( nMergeTestStartCol, nMergeTestStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i );
1767 const ScPatternAttr* pPattern = NULL;
1768 const ScMergeAttr* pMergeFlag = NULL;
1769 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1770 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1772 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1773 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1774 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1775 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1777 ScRange aRange( nTestCol, nTestRow1, i );
1778 pDoc->ExtendOverlapped(aRange);
1779 pDoc->ExtendMerge(aRange, true);
1781 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1783 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1785 ScRange aTestRange( nTestCol, nTestRow, i );
1786 pDoc->ExtendOverlapped( aTestRange );
1787 pDoc->ExtendMerge( aTestRange, true);
1788 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1789 if( !aExtendRange.In( aMergeRange ) )
1791 qIncreaseRange.push_back( aTestRange );
1792 bInsertMerge = true;
1796 else
1798 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1799 if( !aExtendRange.In( aMergeRange ) )
1801 qIncreaseRange.push_back( aRange );
1803 bInsertMerge = true;
1808 if( bInsertMerge )
1810 if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN )
1812 nStartRow = aExtendMergeRange.aStart.Row();
1813 nEndRow = aExtendMergeRange.aEnd.Row();
1815 if( eCmd == INS_CELLSDOWN )
1816 nEndCol = nMergeTestEndCol;
1817 else
1819 nStartCol = 0;
1820 nEndCol = MAXCOL;
1823 else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS )
1826 nStartCol = aExtendMergeRange.aStart.Col();
1827 nEndCol = aExtendMergeRange.aEnd.Col();
1828 if( eCmd == INS_CELLSRIGHT )
1830 nEndRow = nMergeTestEndRow;
1832 else
1834 nStartRow = 0;
1835 nEndRow = MAXROW;
1839 if( !qIncreaseRange.empty() )
1841 for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); ++iIter )
1843 ScRange aRange( *iIter );
1844 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1846 UnmergeCells( aRange, true );
1851 else
1853 if (!bApi)
1854 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1855 rDocShell.GetUndoManager()->LeaveListAction();
1856 delete pUndoData;
1857 return false;
1862 switch (eCmd)
1864 case INS_CELLSDOWN:
1865 bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1866 nPaintEndRow = MAXROW;
1867 break;
1868 case INS_INSROWS:
1869 bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1870 nPaintStartCol = 0;
1871 nPaintEndCol = MAXCOL;
1872 nPaintEndRow = MAXROW;
1873 nPaintFlags |= PAINT_LEFT;
1874 break;
1875 case INS_CELLSRIGHT:
1876 bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1877 nPaintEndCol = MAXCOL;
1878 break;
1879 case INS_INSCOLS:
1880 bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1881 nPaintStartRow = 0;
1882 nPaintEndRow = MAXROW;
1883 nPaintEndCol = MAXCOL;
1884 nPaintFlags |= PAINT_TOP;
1885 break;
1886 default:
1887 OSL_FAIL("Falscher Code beim Einfuegen");
1888 bSuccess = false;
1889 break;
1892 if ( bSuccess )
1894 SCTAB* pTabs = NULL;
1895 SCTAB* pScenarios = NULL;
1896 SCTAB nUndoPos = 0;
1898 if ( bRecord )
1900 pTabs = new SCTAB[nSelCount];
1901 pScenarios = new SCTAB[nSelCount];
1902 nUndoPos = 0;
1903 itr = aMark.begin();
1904 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1906 SCTAB nCount = 0;
1907 for( SCTAB j=*itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1908 nCount ++;
1910 pScenarios[nUndoPos] = nCount;
1911 pTabs[nUndoPos] = *itr;
1912 nUndoPos ++;
1915 if( !bInsertMerge )
1917 rDocShell.GetUndoManager()->LeaveListAction();
1920 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
1921 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),
1922 nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) );
1925 // #i8302 : we remerge growing ranges, with the new part inserted
1927 while( !qIncreaseRange.empty() )
1929 ScRange aRange = qIncreaseRange.back();
1930 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1932 switch (eCmd)
1934 case INS_CELLSDOWN:
1935 case INS_INSROWS:
1936 aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1));
1937 break;
1938 case INS_CELLSRIGHT:
1939 case INS_INSCOLS:
1940 aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1));
1941 break;
1942 default:
1943 break;
1945 ScCellMergeOption aMergeOption(
1946 aRange.aStart.Col(), aRange.aStart.Row(),
1947 aRange.aEnd.Col(), aRange.aEnd.Row() );
1948 aMergeOption.maTabs.insert(aRange.aStart.Tab());
1949 MergeCells(aMergeOption, false, true, true);
1951 qIncreaseRange.pop_back();
1954 if( bInsertMerge )
1955 rDocShell.GetUndoManager()->LeaveListAction();
1957 itr = aMark.begin();
1958 for (; itr != itrEnd && *itr < nTabCount; ++itr)
1960 i = *itr;
1961 pDoc->SetDrawPageSize(i);
1963 if (bNeedRefresh)
1964 pDoc->ExtendMerge( nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow, i, true );
1965 else
1966 pDoc->RefreshAutoFilter( nMergeTestStartCol, nMergeTestStartRow, nMergeTestEndCol, nMergeTestEndRow, i );
1968 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1969 pDoc->UpdatePageBreaks( i );
1971 sal_uInt16 nExtFlags = 0;
1972 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, i );
1974 SCTAB nScenarioCount = 0;
1976 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1977 nScenarioCount ++;
1979 bool bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) :
1980 AdjustRowHeight(ScRange(0, nPaintStartRow, i, MAXCOL, nPaintEndRow, i+nScenarioCount ));
1981 if (bAdjusted)
1983 // paint only what is not done by AdjustRowHeight
1984 if (nPaintFlags & PAINT_TOP)
1985 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, i+nScenarioCount, PAINT_TOP );
1987 else
1988 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, i, nPaintEndCol, nPaintEndRow, i+nScenarioCount, nPaintFlags, nExtFlags );
1991 else
1993 if( bInsertMerge )
1995 while( !qIncreaseRange.empty() )
1997 ScRange aRange = qIncreaseRange.back();
1998 ScCellMergeOption aMergeOption(
1999 aRange.aStart.Col(), aRange.aStart.Row(),
2000 aRange.aEnd.Col(), aRange.aEnd.Row() );
2001 MergeCells(aMergeOption, false, true, true);
2002 qIncreaseRange.pop_back();
2005 if( pViewSh )
2007 pViewSh->MarkRange( rRange, false );
2008 pViewSh->SetCursor( nCursorCol, nCursorRow );
2012 rDocShell.GetUndoManager()->LeaveListAction();
2013 rDocShell.GetUndoManager()->RemoveLastUndoAction();
2015 delete pRefUndoDoc;
2016 delete pUndoData;
2017 if (!bApi)
2018 rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll
2021 aModificator.SetDocumentModified();
2023 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2024 return bSuccess;
2027 bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
2028 bool bRecord, bool bApi )
2030 ScDocShellModificator aModificator( rDocShell );
2032 SCCOL nStartCol = rRange.aStart.Col();
2033 SCROW nStartRow = rRange.aStart.Row();
2034 SCTAB nStartTab = rRange.aStart.Tab();
2035 SCCOL nEndCol = rRange.aEnd.Col();
2036 SCROW nEndRow = rRange.aEnd.Row();
2037 SCTAB nEndTab = rRange.aEnd.Tab();
2039 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
2041 OSL_FAIL("invalid row in DeleteCells");
2042 return false;
2045 ScDocument* pDoc = rDocShell.GetDocument();
2046 SCTAB nTabCount = pDoc->GetTableCount();
2047 SCCOL nPaintStartCol = nStartCol;
2048 SCROW nPaintStartRow = nStartRow;
2049 SCCOL nPaintEndCol = nEndCol;
2050 SCROW nPaintEndRow = nEndRow;
2051 sal_uInt16 nPaintFlags = PAINT_GRID;
2053 if (bRecord && !pDoc->IsUndoEnabled())
2054 bRecord = false;
2056 ScMarkData aMark;
2057 if (pTabMark)
2058 aMark = *pTabMark;
2059 else
2061 SCTAB nCount = 0;
2062 for(SCTAB i=0; i<nTabCount; i++ )
2064 if( !pDoc->IsScenario(i) )
2066 nCount++;
2067 if( nCount == nEndTab+1 )
2069 aMark.SelectTable(i, true);
2070 break;
2076 ScMarkData aFullMark( aMark ); // including scenario sheets
2077 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
2078 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2079 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2080 aFullMark.SelectTable( j, true );
2082 SCTAB nSelCount = aMark.GetSelectCount();
2084 SCCOL nUndoStartCol = nStartCol;
2085 SCROW nUndoStartRow = nStartRow;
2086 SCCOL nUndoEndCol = nEndCol;
2087 SCROW nUndoEndRow = nEndRow;
2089 ScRange aExtendMergeRange( rRange );
2091 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
2093 pDoc->ExtendMerge( aExtendMergeRange );
2094 pDoc->ExtendOverlapped( aExtendMergeRange );
2095 nUndoEndCol = aExtendMergeRange.aEnd.Col();
2096 nUndoEndRow = aExtendMergeRange.aEnd.Row();
2097 nPaintEndCol = nUndoEndCol;
2098 nPaintEndRow = nUndoEndRow;
2101 if (eCmd==DEL_DELROWS)
2103 nUndoStartCol = 0;
2104 nUndoEndCol = MAXCOL;
2106 if (eCmd==DEL_DELCOLS)
2108 nUndoStartRow = 0;
2109 nUndoEndRow = MAXROW;
2111 // Test Zellschutz
2113 SCCOL nEditTestEndX = nUndoEndCol;
2114 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
2115 nEditTestEndX = MAXCOL;
2116 SCROW nEditTestEndY = nUndoEndRow;
2117 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
2118 nEditTestEndY = MAXROW;
2119 ScEditableTester aTester( pDoc, nUndoStartCol, nUndoStartRow, nEditTestEndX, nEditTestEndY, aMark );
2120 if (!aTester.IsEditable())
2122 if (!bApi)
2123 rDocShell.ErrorMessage(aTester.GetMessageId());
2124 return false;
2127 if (!canDeleteCellsByPivot(rRange, aMark, eCmd, pDoc))
2129 if (!bApi)
2130 rDocShell.ErrorMessage(STR_NO_INSERT_DELETE_OVER_PIVOT_TABLE);
2131 return false;
2133 // Test zusammengefasste
2135 SCCOL nMergeTestEndCol = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndCol;
2136 SCROW nMergeTestEndRow = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndRow;
2137 SCCOL nExtendStartCol = nUndoStartCol;
2138 SCROW nExtendStartRow = nUndoStartRow;
2139 bool bNeedRefresh = false;
2141 //Issue 8302 want to be able to insert into the middle of merged cells
2142 //the patch comes from maoyg
2143 ::std::vector<ScRange> qDecreaseRange;
2144 bool bDeletingMerge = false;
2145 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS );
2146 if (bRecord)
2147 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
2149 itr = aMark.begin();
2150 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2152 SCTAB i = *itr;
2153 if ( pDoc->HasAttrib( nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i, HASATTR_MERGED | HASATTR_OVERLAPPED ))
2155 SCCOL nMergeStartCol = nUndoStartCol;
2156 SCROW nMergeStartRow = nUndoStartRow;
2157 SCCOL nMergeEndCol = nMergeTestEndCol;
2158 SCROW nMergeEndRow = nMergeTestEndRow;
2160 pDoc->ExtendMerge( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
2161 pDoc->ExtendOverlapped( nMergeStartCol, nMergeStartRow, nMergeEndCol, nMergeEndRow, i );
2162 if( ( eCmd == DEL_CELLSUP && ( nMergeStartCol != nUndoStartCol || nMergeEndCol != nMergeTestEndCol))||
2163 ( eCmd == DEL_CELLSLEFT && ( nMergeStartRow != nUndoStartRow || nMergeEndRow != nMergeTestEndRow)))
2165 if (!bApi)
2166 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
2167 rDocShell.GetUndoManager()->LeaveListAction();
2168 return false;
2171 nExtendStartCol = nMergeStartCol;
2172 nExtendStartRow = nMergeStartRow;
2173 SCCOL nTestCol = -1;
2174 SCROW nTestRow1 = -1;
2175 SCROW nTestRow2 = -1;
2177 ScDocAttrIterator aTestIter( pDoc, i, nUndoStartCol, nUndoStartRow, nMergeTestEndCol, nMergeTestEndRow );
2178 ScRange aExtendRange( nUndoStartCol, nUndoStartRow, i, nMergeTestEndCol, nMergeTestEndRow, i );
2179 const ScPatternAttr* pPattern = NULL;
2180 const ScMergeAttr* pMergeFlag = NULL;
2181 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
2182 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
2184 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
2185 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
2186 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
2187 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
2189 ScRange aRange( nTestCol, nTestRow1, i );
2190 pDoc->ExtendOverlapped( aRange );
2191 pDoc->ExtendMerge( aRange, true );
2193 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
2195 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
2197 ScRange aTestRange( nTestCol, nTestRow, i );
2198 pDoc->ExtendOverlapped( aTestRange );
2199 pDoc->ExtendMerge( aTestRange, true );
2200 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
2201 if( !aExtendRange.In( aMergeRange ) )
2203 qDecreaseRange.push_back( aTestRange );
2204 bDeletingMerge = true;
2208 else
2210 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
2211 if( !aExtendRange.In( aMergeRange ) )
2213 qDecreaseRange.push_back( aRange );
2215 bDeletingMerge = true;
2220 if( bDeletingMerge )
2223 if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP )
2225 nStartRow = aExtendMergeRange.aStart.Row();
2226 nEndRow = aExtendMergeRange.aEnd.Row();
2227 bNeedRefresh = true;
2229 if( eCmd == DEL_CELLSUP )
2231 nEndCol = aExtendMergeRange.aEnd.Col();
2233 else
2235 nStartCol = 0;
2236 nEndCol = MAXCOL;
2239 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2242 nStartCol = aExtendMergeRange.aStart.Col();
2243 nEndCol = aExtendMergeRange.aEnd.Col();
2244 if( eCmd == DEL_CELLSLEFT )
2246 nEndRow = aExtendMergeRange.aEnd.Row();
2247 bNeedRefresh = true;
2249 else
2251 nStartRow = 0;
2252 nEndRow = MAXROW;
2256 if( !qDecreaseRange.empty() )
2258 for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); ++iIter )
2260 ScRange aRange( *iIter );
2261 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2263 UnmergeCells( aRange, true );
2268 else
2270 if (!bApi)
2271 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
2272 rDocShell.GetUndoManager()->LeaveListAction();
2273 return false;
2279 // ausfuehren
2282 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
2284 ScDocument* pUndoDoc = NULL;
2285 ScDocument* pRefUndoDoc = NULL;
2286 ScRefUndoData* pUndoData = NULL;
2287 if ( bRecord )
2289 // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
2290 // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
2292 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2293 pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) );
2294 itr = aMark.begin();
2295 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2297 SCTAB nScenarioCount = 0;
2299 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2300 nScenarioCount ++;
2302 pDoc->CopyToDocument( nUndoStartCol, nUndoStartRow, *itr, nUndoEndCol, nUndoEndRow, *itr+nScenarioCount,
2303 IDF_ALL | IDF_NOCAPTIONS, false, pUndoDoc );
2306 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2307 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
2309 pUndoData = new ScRefUndoData( pDoc );
2311 pDoc->BeginDrawUndo();
2314 sal_uInt16 nExtFlags = 0;
2315 itr = aMark.begin();
2316 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2318 rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr );
2321 bool bUndoOutline = false;
2322 switch (eCmd)
2324 case DEL_CELLSUP:
2325 pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark );
2326 nPaintEndRow = MAXROW;
2327 break;
2328 case DEL_DELROWS:
2329 pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2330 nPaintStartCol = 0;
2331 nPaintEndCol = MAXCOL;
2332 nPaintEndRow = MAXROW;
2333 nPaintFlags |= PAINT_LEFT;
2334 break;
2335 case DEL_CELLSLEFT:
2336 pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark );
2337 nPaintEndCol = MAXCOL;
2338 break;
2339 case DEL_DELCOLS:
2340 pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2341 nPaintStartRow = 0;
2342 nPaintEndRow = MAXROW;
2343 nPaintEndCol = MAXCOL;
2344 nPaintFlags |= PAINT_TOP;
2345 break;
2346 default:
2347 OSL_FAIL("Falscher Code beim Loeschen");
2348 break;
2351 //! Test, ob Outline in Groesse geaendert
2353 if ( bRecord )
2355 itr = aFullMark.begin(), itrEnd = aFullMark.end();
2356 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2357 pRefUndoDoc->DeleteAreaTab(nUndoStartCol,nUndoStartRow,nUndoEndCol,nUndoEndRow, *itr, IDF_ALL);
2359 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2360 pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
2362 // kopieren mit bColRowFlags=false (#54194#)
2363 pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,false,pUndoDoc,NULL,false);
2364 delete pRefUndoDoc;
2366 SCTAB* pTabs = new SCTAB[nSelCount];
2367 SCTAB* pScenarios = new SCTAB[nSelCount];
2368 SCTAB nUndoPos = 0;
2370 itr = aMark.begin(), itrEnd = aMark.end();
2371 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2373 SCTAB nCount = 0;
2374 for( SCTAB j=*itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2375 nCount ++;
2377 pScenarios[nUndoPos] = nCount;
2378 pTabs[nUndoPos] = *itr;
2379 nUndoPos ++;
2382 if( !bDeletingMerge )
2384 rDocShell.GetUndoManager()->LeaveListAction();
2387 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
2388 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
2389 eCmd, pUndoDoc, pUndoData ) );
2392 // #i8302 want to be able to insert into the middle of merged cells
2393 // the patch comes from maoyg
2395 while( !qDecreaseRange.empty() )
2397 ScRange aRange = qDecreaseRange.back();
2399 long nDecreaseRowCount = 0;
2400 long nDecreaseColCount = 0;
2401 if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS )
2403 if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2404 nDecreaseRowCount = nEndRow-nStartRow+1;
2405 else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() )
2406 nDecreaseRowCount = aRange.aEnd.Row()-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()-nEndRow+1;
2410 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2412 if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2413 nDecreaseColCount = nEndCol-nStartCol+1;
2414 else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() )
2415 nDecreaseColCount = aRange.aEnd.Col()-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()-nEndCol+1;
2420 switch (eCmd)
2422 case DEL_CELLSUP:
2423 case DEL_DELROWS:
2424 aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount));
2425 break;
2426 case DEL_CELLSLEFT:
2427 case DEL_DELCOLS:
2428 aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount));
2429 break;
2430 default:
2431 break;
2434 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2436 ScCellMergeOption aMergeOption(aRange);
2437 MergeCells( aMergeOption, false, true, true );
2439 qDecreaseRange.pop_back();
2442 if( bDeletingMerge )
2443 rDocShell.GetUndoManager()->LeaveListAction();
2445 if ( bNeedRefresh )
2447 // #i51445# old merge flag attributes must be deleted also for single cells,
2448 // not only for whole columns/rows
2450 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
2451 nMergeTestEndCol = MAXCOL;
2452 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
2453 nMergeTestEndRow = MAXROW;
2454 ScPatternAttr aPattern( pDoc->GetPool() );
2455 aPattern.GetItemSet().Put( ScMergeFlagAttr() );
2457 pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndCol, nMergeTestEndRow, aMark, aPattern );
2459 itr = aMark.begin(), itrEnd = aMark.end();
2460 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2462 SCTAB nScenarioCount = 0;
2464 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2465 nScenarioCount ++;
2467 ScRange aMergedRange( nExtendStartCol, nExtendStartRow, *itr, nMergeTestEndCol, nMergeTestEndRow, *itr+nScenarioCount );
2468 pDoc->ExtendMerge( aMergedRange, true );
2472 itr = aMark.begin(), itrEnd = aMark.end();
2473 for (; itr != itrEnd && *itr < nTabCount; ++itr)
2475 pDoc->SetDrawPageSize(*itr);
2477 if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS )
2478 pDoc->UpdatePageBreaks( *itr );
2480 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr );
2482 SCTAB nScenarioCount = 0;
2484 for( SCTAB j = *itr+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2485 nScenarioCount ++;
2487 // ganze Zeilen loeschen: nichts anpassen
2488 if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartRow, *itr, MAXCOL, nPaintEndRow, *itr+nScenarioCount )) )
2489 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr+nScenarioCount, nPaintFlags, nExtFlags );
2490 else
2492 // paint only what is not done by AdjustRowHeight
2493 if (nExtFlags & SC_PF_LINES)
2494 lcl_PaintAbove( rDocShell, ScRange( nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr+nScenarioCount) );
2495 if (nPaintFlags & PAINT_TOP)
2496 rDocShell.PostPaint( nPaintStartCol, nPaintStartRow, *itr, nPaintEndCol, nPaintEndRow, *itr+nScenarioCount, PAINT_TOP );
2500 aModificator.SetDocumentModified();
2502 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2504 return true;
2507 bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
2508 bool bCut, bool bRecord, bool bPaint, bool bApi )
2510 ScDocShellModificator aModificator( rDocShell );
2512 SCCOL nStartCol = rSource.aStart.Col();
2513 SCROW nStartRow = rSource.aStart.Row();
2514 SCTAB nStartTab = rSource.aStart.Tab();
2515 SCCOL nEndCol = rSource.aEnd.Col();
2516 SCROW nEndRow = rSource.aEnd.Row();
2517 SCTAB nEndTab = rSource.aEnd.Tab();
2518 SCCOL nDestCol = rDestPos.Col();
2519 SCROW nDestRow = rDestPos.Row();
2520 SCTAB nDestTab = rDestPos.Tab();
2522 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) )
2524 OSL_FAIL("invalid row in MoveBlock");
2525 return false;
2528 // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
2529 bool bScenariosAdded = false;
2530 ScDocument* pDoc = rDocShell.GetDocument();
2531 if (bRecord && !pDoc->IsUndoEnabled())
2532 bRecord = false;
2534 SCTAB nTabCount = pDoc->GetTableCount();
2535 if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) )
2536 while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) )
2538 ++nEndTab;
2539 bScenariosAdded = true;
2542 SCTAB nSrcTabCount = nEndTab-nStartTab+1;
2543 SCTAB nDestEndTab = nDestTab+nSrcTabCount-1;
2544 SCTAB nTab;
2546 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
2548 ScMarkData aSourceMark;
2549 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2550 aSourceMark.SelectTable( nTab, true ); // Source selektieren
2551 aSourceMark.SetMarkArea( rSource );
2553 ScDocShellRef aDragShellRef;
2554 if ( pDoc->HasOLEObjectsInArea( rSource ) )
2556 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
2557 aDragShellRef->DoInitNew(NULL);
2559 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
2561 ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut);
2562 pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
2564 ScDrawLayer::SetGlobalDrawPersist(NULL);
2566 SCCOL nOldEndCol = nEndCol;
2567 SCROW nOldEndRow = nEndRow;
2568 bool bClipOver = false;
2569 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2571 SCCOL nTmpEndCol = nOldEndCol;
2572 SCROW nTmpEndRow = nOldEndRow;
2573 if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab ))
2574 bClipOver = true;
2575 if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol;
2576 if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow;
2579 SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol );
2580 SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow );
2582 SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock
2583 SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow );
2585 bool bIncludeFiltered = bCut;
2586 if ( !bIncludeFiltered )
2588 // adjust sizes to include only non-filtered rows
2590 SCCOL nClipX;
2591 SCROW nClipY;
2592 pClipDoc->GetClipArea( nClipX, nClipY, false );
2593 SCROW nUndoAdd = nUndoEndRow - nDestEndRow;
2594 nDestEndRow = nDestRow + nClipY;
2595 nUndoEndRow = nDestEndRow + nUndoAdd;
2598 if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow))
2600 if (!bApi)
2601 rDocShell.ErrorMessage(STR_PASTE_FULL);
2602 delete pClipDoc;
2603 return false;
2606 // Test auf Zellschutz
2608 ScEditableTester aTester;
2609 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2610 aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow );
2611 if (bCut)
2612 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2613 aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
2615 if (!aTester.IsEditable())
2617 if (!bApi)
2618 rDocShell.ErrorMessage(aTester.GetMessageId());
2619 delete pClipDoc;
2620 return false;
2623 // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
2625 if (bClipOver && !bCut)
2626 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab,
2627 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2628 { // "Zusammenfassen nicht verschachteln !"
2629 if (!bApi)
2630 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2631 delete pClipDoc;
2632 return false;
2635 // Are there borders in the cells? (for painting)
2637 sal_uInt16 nSourceExt = 0;
2638 rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab );
2639 sal_uInt16 nDestExt = 0;
2640 rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab );
2643 // ausfuehren
2646 ScDocument* pUndoDoc = NULL;
2647 ScDocument* pRefUndoDoc = NULL;
2648 ScRefUndoData* pUndoData = NULL;
2649 if (bRecord)
2651 bool bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW );
2652 bool bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL );
2653 sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
2655 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2656 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows );
2658 if (bCut)
2660 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
2661 nUndoFlags, false, pUndoDoc );
2662 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2663 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, false, false );
2666 if ( nDestTab != nStartTab )
2667 pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows );
2668 pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab,
2669 nDestEndCol, nDestEndRow, nDestEndTab,
2670 nUndoFlags, false, pUndoDoc );
2672 pUndoData = new ScRefUndoData( pDoc );
2674 pDoc->BeginDrawUndo();
2677 bool bSourceHeight = false; // Hoehen angepasst?
2678 if (bCut)
2680 ScMarkData aDelMark; // only for tables
2681 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2683 pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL );
2684 aDelMark.SelectTable( nTab, true );
2686 pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark );
2688 // Test auf zusammengefasste
2690 if (bClipOver)
2691 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab,
2692 nUndoEndCol,nUndoEndRow,nDestEndTab,
2693 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2695 pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc );
2696 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2698 SCCOL nTmpEndCol = nEndCol;
2699 SCROW nTmpEndRow = nEndRow;
2700 pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, true );
2703 // Fehlermeldung erst nach dem Wiederherstellen des Inhalts
2704 if (!bApi) // "Zusammenfassen nicht verschachteln !"
2705 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2707 delete pUndoDoc;
2708 delete pRefUndoDoc;
2709 delete pUndoData;
2710 delete pClipDoc;
2711 return false;
2714 bSourceHeight = AdjustRowHeight( rSource, false );
2717 ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab );
2719 ScMarkData aDestMark;
2720 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2721 aDestMark.SelectTable( nTab, true ); // Destination selektieren
2722 aDestMark.SetMarkArea( aPasteDest );
2724 /* Do not drawing objects here. While pasting, the
2725 function ScDocument::UpdateReference() is called which calls
2726 ScDrawLayer::MoveCells() which may move away inserted objects to wrong
2727 positions (e.g. if source and destination range overlaps).*/
2728 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_OBJECTS),
2729 NULL, pClipDoc, true, false, bIncludeFiltered );
2732 // skipped rows and merged cells don't mix
2733 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
2734 UnmergeCells( aPasteDest, false );
2736 VirtualDevice aVirtDev;
2737 bool bDestHeight = AdjustRowHeight(
2738 ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ),
2739 false );
2741 /* Paste drawing objects after adjusting formula references
2742 and row heights. There are no cell notes or drawing objects, if the
2743 clipdoc does not contain a drawing layer.*/
2744 if ( pClipDoc->GetDrawLayer() )
2745 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_OBJECTS,
2746 pRefUndoDoc, pClipDoc, true, false, bIncludeFiltered );
2748 if (bRecord)
2750 if (pRefUndoDoc)
2752 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2753 pUndoDoc->AddUndoTab( 0, nTabCount-1, false, false );
2755 pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL );
2756 // kopieren mit bColRowFlags=sal_False (#54194#)
2757 pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB,
2758 IDF_FORMULA, false, pUndoDoc, NULL, false );
2759 delete pRefUndoDoc;
2762 rDocShell.GetUndoManager()->AddUndoAction(
2763 new ScUndoDragDrop( &rDocShell, ScRange(
2764 nStartCol, nStartRow, nStartTab,
2765 nOldEndCol, nOldEndRow, nEndTab ),
2766 ScAddress( nDestCol, nDestRow, nDestTab ),
2767 bCut, pUndoDoc, pUndoData, bScenariosAdded ) );
2770 SCCOL nDestPaintEndCol = nDestEndCol;
2771 SCROW nDestPaintEndRow = nDestEndRow;
2772 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2774 SCCOL nTmpEndCol = nDestEndCol;
2775 SCROW nTmpEndRow = nDestEndRow;
2776 pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, true );
2777 if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol;
2778 if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow;
2781 if (bCut)
2782 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2783 pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
2785 if (bPaint)
2787 // Zielbereich:
2789 SCCOL nPaintStartX = nDestCol;
2790 SCROW nPaintStartY = nDestRow;
2791 SCCOL nPaintEndX = nDestPaintEndCol;
2792 SCROW nPaintEndY = nDestPaintEndRow;
2793 sal_uInt16 nFlags = PAINT_GRID;
2795 if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert?
2797 nPaintEndX = MAXCOL;
2798 nPaintStartY = 0;
2799 nPaintEndY = MAXROW;
2800 nFlags |= PAINT_TOP;
2802 if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) )
2804 nPaintEndY = MAXROW;
2805 nPaintStartX = 0;
2806 nPaintEndX = MAXCOL;
2807 nFlags |= PAINT_LEFT;
2809 if ( bScenariosAdded )
2811 nPaintStartX = 0;
2812 nPaintStartY = 0;
2813 nPaintEndX = MAXCOL;
2814 nPaintEndY = MAXROW;
2817 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab,
2818 nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt );
2820 if ( bCut )
2822 // Quellbereich:
2824 nPaintStartX = nStartCol;
2825 nPaintStartY = nStartRow;
2826 nPaintEndX = nEndCol;
2827 nPaintEndY = nEndRow;
2828 nFlags = PAINT_GRID;
2830 if ( bSourceHeight )
2832 nPaintEndY = MAXROW;
2833 nPaintStartX = 0;
2834 nPaintEndX = MAXCOL;
2835 nFlags |= PAINT_LEFT;
2837 if ( bScenariosAdded )
2839 nPaintStartX = 0;
2840 nPaintStartY = 0;
2841 nPaintEndX = MAXCOL;
2842 nPaintEndY = MAXROW;
2845 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab,
2846 nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt );
2850 aModificator.SetDocumentModified();
2852 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2854 delete pClipDoc;
2855 return true;
2859 uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, OUString& sCodeName )
2861 uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY);
2862 uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess;
2863 uno::Reference< uno::XInterface > xDocModuleApiObject;
2864 if ( xSF.is() )
2866 xVBACodeNamedObjectAccess.set( xSF->createInstance("ooo.vba.VBAObjectModuleObjectProvider"), uno::UNO_QUERY );
2867 xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY );
2869 return xDocModuleApiObject;
2873 static script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, OUString& sModule )
2875 script::ModuleInfo sModuleInfo;
2876 sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
2877 sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule );
2878 return sModuleInfo;
2881 void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, const OUString& sModuleName, const OUString& sSource )
2883 SfxObjectShell& rDocSh = *rDoc.GetDocumentShell();
2884 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2885 OSL_ENSURE( xLibContainer.is(), "No BasicContainer!" );
2887 uno::Reference< container::XNameContainer > xLib;
2888 if( xLibContainer.is() )
2890 OUString aLibName( "Standard" );
2891 if ( rDocSh.GetBasicManager() && !rDocSh.GetBasicManager()->GetName().isEmpty() )
2893 aLibName = rDocSh.GetBasicManager()->GetName();
2895 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2896 aLibAny >>= xLib;
2898 if( xLib.is() )
2900 // if the Module with codename exists then find a new name
2901 sal_Int32 nNum = 0;
2902 OUString genModuleName;
2903 if ( !sModuleName.isEmpty() )
2904 genModuleName = sModuleName;
2905 else
2907 genModuleName = "Sheet1";
2908 nNum = 1;
2910 while( xLib->hasByName( genModuleName ) )
2911 genModuleName = "Sheet" + OUString::number( ++nNum );
2913 uno::Any aSourceAny;
2914 OUString sTmpSource = sSource;
2915 if ( sTmpSource.isEmpty() )
2916 sTmpSource = "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n";
2917 aSourceAny <<= sTmpSource;
2918 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2919 if ( xVBAModuleInfo.is() )
2921 rDoc.SetCodeName( nTab, genModuleName );
2922 script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, genModuleName );
2923 xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo );
2924 xLib->insertByName( genModuleName, aSourceAny );
2930 void VBA_DeleteModule( ScDocShell& rDocSh, const OUString& sModuleName )
2932 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2933 OSL_ENSURE( xLibContainer.is(), "No BasicContainer!" );
2935 uno::Reference< container::XNameContainer > xLib;
2936 if( xLibContainer.is() )
2938 OUString aLibName( "Standard" );
2939 if ( rDocSh.GetBasicManager() && !rDocSh.GetBasicManager()->GetName().isEmpty() )
2941 aLibName = rDocSh.GetBasicManager()->GetName();
2943 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2944 aLibAny >>= xLib;
2946 if( xLib.is() )
2948 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2949 if( xLib->hasByName( sModuleName ) )
2950 xLib->removeByName( sModuleName );
2951 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo(sModuleName) )
2952 xVBAModuleInfo->removeModuleInfo( sModuleName );
2958 bool ScDocFunc::InsertTable( SCTAB nTab, const OUString& rName, bool bRecord, bool bApi )
2960 bool bSuccess = false;
2961 WaitObject aWait( rDocShell.GetActiveDialogParent() );
2963 ScDocShellModificator aModificator( rDocShell );
2965 ScDocument* pDoc = rDocShell.GetDocument();
2968 // Strange loop, also basic is loaded too early ( InsertTable )
2969 // is called via the xml import for sheets in described in ODF
2970 bool bInsertDocModule = false;
2972 if( !rDocShell.GetDocument()->IsImportingXML() )
2974 bInsertDocModule = pDoc && pDoc->IsInVBAMode();
2976 if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) )
2977 bRecord = false;
2979 if (bRecord)
2980 pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage
2982 SCTAB nTabCount = pDoc->GetTableCount();
2983 bool bAppend = ( nTab >= nTabCount );
2984 if ( bAppend )
2985 nTab = nTabCount; // wichtig fuer Undo
2987 if (pDoc->InsertTab( nTab, rName ))
2989 if (bRecord)
2990 rDocShell.GetUndoManager()->AddUndoAction(
2991 new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName));
2992 // Views updaten:
2993 // Only insert vba modules if vba mode ( and not currently importing XML )
2994 if( bInsertDocModule )
2996 OUString sSource, sCodeName;
2997 VBA_InsertModule( *pDoc, nTab, sCodeName, sSource );
2999 rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
3001 rDocShell.PostPaintExtras();
3002 aModificator.SetDocumentModified();
3003 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3004 bSuccess = true;
3006 else if (!bApi)
3007 rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
3009 return bSuccess;
3012 bool ScDocFunc::DeleteTable( SCTAB nTab, bool bRecord, bool /* bApi */ )
3014 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3016 ScDocShellModificator aModificator( rDocShell );
3018 bool bSuccess = false;
3019 ScDocument* pDoc = rDocShell.GetDocument();
3020 bool bVbaEnabled = pDoc && pDoc->IsInVBAMode();
3021 if (bRecord && !pDoc->IsUndoEnabled())
3022 bRecord = false;
3023 if ( bVbaEnabled )
3024 bRecord = false;
3025 bool bWasLinked = pDoc->IsLinked(nTab);
3026 ScDocument* pUndoDoc = NULL;
3027 ScRefUndoData* pUndoData = NULL;
3028 if (bRecord)
3030 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3031 SCTAB nCount = pDoc->GetTableCount();
3033 pUndoDoc->InitUndo( pDoc, nTab, nTab, true, true ); // nur nTab mit Flags
3034 pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen
3036 pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pUndoDoc );
3037 OUString aOldName;
3038 pDoc->GetName( nTab, aOldName );
3039 pUndoDoc->RenameTab( nTab, aOldName, false );
3040 if (bWasLinked)
3041 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
3042 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
3043 pDoc->GetLinkTab(nTab),
3044 pDoc->GetLinkRefreshDelay(nTab) );
3046 if ( pDoc->IsScenario(nTab) )
3048 pUndoDoc->SetScenario( nTab, true );
3049 OUString aComment;
3050 Color aColor;
3051 sal_uInt16 nScenFlags;
3052 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
3053 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
3054 bool bActive = pDoc->IsActiveScenario( nTab );
3055 pUndoDoc->SetActiveScenario( nTab, bActive );
3057 pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
3058 pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
3059 pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
3061 // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
3062 pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage
3064 pUndoData = new ScRefUndoData( pDoc );
3067 if (pDoc->DeleteTab(nTab))
3069 if (bRecord)
3071 vector<SCTAB> theTabs;
3072 theTabs.push_back(nTab);
3073 rDocShell.GetUndoManager()->AddUndoAction(
3074 new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData ));
3076 // Views updaten:
3077 if( bVbaEnabled )
3079 OUString sCodeName;
3080 if( pDoc->GetCodeName( nTab, sCodeName ) )
3082 VBA_DeleteModule( rDocShell, sCodeName );
3085 rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
3087 if (bWasLinked)
3089 rDocShell.UpdateLinks(); // Link-Manager updaten
3090 SfxBindings* pBindings = rDocShell.GetViewBindings();
3091 if (pBindings)
3092 pBindings->Invalidate(SID_LINKS);
3095 rDocShell.PostPaintExtras();
3096 aModificator.SetDocumentModified();
3098 SfxApplication* pSfxApp = SFX_APP(); // Navigator
3099 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3100 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
3101 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
3103 bSuccess = true;
3105 else
3107 delete pUndoDoc;
3108 delete pUndoData;
3110 return bSuccess;
3113 bool ScDocFunc::SetTableVisible( SCTAB nTab, bool bVisible, bool bApi )
3115 ScDocument* pDoc = rDocShell.GetDocument();
3116 bool bUndo(pDoc->IsUndoEnabled());
3117 if ( pDoc->IsVisible( nTab ) == bVisible )
3118 return true; // nichts zu tun - ok
3120 if ( !pDoc->IsDocEditable() )
3122 if (!bApi)
3123 rDocShell.ErrorMessage(STR_PROTECTIONERR);
3124 return false;
3127 ScDocShellModificator aModificator( rDocShell );
3129 if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading
3131 // nicht alle Tabellen ausblenden
3133 sal_uInt16 nVisCount = 0;
3134 SCTAB nCount = pDoc->GetTableCount();
3135 for (SCTAB i=0; i<nCount && nVisCount<2; i++)
3136 if (pDoc->IsVisible(i))
3137 ++nVisCount;
3139 if (nVisCount <= 1)
3141 if (!bApi)
3142 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
3143 return false;
3147 pDoc->SetVisible( nTab, bVisible );
3148 if (bUndo)
3150 std::vector<SCTAB> undoTabs;
3151 undoTabs.push_back(nTab);
3152 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, undoTabs, bVisible ) );
3155 // Views updaten:
3156 if (!bVisible)
3157 rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
3159 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3160 rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
3161 aModificator.SetDocumentModified();
3163 return true;
3166 bool ScDocFunc::SetLayoutRTL( SCTAB nTab, bool bRTL, bool /* bApi */ )
3168 ScDocument* pDoc = rDocShell.GetDocument();
3169 bool bUndo(pDoc->IsUndoEnabled());
3170 if ( pDoc->IsLayoutRTL( nTab ) == bRTL )
3171 return true; // nothing to do - ok
3173 //! protection (sheet or document?)
3175 ScDocShellModificator aModificator( rDocShell );
3177 pDoc->SetLayoutRTL( nTab, bRTL );
3179 if (bUndo)
3181 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) );
3184 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
3185 aModificator.SetDocumentModified();
3187 SfxBindings* pBindings = rDocShell.GetViewBindings();
3188 if (pBindings)
3190 pBindings->Invalidate( FID_TAB_RTL );
3191 pBindings->Invalidate( SID_ATTR_SIZE );
3194 return true;
3197 bool ScDocFunc::RenameTable( SCTAB nTab, const OUString& rName, bool bRecord, bool bApi )
3199 ScDocument* pDoc = rDocShell.GetDocument();
3200 if (bRecord && !pDoc->IsUndoEnabled())
3201 bRecord = false;
3202 if ( !pDoc->IsDocEditable() )
3204 if (!bApi)
3205 rDocShell.ErrorMessage(STR_PROTECTIONERR);
3206 return false;
3209 ScDocShellModificator aModificator( rDocShell );
3211 bool bSuccess = false;
3212 OUString sOldName;
3213 pDoc->GetName(nTab, sOldName);
3214 if (pDoc->RenameTab( nTab, rName ))
3216 if (bRecord)
3218 rDocShell.GetUndoManager()->AddUndoAction(
3219 new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName));
3221 rDocShell.PostPaintExtras();
3222 aModificator.SetDocumentModified();
3223 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3225 bSuccess = true;
3227 return bSuccess;
3230 bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi )
3233 ScDocument* pDoc = rDocShell.GetDocument();
3234 if (bRecord && !pDoc->IsUndoEnabled())
3235 bRecord = false;
3236 if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) )
3238 if (!bApi)
3239 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is...
3240 return false;
3243 Color aOldTabBgColor;
3244 aOldTabBgColor = pDoc->GetTabBgColor(nTab);
3246 bool bSuccess = false;
3247 pDoc->SetTabBgColor(nTab, rColor);
3248 if ( pDoc->GetTabBgColor(nTab) == rColor)
3249 bSuccess = true;
3250 if (bSuccess)
3252 if (bRecord)
3254 rDocShell.GetUndoManager()->AddUndoAction(
3255 new ScUndoTabColor( &rDocShell, nTab, aOldTabBgColor, rColor));
3257 rDocShell.PostPaintExtras();
3258 ScDocShellModificator aModificator( rDocShell );
3259 aModificator.SetDocumentModified();
3260 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3262 bSuccess = true;
3264 return bSuccess;
3267 bool ScDocFunc::SetTabBgColor(
3268 ScUndoTabColorInfo::List& rUndoTabColorList, bool bRecord, bool bApi )
3270 ScDocument* pDoc = rDocShell.GetDocument();
3271 if (bRecord && !pDoc->IsUndoEnabled())
3272 bRecord = false;
3274 if ( !pDoc->IsDocEditable() )
3276 if (!bApi)
3277 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3278 return false;
3281 sal_uInt16 nTab;
3282 Color aNewTabBgColor;
3283 bool bSuccess = true;
3284 size_t nTabProtectCount = 0;
3285 size_t nTabListCount = rUndoTabColorList.size();
3286 for ( size_t i = 0; i < nTabListCount; ++i )
3288 ScUndoTabColorInfo& rInfo = rUndoTabColorList[i];
3289 nTab = rInfo.mnTabId;
3290 if ( !pDoc->IsTabProtected(nTab) )
3292 aNewTabBgColor = rInfo.maNewTabBgColor;
3293 rInfo.maOldTabBgColor = pDoc->GetTabBgColor(nTab);
3294 pDoc->SetTabBgColor(nTab, aNewTabBgColor);
3295 if ( pDoc->GetTabBgColor(nTab) != aNewTabBgColor)
3297 bSuccess = false;
3298 break;
3301 else
3303 nTabProtectCount++;
3307 if ( nTabProtectCount == nTabListCount )
3309 if (!bApi)
3310 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3311 return false;
3314 if (bSuccess)
3316 if (bRecord)
3318 rDocShell.GetUndoManager()->AddUndoAction(
3319 new ScUndoTabColor( &rDocShell, rUndoTabColorList));
3321 rDocShell.PostPaintExtras();
3322 ScDocShellModificator aModificator( rDocShell );
3323 aModificator.SetDocumentModified();
3325 return bSuccess;
3328 //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
3329 //! Probleme:
3330 //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
3331 //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
3333 static sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, bool bFormula )
3335 ScSizeDeviceProvider aProv(&rDocShell);
3336 OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode
3337 double nPPTX = aProv.GetPPTX();
3338 double nPPTY = aProv.GetPPTY();
3340 ScDocument* pDoc = rDocShell.GetDocument();
3341 Fraction aOne(1,1);
3342 sal_uInt16 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
3343 bFormula, NULL );
3345 return nTwips;
3348 bool ScDocFunc::SetWidthOrHeight(
3349 bool bWidth, const std::vector<sc::ColRowSpan>& rRanges, SCTAB nTab,
3350 ScSizeMode eMode, sal_uInt16 nSizeTwips, bool bRecord, bool bApi )
3352 ScDocShellModificator aModificator( rDocShell );
3354 if (rRanges.empty())
3355 return true;
3357 ScDocument* pDoc = rDocShell.GetDocument();
3358 if ( bRecord && !pDoc->IsUndoEnabled() )
3359 bRecord = false;
3361 // import into read-only document is possible
3362 if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
3364 if (!bApi)
3365 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
3366 return false;
3369 bool bSuccess = false;
3370 SCCOLROW nStart = rRanges[0].mnStart;
3371 SCCOLROW nEnd = rRanges[0].mnEnd;
3373 bool bFormula = false;
3374 if ( eMode == SC_SIZE_OPTIMAL )
3376 //! Option "Formeln anzeigen" - woher nehmen?
3379 ScDocument* pUndoDoc = NULL;
3380 ScOutlineTable* pUndoTab = NULL;
3381 std::vector<sc::ColRowSpan> aUndoRanges;
3383 if ( bRecord )
3385 pDoc->BeginDrawUndo(); // Drawing Updates
3387 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3388 if (bWidth)
3390 pUndoDoc->InitUndo( pDoc, nTab, nTab, true, false );
3391 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, false, pUndoDoc );
3393 else
3395 pUndoDoc->InitUndo( pDoc, nTab, nTab, false, true );
3396 pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, false, pUndoDoc );
3399 aUndoRanges = rRanges;
3401 ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
3402 if (pTable)
3403 pUndoTab = new ScOutlineTable( *pTable );
3406 bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
3407 bool bOutline = false;
3409 for (size_t i = 0, n = rRanges.size(); i < n; ++i)
3411 SCCOLROW nStartNo = rRanges[i].mnStart;
3412 SCCOLROW nEndNo = rRanges[i].mnEnd;
3414 if ( !bWidth ) // Hoehen immer blockweise
3416 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3418 bool bAll = ( eMode==SC_SIZE_OPTIMAL );
3419 if (!bAll)
3421 // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
3422 // dann SetOptimalHeight mit bShrink = FALSE
3423 for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
3425 sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab);
3426 SCROW nLastRow = -1;
3427 bool bHidden = pDoc->RowHidden(nRow, nTab, NULL, &nLastRow);
3428 if ( !bHidden && ( nOld & CR_MANUALSIZE ) )
3429 pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
3433 ScSizeDeviceProvider aProv( &rDocShell );
3434 Fraction aOne(1,1);
3435 sc::RowHeightContext aCxt(aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, aProv.GetDevice());
3436 aCxt.setForceAutoSize(bAll);
3437 pDoc->SetOptimalHeight(aCxt, nStartNo, nEndNo, nTab);
3439 if (bAll)
3440 pDoc->ShowRows( nStartNo, nEndNo, nTab, true );
3442 // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt
3443 // (an bei Extra-Height, sonst aus).
3445 else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
3447 if (nSizeTwips)
3449 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
3450 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, true ); // height was set manually
3452 if ( eMode != SC_SIZE_ORIGINAL )
3453 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
3455 else if ( eMode==SC_SIZE_SHOW )
3457 pDoc->ShowRows( nStartNo, nEndNo, nTab, true );
3460 else // Spaltenbreiten
3462 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
3464 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) )
3466 sal_uInt16 nThisSize = nSizeTwips;
3468 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3469 nThisSize = nSizeTwips +
3470 lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
3471 if ( nThisSize )
3472 pDoc->SetColWidth( nCol, nTab, nThisSize );
3474 if ( eMode != SC_SIZE_ORIGINAL )
3475 pDoc->ShowCol( nCol, nTab, bShow );
3480 // adjust outlines
3482 if ( eMode != SC_SIZE_ORIGINAL )
3484 if (bWidth)
3485 bOutline = bOutline || pDoc->UpdateOutlineCol(
3486 static_cast<SCCOL>(nStartNo),
3487 static_cast<SCCOL>(nEndNo), nTab, bShow );
3488 else
3489 bOutline = bOutline || pDoc->UpdateOutlineRow(
3490 static_cast<SCROW>(nStartNo),
3491 static_cast<SCROW>(nEndNo), nTab, bShow );
3494 pDoc->SetDrawPageSize(nTab);
3496 if (!bOutline)
3497 DELETEZ(pUndoTab);
3499 if (bRecord)
3501 ScMarkData aMark;
3502 aMark.SelectOneTable( nTab );
3503 rDocShell.GetUndoManager()->AddUndoAction(
3504 new ScUndoWidthOrHeight(
3505 &rDocShell, aMark, nStart, nTab, nEnd, nTab, pUndoDoc,
3506 aUndoRanges, pUndoTab, eMode, nSizeTwips, bWidth));
3509 pDoc->UpdatePageBreaks( nTab );
3511 rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
3512 aModificator.SetDocumentModified();
3514 return bSuccess;
3518 bool ScDocFunc::InsertPageBreak( bool bColumn, const ScAddress& rPos,
3519 bool bRecord, bool bSetModified, bool /* bApi */ )
3521 ScDocShellModificator aModificator( rDocShell );
3523 ScDocument* pDoc = rDocShell.GetDocument();
3524 if (bRecord && !pDoc->IsUndoEnabled())
3525 bRecord = false;
3526 SCTAB nTab = rPos.Tab();
3527 SfxBindings* pBindings = rDocShell.GetViewBindings();
3529 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3530 static_cast<SCCOLROW>(rPos.Row());
3531 if (nPos == 0)
3532 return false; // erste Spalte / Zeile
3534 ScBreakType nBreak = bColumn ?
3535 pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) :
3536 pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3537 if (nBreak & BREAK_MANUAL)
3538 return true;
3540 if (bRecord)
3541 rDocShell.GetUndoManager()->AddUndoAction(
3542 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, true ) );
3544 if (bColumn)
3545 pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3546 else
3547 pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3549 pDoc->InvalidatePageBreaks(nTab);
3550 pDoc->UpdatePageBreaks( nTab );
3552 if (pDoc->IsStreamValid(nTab))
3553 pDoc->SetStreamValid(nTab, false);
3555 if (bColumn)
3557 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3558 if (pBindings)
3560 pBindings->Invalidate( FID_INS_COLBRK );
3561 pBindings->Invalidate( FID_DEL_COLBRK );
3564 else
3566 rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3567 if (pBindings)
3569 pBindings->Invalidate( FID_INS_ROWBRK );
3570 pBindings->Invalidate( FID_DEL_ROWBRK );
3573 if (pBindings)
3574 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3576 if (bSetModified)
3577 aModificator.SetDocumentModified();
3579 return true;
3582 bool ScDocFunc::RemovePageBreak( bool bColumn, const ScAddress& rPos,
3583 bool bRecord, bool bSetModified, bool /* bApi */ )
3585 ScDocShellModificator aModificator( rDocShell );
3587 ScDocument* pDoc = rDocShell.GetDocument();
3588 if (bRecord && !pDoc->IsUndoEnabled())
3589 bRecord = false;
3590 SCTAB nTab = rPos.Tab();
3591 SfxBindings* pBindings = rDocShell.GetViewBindings();
3593 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3594 static_cast<SCCOLROW>(rPos.Row());
3596 ScBreakType nBreak;
3597 if (bColumn)
3598 nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab);
3599 else
3600 nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3601 if ((nBreak & BREAK_MANUAL) == 0)
3602 // There is no manual break.
3603 return false;
3605 if (bRecord)
3606 rDocShell.GetUndoManager()->AddUndoAction(
3607 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, false ) );
3609 if (bColumn)
3610 pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3611 else
3612 pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3614 pDoc->UpdatePageBreaks( nTab );
3616 if (pDoc->IsStreamValid(nTab))
3617 pDoc->SetStreamValid(nTab, false);
3619 if (bColumn)
3621 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3622 if (pBindings)
3624 pBindings->Invalidate( FID_INS_COLBRK );
3625 pBindings->Invalidate( FID_DEL_COLBRK );
3628 else
3630 rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3631 if (pBindings)
3633 pBindings->Invalidate( FID_INS_ROWBRK );
3634 pBindings->Invalidate( FID_DEL_ROWBRK );
3637 if (pBindings)
3638 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3640 if (bSetModified)
3641 aModificator.SetDocumentModified();
3643 return true;
3646 void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
3648 ScDocument* pDoc = rDocShell.GetDocument();
3650 pDoc->SetTabProtection(nTab, &rProtect);
3651 if (pDoc->IsUndoEnabled())
3653 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3654 OSL_ENSURE(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3655 if (pProtect)
3657 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3658 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3659 SAL_WNODEPRECATED_DECLARATIONS_POP
3660 p->setProtected(true); // just in case ...
3661 rDocShell.GetUndoManager()->AddUndoAction(
3662 new ScUndoTabProtect(&rDocShell, nTab, p) );
3664 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3668 rDocShell.PostPaintGridAll();
3669 ScDocShellModificator aModificator(rDocShell);
3670 aModificator.SetDocumentModified();
3673 bool ScDocFunc::Protect( SCTAB nTab, const OUString& rPassword, bool /*bApi*/ )
3675 ScDocument* pDoc = rDocShell.GetDocument();
3676 if (nTab == TABLEID_DOC)
3678 // document protection
3679 ScDocProtection aProtection;
3680 aProtection.setProtected(true);
3681 aProtection.setPassword(rPassword);
3682 pDoc->SetDocProtection(&aProtection);
3683 if (pDoc->IsUndoEnabled())
3685 ScDocProtection* pProtect = pDoc->GetDocProtection();
3686 OSL_ENSURE(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
3687 if (pProtect)
3689 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3690 ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
3691 SAL_WNODEPRECATED_DECLARATIONS_POP
3692 p->setProtected(true); // just in case ...
3693 rDocShell.GetUndoManager()->AddUndoAction(
3694 new ScUndoDocProtect(&rDocShell, p) );
3695 // ownership of auto_ptr is transferred to ScUndoDocProtect.
3699 else
3701 // sheet protection
3703 ScTableProtection aProtection;
3704 aProtection.setProtected(true);
3705 aProtection.setPassword(rPassword);
3706 pDoc->SetTabProtection(nTab, &aProtection);
3707 if (pDoc->IsUndoEnabled())
3709 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3710 OSL_ENSURE(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3711 if (pProtect)
3713 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3714 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3715 SAL_WNODEPRECATED_DECLARATIONS_POP
3716 p->setProtected(true); // just in case ...
3717 rDocShell.GetUndoManager()->AddUndoAction(
3718 new ScUndoTabProtect(&rDocShell, nTab, p) );
3719 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3724 rDocShell.PostPaintGridAll();
3725 ScDocShellModificator aModificator( rDocShell );
3726 aModificator.SetDocumentModified();
3728 return true;
3731 bool ScDocFunc::Unprotect( SCTAB nTab, const OUString& rPassword, bool bApi )
3733 ScDocument* pDoc = rDocShell.GetDocument();
3735 if (nTab == TABLEID_DOC)
3737 // document protection
3739 ScDocProtection* pDocProtect = pDoc->GetDocProtection();
3740 if (!pDocProtect || !pDocProtect->isProtected())
3741 // already unprotected (should not happen)!
3742 return true;
3744 // save the protection state before unprotect (for undo).
3745 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3746 ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
3747 SAL_WNODEPRECATED_DECLARATIONS_POP
3749 if (!pDocProtect->verifyPassword(rPassword))
3751 if (!bApi)
3753 InfoBox aBox( rDocShell.GetActiveDialogParent(), OUString( ScResId( SCSTR_WRONGPASSWORD ) ) );
3754 aBox.Execute();
3756 return false;
3759 pDoc->SetDocProtection(NULL);
3760 if (pDoc->IsUndoEnabled())
3762 pProtectCopy->setProtected(false);
3763 rDocShell.GetUndoManager()->AddUndoAction(
3764 new ScUndoDocProtect(&rDocShell, pProtectCopy) );
3765 // ownership of auto_ptr now transferred to ScUndoDocProtect.
3768 else
3770 // sheet protection
3772 ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
3773 if (!pTabProtect || !pTabProtect->isProtected())
3774 // already unprotected (should not happen)!
3775 return true;
3777 // save the protection state before unprotect (for undo).
3778 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3779 ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
3780 SAL_WNODEPRECATED_DECLARATIONS_POP
3781 if (!pTabProtect->verifyPassword(rPassword))
3783 if (!bApi)
3785 InfoBox aBox( rDocShell.GetActiveDialogParent(), OUString( ScResId( SCSTR_WRONGPASSWORD ) ) );
3786 aBox.Execute();
3788 return false;
3791 pDoc->SetTabProtection(nTab, NULL);
3792 if (pDoc->IsUndoEnabled())
3794 pProtectCopy->setProtected(false);
3795 rDocShell.GetUndoManager()->AddUndoAction(
3796 new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
3797 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3801 rDocShell.PostPaintGridAll();
3802 ScDocShellModificator aModificator( rDocShell );
3803 aModificator.SetDocumentModified();
3805 return true;
3808 bool ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, bool bApi )
3810 ScDocShellModificator aModificator( rDocShell );
3812 ScDocument* pDoc = rDocShell.GetDocument();
3813 bool bUndo (pDoc->IsUndoEnabled());
3814 ScEditableTester aTester( pDoc, rMark );
3815 if (!aTester.IsEditable())
3817 if (!bApi)
3818 rDocShell.ErrorMessage(aTester.GetMessageId());
3819 return false;
3822 // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
3823 // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
3824 // here.
3826 ScRange aMarkRange;
3827 ScMarkData aMultiMark = rMark;
3828 aMultiMark.SetMarking(false); // for MarkToMulti
3829 aMultiMark.MarkToMulti();
3830 aMultiMark.GetMultiMarkArea( aMarkRange );
3832 if (bUndo)
3834 SCTAB nStartTab = aMarkRange.aStart.Tab();
3835 SCTAB nEndTab = aMarkRange.aEnd.Tab();
3837 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3838 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3839 pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, true, pUndoDoc, (ScMarkData*)&aMultiMark );
3841 rDocShell.GetUndoManager()->AddUndoAction(
3842 new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) );
3845 pDoc->ClearSelectionItems( pWhich, aMultiMark );
3847 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3848 aModificator.SetDocumentModified();
3850 //! Bindings-Invalidate etc.?
3852 return true;
3855 bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, bool bIncrement, bool bApi )
3857 ScDocShellModificator aModificator( rDocShell );
3859 ScDocument* pDoc = rDocShell.GetDocument();
3860 bool bUndo(pDoc->IsUndoEnabled());
3861 ScEditableTester aTester( pDoc, rMark );
3862 if (!aTester.IsEditable())
3864 if (!bApi)
3865 rDocShell.ErrorMessage(aTester.GetMessageId());
3866 return false;
3869 ScRange aMarkRange;
3870 rMark.GetMultiMarkArea( aMarkRange );
3872 if (bUndo)
3874 SCTAB nStartTab = aMarkRange.aStart.Tab();
3875 SCTAB nTabCount = pDoc->GetTableCount();
3877 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3878 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
3879 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
3880 for (; itr != itrEnd && *itr < nTabCount; ++itr)
3881 if (*itr != nStartTab)
3882 pUndoDoc->AddUndoTab( *itr, *itr );
3884 ScRange aCopyRange = aMarkRange;
3885 aCopyRange.aStart.SetTab(0);
3886 aCopyRange.aEnd.SetTab(nTabCount-1);
3887 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, true, pUndoDoc, (ScMarkData*)&rMark );
3889 rDocShell.GetUndoManager()->AddUndoAction(
3890 new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) );
3893 pDoc->ChangeSelectionIndent( bIncrement, rMark );
3895 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3896 aModificator.SetDocumentModified();
3898 SfxBindings* pBindings = rDocShell.GetViewBindings();
3899 if (pBindings)
3901 pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links
3902 pBindings->Invalidate( SID_ALIGNRIGHT );
3903 pBindings->Invalidate( SID_ALIGNBLOCK );
3904 pBindings->Invalidate( SID_ALIGNCENTERHOR );
3905 pBindings->Invalidate( SID_ATTR_LRSPACE );
3906 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_LEFT );
3907 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT );
3908 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK );
3909 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_CENTER);
3910 // pseudo slots for Format menu
3911 pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT );
3912 pBindings->Invalidate( SID_ALIGN_ANY_LEFT );
3913 pBindings->Invalidate( SID_ALIGN_ANY_HCENTER );
3914 pBindings->Invalidate( SID_ALIGN_ANY_RIGHT );
3915 pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED );
3918 return true;
3921 bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
3922 sal_uInt16 nFormatNo, bool bRecord, bool bApi )
3924 ScDocShellModificator aModificator( rDocShell );
3926 bool bSuccess = false;
3927 ScDocument* pDoc = rDocShell.GetDocument();
3928 SCCOL nStartCol = rRange.aStart.Col();
3929 SCROW nStartRow = rRange.aStart.Row();
3930 SCTAB nStartTab = rRange.aStart.Tab();
3931 SCCOL nEndCol = rRange.aEnd.Col();
3932 SCROW nEndRow = rRange.aEnd.Row();
3933 SCTAB nEndTab = rRange.aEnd.Tab();
3935 if (bRecord && !pDoc->IsUndoEnabled())
3936 bRecord = false;
3937 ScMarkData aMark;
3938 if (pTabMark)
3939 aMark = *pTabMark;
3940 else
3942 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3943 aMark.SelectTable( nTab, true );
3946 ScAutoFormat* pAutoFormat = ScGlobal::GetOrCreateAutoFormat();
3947 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3948 if ( nFormatNo < pAutoFormat->size() && aTester.IsEditable() )
3950 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3952 bool bSize = pAutoFormat->findByIndex(nFormatNo)->GetIncludeWidthHeight();
3954 SCTAB nTabCount = pDoc->GetTableCount();
3955 ScDocument* pUndoDoc = NULL;
3956 if ( bRecord )
3958 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3959 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize );
3960 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
3961 for (; itr != itrEnd && *itr < nTabCount; ++itr)
3962 if (*itr != nStartTab)
3963 pUndoDoc->AddUndoTab( *itr, *itr, bSize, bSize );
3965 ScRange aCopyRange = rRange;
3966 aCopyRange.aStart.SetTab(0);
3967 aCopyRange.aStart.SetTab(nTabCount-1);
3968 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, false, pUndoDoc, &aMark );
3969 if (bSize)
3971 pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1,
3972 IDF_NONE, false, pUndoDoc, &aMark );
3973 pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1,
3974 IDF_NONE, false, pUndoDoc, &aMark );
3976 pDoc->BeginDrawUndo();
3979 pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark );
3981 if (bSize)
3983 std::vector<sc::ColRowSpan> aCols(1, sc::ColRowSpan(nStartCol,nEndCol));
3984 std::vector<sc::ColRowSpan> aRows(1, sc::ColRowSpan(nStartRow,nEndRow));
3986 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
3987 for (; itr != itrEnd && *itr < nTabCount; ++itr)
3989 SetWidthOrHeight(true, aCols, *itr, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, false, true);
3990 SetWidthOrHeight(false, aRows, *itr, SC_SIZE_VISOPT, 0, false, false);
3991 rDocShell.PostPaint( 0,0,*itr, MAXCOL,MAXROW,*itr,
3992 PAINT_GRID | PAINT_LEFT | PAINT_TOP );
3995 else
3997 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
3998 for (; itr != itrEnd && *itr < nTabCount; ++itr)
4000 bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, *itr,
4001 nEndCol, nEndRow, *itr), false );
4002 if (bAdj)
4003 rDocShell.PostPaint( 0,nStartRow,*itr, MAXCOL,MAXROW,*itr,
4004 PAINT_GRID | PAINT_LEFT );
4005 else
4006 rDocShell.PostPaint( nStartCol, nStartRow, *itr,
4007 nEndCol, nEndRow, *itr, PAINT_GRID );
4011 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4013 rDocShell.GetUndoManager()->AddUndoAction(
4014 new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) );
4017 aModificator.SetDocumentModified();
4019 else if (!bApi)
4020 rDocShell.ErrorMessage(aTester.GetMessageId());
4022 return bSuccess;
4025 bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
4026 const ScTokenArray* pTokenArray, const OUString& rString, bool bApi, bool bEnglish,
4027 const OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
4029 ScDocShellModificator aModificator( rDocShell );
4031 bool bSuccess = false;
4032 ScDocument* pDoc = rDocShell.GetDocument();
4033 SCCOL nStartCol = rRange.aStart.Col();
4034 SCROW nStartRow = rRange.aStart.Row();
4035 SCTAB nStartTab = rRange.aStart.Tab();
4036 SCCOL nEndCol = rRange.aEnd.Col();
4037 SCROW nEndRow = rRange.aEnd.Row();
4038 SCTAB nEndTab = rRange.aEnd.Tab();
4040 bool bUndo(pDoc->IsUndoEnabled());
4042 ScMarkData aMark;
4043 if (pTabMark)
4044 aMark = *pTabMark;
4045 else
4047 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4048 aMark.SelectTable( nTab, true );
4051 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4052 if ( aTester.IsEditable() )
4054 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4056 ScDocument* pUndoDoc = NULL;
4058 if (bUndo)
4060 //! auch bei Undo selektierte Tabellen beruecksichtigen
4061 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4062 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
4063 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, false, pUndoDoc );
4066 // use TokenArray if given, string (and flags) otherwise
4067 if ( pTokenArray )
4069 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4070 aMark, EMPTY_OUSTRING, pTokenArray, eGrammar);
4072 else if ( pDoc->IsImportingXML() )
4074 ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
4075 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4076 aMark, EMPTY_OUSTRING, pCode, eGrammar);
4077 delete pCode;
4078 pDoc->IncXMLImportedFormulaCount( rString.getLength() );
4080 else if (bEnglish)
4082 ScCompiler aComp( pDoc, rRange.aStart);
4083 aComp.SetGrammar(eGrammar);
4084 ScTokenArray* pCode = aComp.CompileString( rString );
4085 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4086 aMark, EMPTY_OUSTRING, pCode, eGrammar);
4087 delete pCode;
4089 else
4090 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
4091 aMark, rString, NULL, eGrammar);
4093 if (bUndo)
4095 //! auch bei Undo selektierte Tabellen beruecksichtigen
4096 rDocShell.GetUndoManager()->AddUndoAction(
4097 new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) );
4100 // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
4101 rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
4102 aModificator.SetDocumentModified();
4104 bSuccess = true;
4106 else if (!bApi)
4107 rDocShell.ErrorMessage(aTester.GetMessageId());
4109 return bSuccess;
4112 bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
4113 const ScTabOpParam& rParam, bool bRecord, bool bApi )
4115 ScDocShellModificator aModificator( rDocShell );
4117 bool bSuccess = false;
4118 ScDocument* pDoc = rDocShell.GetDocument();
4119 SCCOL nStartCol = rRange.aStart.Col();
4120 SCROW nStartRow = rRange.aStart.Row();
4121 SCTAB nStartTab = rRange.aStart.Tab();
4122 SCCOL nEndCol = rRange.aEnd.Col();
4123 SCROW nEndRow = rRange.aEnd.Row();
4124 SCTAB nEndTab = rRange.aEnd.Tab();
4126 if (bRecord && !pDoc->IsUndoEnabled())
4127 bRecord = false;
4129 ScMarkData aMark;
4130 if (pTabMark)
4131 aMark = *pTabMark;
4132 else
4134 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4135 aMark.SelectTable( nTab, true );
4138 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4139 if ( aTester.IsEditable() )
4141 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4142 pDoc->SetDirty( rRange );
4143 if ( bRecord )
4145 //! auch bei Undo selektierte Tabellen beruecksichtigen
4146 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4147 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
4148 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, false, pUndoDoc );
4150 rDocShell.GetUndoManager()->AddUndoAction(
4151 new ScUndoTabOp( &rDocShell,
4152 nStartCol, nStartRow, nStartTab,
4153 nEndCol, nEndRow, nEndTab, pUndoDoc,
4154 rParam.aRefFormulaCell,
4155 rParam.aRefFormulaEnd,
4156 rParam.aRefRowCell,
4157 rParam.aRefColCell,
4158 rParam.meMode) );
4160 pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
4161 rDocShell.PostPaintGridAll();
4162 aModificator.SetDocumentModified();
4163 bSuccess = true;
4165 else if (!bApi)
4166 rDocShell.ErrorMessage(aTester.GetMessageId());
4168 return bSuccess;
4171 inline ScDirection DirFromFillDir( FillDir eDir )
4173 if (eDir==FILL_TO_BOTTOM)
4174 return DIR_BOTTOM;
4175 else if (eDir==FILL_TO_RIGHT)
4176 return DIR_RIGHT;
4177 else if (eDir==FILL_TO_TOP)
4178 return DIR_TOP;
4179 else // if (eDir==FILL_TO_LEFT)
4180 return DIR_LEFT;
4183 namespace {
4186 * Expand the fill range as necessary, to allow copying of adjacent cell(s)
4187 * even when those cells are not in the original range.
4189 void adjustFillRangeForAdjacentCopy(ScRange& rRange, FillDir eDir)
4191 switch (eDir)
4193 case FILL_TO_BOTTOM:
4195 if (rRange.aStart.Row() == 0)
4196 return;
4198 if (rRange.aStart.Row() != rRange.aEnd.Row())
4199 return;
4201 // Include the above row.
4202 ScAddress& s = rRange.aStart;
4203 s.SetRow(s.Row()-1);
4205 break;
4206 case FILL_TO_TOP:
4208 if (rRange.aStart.Row() == MAXROW)
4209 return;
4211 if (rRange.aStart.Row() != rRange.aEnd.Row())
4212 return;
4214 // Include the row below.
4215 ScAddress& e = rRange.aEnd;
4216 e.SetRow(e.Row()+1);
4218 break;
4219 case FILL_TO_LEFT:
4221 if (rRange.aStart.Col() == MAXCOL)
4222 return;
4224 if (rRange.aStart.Col() != rRange.aEnd.Col())
4225 return;
4227 // Include the column to the right.
4228 ScAddress& e = rRange.aEnd;
4229 e.SetCol(e.Col()+1);
4231 break;
4232 case FILL_TO_RIGHT:
4234 if (rRange.aStart.Col() == 0)
4235 return;
4237 if (rRange.aStart.Col() != rRange.aEnd.Col())
4238 return;
4240 // Include the column to the left.
4241 ScAddress& s = rRange.aStart;
4242 s.SetCol(s.Col()-1);
4244 break;
4245 default:
4252 bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
4253 FillDir eDir, bool bRecord, bool bApi )
4255 ScDocShellModificator aModificator( rDocShell );
4256 ScDocument* pDoc = rDocShell.GetDocument();
4258 bool bSuccess = false;
4259 ScRange aRange = rRange;
4260 adjustFillRangeForAdjacentCopy(aRange, eDir);
4262 SCCOL nStartCol = aRange.aStart.Col();
4263 SCROW nStartRow = aRange.aStart.Row();
4264 SCTAB nStartTab = aRange.aStart.Tab();
4265 SCCOL nEndCol = aRange.aEnd.Col();
4266 SCROW nEndRow = aRange.aEnd.Row();
4267 SCTAB nEndTab = aRange.aEnd.Tab();
4269 if (bRecord && !pDoc->IsUndoEnabled())
4270 bRecord = false;
4272 ScMarkData aMark;
4273 if (pTabMark)
4274 aMark = *pTabMark;
4275 else
4277 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4278 aMark.SelectTable( nTab, true );
4281 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4282 if ( aTester.IsEditable() )
4284 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4286 ScRange aSourceArea = aRange;
4287 ScRange aDestArea = aRange;
4289 SCCOLROW nCount = 0;
4290 switch (eDir)
4292 case FILL_TO_BOTTOM:
4293 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4294 aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() );
4295 break;
4296 case FILL_TO_RIGHT:
4297 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4298 aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() );
4299 break;
4300 case FILL_TO_TOP:
4301 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4302 aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() );
4303 break;
4304 case FILL_TO_LEFT:
4305 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4306 aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() );
4307 break;
4310 ScDocument* pUndoDoc = NULL;
4311 if ( bRecord )
4313 SCTAB nTabCount = pDoc->GetTableCount();
4314 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4316 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4317 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4318 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
4319 for (; itr != itrEnd && *itr < nTabCount; ++itr)
4320 if (*itr != nDestStartTab)
4321 pUndoDoc->AddUndoTab( *itr, *itr );
4323 ScRange aCopyRange = aDestArea;
4324 aCopyRange.aStart.SetTab(0);
4325 aCopyRange.aEnd.SetTab(nTabCount-1);
4326 pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, false, pUndoDoc, &aMark );
4329 sal_uLong nProgCount;
4330 if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP)
4331 nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1;
4332 else
4333 nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1;
4334 nProgCount *= nCount;
4335 ScProgress aProgress( pDoc->GetDocumentShell(),
4336 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
4338 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4339 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress,
4340 aMark, nCount, eDir, FILL_SIMPLE );
4341 AdjustRowHeight(aRange);
4343 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4345 rDocShell.GetUndoManager()->AddUndoAction(
4346 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4347 eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307) );
4350 rDocShell.PostPaintGridAll();
4351 aModificator.SetDocumentModified();
4353 bSuccess = true;
4355 else if (!bApi)
4356 rDocShell.ErrorMessage(aTester.GetMessageId());
4358 return bSuccess;
4361 bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
4362 FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
4363 double fStart, double fStep, double fMax,
4364 bool bRecord, bool bApi )
4366 ScDocShellModificator aModificator( rDocShell );
4368 bool bSuccess = false;
4369 ScDocument* pDoc = rDocShell.GetDocument();
4370 SCCOL nStartCol = rRange.aStart.Col();
4371 SCROW nStartRow = rRange.aStart.Row();
4372 SCTAB nStartTab = rRange.aStart.Tab();
4373 SCCOL nEndCol = rRange.aEnd.Col();
4374 SCROW nEndRow = rRange.aEnd.Row();
4375 SCTAB nEndTab = rRange.aEnd.Tab();
4377 if (bRecord && !pDoc->IsUndoEnabled())
4378 bRecord = false;
4380 ScMarkData aMark;
4381 if (pTabMark)
4382 aMark = *pTabMark;
4383 else
4385 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4386 aMark.SelectTable( nTab, true );
4389 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4390 if ( aTester.IsEditable() )
4392 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4394 ScRange aSourceArea = rRange;
4395 ScRange aDestArea = rRange;
4397 SCSIZE nCount = pDoc->GetEmptyLinesInBlock(
4398 aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(),
4399 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(),
4400 DirFromFillDir(eDir) );
4402 // mindestens eine Zeile/Spalte als Quellbereich behalten:
4403 SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ?
4404 static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) :
4405 static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 );
4406 if ( nCount >= nTotLines )
4407 nCount = nTotLines - 1;
4409 switch (eDir)
4411 case FILL_TO_BOTTOM:
4412 aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) );
4413 break;
4414 case FILL_TO_RIGHT:
4415 aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) );
4416 break;
4417 case FILL_TO_TOP:
4418 aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) );
4419 break;
4420 case FILL_TO_LEFT:
4421 aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) );
4422 break;
4425 ScDocument* pUndoDoc = NULL;
4426 if ( bRecord )
4428 SCTAB nTabCount = pDoc->GetTableCount();
4429 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4431 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4432 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4433 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
4434 for (; itr != itrEnd && *itr < nTabCount; ++itr)
4435 if (*itr != nDestStartTab)
4436 pUndoDoc->AddUndoTab( *itr, *itr );
4438 pDoc->CopyToDocument(
4439 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4440 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4441 IDF_AUTOFILL, false, pUndoDoc, &aMark );
4444 if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() &&
4445 aDestArea.aStart.Row() <= aDestArea.aEnd.Row())
4447 if ( fStart != MAXDOUBLE )
4449 SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col();
4450 SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row();
4451 SCTAB nTab = aDestArea.aStart.Tab();
4452 pDoc->SetValue( nValX, nValY, nTab, fStart );
4455 sal_uLong nProgCount;
4456 if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP)
4457 nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1;
4458 else
4459 nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1;
4460 nProgCount *= nCount;
4461 ScProgress aProgress( pDoc->GetDocumentShell(),
4462 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
4464 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4465 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress,
4466 aMark, nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4467 AdjustRowHeight(rRange);
4469 rDocShell.PostPaintGridAll();
4470 aModificator.SetDocumentModified();
4473 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4475 rDocShell.GetUndoManager()->AddUndoAction(
4476 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4477 eDir, eCmd, eDateCmd, fStart, fStep, fMax) );
4480 bSuccess = true;
4482 else if (!bApi)
4483 rDocShell.ErrorMessage(aTester.GetMessageId());
4485 return bSuccess;
4488 bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
4489 FillDir eDir, sal_uLong nCount, bool bRecord, bool bApi )
4491 double fStep = 1.0;
4492 double fMax = MAXDOUBLE;
4493 return FillAuto( rRange, pTabMark, eDir, FILL_AUTO, FILL_DAY, nCount, fStep, fMax, bRecord, bApi );
4496 bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, sal_uLong nCount, double fStep, double fMax, bool bRecord, bool bApi )
4498 ScDocShellModificator aModificator( rDocShell );
4500 ScDocument* pDoc = rDocShell.GetDocument();
4501 SCCOL nStartCol = rRange.aStart.Col();
4502 SCROW nStartRow = rRange.aStart.Row();
4503 SCTAB nStartTab = rRange.aStart.Tab();
4504 SCCOL nEndCol = rRange.aEnd.Col();
4505 SCROW nEndRow = rRange.aEnd.Row();
4506 SCTAB nEndTab = rRange.aEnd.Tab();
4508 if (bRecord && !pDoc->IsUndoEnabled())
4509 bRecord = false;
4511 ScMarkData aMark;
4512 if (pTabMark)
4513 aMark = *pTabMark;
4514 else
4516 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4517 aMark.SelectTable( nTab, true );
4520 ScRange aSourceArea = rRange;
4521 ScRange aDestArea = rRange;
4524 switch (eDir)
4526 case FILL_TO_BOTTOM:
4527 aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) );
4528 break;
4529 case FILL_TO_TOP:
4530 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() ))
4532 OSL_FAIL("FillAuto: Row < 0");
4533 nCount = aSourceArea.aStart.Row();
4535 aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) );
4536 break;
4537 case FILL_TO_RIGHT:
4538 aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) );
4539 break;
4540 case FILL_TO_LEFT:
4541 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() ))
4543 OSL_FAIL("FillAuto: Col < 0");
4544 nCount = aSourceArea.aStart.Col();
4546 aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) );
4547 break;
4548 default:
4549 OSL_FAIL("Falsche Richtung bei FillAuto");
4550 break;
4553 // Zellschutz testen
4554 //! Quellbereich darf geschuetzt sein !!!
4555 //! aber kein Matrixfragment enthalten !!!
4557 ScEditableTester aTester( pDoc, aDestArea );
4558 if ( !aTester.IsEditable() )
4560 if (!bApi)
4561 rDocShell.ErrorMessage(aTester.GetMessageId());
4562 return false;
4565 if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow,
4566 nEndCol, nEndRow, aMark ) )
4568 if (!bApi)
4569 rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR);
4570 return false;
4573 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4575 ScDocument* pUndoDoc = NULL;
4576 if ( bRecord )
4578 SCTAB nTabCount = pDoc->GetTableCount();
4579 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4581 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4582 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4583 ScMarkData::iterator itr = aMark.begin(), itrEnd = aMark.end();
4584 for (; itr != itrEnd && nTabCount; ++itr)
4585 if (*itr != nDestStartTab)
4586 pUndoDoc->AddUndoTab( *itr, *itr );
4588 // do not clone note captions in undo document
4589 pDoc->CopyToDocument(
4590 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4591 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4592 IDF_AUTOFILL, false, pUndoDoc, &aMark );
4595 sal_uLong nProgCount;
4596 if (eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP)
4597 nProgCount = aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1;
4598 else
4599 nProgCount = aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1;
4600 nProgCount *= nCount;
4601 ScProgress aProgress( pDoc->GetDocumentShell(),
4602 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
4604 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4605 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), &aProgress,
4606 aMark, nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4608 AdjustRowHeight(aDestArea);
4610 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4612 rDocShell.GetUndoManager()->AddUndoAction(
4613 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4614 eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax) );
4617 rDocShell.PostPaintGridAll();
4618 aModificator.SetDocumentModified();
4620 rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren)
4621 return true;
4624 bool ScDocFunc::MergeCells( const ScCellMergeOption& rOption, bool bContents, bool bRecord, bool bApi )
4626 using ::std::set;
4628 ScDocShellModificator aModificator( rDocShell );
4630 SCCOL nStartCol = rOption.mnStartCol;
4631 SCROW nStartRow = rOption.mnStartRow;
4632 SCCOL nEndCol = rOption.mnEndCol;
4633 SCROW nEndRow = rOption.mnEndRow;
4634 if ((nStartCol == nEndCol && nStartRow == nEndRow) || rOption.maTabs.empty())
4636 // Nothing to do. Bail out quick.
4637 return true;
4640 ScDocument* pDoc = rDocShell.GetDocument();
4641 set<SCTAB>::const_iterator itrBeg = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
4642 SCTAB nTab1 = *itrBeg, nTab2 = *rOption.maTabs.rbegin();
4644 if (bRecord && !pDoc->IsUndoEnabled())
4645 bRecord = false;
4647 for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
4649 ScEditableTester aTester( pDoc, *itr, nStartCol, nStartRow, nEndCol, nEndRow );
4650 if (!aTester.IsEditable())
4652 if (!bApi)
4653 rDocShell.ErrorMessage(aTester.GetMessageId());
4654 return false;
4657 if ( pDoc->HasAttrib( nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr,
4658 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
4660 // "Zusammenfassen nicht verschachteln !"
4661 if (!bApi)
4662 rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
4663 return false;
4667 ScDocument* pUndoDoc = NULL;
4668 bool bNeedContentsUndo = false;
4669 for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
4671 SCTAB nTab = *itr;
4672 bool bNeedContents = bContents &&
4673 ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
4674 !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
4676 if (bRecord)
4678 // test if the range contains other notes which also implies that we need an undo document
4679 bool bHasNotes = false;
4680 for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
4681 for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
4682 bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->HasNote(aPos));
4684 if (!pUndoDoc)
4686 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4687 pUndoDoc->InitUndo(pDoc, nTab1, nTab2);
4689 // note captions are collected by drawing undo
4690 pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
4691 IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
4692 if( bHasNotes )
4693 pDoc->BeginDrawUndo();
4696 if (bNeedContents)
4697 pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4698 pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4700 if (rOption.mbCenter)
4702 pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
4703 pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) );
4706 if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
4707 rDocShell.PostPaint( nStartCol, nStartRow, nTab,
4708 nEndCol, nEndRow, nTab, PAINT_GRID );
4709 if (bNeedContents || rOption.mbCenter)
4711 ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab);
4712 pDoc->SetDirty(aRange);
4715 bNeedContentsUndo |= bNeedContents;
4718 if (pUndoDoc)
4720 SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : NULL;
4721 rDocShell.GetUndoManager()->AddUndoAction(
4722 new ScUndoMerge(&rDocShell, rOption, bNeedContentsUndo, pUndoDoc, pDrawUndo) );
4725 aModificator.SetDocumentModified();
4727 SfxBindings* pBindings = rDocShell.GetViewBindings();
4728 if (pBindings)
4730 pBindings->Invalidate( FID_MERGE_ON );
4731 pBindings->Invalidate( FID_MERGE_OFF );
4732 pBindings->Invalidate( FID_MERGE_TOGGLE );
4735 return true;
4738 bool ScDocFunc::UnmergeCells( const ScRange& rRange, bool bRecord )
4740 ScCellMergeOption aOption(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
4741 SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
4742 for (SCTAB i = nTab1; i <= nTab2; ++i)
4743 aOption.maTabs.insert(i);
4745 return UnmergeCells(aOption, bRecord);
4748 bool ScDocFunc::UnmergeCells( const ScCellMergeOption& rOption, bool bRecord )
4750 using ::std::set;
4752 if (rOption.maTabs.empty())
4753 // Nothing to unmerge.
4754 return true;
4756 ScDocShellModificator aModificator( rDocShell );
4757 ScDocument* pDoc = rDocShell.GetDocument();
4759 if (bRecord && !pDoc->IsUndoEnabled())
4760 bRecord = false;
4762 ScDocument* pUndoDoc = NULL;
4763 for (set<SCTAB>::const_iterator itr = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
4764 itr != itrEnd; ++itr)
4766 SCTAB nTab = *itr;
4767 ScRange aRange = rOption.getSingleRange(nTab);
4768 if ( !pDoc->HasAttrib(aRange, HASATTR_MERGED) )
4769 continue;
4771 ScRange aExtended = aRange;
4772 pDoc->ExtendMerge(aExtended);
4773 ScRange aRefresh = aExtended;
4774 pDoc->ExtendOverlapped(aRefresh);
4776 if (bRecord)
4778 if (!pUndoDoc)
4780 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4781 pUndoDoc->InitUndo(pDoc, *rOption.maTabs.begin(), *rOption.maTabs.rbegin());
4783 pDoc->CopyToDocument(aExtended, IDF_ATTRIB, false, pUndoDoc);
4786 const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
4787 ScPatternAttr aPattern( pDoc->GetPool() );
4788 aPattern.GetItemSet().Put( rDefAttr );
4789 pDoc->ApplyPatternAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
4790 aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
4791 aPattern );
4793 pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
4794 aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
4795 SC_MF_HOR | SC_MF_VER );
4797 pDoc->ExtendMerge( aRefresh, true );
4799 if ( !AdjustRowHeight( aExtended ) )
4800 rDocShell.PostPaint( aExtended, PAINT_GRID );
4803 if (bRecord)
4805 rDocShell.GetUndoManager()->AddUndoAction(
4806 new ScUndoRemoveMerge( &rDocShell, rOption, pUndoDoc ) );
4808 aModificator.SetDocumentModified();
4810 return true;
4813 bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, SCTAB nTab )
4815 return SetNewRangeNames( new ScRangeName(rNewRanges), true, nTab );
4818 bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, bool bModifyDoc, SCTAB nTab ) // takes ownership of pNewRanges
4820 ScDocShellModificator aModificator( rDocShell );
4822 OSL_ENSURE( pNewRanges, "pNewRanges is 0" );
4823 ScDocument* pDoc = rDocShell.GetDocument();
4824 bool bUndo(pDoc->IsUndoEnabled());
4826 if (bUndo)
4828 ScRangeName* pOld;
4829 if (nTab >=0)
4831 pOld = pDoc->GetRangeName(nTab);
4833 else
4835 pOld = pDoc->GetRangeName();
4837 ScRangeName* pUndoRanges = new ScRangeName(*pOld);
4838 ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges);
4839 rDocShell.GetUndoManager()->AddUndoAction(
4840 new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges, nTab ) );
4843 // #i55926# While loading XML, formula cells only have a single string token,
4844 // so CompileNameFormula would never find any name (index) tokens, and would
4845 // unnecessarily loop through all cells.
4846 bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
4848 if ( bCompile )
4849 pDoc->PreprocessRangeNameUpdate();
4850 if (nTab >= 0)
4851 pDoc->SetRangeName( nTab, pNewRanges ); // takes ownership
4852 else
4853 pDoc->SetRangeName( pNewRanges ); // takes ownership
4854 if ( bCompile )
4855 pDoc->CompileHybridFormula();
4857 if (bModifyDoc)
4859 aModificator.SetDocumentModified();
4860 SFX_APP()->Broadcast( SfxSimpleHint(SC_HINT_AREAS_CHANGED) );
4863 return true;
4866 void ScDocFunc::ModifyAllRangeNames( const boost::ptr_map<OUString, ScRangeName>& rRangeMap )
4868 ScDocShellModificator aModificator(rDocShell);
4869 ScDocument* pDoc = rDocShell.GetDocument();
4871 if (pDoc->IsUndoEnabled())
4873 std::map<OUString, ScRangeName*> aOldRangeMap;
4874 pDoc->GetRangeNameMap(aOldRangeMap);
4875 rDocShell.GetUndoManager()->AddUndoAction(
4876 new ScUndoAllRangeNames(&rDocShell, aOldRangeMap, rRangeMap));
4879 pDoc->PreprocessRangeNameUpdate();
4880 pDoc->SetAllRangeNames(rRangeMap);
4881 pDoc->CompileHybridFormula();
4883 aModificator.SetDocumentModified();
4884 SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
4887 void ScDocFunc::CreateOneName( ScRangeName& rList,
4888 SCCOL nPosX, SCROW nPosY, SCTAB nTab,
4889 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
4890 bool& rCancel, bool bApi )
4892 if (rCancel)
4893 return;
4895 ScDocument* pDoc = rDocShell.GetDocument();
4896 if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
4898 OUString aName = pDoc->GetString(nPosX, nPosY, nTab);
4899 ScRangeData::MakeValidName(aName);
4900 if (!aName.isEmpty())
4902 OUString aContent(ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format(SCR_ABS_3D, pDoc));
4904 bool bInsert = false;
4905 ScRangeData* pOld = rList.findByUpperName(ScGlobal::pCharClass->uppercase(aName));
4906 if (pOld)
4908 OUString aOldStr;
4909 pOld->GetSymbol( aOldStr );
4910 if (aOldStr != aContent)
4912 if (bApi)
4913 bInsert = true; // per API nicht nachfragen
4914 else
4916 OUString aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
4918 OUString aMessage = aTemplate.getToken( 0, '#' );
4919 aMessage += aName;
4920 aMessage += aTemplate.getToken( 1, '#' );
4922 short nResult = QueryBox( rDocShell.GetActiveDialogParent(),
4923 WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
4924 aMessage ).Execute();
4925 if ( nResult == RET_YES )
4927 rList.erase(*pOld);
4928 bInsert = true;
4930 else if ( nResult == RET_CANCEL )
4931 rCancel = true;
4935 else
4936 bInsert = true;
4938 if (bInsert)
4940 ScRangeData* pData = new ScRangeData( pDoc, aName, aContent,
4941 ScAddress( nPosX, nPosY, nTab));
4942 if (!rList.insert(pData))
4944 OSL_FAIL("nanu?");
4951 bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, bool bApi, SCTAB aTab )
4953 if (!nFlags)
4954 return false; // war nix
4956 ScDocShellModificator aModificator( rDocShell );
4958 bool bDone = false;
4959 SCCOL nStartCol = rRange.aStart.Col();
4960 SCROW nStartRow = rRange.aStart.Row();
4961 SCCOL nEndCol = rRange.aEnd.Col();
4962 SCROW nEndRow = rRange.aEnd.Row();
4963 SCTAB nTab = rRange.aStart.Tab();
4964 OSL_ENSURE(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
4966 bool bValid = true;
4967 if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
4968 if ( nStartRow == nEndRow )
4969 bValid = false;
4970 if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
4971 if ( nStartCol == nEndCol )
4972 bValid = false;
4974 if (bValid)
4976 ScDocument* pDoc = rDocShell.GetDocument();
4977 ScRangeName* pNames;
4978 if (aTab >=0)
4979 pNames = pDoc->GetRangeName(nTab);
4980 else
4981 pNames = pDoc->GetRangeName();
4983 if (!pNames)
4984 return false; // soll nicht sein
4985 ScRangeName aNewRanges( *pNames );
4987 bool bTop = ( ( nFlags & NAME_TOP ) != 0 );
4988 bool bLeft = ( ( nFlags & NAME_LEFT ) != 0 );
4989 bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
4990 bool bRight = ( ( nFlags & NAME_RIGHT ) != 0 );
4992 SCCOL nContX1 = nStartCol;
4993 SCROW nContY1 = nStartRow;
4994 SCCOL nContX2 = nEndCol;
4995 SCROW nContY2 = nEndRow;
4997 if ( bTop )
4998 ++nContY1;
4999 if ( bLeft )
5000 ++nContX1;
5001 if ( bBottom )
5002 --nContY2;
5003 if ( bRight )
5004 --nContX2;
5006 bool bCancel = false;
5007 SCCOL i;
5008 SCROW j;
5010 if ( bTop )
5011 for (i=nContX1; i<=nContX2; i++)
5012 CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
5013 if ( bLeft )
5014 for (j=nContY1; j<=nContY2; j++)
5015 CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
5016 if ( bBottom )
5017 for (i=nContX1; i<=nContX2; i++)
5018 CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
5019 if ( bRight )
5020 for (j=nContY1; j<=nContY2; j++)
5021 CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
5023 if ( bTop && bLeft )
5024 CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5025 if ( bTop && bRight )
5026 CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5027 if ( bBottom && bLeft )
5028 CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5029 if ( bBottom && bRight )
5030 CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
5032 bDone = ModifyRangeNames( aNewRanges, aTab );
5034 aModificator.SetDocumentModified();
5035 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
5038 return bDone;
5041 bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, bool bApi )
5043 ScDocShellModificator aModificator( rDocShell );
5045 bool bDone = false;
5046 ScDocument* pDoc = rDocShell.GetDocument();
5047 const bool bRecord = pDoc->IsUndoEnabled();
5048 SCTAB nTab = rStartPos.Tab();
5049 ScDocument* pUndoDoc = NULL;
5051 //local names have higher priority than global names
5052 ScRangeName* pLocalList = pDoc->GetRangeName(nTab);
5053 sal_uInt16 nValidCount = 0;
5054 ScRangeName::iterator itrLocalBeg = pLocalList->begin(), itrLocalEnd = pLocalList->end();
5055 for (ScRangeName::iterator itr = itrLocalBeg; itr != itrLocalEnd; ++itr)
5057 const ScRangeData& r = *itr->second;
5058 if (!r.HasType(RT_DATABASE))
5059 ++nValidCount;
5061 ScRangeName* pList = pDoc->GetRangeName();
5062 ScRangeName::iterator itrBeg = pList->begin(), itrEnd = pList->end();
5063 for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
5065 const ScRangeData& r = *itr->second;
5066 if (!r.HasType(RT_DATABASE) && !pLocalList->findByUpperName(r.GetUpperName()))
5067 ++nValidCount;
5070 if (nValidCount)
5072 SCCOL nStartCol = rStartPos.Col();
5073 SCROW nStartRow = rStartPos.Row();
5074 SCCOL nEndCol = nStartCol + 1;
5075 SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1;
5077 ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
5078 if (aTester.IsEditable())
5080 if (bRecord)
5082 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
5083 pUndoDoc->InitUndo( pDoc, nTab, nTab );
5084 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
5085 IDF_ALL, false, pUndoDoc );
5087 pDoc->BeginDrawUndo(); // wegen Hoehenanpassung
5090 boost::scoped_array<ScRangeData*> ppSortArray(new ScRangeData* [ nValidCount ]);
5091 sal_uInt16 j = 0;
5092 for (ScRangeName::iterator itr = itrLocalBeg; itr != itrLocalEnd; ++itr)
5094 ScRangeData& r = *itr->second;
5095 if (!r.HasType(RT_DATABASE))
5096 ppSortArray[j++] = &r;
5098 for (ScRangeName::iterator itr = itrBeg; itr != itrEnd; ++itr)
5100 ScRangeData& r = *itr->second;
5101 if (!r.HasType(RT_DATABASE) && !pLocalList->findByUpperName(itr->first))
5102 ppSortArray[j++] = &r;
5104 qsort( (void*)ppSortArray.get(), nValidCount, sizeof(ScRangeData*),
5105 &ScRangeData_QsortNameCompare );
5106 OUString aName;
5107 OUStringBuffer aContent;
5108 OUString aFormula;
5109 SCROW nOutRow = nStartRow;
5110 for (j=0; j<nValidCount; j++)
5112 ScRangeData* pData = ppSortArray[j];
5113 pData->GetName(aName);
5114 // relative Referenzen Excel-konform auf die linke Spalte anpassen:
5115 pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
5116 aFormula = "=" + aContent.toString();
5117 ScSetStringParam aParam;
5118 aParam.setTextInput();
5119 pDoc->SetString(ScAddress(nStartCol,nOutRow,nTab), aName, &aParam);
5120 pDoc->SetString(ScAddress(nEndCol,nOutRow,nTab), aFormula, &aParam);
5121 ++nOutRow;
5124 ppSortArray.reset();
5126 if (bRecord)
5128 ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
5129 pRedoDoc->InitUndo( pDoc, nTab, nTab );
5130 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
5131 IDF_ALL, false, pRedoDoc );
5133 rDocShell.GetUndoManager()->AddUndoAction(
5134 new ScUndoListNames( &rDocShell,
5135 ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ),
5136 pUndoDoc, pRedoDoc ) );
5139 if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
5140 rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
5142 aModificator.SetDocumentModified();
5143 bDone = true;
5145 else if (!bApi)
5146 rDocShell.ErrorMessage(aTester.GetMessageId());
5148 return bDone;
5151 bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, bool bApi )
5153 ScDocument* pDoc = rDocShell.GetDocument();
5154 SCCOL nStartCol = rOldRange.aStart.Col();
5155 SCROW nStartRow = rOldRange.aStart.Row();
5156 SCTAB nTab = rOldRange.aStart.Tab();
5158 bool bUndo(pDoc->IsUndoEnabled());
5160 bool bRet = false;
5162 OUString aFormula;
5163 pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula );
5164 if ( aFormula.startsWith("{") && aFormula.endsWith("}") )
5166 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX );
5167 if (bUndo)
5168 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
5170 aFormula = aFormula.copy(1, aFormula.getLength()-2);
5172 ScMarkData aMark;
5173 aMark.SetMarkArea( rOldRange );
5174 aMark.SelectTable( nTab, true );
5175 ScRange aNewRange( rOldRange.aStart, rNewEnd );
5177 if ( DeleteContents( aMark, IDF_CONTENTS, true, bApi ) )
5179 // GRAM_PODF_A1 for API compatibility.
5180 bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, false, EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_PODF_A1 );
5181 if (!bRet)
5183 // versuchen, alten Zustand wiederherzustellen
5184 EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, false, EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_PODF_A1 );
5188 if (bUndo)
5189 rDocShell.GetUndoManager()->LeaveListAction();
5192 return bRet;
5195 bool ScDocFunc::InsertAreaLink( const OUString& rFile, const OUString& rFilter,
5196 const OUString& rOptions, const OUString& rSource,
5197 const ScRange& rDestRange, sal_uLong nRefresh,
5198 bool bFitBlock, bool bApi )
5200 ScDocument* pDoc = rDocShell.GetDocument();
5201 bool bUndo (pDoc->IsUndoEnabled());
5203 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
5205 // #i52120# if other area links exist at the same start position,
5206 // remove them first (file format specifies only one link definition
5207 // for a cell)
5209 sal_uInt16 nLinkCount = pLinkManager->GetLinks().size();
5210 sal_uInt16 nRemoved = 0;
5211 sal_uInt16 nLinkPos = 0;
5212 while (nLinkPos<nLinkCount)
5214 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
5215 if ( pBase->ISA(ScAreaLink) &&
5216 static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart )
5218 if ( bUndo )
5220 if ( !nRemoved )
5222 // group all remove and the insert action
5223 OUString aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK );
5224 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
5227 ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
5228 rDocShell.GetUndoManager()->AddUndoAction(
5229 new ScUndoRemoveAreaLink( &rDocShell,
5230 pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
5231 pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) );
5233 pLinkManager->Remove( pBase );
5234 nLinkCount = pLinkManager->GetLinks().size();
5235 ++nRemoved;
5237 else
5238 ++nLinkPos;
5241 OUString aFilterName = rFilter;
5242 OUString aNewOptions = rOptions;
5243 if (aFilterName.isEmpty())
5244 ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, true, !bApi );
5246 // remove application prefix from filter name here, so the filter options
5247 // aren't reset when the filter name is changed in ScAreaLink::DataChanged
5248 ScDocumentLoader::RemoveAppPrefix( aFilterName );
5250 ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
5251 aNewOptions, rSource, rDestRange, nRefresh );
5252 OUString aTmp = aFilterName;
5253 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aTmp, &rSource );
5255 // Undo fuer den leeren Link
5257 if (bUndo)
5259 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell,
5260 rFile, aFilterName, aNewOptions,
5261 rSource, rDestRange, nRefresh ) );
5262 if ( nRemoved )
5263 rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
5266 // Update hat sein eigenes Undo
5267 if (pDoc->IsExecuteLinkEnabled())
5269 pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen
5270 pLink->Update(); // kein SetInCreate -> Update ausfuehren
5272 pLink->SetDoInsert(true); // Default = true
5274 SfxBindings* pBindings = rDocShell.GetViewBindings();
5275 if (pBindings)
5276 pBindings->Invalidate( SID_LINKS );
5278 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator
5280 return true;
5283 namespace {
5285 void RemoveCondFormatAttributes(ScDocument* pDoc, const ScConditionalFormat* pFormat, SCTAB nTab)
5287 const ScRangeList& rRangeList = pFormat->GetRange();
5288 pDoc->RemoveCondFormatData( rRangeList, nTab, pFormat->GetKey() );
5291 void SetConditionalFormatAttributes(ScDocument* pDoc, const ScRangeList& rRanges, sal_uLong nIndex, SCTAB nTab)
5293 pDoc->AddCondFormatData( rRanges, nTab, nIndex );
5298 void ScDocFunc::ReplaceConditionalFormat( sal_uLong nOldFormat, ScConditionalFormat* pFormat, SCTAB nTab, const ScRangeList& rRanges )
5300 ScDocShellModificator aModificator(rDocShell);
5301 ScDocument* pDoc = rDocShell.GetDocument();
5302 if(pDoc->IsTabProtected(nTab))
5303 return;
5305 bool bUndo = pDoc->IsUndoEnabled();
5306 ScDocument* pUndoDoc = NULL;
5307 ScRange aCombinedRange = rRanges.Combine();
5308 ScRange aCompleteRange;
5309 if(bUndo)
5311 pUndoDoc = new ScDocument(SCDOCMODE_UNDO);
5312 pUndoDoc->InitUndo( pDoc, nTab, nTab );
5314 if(pFormat)
5316 aCompleteRange = aCombinedRange;
5318 if(nOldFormat)
5320 ScConditionalFormat* pOldFormat = pDoc->GetCondFormList(nTab)->GetFormat(nOldFormat);
5321 if(pOldFormat)
5322 aCompleteRange.ExtendTo(pOldFormat->GetRange().Combine());
5325 pDoc->CopyToDocument( aCompleteRange.aStart.Col(),aCompleteRange.aStart.Row(),nTab,
5326 aCompleteRange.aEnd.Col(),aCompleteRange.aEnd.Row(),nTab,
5327 IDF_ALL, false, pUndoDoc );
5330 boost::scoped_ptr<ScRange> pRepaintRange;
5331 if(nOldFormat)
5333 ScConditionalFormat* pOldFormat = pDoc->GetCondFormList(nTab)->GetFormat(nOldFormat);
5334 if(pOldFormat)
5336 pRepaintRange.reset(new ScRange( pOldFormat->GetRange().Combine() ));
5337 RemoveCondFormatAttributes(pDoc, pOldFormat, nTab);
5340 pDoc->DeleteConditionalFormat(nOldFormat, nTab);
5341 pDoc->SetStreamValid(nTab, false);
5343 if(pFormat)
5345 if(pRepaintRange)
5346 pRepaintRange->ExtendTo(aCombinedRange);
5347 else
5348 pRepaintRange.reset(new ScRange(aCombinedRange));
5350 sal_uLong nIndex = pDoc->AddCondFormat(pFormat, nTab);
5352 SetConditionalFormatAttributes(pDoc, rRanges, nIndex, nTab);
5353 pDoc->SetStreamValid(nTab, false);
5356 if(bUndo)
5358 ScDocument* pRedoDoc = new ScDocument(SCDOCMODE_UNDO);
5359 pRedoDoc->InitUndo( pDoc, nTab, nTab );
5360 pDoc->CopyToDocument( aCompleteRange.aStart.Col(),aCompleteRange.aStart.Row(),nTab,
5361 aCompleteRange.aEnd.Col(),aCompleteRange.aEnd.Row(),nTab,
5362 IDF_ALL, false, pRedoDoc );
5363 rDocShell.GetUndoManager()->AddUndoAction(
5364 new ScUndoConditionalFormat(&rDocShell, pUndoDoc, pRedoDoc, aCompleteRange));
5367 if(pRepaintRange)
5368 rDocShell.PostPaint(*pRepaintRange, PAINT_GRID);
5370 aModificator.SetDocumentModified();
5371 SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
5374 void ScDocFunc::SetConditionalFormatList( ScConditionalFormatList* pList, SCTAB nTab )
5376 ScDocShellModificator aModificator(rDocShell);
5377 ScDocument* pDoc = rDocShell.GetDocument();
5378 if(pDoc->IsTabProtected(nTab))
5379 return;
5381 // first remove all old entries
5382 ScConditionalFormatList* pOldList = pDoc->GetCondFormList(nTab);
5383 for(ScConditionalFormatList::const_iterator itr = pOldList->begin(), itrEnd = pOldList->end(); itr != itrEnd; ++itr)
5385 RemoveCondFormatAttributes(pDoc, &(*itr), nTab);
5388 // then set new entries
5389 for(ScConditionalFormatList::iterator itr = pList->begin(); itr != pList->end(); ++itr)
5391 sal_uLong nIndex = itr->GetKey();
5392 const ScRangeList& rRange = itr->GetRange();
5393 SetConditionalFormatAttributes(pDoc, rRange, nIndex, nTab);
5396 pDoc->SetCondFormList(pList, nTab);
5397 rDocShell.PostPaintGridAll();
5399 pDoc->SetStreamValid(nTab, false);
5400 aModificator.SetDocumentModified();
5401 SFX_APP()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
5404 void ScDocFunc::EnterListAction( sal_uInt16 nNameResId )
5406 OUString aUndo( ScGlobal::GetRscString( nNameResId ) );
5407 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
5410 void ScDocFunc::EndListAction()
5412 rDocShell.GetUndoManager()->LeaveListAction();
5415 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */