re-enabled user-defined numeric fields for dBase export
[LibreOffice.git] / sc / source / core / data / document.cxx
blob6369388f159be448a77fb00acb1d44c8669e9ee7
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"
21 #include <editeng/eeitem.hxx>
23 #include <editeng/boxitem.hxx>
24 #include <editeng/frmdiritem.hxx>
25 #include "editeng/editobj.hxx"
26 #include <svx/pageitem.hxx>
27 #include <editeng/editeng.hxx>
28 #include <svx/svditer.hxx>
29 #include <svx/svdpage.hxx>
30 #include <svx/svdocapt.hxx>
31 #include <sfx2/app.hxx>
32 #include <sfx2/objsh.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <svl/poolcach.hxx>
35 #include <unotools/saveopt.hxx>
36 #include <svl/zforlist.hxx>
37 #include <unotools/charclass.hxx>
38 #include <unotools/transliterationwrapper.hxx>
39 #include <tools/tenccvt.hxx>
40 #include <tools/urlobj.hxx>
42 #include <com/sun/star/text/WritingMode2.hpp>
43 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
44 #include <com/sun/star/sheet/TablePageBreakData.hpp>
45 #include <com/sun/star/lang/NotInitializedException.hpp>
47 #include "document.hxx"
48 #include "table.hxx"
49 #include "attrib.hxx"
50 #include "attarray.hxx"
51 #include "markarr.hxx"
52 #include "patattr.hxx"
53 #include "rangenam.hxx"
54 #include "poolhelp.hxx"
55 #include "docpool.hxx"
56 #include "stlpool.hxx"
57 #include "stlsheet.hxx"
58 #include "globstr.hrc"
59 #include "rechead.hxx"
60 #include "dbdata.hxx"
61 #include "pivot.hxx"
62 #include "chartlis.hxx"
63 #include "rangelst.hxx"
64 #include "markdata.hxx"
65 #include "drwlayer.hxx"
66 #include "conditio.hxx"
67 #include "colorscale.hxx"
68 #include "validat.hxx"
69 #include "prnsave.hxx"
70 #include "chgtrack.hxx"
71 #include "sc.hrc"
72 #include "scresid.hxx"
73 #include "hints.hxx"
74 #include "detdata.hxx"
75 #include "cell.hxx"
76 #include "dpobject.hxx"
77 #include "detfunc.hxx" // for UpdateAllComments
78 #include "scmod.hxx"
79 #include "dociter.hxx"
80 #include "progress.hxx"
81 #include "autonamecache.hxx"
82 #include "bcaslot.hxx"
83 #include "postit.hxx"
84 #include "externalrefmgr.hxx"
85 #include "tabprotection.hxx"
86 #include "clipparam.hxx"
87 #include "stlalgorithm.hxx"
88 #include "defaultsoptions.hxx"
89 #include "editutil.hxx"
90 #include "stringutil.hxx"
91 #include "formulaiter.hxx"
92 #include "formulacell.hxx"
93 #include "clipcontext.hxx"
94 #include "listenercontext.hxx"
96 #include <map>
97 #include <limits>
98 #include <boost/scoped_ptr.hpp>
100 using ::editeng::SvxBorderLine;
101 using namespace ::com::sun::star;
103 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
104 using ::com::sun::star::uno::Sequence;
105 using ::com::sun::star::sheet::TablePageBreakData;
106 using ::std::set;
108 namespace {
110 std::pair<SCTAB,SCTAB> getMarkedTableRange(const std::vector<ScTable*>& rTables, const ScMarkData& rMark)
112 SCTAB nTabStart = MAXTAB;
113 SCTAB nTabEnd = 0;
114 SCTAB nMax = static_cast<SCTAB>(rTables.size());
115 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
116 for (; itr != itrEnd && *itr < nMax; ++itr)
118 if (!rTables[*itr])
119 continue;
121 if (*itr < nTabStart)
122 nTabStart = *itr;
123 nTabEnd = *itr;
126 return std::pair<SCTAB,SCTAB>(nTabStart,nTabEnd);
131 struct ScDefaultAttr
133 const ScPatternAttr* pAttr;
134 SCROW nFirst;
135 SCSIZE nCount;
136 ScDefaultAttr(const ScPatternAttr* pPatAttr) : pAttr(pPatAttr), nFirst(0), nCount(0) {}
139 struct ScLessDefaultAttr
141 bool operator() (const ScDefaultAttr& rValue1, const ScDefaultAttr& rValue2) const
143 return rValue1.pAttr < rValue2.pAttr;
147 typedef std::set<ScDefaultAttr, ScLessDefaultAttr> ScDefaultAttrSet;
149 void ScDocument::MakeTable( SCTAB nTab,bool _bNeedsNameCheck )
151 if ( ValidTab(nTab) && ( nTab >= static_cast<SCTAB>(maTabs.size()) ||!maTabs[nTab]) )
153 // Get Custom prefix
154 const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
155 OUString aString = rOpt.GetInitTabPrefix();
157 aString += OUString::valueOf(static_cast<sal_Int32>(nTab+1));
158 if ( _bNeedsNameCheck )
159 CreateValidTabName( aString ); // no doubles
160 if (nTab < static_cast<SCTAB>(maTabs.size()))
162 maTabs[nTab] = new ScTable(this, nTab, aString);
164 else
166 while(nTab > static_cast<SCTAB>(maTabs.size()))
167 maTabs.push_back(NULL);
168 maTabs.push_back( new ScTable(this, nTab, aString) );
170 maTabs[nTab]->SetLoadingMedium(bLoadingMedium);
175 bool ScDocument::HasTable( SCTAB nTab ) const
177 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
178 if (maTabs[nTab])
179 return true;
181 return false;
184 bool ScDocument::GetName( SCTAB nTab, OUString& rName ) const
186 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
187 if (maTabs[nTab])
189 maTabs[nTab]->GetName( rName );
190 return true;
192 rName = OUString();
193 return false;
196 OUString ScDocument::GetCopyTabName( SCTAB nTab ) const
198 if (nTab < static_cast<SCTAB>(maTabNames.size()))
199 return maTabNames[nTab];
200 else
201 return OUString();
204 bool ScDocument::SetCodeName( SCTAB nTab, const OUString& rName )
206 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
208 if (maTabs[nTab])
210 maTabs[nTab]->SetCodeName( rName );
211 return true;
214 OSL_TRACE( "**** can't set code name %s", OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() );
215 return false;
218 bool ScDocument::GetCodeName( SCTAB nTab, OUString& rName ) const
220 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
221 if (maTabs[nTab])
223 maTabs[nTab]->GetCodeName( rName );
224 return true;
226 rName = OUString();
227 return false;
230 bool ScDocument::GetTable( const OUString& rName, SCTAB& rTab ) const
232 OUString aUpperName = ScGlobal::pCharClass->uppercase(rName);
234 for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
235 if (maTabs[i])
237 if (aUpperName.equals(maTabs[i]->GetUpperName()))
239 rTab = i;
240 return true;
243 rTab = 0;
244 return false;
247 ScDBData* ScDocument::GetAnonymousDBData(SCTAB nTab)
249 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
250 return maTabs[nTab]->GetAnonymousDBData();
251 return NULL;
254 void ScDocument::SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData)
256 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
257 maTabs[nTab]->SetAnonymousDBData(pDBData);
261 bool ScDocument::ValidTabName( const OUString& rName )
263 if (rName.isEmpty())
264 return false;
265 sal_Int32 nLen = rName.getLength();
267 #if 1
268 // Restrict sheet names to what Excel accepts.
269 /* TODO: We may want to remove this restriction for full ODFF compliance.
270 * Merely loading and calculating ODF documents using these characters in
271 * sheet names is not affected by this, but all sheet name editing and
272 * copying functionality is, maybe falling back to "Sheet4" or similar. */
273 for (sal_Int32 i = 0; i < nLen; ++i)
275 const sal_Unicode c = rName[i];
276 switch (c)
278 case ':':
279 case '\\':
280 case '/':
281 case '?':
282 case '*':
283 case '[':
284 case ']':
285 // these characters are not allowed to match XL's convention.
286 return false;
287 case '\'':
288 if (i == 0 || i == nLen - 1)
289 // single quote is not allowed at the first or last
290 // character position.
291 return false;
292 break;
295 #endif
297 return true;
301 bool ScDocument::ValidNewTabName( const OUString& rName ) const
303 bool bValid = ValidTabName(rName);
304 TableContainer::const_iterator it = maTabs.begin();
305 for (; it != maTabs.end() && bValid; ++it)
306 if ( *it )
308 OUString aOldName;
309 (*it)->GetName(aOldName);
310 bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
312 return bValid;
316 void ScDocument::CreateValidTabName(OUString& rName) const
318 if ( !ValidTabName(rName) )
320 // Find new one
322 // Get Custom prefix
323 const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
324 OUString aStrTable = rOpt.GetInitTabPrefix();
326 bool bOk = false;
328 // First test if the prefix is valid, if so only avoid doubles
329 bool bPrefix = ValidTabName( aStrTable );
330 OSL_ENSURE(bPrefix, "Invalid Table Name");
331 SCTAB nDummy;
333 for ( SCTAB i = static_cast<SCTAB>(maTabs.size())+1; !bOk ; i++ )
335 OUStringBuffer aBuf;
336 aBuf.append(aStrTable);
337 aBuf.append(static_cast<sal_Int32>(i));
338 rName = aBuf.makeStringAndClear();
339 if (bPrefix)
340 bOk = ValidNewTabName( rName );
341 else
342 bOk = !GetTable( rName, nDummy );
345 else
347 // testing the supplied Name
349 if ( !ValidNewTabName(rName) )
351 SCTAB i = 1;
352 OUStringBuffer aName;
355 i++;
356 aName = rName;
357 aName.append('_');
358 aName.append(static_cast<sal_Int32>(i));
360 while (!ValidNewTabName(aName.toString()) && (i < MAXTAB+1));
361 rName = aName.makeStringAndClear();
366 void ScDocument::CreateValidTabNames(std::vector<OUString>& aNames, SCTAB nCount) const
368 aNames.clear();//ensure that the vector is empty
370 // Get Custom prefix
371 const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
372 OUString aStrTable = rOpt.GetInitTabPrefix();
374 OUStringBuffer rName;
375 bool bOk = false;
377 // First test if the prefix is valid, if so only avoid doubles
378 bool bPrefix = ValidTabName( aStrTable );
379 OSL_ENSURE(bPrefix, "Invalid Table Name");
380 SCTAB nDummy;
381 SCTAB i = static_cast<SCTAB>(maTabs.size())+1;
383 for (SCTAB j = 0; j < nCount; ++j)
385 bOk = false;
386 while(!bOk)
388 rName = aStrTable;
389 rName.append(static_cast<sal_Int32>(i));
390 if (bPrefix)
391 bOk = ValidNewTabName( rName.toString() );
392 else
393 bOk = !GetTable( rName.toString(), nDummy );
394 i++;
396 aNames.push_back(rName.makeStringAndClear());
400 void ScDocument::AppendTabOnLoad(const OUString& rName)
402 SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
403 if (!ValidTab(nTabCount))
404 // max table count reached. No more tables.
405 return;
407 OUString aName = rName;
408 CreateValidTabName(aName);
409 maTabs.push_back( new ScTable(this, nTabCount, aName) );
412 void ScDocument::SetTabNameOnLoad(SCTAB nTab, const OUString& rName)
414 if (!ValidTab(nTab) || static_cast<SCTAB>(maTabs.size()) <= nTab)
415 return;
417 if (!ValidTabName(rName))
418 return;
420 maTabs[nTab]->SetName(rName);
423 void ScDocument::InvalidateStreamOnSave()
425 TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
426 for (; it != itEnd; ++it)
428 ScTable* pTab = *it;
429 if (pTab)
430 pTab->SetStreamValid(false);
434 bool ScDocument::InsertTab( SCTAB nPos, const OUString& rName,
435 bool bExternalDocument )
437 SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
438 bool bValid = ValidTab(nTabCount);
439 if ( !bExternalDocument ) // else test rName == "'Doc'!Tab" first
440 bValid = (bValid && ValidNewTabName(rName));
441 if (bValid)
443 if (nPos == SC_TAB_APPEND || nPos >= nTabCount)
445 maTabs.push_back( new ScTable(this, nTabCount, rName) );
446 if ( bExternalDocument )
447 maTabs[nTabCount]->SetVisible( false );
449 else
451 if (ValidTab(nPos) && (nPos < nTabCount))
453 ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
454 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
455 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
456 if (pRangeName)
457 pRangeName->UpdateTabRef( nPos, 1 );
458 pDBCollection->UpdateReference(
459 URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
460 if (pDPCollection)
461 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
462 if (pDetOpList)
463 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
464 UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
465 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 );
466 if ( pUnoBroadcaster )
467 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
469 SCTAB i;
470 TableContainer::iterator it = maTabs.begin();
471 for (; it != maTabs.end(); ++it)
472 if ( *it )
473 (*it)->UpdateInsertTab(nPos);
474 maTabs.push_back(NULL);
475 for (i = nTabCount; i > nPos; i--)
477 maTabs[i] = maTabs[i - 1];
480 maTabs[nPos] = new ScTable(this, nPos, rName);
482 // UpdateBroadcastAreas must be called between UpdateInsertTab,
483 // which ends listening, and StartAllListeners, to not modify
484 // areas that are to be inserted by starting listeners.
485 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,1);
486 it = maTabs.begin();
487 for (; it != maTabs.end(); ++it)
488 if ( *it )
489 (*it)->UpdateCompile();
490 it = maTabs.begin();
491 for (; it != maTabs.end(); ++it)
492 if ( *it )
493 (*it)->StartAllListeners();
495 if ( pValidationList )
496 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
497 // sheet names of references are not valid until sheet is inserted
498 if ( pChartListenerCollection )
499 pChartListenerCollection->UpdateScheduledSeriesRanges();
501 bValid = true;
503 else
504 bValid = false;
508 if (bValid)
509 SetDirty();
511 return bValid;
515 bool ScDocument::InsertTabs( SCTAB nPos, const std::vector<OUString>& rNames,
516 bool bExternalDocument, bool bNamesValid )
518 SCTAB nNewSheets = static_cast<SCTAB>(rNames.size());
519 SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
520 bool bValid = bNamesValid || ValidTab(nTabCount+nNewSheets);
521 // if ( !bExternalDocument ) // else test rName == "'Doc'!Tab" first
522 // bValid = (bValid && ValidNewTabName(rNames));
523 if (bValid)
525 if (nPos == SC_TAB_APPEND || nPos >= nTabCount)
527 for ( SCTAB i = 0; i < nNewSheets; ++i )
529 maTabs.push_back( new ScTable(this, nTabCount + i, rNames.at(i)) );
530 if ( bExternalDocument )
531 maTabs[nTabCount+i]->SetVisible( false );
534 else
536 if (ValidTab(nPos) && (nPos < nTabCount))
538 ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
539 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets );
540 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets );
541 if (pRangeName)
542 pRangeName->UpdateTabRef( nPos, 1, 0, nNewSheets);
543 pDBCollection->UpdateReference(
544 URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,nNewSheets );
545 if (pDPCollection)
546 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,nNewSheets );
547 if (pDetOpList)
548 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,nNewSheets );
549 UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,nNewSheets );
550 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0, nNewSheets );
551 if ( pUnoBroadcaster )
552 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,nNewSheets ) );
554 TableContainer::iterator it = maTabs.begin();
555 for (; it != maTabs.end(); ++it)
556 if ( *it )
557 (*it)->UpdateInsertTab(nPos, nNewSheets);
558 it = maTabs.begin();
559 maTabs.insert(it+nPos,nNewSheets, NULL);
560 for (SCTAB i = 0; i < nNewSheets; ++i)
562 maTabs[nPos + i] = new ScTable(this, nPos + i, rNames.at(i));
565 // UpdateBroadcastAreas must be called between UpdateInsertTab,
566 // which ends listening, and StartAllListeners, to not modify
567 // areas that are to be inserted by starting listeners.
568 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,nNewSheets);
569 it = maTabs.begin();
570 for (; it != maTabs.end(); ++it)
572 if ( *it )
573 (*it)->UpdateCompile();
575 it = maTabs.begin();
576 for (; it != maTabs.end(); ++it)
577 if ( *it )
578 (*it)->StartAllListeners();
580 if ( pValidationList )
581 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,nNewSheets );
582 // sheet names of references are not valid until sheet is inserted
583 if ( pChartListenerCollection )
584 pChartListenerCollection->UpdateScheduledSeriesRanges();
586 bValid = true;
588 else
589 bValid = false;
593 if (bValid)
594 SetDirty();
596 return bValid;
600 bool ScDocument::DeleteTab( SCTAB nTab, ScDocument* pRefUndoDoc )
602 bool bValid = false;
603 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
605 if (maTabs[nTab])
607 SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
608 if (nTabCount > 1)
610 bool bOldAutoCalc = GetAutoCalc();
611 SetAutoCalc( false ); // avoid multiple calculations
612 ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab );
613 DelBroadcastAreasInRange( aRange );
615 // #i8180# remove database ranges etc. that are on the deleted tab
616 // (restored in undo with ScRefUndoData)
618 xColNameRanges->DeleteOnTab( nTab );
619 xRowNameRanges->DeleteOnTab( nTab );
620 pDBCollection->DeleteOnTab( nTab );
621 if (pDPCollection)
622 pDPCollection->DeleteOnTab( nTab );
623 if (pDetOpList)
624 pDetOpList->DeleteOnTab( nTab );
625 DeleteAreaLinksOnTab( nTab );
627 // normal reference update
629 aRange.aEnd.SetTab( static_cast<SCTAB>(maTabs.size())-1 );
630 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
631 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
632 if (pRangeName)
633 pRangeName->UpdateTabRef( nTab, 2 );
634 pDBCollection->UpdateReference(
635 URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
636 if (pDPCollection)
637 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
638 if (pDetOpList)
639 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1 );
640 UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
641 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1 );
642 if ( pValidationList )
643 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
644 if ( pUnoBroadcaster )
645 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1 ) );
647 for (SCTAB i = 0, n = static_cast<SCTAB>(maTabs.size()); i < n; ++i)
648 if (maTabs[i])
649 maTabs[i]->UpdateDeleteTab(
650 nTab, false, pRefUndoDoc ? pRefUndoDoc->maTabs[i] : 0);
652 TableContainer::iterator it = maTabs.begin() + nTab;
653 delete *it;
654 maTabs.erase(it);
655 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
656 // which ends listening, and StartAllListeners, to not modify
657 // areas that are to be inserted by starting listeners.
658 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1);
659 it = maTabs.begin();
660 for (; it != maTabs.end(); ++it)
661 if ( *it )
662 (*it)->UpdateCompile();
663 // Excel-Filter deletes some Tables while loading, Listeners will
664 // only be triggered after the loading is done.
665 if ( !bInsertingFromOtherDoc )
667 it = maTabs.begin();
668 for (; it != maTabs.end(); ++it)
669 if ( *it )
670 (*it)->StartAllListeners();
671 SetDirty();
673 // sheet names of references are not valid until sheet is deleted
674 pChartListenerCollection->UpdateScheduledSeriesRanges();
676 SetAutoCalc( bOldAutoCalc );
677 bValid = true;
681 return bValid;
685 bool ScDocument::DeleteTabs( SCTAB nTab, SCTAB nSheets, ScDocument* pRefUndoDoc )
687 bool bValid = false;
688 if (ValidTab(nTab) && (nTab + nSheets) < static_cast<SCTAB>(maTabs.size()))
690 if (maTabs[nTab])
692 SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
693 if (nTabCount > nSheets)
695 bool bOldAutoCalc = GetAutoCalc();
696 SetAutoCalc( false ); // avoid multiple calculations
697 for (SCTAB aTab = 0; aTab < nSheets; ++aTab)
699 ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab + aTab );
700 DelBroadcastAreasInRange( aRange );
702 // #i8180# remove database ranges etc. that are on the deleted tab
703 // (restored in undo with ScRefUndoData)
705 xColNameRanges->DeleteOnTab( nTab + aTab );
706 xRowNameRanges->DeleteOnTab( nTab + aTab );
707 pDBCollection->DeleteOnTab( nTab + aTab );
708 if (pDPCollection)
709 pDPCollection->DeleteOnTab( nTab + aTab );
710 if (pDetOpList)
711 pDetOpList->DeleteOnTab( nTab + aTab );
712 DeleteAreaLinksOnTab( nTab + aTab );
713 if (pRangeName)
714 pRangeName->UpdateTabRef( nTab + aTab, 2 );
716 // normal reference update
718 ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTabCount - 1 );
719 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets );
720 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets );
721 pDBCollection->UpdateReference(
722 URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1*nSheets );
723 if (pDPCollection)
724 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1*nSheets );
725 if (pDetOpList)
726 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1*nSheets );
727 UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1*nSheets );
728 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1*nSheets );
729 if ( pValidationList )
730 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,-1*nSheets );
731 if ( pUnoBroadcaster )
732 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1*nSheets ) );
734 for (SCTAB i = 0, n = static_cast<SCTAB>(maTabs.size()); i < n; ++i)
735 if (maTabs[i])
736 maTabs[i]->UpdateDeleteTab(
737 nTab, false, pRefUndoDoc ? pRefUndoDoc->maTabs[i] : 0,nSheets);
739 TableContainer::iterator it = maTabs.begin() + nTab;
740 TableContainer::iterator itEnd = it + nSheets;
741 std::for_each(it, itEnd, ScDeleteObjectByPtr<ScTable>());
742 maTabs.erase(it, itEnd);
743 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
744 // which ends listening, and StartAllListeners, to not modify
745 // areas that are to be inserted by starting listeners.
746 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1*nSheets);
747 it = maTabs.begin();
748 for (; it != maTabs.end(); ++it)
749 if ( *it )
750 (*it)->UpdateCompile();
751 // Excel-Filter deletes some Tables while loading, Listeners will
752 // only be triggered after the loading is done.
753 if ( !bInsertingFromOtherDoc )
755 it = maTabs.begin();
756 for (; it != maTabs.end(); ++it)
757 if ( *it )
758 (*it)->StartAllListeners();
759 SetDirty();
761 // sheet names of references are not valid until sheet is deleted
762 pChartListenerCollection->UpdateScheduledSeriesRanges();
764 SetAutoCalc( bOldAutoCalc );
765 bValid = true;
769 return bValid;
773 bool ScDocument::RenameTab( SCTAB nTab, const OUString& rName, bool /* bUpdateRef */,
774 bool bExternalDocument )
776 bool bValid = false;
777 SCTAB i;
778 if (ValidTab(nTab))
780 if (maTabs[nTab])
782 if ( bExternalDocument )
783 bValid = true; // composed name
784 else
785 bValid = ValidTabName(rName);
786 for (i=0; (i< static_cast<SCTAB>(maTabs.size())) && bValid; i++)
787 if (maTabs[i] && (i != nTab))
789 OUString aOldName;
790 maTabs[i]->GetName(aOldName);
791 bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
793 if (bValid)
795 // #i75258# update charts before renaming, so they can get their live data objects.
796 // Once the charts are live, the sheet can be renamed without problems.
797 if ( pChartListenerCollection )
798 pChartListenerCollection->UpdateChartsContainingTab( nTab );
799 maTabs[nTab]->SetName(rName);
801 // If formulas refer to the renamed sheet, the TokenArray remains valid,
802 // but the XML stream must be re-generated.
803 TableContainer::iterator it = maTabs.begin();
804 for (; it != maTabs.end(); ++it)
805 if ( *it && (*it)->IsStreamValid())
806 (*it)->SetStreamValid( false );
810 return bValid;
814 void ScDocument::SetVisible( SCTAB nTab, bool bVisible )
816 if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
817 if (maTabs[nTab])
818 maTabs[nTab]->SetVisible(bVisible);
822 bool ScDocument::IsVisible( SCTAB nTab ) const
824 if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
825 if (maTabs[nTab])
826 return maTabs[nTab]->IsVisible();
828 return false;
832 bool ScDocument::IsStreamValid( SCTAB nTab ) const
834 if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
835 return maTabs[nTab]->IsStreamValid();
837 return false;
841 void ScDocument::SetStreamValid( SCTAB nTab, bool bSet, bool bIgnoreLock )
843 if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
844 maTabs[nTab]->SetStreamValid( bSet, bIgnoreLock );
848 void ScDocument::LockStreamValid( bool bLock )
850 mbStreamValidLocked = bLock;
854 bool ScDocument::IsPendingRowHeights( SCTAB nTab ) const
856 if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
857 return maTabs[nTab]->IsPendingRowHeights();
859 return false;
863 void ScDocument::SetPendingRowHeights( SCTAB nTab, bool bSet )
865 if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
866 maTabs[nTab]->SetPendingRowHeights( bSet );
870 void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL )
872 if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
874 if ( bImportingXML )
876 // #i57869# only set the LoadingRTL flag, the real setting (including mirroring)
877 // is applied in SetImportingXML(false). This is so the shapes can be loaded in
878 // normal LTR mode.
880 maTabs[nTab]->SetLoadingRTL( bRTL );
881 return;
884 maTabs[nTab]->SetLayoutRTL( bRTL ); // only sets the flag
885 maTabs[nTab]->SetDrawPageSize();
887 // mirror existing objects:
889 if (pDrawLayer)
891 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
892 OSL_ENSURE(pPage,"Page ?");
893 if (pPage)
895 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
896 SdrObject* pObject = aIter.Next();
897 while (pObject)
899 // objects with ScDrawObjData are re-positioned in SetPageSize,
900 // don't mirror again
901 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
902 if ( !pData )
903 pDrawLayer->MirrorRTL( pObject );
905 pObject->SetContextWritingMode( bRTL ? WritingMode2::RL_TB : WritingMode2::LR_TB );
907 pObject = aIter.Next();
915 bool ScDocument::IsLayoutRTL( SCTAB nTab ) const
917 if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
918 return maTabs[nTab]->IsLayoutRTL();
920 return false;
924 bool ScDocument::IsNegativePage( SCTAB nTab ) const
926 // Negative page area is always used for RTL layout.
927 // The separate method is used to find all RTL handling of drawing objects.
928 return IsLayoutRTL( nTab );
932 /* ----------------------------------------------------------------------------
933 used search area:
935 GetCellArea - Only Data
936 GetTableArea - Data / Attributes
937 GetPrintArea - intended for character objects,
938 sweeps attributes all the way to bottom / right
939 ---------------------------------------------------------------------------- */
942 bool ScDocument::GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
944 if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
945 if (maTabs[nTab])
946 return maTabs[nTab]->GetCellArea( rEndCol, rEndRow );
948 rEndCol = 0;
949 rEndRow = 0;
950 return false;
954 bool ScDocument::GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
956 if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
957 if (maTabs[nTab])
958 return maTabs[nTab]->GetTableArea( rEndCol, rEndRow );
960 rEndCol = 0;
961 rEndRow = 0;
962 return false;
965 bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow) const
967 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab])
968 return false;
970 SCCOL nCol1, nCol2;
971 SCROW nRow1, nRow2;
972 maTabs[nTab]->GetFirstDataPos(nCol1, nRow1);
973 maTabs[nTab]->GetLastDataPos(nCol2, nRow2);
975 if (nCol1 > nCol2 || nRow1 > nRow2)
976 // invalid range.
977 return false;
979 // Make sure the area only shrinks, and doesn't grow.
980 if (rStartCol < nCol1)
981 rStartCol = nCol1;
982 if (nCol2 < rEndCol)
983 rEndCol = nCol2;
984 if (rStartRow < nRow1)
985 rStartRow = nRow1;
986 if (nRow2 < rEndRow)
987 rEndRow = nRow2;
989 if (rStartCol > rEndCol || rStartRow > rEndRow)
990 // invalid range.
991 return false;
993 return true; // success!
996 bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol,
997 SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
999 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab])
1001 o_bShrunk = false;
1002 return false;
1004 return maTabs[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly);
1007 // connected area
1009 void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
1010 SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const
1012 if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab])
1013 maTabs[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown );
1017 void ScDocument::LimitChartArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
1018 SCCOL& rEndCol, SCROW& rEndRow )
1020 if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
1021 if (maTabs[nTab])
1022 maTabs[nTab]->LimitChartArea( rStartCol, rStartRow, rEndCol, rEndRow );
1026 void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList )
1028 ScRangeListRef aNew = new ScRangeList;
1029 if (rRangeList.Is())
1031 for ( size_t i = 0, nCount = rRangeList->size(); i < nCount; i++ )
1033 ScRange aRange( *(*rRangeList)[i] );
1034 if ( ( aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL ) ||
1035 ( aRange.aStart.Row() == 0 && aRange.aEnd.Row() == MAXROW ) )
1037 SCCOL nStartCol = aRange.aStart.Col();
1038 SCROW nStartRow = aRange.aStart.Row();
1039 SCCOL nEndCol = aRange.aEnd.Col();
1040 SCROW nEndRow = aRange.aEnd.Row();
1041 SCTAB nTab = aRange.aStart.Tab();
1042 if ( nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab])
1043 maTabs[nTab]->LimitChartArea(nStartCol, nStartRow, nEndCol, nEndRow);
1044 aRange.aStart.SetCol( nStartCol );
1045 aRange.aStart.SetRow( nStartRow );
1046 aRange.aEnd.SetCol( nEndCol );
1047 aRange.aEnd.SetRow( nEndRow );
1049 aNew->Append(aRange);
1052 else
1054 OSL_FAIL("LimitChartIfAll: Ref==0");
1056 rRangeList = aNew;
1060 static void lcl_GetFirstTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab )
1062 // without ScMarkData, leave start/end unchanged
1063 if ( pTabMark )
1065 for (SCTAB nTab=0; nTab< aMaxTab; ++nTab)
1066 if (pTabMark->GetTableSelect(nTab))
1068 // find first range of consecutive selected sheets
1069 rTabRangeStart = pTabMark->GetFirstSelected();
1070 while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) )
1071 ++nTab;
1072 rTabRangeEnd = nTab;
1073 return;
1078 static bool lcl_GetNextTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab )
1080 if ( pTabMark )
1082 // find next range of consecutive selected sheets after rTabRangeEnd
1083 for (SCTAB nTab=rTabRangeEnd+1; nTab< aMaxTab; ++nTab)
1084 if (pTabMark->GetTableSelect(nTab))
1086 rTabRangeStart = nTab;
1087 while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) )
1088 ++nTab;
1089 rTabRangeEnd = nTab;
1090 return true;
1093 return false;
1097 bool ScDocument::CanInsertRow( const ScRange& rRange ) const
1099 SCCOL nStartCol = rRange.aStart.Col();
1100 SCROW nStartRow = rRange.aStart.Row();
1101 SCTAB nStartTab = rRange.aStart.Tab();
1102 SCCOL nEndCol = rRange.aEnd.Col();
1103 SCROW nEndRow = rRange.aEnd.Row();
1104 SCTAB nEndTab = rRange.aEnd.Tab();
1105 PutInOrder( nStartCol, nEndCol );
1106 PutInOrder( nStartRow, nEndRow );
1107 PutInOrder( nStartTab, nEndTab );
1108 SCSIZE nSize = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
1110 bool bTest = true;
1111 for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1112 if (maTabs[i])
1113 bTest &= maTabs[i]->TestInsertRow( nStartCol, nEndCol, nSize );
1115 return bTest;
1118 namespace {
1120 struct BroadcastRecalcOnRefMoveHandler : std::unary_function<ScTable*, void>
1122 void operator() (ScTable* p)
1124 if (p)
1125 p->BroadcastRecalcOnRefMove();
1131 bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
1132 SCCOL nEndCol, SCTAB nEndTab,
1133 SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc,
1134 const ScMarkData* pTabMark )
1136 SCTAB i;
1138 PutInOrder( nStartCol, nEndCol );
1139 PutInOrder( nStartTab, nEndTab );
1140 if ( pTabMark )
1142 nStartTab = 0;
1143 nEndTab = static_cast<SCTAB>(maTabs.size()) -1;
1146 bool bTest = true;
1147 bool bRet = false;
1148 bool bOldAutoCalc = GetAutoCalc();
1149 SetAutoCalc( false ); // avoid mulitple calculations
1150 for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1151 if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1152 bTest &= maTabs[i]->TestInsertRow( nStartCol, nEndCol, nSize );
1153 if (bTest)
1155 // UpdateBroadcastAreas have to be called before UpdateReference, so that entries
1156 // aren't shifted that would be rebuild at UpdateReference
1158 // handle chunks of consecutive selected sheets together
1159 SCTAB nTabRangeStart = nStartTab;
1160 SCTAB nTabRangeEnd = nEndTab;
1161 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1164 UpdateBroadcastAreas( URM_INSDEL, ScRange(
1165 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1166 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, static_cast<SCsROW>(nSize), 0 );
1168 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1170 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1173 UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart,
1174 nEndCol, MAXROW, nTabRangeEnd,
1175 0, static_cast<SCsROW>(nSize), 0, pRefUndoDoc, false ); // without drawing objects
1177 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1179 for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1180 if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1181 maTabs[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize );
1183 // UpdateRef for drawing layer must be after inserting,
1184 // when the new row heights are known.
1185 for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1186 if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1187 maTabs[i]->UpdateDrawRef( URM_INSDEL,
1188 nStartCol, nStartRow, nStartTab, nEndCol, MAXROW, nEndTab,
1189 0, static_cast<SCsROW>(nSize), 0 );
1191 if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
1192 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
1193 // ein neues Listening faellig, bisherige Listener wurden in
1194 // FormulaCell UpdateReference abgehaengt
1195 StartAllListeners();
1197 else
1198 { // Listeners have been removed in UpdateReference
1199 TableContainer::iterator it = maTabs.begin();
1200 for (; it != maTabs.end(); ++it)
1201 if (*it)
1202 (*it)->StartNeededListeners();
1203 // At least all cells using range names pointing relative to the
1204 // moved range must be recalculated, and all cells marked postponed
1205 // dirty.
1206 it = maTabs.begin();
1207 for (; it != maTabs.end(); ++it)
1208 if (*it)
1209 (*it)->SetDirtyIfPostponed();
1211 // Cells containing functions such as CELL, COLUMN or ROW may have
1212 // changed their values on relocation. Broadcast them.
1213 std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1215 bRet = true;
1217 SetAutoCalc( bOldAutoCalc );
1218 if ( bRet )
1219 pChartListenerCollection->UpdateDirtyCharts();
1220 return bRet;
1224 bool ScDocument::InsertRow( const ScRange& rRange, ScDocument* pRefUndoDoc )
1226 return InsertRow( rRange.aStart.Col(), rRange.aStart.Tab(),
1227 rRange.aEnd.Col(), rRange.aEnd.Tab(),
1228 rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
1229 pRefUndoDoc );
1233 void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
1234 SCCOL nEndCol, SCTAB nEndTab,
1235 SCROW nStartRow, SCSIZE nSize,
1236 ScDocument* pRefUndoDoc, bool* pUndoOutline,
1237 const ScMarkData* pTabMark )
1239 SCTAB i;
1241 PutInOrder( nStartCol, nEndCol );
1242 PutInOrder( nStartTab, nEndTab );
1243 if ( pTabMark )
1245 nStartTab = 0;
1246 nEndTab = static_cast<SCTAB>(maTabs.size())-1;
1249 bool bOldAutoCalc = GetAutoCalc();
1250 SetAutoCalc( false ); // avoid multiple calculations
1252 // handle chunks of consecutive selected sheets together
1253 SCTAB nTabRangeStart = nStartTab;
1254 SCTAB nTabRangeEnd = nEndTab;
1255 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1258 if ( ValidRow(nStartRow+nSize) )
1260 DelBroadcastAreasInRange( ScRange(
1261 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1262 ScAddress( nEndCol, nStartRow+nSize-1, nTabRangeEnd ) ) );
1263 UpdateBroadcastAreas( URM_INSDEL, ScRange(
1264 ScAddress( nStartCol, nStartRow+nSize, nTabRangeStart ),
1265 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, -(static_cast<SCsROW>(nSize)), 0 );
1267 else
1268 DelBroadcastAreasInRange( ScRange(
1269 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1270 ScAddress( nEndCol, MAXROW, nTabRangeEnd ) ) );
1272 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1274 if ( ValidRow(nStartRow+nSize) )
1276 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1279 UpdateReference( URM_INSDEL, nStartCol, nStartRow+nSize, nTabRangeStart,
1280 nEndCol, MAXROW, nTabRangeEnd,
1281 0, -(static_cast<SCsROW>(nSize)), 0, pRefUndoDoc, true, false );
1283 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1286 if (pUndoOutline)
1287 *pUndoOutline = false;
1289 for ( i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1290 if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1291 maTabs[i]->DeleteRow( nStartCol, nEndCol, nStartRow, nSize, pUndoOutline );
1293 if ( ValidRow(nStartRow+nSize) )
1294 { // Listeners have been removed in UpdateReference
1295 TableContainer::iterator it = maTabs.begin();
1296 for (; it != maTabs.end(); ++it)
1297 if (*it)
1298 (*it)->StartNeededListeners();
1299 // At least all cells using range names pointing relative to the moved
1300 // range must be recalculated, and all cells marked postponed dirty.
1301 it = maTabs.begin();
1302 for (; it != maTabs.end(); ++it)
1303 if (*it)
1304 (*it)->SetDirtyIfPostponed();
1306 // Cells containing functions such as CELL, COLUMN or ROW may have
1307 // changed their values on relocation. Broadcast them.
1308 std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1311 SetAutoCalc( bOldAutoCalc );
1312 pChartListenerCollection->UpdateDirtyCharts();
1316 void ScDocument::DeleteRow( const ScRange& rRange, ScDocument* pRefUndoDoc, bool* pUndoOutline )
1318 DeleteRow( rRange.aStart.Col(), rRange.aStart.Tab(),
1319 rRange.aEnd.Col(), rRange.aEnd.Tab(),
1320 rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
1321 pRefUndoDoc, pUndoOutline );
1325 bool ScDocument::CanInsertCol( const ScRange& rRange ) const
1327 SCCOL nStartCol = rRange.aStart.Col();
1328 SCROW nStartRow = rRange.aStart.Row();
1329 SCTAB nStartTab = rRange.aStart.Tab();
1330 SCCOL nEndCol = rRange.aEnd.Col();
1331 SCROW nEndRow = rRange.aEnd.Row();
1332 SCTAB nEndTab = rRange.aEnd.Tab();
1333 PutInOrder( nStartCol, nEndCol );
1334 PutInOrder( nStartRow, nEndRow );
1335 PutInOrder( nStartTab, nEndTab );
1336 SCSIZE nSize = static_cast<SCSIZE>(nEndCol - nStartCol + 1);
1338 bool bTest = true;
1339 for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1340 if (maTabs[i])
1341 bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize );
1343 return bTest;
1347 bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
1348 SCROW nEndRow, SCTAB nEndTab,
1349 SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
1350 const ScMarkData* pTabMark )
1352 SCTAB i;
1354 PutInOrder( nStartRow, nEndRow );
1355 PutInOrder( nStartTab, nEndTab );
1356 if ( pTabMark )
1358 nStartTab = 0;
1359 nEndTab = static_cast<SCTAB>(maTabs.size())-1;
1362 bool bTest = true;
1363 bool bRet = false;
1364 bool bOldAutoCalc = GetAutoCalc();
1365 SetAutoCalc( false ); // avoid multiple calculations
1366 for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1367 if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1368 bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize );
1369 if (bTest)
1371 // handle chunks of consecutive selected sheets together
1372 SCTAB nTabRangeStart = nStartTab;
1373 SCTAB nTabRangeEnd = nEndTab;
1374 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1377 UpdateBroadcastAreas( URM_INSDEL, ScRange(
1378 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1379 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), static_cast<SCsCOL>(nSize), 0, 0 );
1381 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1383 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1386 UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart,
1387 MAXCOL, nEndRow, nTabRangeEnd,
1388 static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc, true, false );
1390 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1392 for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1393 if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1394 maTabs[i]->InsertCol( nStartCol, nStartRow, nEndRow, nSize );
1396 if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
1397 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
1398 // ein neues Listening faellig, bisherige Listener wurden in
1399 // FormulaCell UpdateReference abgehaengt
1400 StartAllListeners();
1402 else
1403 {// Listeners have been removed in UpdateReference
1404 TableContainer::iterator it = maTabs.begin();
1405 for (; it != maTabs.end(); ++it)
1406 if (*it)
1407 (*it)->StartNeededListeners();
1408 // At least all cells using range names pointing relative to the
1409 // moved range must be recalculated, and all cells marked postponed
1410 // dirty.
1411 it = maTabs.begin();
1412 for (; it != maTabs.end(); ++it)
1413 if (*it)
1414 (*it)->SetDirtyIfPostponed();
1416 // Cells containing functions such as CELL, COLUMN or ROW may have
1417 // changed their values on relocation. Broadcast them.
1418 std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1420 bRet = true;
1422 SetAutoCalc( bOldAutoCalc );
1423 if ( bRet )
1424 pChartListenerCollection->UpdateDirtyCharts();
1425 return bRet;
1429 bool ScDocument::InsertCol( const ScRange& rRange, ScDocument* pRefUndoDoc )
1431 return InsertCol( rRange.aStart.Row(), rRange.aStart.Tab(),
1432 rRange.aEnd.Row(), rRange.aEnd.Tab(),
1433 rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
1434 pRefUndoDoc );
1438 void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab,
1439 SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
1440 bool* pUndoOutline, const ScMarkData* pTabMark )
1442 SCTAB i;
1444 PutInOrder( nStartRow, nEndRow );
1445 PutInOrder( nStartTab, nEndTab );
1446 if ( pTabMark )
1448 nStartTab = 0;
1449 nEndTab = static_cast<SCTAB>(maTabs.size())-1;
1452 bool bOldAutoCalc = GetAutoCalc();
1453 SetAutoCalc( false ); // avoid multiple calculations
1455 // handle chunks of consecutive selected sheets together
1456 SCTAB nTabRangeStart = nStartTab;
1457 SCTAB nTabRangeEnd = nEndTab;
1458 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1461 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1463 DelBroadcastAreasInRange( ScRange(
1464 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1465 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nTabRangeEnd ) ) );
1466 UpdateBroadcastAreas( URM_INSDEL, ScRange(
1467 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart ),
1468 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), -static_cast<SCsCOL>(nSize), 0, 0 );
1470 else
1471 DelBroadcastAreasInRange( ScRange(
1472 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1473 ScAddress( MAXCOL, nEndRow, nTabRangeEnd ) ) );
1475 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1477 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1479 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1482 UpdateReference( URM_INSDEL, sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart,
1483 MAXCOL, nEndRow, nTabRangeEnd,
1484 -static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc, true, false );
1486 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1489 if (pUndoOutline)
1490 *pUndoOutline = false;
1492 for ( i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1493 if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1494 maTabs[i]->DeleteCol( nStartCol, nStartRow, nEndRow, nSize, pUndoOutline );
1496 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1497 {// Listeners have been removed in UpdateReference
1498 TableContainer::iterator it = maTabs.begin();
1499 for (; it != maTabs.end(); ++it)
1500 if (*it)
1501 (*it)->StartNeededListeners();
1502 // At least all cells using range names pointing relative to the moved
1503 // range must be recalculated, and all cells marked postponed dirty.
1504 it = maTabs.begin();
1505 for (; it != maTabs.end(); ++it)
1506 if (*it)
1507 (*it)->SetDirtyIfPostponed();
1509 // Cells containing functions such as CELL, COLUMN or ROW may have
1510 // changed their values on relocation. Broadcast them.
1511 std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1514 SetAutoCalc( bOldAutoCalc );
1515 pChartListenerCollection->UpdateDirtyCharts();
1519 void ScDocument::DeleteCol( const ScRange& rRange, ScDocument* pRefUndoDoc, bool* pUndoOutline )
1521 DeleteCol( rRange.aStart.Row(), rRange.aStart.Tab(),
1522 rRange.aEnd.Row(), rRange.aEnd.Tab(),
1523 rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
1524 pRefUndoDoc, pUndoOutline );
1528 // fuer Area-Links: Zellen einuegen/loeschen, wenn sich der Bereich veraendert
1529 // (ohne Paint)
1532 static void lcl_GetInsDelRanges( const ScRange& rOld, const ScRange& rNew,
1533 ScRange& rColRange, bool& rInsCol, bool& rDelCol,
1534 ScRange& rRowRange, bool& rInsRow, bool& rDelRow )
1536 OSL_ENSURE( rOld.aStart == rNew.aStart, "FitBlock: Beginning is different" );
1538 rInsCol = rDelCol = rInsRow = rDelRow = false;
1540 SCCOL nStartX = rOld.aStart.Col();
1541 SCROW nStartY = rOld.aStart.Row();
1542 SCCOL nOldEndX = rOld.aEnd.Col();
1543 SCROW nOldEndY = rOld.aEnd.Row();
1544 SCCOL nNewEndX = rNew.aEnd.Col();
1545 SCROW nNewEndY = rNew.aEnd.Row();
1546 SCTAB nTab = rOld.aStart.Tab();
1548 // wenn es mehr Zeilen werden, werden Spalten auf der alten Hoehe eingefuegt/geloescht
1549 bool bGrowY = ( nNewEndY > nOldEndY );
1550 SCROW nColEndY = bGrowY ? nOldEndY : nNewEndY;
1551 SCCOL nRowEndX = bGrowY ? nNewEndX : nOldEndX;
1553 // Spalten
1555 if ( nNewEndX > nOldEndX ) // Spalten einfuegen
1557 rColRange = ScRange( nOldEndX+1, nStartY, nTab, nNewEndX, nColEndY, nTab );
1558 rInsCol = true;
1560 else if ( nNewEndX < nOldEndX ) // Spalten loeschen
1562 rColRange = ScRange( nNewEndX+1, nStartY, nTab, nOldEndX, nColEndY, nTab );
1563 rDelCol = true;
1566 // Zeilen
1568 if ( nNewEndY > nOldEndY ) // Zeilen einfuegen
1570 rRowRange = ScRange( nStartX, nOldEndY+1, nTab, nRowEndX, nNewEndY, nTab );
1571 rInsRow = true;
1573 else if ( nNewEndY < nOldEndY ) // Zeilen loeschen
1575 rRowRange = ScRange( nStartX, nNewEndY+1, nTab, nRowEndX, nOldEndY, nTab );
1576 rDelRow = true;
1581 bool ScDocument::HasPartOfMerged( const ScRange& rRange )
1583 bool bPart = false;
1584 SCTAB nTab = rRange.aStart.Tab();
1586 SCCOL nStartX = rRange.aStart.Col();
1587 SCROW nStartY = rRange.aStart.Row();
1588 SCCOL nEndX = rRange.aEnd.Col();
1589 SCROW nEndY = rRange.aEnd.Row();
1591 if (HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab,
1592 HASATTR_MERGED | HASATTR_OVERLAPPED ))
1594 ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
1595 ExtendOverlapped( nStartX, nStartY, nEndX, nEndY, nTab );
1597 bPart = ( nStartX != rRange.aStart.Col() || nEndX != rRange.aEnd.Col() ||
1598 nStartY != rRange.aStart.Row() || nEndY != rRange.aEnd.Row() );
1600 return bPart;
1603 size_t ScDocument::GetFormulaHash( const ScAddress& rPos ) const
1605 SCTAB nTab = rPos.Tab();
1606 if (!ValidTab(nTab) || static_cast<size_t>(nTab) >= maTabs.size() || !maTabs[nTab])
1607 return 0;
1609 return maTabs[nTab]->GetFormulaHash(rPos.Col(), rPos.Row());
1612 ScFormulaVectorState ScDocument::GetFormulaVectorState( const ScAddress& rPos ) const
1614 SCTAB nTab = rPos.Tab();
1615 if (!ValidTab(nTab) || static_cast<size_t>(nTab) >= maTabs.size() || !maTabs[nTab])
1616 return FormulaVectorUnknown;
1618 return maTabs[nTab]->GetFormulaVectorState(rPos.Col(), rPos.Row());
1621 formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScAddress& rPos )
1623 SCTAB nTab = rPos.Tab();
1624 if (!TableExists(nTab))
1625 return formula::FormulaTokenRef();
1627 return maTabs[nTab]->ResolveStaticReference(rPos.Col(), rPos.Row());
1630 formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRange )
1632 SCTAB nTab = rRange.aStart.Tab();
1633 if (nTab != rRange.aEnd.Tab() || !TableExists(nTab))
1634 return formula::FormulaTokenRef();
1636 return maTabs[nTab]->ResolveStaticReference(
1637 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
1640 const double* ScDocument::FetchDoubleArray(
1641 sc::FormulaGroupContext& rCxt, const ScAddress& rPos, SCROW nLength ) const
1643 SCTAB nTab = rPos.Tab();
1644 if (!TableExists(nTab))
1645 return NULL;
1647 return maTabs[nTab]->FetchDoubleArray(rCxt, rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
1650 bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
1652 if ( rOld == rNew )
1653 return true;
1655 bool bOk = true;
1656 bool bInsCol,bDelCol,bInsRow,bDelRow;
1657 ScRange aColRange,aRowRange;
1658 lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
1660 if ( bInsCol && !CanInsertCol( aColRange ) ) // Zellen am Rand ?
1661 bOk = false;
1662 if ( bInsRow && !CanInsertRow( aRowRange ) ) // Zellen am Rand ?
1663 bOk = false;
1665 if ( bInsCol || bDelCol )
1667 aColRange.aEnd.SetCol(MAXCOL);
1668 if ( HasPartOfMerged(aColRange) )
1669 bOk = false;
1671 if ( bInsRow || bDelRow )
1673 aRowRange.aEnd.SetRow(MAXROW);
1674 if ( HasPartOfMerged(aRowRange) )
1675 bOk = false;
1678 return bOk;
1682 void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, bool bClear )
1684 if (bClear)
1685 DeleteAreaTab( rOld, IDF_ALL );
1687 bool bInsCol,bDelCol,bInsRow,bDelRow;
1688 ScRange aColRange,aRowRange;
1689 lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
1691 if ( bInsCol )
1692 InsertCol( aColRange ); // Spalten zuerst einfuegen
1693 if ( bInsRow )
1694 InsertRow( aRowRange );
1696 if ( bDelRow )
1697 DeleteRow( aRowRange ); // Zeilen zuerst loeschen
1698 if ( bDelCol )
1699 DeleteCol( aColRange );
1701 // Referenzen um eingefuegte Zeilen erweitern
1703 if ( bInsCol || bInsRow )
1705 ScRange aGrowSource = rOld;
1706 aGrowSource.aEnd.SetCol(std::min( rOld.aEnd.Col(), rNew.aEnd.Col() ));
1707 aGrowSource.aEnd.SetRow(std::min( rOld.aEnd.Row(), rNew.aEnd.Row() ));
1708 SCCOL nGrowX = bInsCol ? ( rNew.aEnd.Col() - rOld.aEnd.Col() ) : 0;
1709 SCROW nGrowY = bInsRow ? ( rNew.aEnd.Row() - rOld.aEnd.Row() ) : 0;
1710 UpdateGrow( aGrowSource, nGrowX, nGrowY );
1715 void ScDocument::DeleteArea(SCCOL nCol1, SCROW nRow1,
1716 SCCOL nCol2, SCROW nRow2,
1717 const ScMarkData& rMark, sal_uInt16 nDelFlag)
1719 PutInOrder( nCol1, nCol2 );
1720 PutInOrder( nRow1, nRow2 );
1721 bool bOldAutoCalc = GetAutoCalc();
1722 SetAutoCalc( false ); // avoid multiple calculations
1723 for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++)
1724 if (maTabs[i])
1725 if ( rMark.GetTableSelect(i) || bIsUndo )
1726 maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
1727 SetAutoCalc( bOldAutoCalc );
1731 void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1,
1732 SCCOL nCol2, SCROW nRow2,
1733 SCTAB nTab, sal_uInt16 nDelFlag)
1735 PutInOrder( nCol1, nCol2 );
1736 PutInOrder( nRow1, nRow2 );
1737 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1739 bool bOldAutoCalc = GetAutoCalc();
1740 SetAutoCalc( false ); // avoid multiple calculations
1741 maTabs[nTab]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
1742 SetAutoCalc( bOldAutoCalc );
1747 void ScDocument::DeleteAreaTab( const ScRange& rRange, sal_uInt16 nDelFlag )
1749 for ( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); nTab++ )
1750 DeleteAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
1751 rRange.aEnd.Col(), rRange.aEnd.Row(),
1752 nTab, nDelFlag );
1756 void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSelection,
1757 bool bColInfo, bool bRowInfo )
1759 if (bIsUndo)
1761 Clear();
1763 xPoolHelper = pSrcDoc->xPoolHelper;
1766 OUString aString;
1767 for (SCTAB nTab = 0; nTab <= rTabSelection.GetLastSelected(); nTab++)
1768 if ( rTabSelection.GetTableSelect( nTab ) )
1770 ScTable* pTable = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1771 if (nTab < static_cast<SCTAB>(maTabs.size()))
1772 maTabs[nTab] = pTable;
1773 else
1774 maTabs.push_back(pTable);
1776 else
1778 if (nTab < static_cast<SCTAB>(maTabs.size()))
1779 maTabs[nTab]=NULL;
1780 else
1781 maTabs.push_back(NULL);
1784 else
1786 OSL_FAIL("InitUndo");
1791 void ScDocument::InitUndo( ScDocument* pSrcDoc, SCTAB nTab1, SCTAB nTab2,
1792 bool bColInfo, bool bRowInfo )
1794 if (bIsUndo)
1796 Clear();
1798 xPoolHelper = pSrcDoc->xPoolHelper;
1799 if (pSrcDoc->pShell->GetMedium())
1800 maFileURL = pSrcDoc->pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
1802 OUString aString;
1803 if ( nTab2 >= static_cast<SCTAB>(maTabs.size()))
1804 maTabs.resize(nTab2 + 1, NULL);
1805 for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
1807 ScTable* pTable = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1808 maTabs[nTab] = pTable;
1811 else
1813 OSL_FAIL("InitUndo");
1818 void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, bool bColInfo, bool bRowInfo )
1820 if (bIsUndo)
1822 OUString aString;
1823 if (nTab2 >= static_cast<SCTAB>(maTabs.size()))
1825 maTabs.resize(nTab2+1,NULL);
1827 for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
1828 if (!maTabs[nTab])
1830 maTabs[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1834 else
1836 OSL_FAIL("InitUndo");
1841 void ScDocument::SetCutMode( bool bVal )
1843 if (bIsClip)
1844 GetClipParam().mbCutMode = bVal;
1845 else
1847 OSL_FAIL("SetCutMode without bIsClip");
1852 bool ScDocument::IsCutMode()
1854 if (bIsClip)
1855 return GetClipParam().mbCutMode;
1856 else
1858 OSL_FAIL("IsCutMode without bIsClip");
1859 return false;
1864 void ScDocument::CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1865 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1866 sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
1867 const ScMarkData* pMarks, bool bColRowFlags )
1869 PutInOrder( nCol1, nCol2 );
1870 PutInOrder( nRow1, nRow2 );
1871 PutInOrder( nTab1, nTab2 );
1872 if( pDestDoc->aDocName.isEmpty() )
1873 pDestDoc->aDocName = aDocName;
1874 if (ValidTab(nTab1) && ValidTab(nTab2))
1876 sc::CopyToDocContext aCxt(*pDestDoc);
1877 bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1878 pDestDoc->SetAutoCalc( false ); // avoid multiple calculations
1879 SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
1880 for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
1882 if (maTabs[i] && pDestDoc->maTabs[i])
1883 maTabs[i]->CopyToTable(aCxt, nCol1, nRow1, nCol2, nRow2, nFlags,
1884 bOnlyMarked, pDestDoc->maTabs[i], pMarks,
1885 false, bColRowFlags );
1887 pDestDoc->SetAutoCalc( bOldAutoCalc );
1892 void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1893 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1894 sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
1895 const ScMarkData* pMarks)
1897 PutInOrder( nCol1, nCol2 );
1898 PutInOrder( nRow1, nRow2 );
1899 PutInOrder( nTab1, nTab2 );
1900 if (ValidTab(nTab1) && ValidTab(nTab2))
1902 bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1903 pDestDoc->SetAutoCalc( false ); // avoid multiple calculations
1904 if (nTab1 > 0)
1905 CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, false, pDestDoc, pMarks );
1907 sc::CopyToDocContext aCxt(*pDestDoc);
1908 OSL_ASSERT( nTab2 < static_cast<SCTAB>(maTabs.size()) && nTab2 < static_cast<SCTAB>(pDestDoc->maTabs.size()));
1909 for (SCTAB i = nTab1; i <= nTab2; i++)
1911 if (maTabs[i] && pDestDoc->maTabs[i])
1912 maTabs[i]->UndoToTable(aCxt, nCol1, nRow1, nCol2, nRow2, nFlags,
1913 bOnlyMarked, pDestDoc->maTabs[i], pMarks);
1916 if (nTab2 < MAXTAB)
1917 CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, false, pDestDoc, pMarks );
1918 pDestDoc->SetAutoCalc( bOldAutoCalc );
1923 void ScDocument::CopyToDocument(const ScRange& rRange,
1924 sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
1925 const ScMarkData* pMarks, bool bColRowFlags)
1927 ScRange aNewRange = rRange;
1928 aNewRange.Justify();
1930 if( pDestDoc->aDocName.isEmpty() )
1931 pDestDoc->aDocName = aDocName;
1932 bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1933 pDestDoc->SetAutoCalc( false ); // avoid multiple calculations
1934 sc::CopyToDocContext aCxt(*pDestDoc);
1935 SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
1936 for (SCTAB i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab() && i < nMinSizeBothTabs; i++)
1938 if (!TableExists(i) || !pDestDoc->TableExists(i))
1939 continue;
1941 maTabs[i]->CopyToTable(aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(),
1942 aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
1943 nFlags, bOnlyMarked, pDestDoc->maTabs[i],
1944 pMarks, false, bColRowFlags);
1946 pDestDoc->SetAutoCalc( bOldAutoCalc );
1950 void ScDocument::UndoToDocument(const ScRange& rRange,
1951 sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
1952 const ScMarkData* pMarks)
1954 ScRange aNewRange = rRange;
1955 aNewRange.Justify();
1956 SCTAB nTab1 = aNewRange.aStart.Tab();
1957 SCTAB nTab2 = aNewRange.aEnd.Tab();
1959 bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1960 pDestDoc->SetAutoCalc( false ); // avoid multiple calculations
1961 sc::CopyToDocContext aCxt(*pDestDoc);
1962 if (nTab1 > 0)
1963 CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, false, pDestDoc, pMarks );
1965 SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
1966 for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
1968 if (maTabs[i] && pDestDoc->maTabs[i])
1969 maTabs[i]->UndoToTable(aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(),
1970 aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
1971 nFlags, bOnlyMarked, pDestDoc->maTabs[i], pMarks);
1974 if (nTab2 < static_cast<SCTAB>(maTabs.size()))
1975 CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,maTabs.size(), IDF_FORMULA, false, pDestDoc, pMarks );
1976 pDestDoc->SetAutoCalc( bOldAutoCalc );
1979 // bUseRangeForVBA added for VBA api support to allow content of a specified
1980 // range to be copied ( e.g. don't use marked data but the just the range
1981 // specified by rClipParam
1982 void ScDocument::CopyToClip(const ScClipParam& rClipParam,
1983 ScDocument* pClipDoc, const ScMarkData* pMarks,
1984 bool bAllTabs, bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions, bool bUseRangeForVBA )
1986 OSL_ENSURE( !bUseRangeForVBA && ( bAllTabs || pMarks ), "CopyToClip: ScMarkData fails" );
1988 if (bIsClip)
1989 return;
1991 if (!pClipDoc)
1993 OSL_TRACE("CopyToClip: no ClipDoc");
1994 pClipDoc = SC_MOD()->GetClipDoc();
1997 if (pShell->GetMedium())
1999 pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
2000 // for unsaved files use the title name and adjust during save of file
2001 if (pClipDoc->maFileURL.isEmpty())
2002 pClipDoc->maFileURL = pShell->GetName();
2004 else
2006 pClipDoc->maFileURL = pShell->GetName();
2009 //init maTabNames
2010 for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
2012 if( *itr )
2014 OUString aTabName;
2015 (*itr)->GetName(aTabName);
2016 pClipDoc->maTabNames.push_back(aTabName);
2018 else
2019 pClipDoc->maTabNames.push_back(OUString());
2022 pClipDoc->aDocName = aDocName;
2023 pClipDoc->SetClipParam(rClipParam);
2024 ScRange aClipRange = rClipParam.getWholeRange();
2025 SCTAB nTab = aClipRange.aStart.Tab();
2026 SCTAB i = 0;
2027 SCTAB nEndTab = static_cast<SCTAB>(maTabs.size());
2029 if ( bUseRangeForVBA )
2031 pClipDoc->ResetClip( this, nTab );
2032 i = nTab;
2033 nEndTab = nTab + 1;
2035 else
2036 pClipDoc->ResetClip(this, pMarks);
2038 sc::CopyToClipContext aCxt(*pClipDoc, bKeepScenarioFlags, bCloneNoteCaptions);
2039 CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
2041 for ( ; i < nEndTab; ++i)
2043 if (!maTabs[i] || i >= static_cast<SCTAB>(pClipDoc->maTabs.size()) || !pClipDoc->maTabs[i])
2044 continue;
2046 if ( !bUseRangeForVBA && ( pMarks && !pMarks->GetTableSelect(i) ) )
2047 continue;
2049 maTabs[i]->CopyToClip(aCxt, rClipParam.maRanges, pClipDoc->maTabs[i]);
2051 if (pDrawLayer && bIncludeObjects)
2053 // also copy drawing objects
2054 Rectangle aObjRect = GetMMRect(
2055 aClipRange.aStart.Col(), aClipRange.aStart.Row(), aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i);
2056 pDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
2060 // Make sure to mark overlapped cells.
2061 pClipDoc->ExtendMerge(aClipRange, true);
2064 void ScDocument::CopyStaticToDocument(const ScRange& rSrcRange, SCTAB nDestTab, ScDocument* pDestDoc)
2066 if (!pDestDoc)
2067 return;
2069 ScTable* pSrcTab = rSrcRange.aStart.Tab() < static_cast<SCTAB>(maTabs.size()) ? maTabs[rSrcRange.aStart.Tab()] : NULL;
2070 ScTable* pDestTab = nDestTab < static_cast<SCTAB>(pDestDoc->maTabs.size()) ? pDestDoc->maTabs[nDestTab] : NULL;
2072 if (!pSrcTab || !pDestTab)
2073 return;
2075 pSrcTab->CopyStaticToDocument(
2076 rSrcRange.aStart.Col(), rSrcRange.aStart.Row(), rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(), pDestTab);
2079 void ScDocument::CopyCellToDocument( const ScAddress& rSrcPos, const ScAddress& rDestPos, ScDocument& rDestDoc )
2081 if (!TableExists(rSrcPos.Tab()) || !rDestDoc.TableExists(rDestPos.Tab()))
2082 return;
2084 ScTable& rSrcTab = *maTabs[rSrcPos.Tab()];
2085 ScTable& rDestTab = *rDestDoc.maTabs[rDestPos.Tab()];
2087 rSrcTab.CopyCellToDocument(rSrcPos.Col(), rSrcPos.Row(), rDestPos.Col(), rDestPos.Row(), rDestTab);
2090 void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
2091 SCCOL nCol2, SCROW nRow2,
2092 SCTAB nTab, ScDocument* pClipDoc)
2094 if (!bIsClip)
2096 if (pShell->GetMedium())
2098 pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
2099 // for unsaved files use the title name and adjust during save of file
2100 if (pClipDoc->maFileURL.isEmpty())
2101 pClipDoc->maFileURL = pShell->GetName();
2103 else
2105 pClipDoc->maFileURL = pShell->GetName();
2108 //init maTabNames
2109 for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
2111 if( *itr )
2113 OUString aTabName;
2114 (*itr)->GetName(aTabName);
2115 pClipDoc->maTabNames.push_back(aTabName);
2117 else
2118 pClipDoc->maTabNames.push_back(OUString());
2121 PutInOrder( nCol1, nCol2 );
2122 PutInOrder( nRow1, nRow2 );
2123 if (!pClipDoc)
2125 OSL_TRACE("CopyTabToClip: no ClipDoc");
2126 pClipDoc = SC_MOD()->GetClipDoc();
2129 ScClipParam& rClipParam = pClipDoc->GetClipParam();
2130 pClipDoc->aDocName = aDocName;
2131 rClipParam.maRanges.RemoveAll();
2132 rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
2133 pClipDoc->ResetClip( this, nTab );
2135 sc::CopyToClipContext aCxt(*pClipDoc, false, true);
2136 if (nTab < static_cast<SCTAB>(maTabs.size()) && nTab < static_cast<SCTAB>(pClipDoc->maTabs.size()))
2137 if (maTabs[nTab] && pClipDoc->maTabs[nTab])
2138 maTabs[nTab]->CopyToClip(aCxt, nCol1, nRow1, nCol2, nRow2, pClipDoc->maTabs[nTab]);
2140 pClipDoc->GetClipParam().mbCutMode = false;
2145 void ScDocument::TransposeClip( ScDocument* pTransClip, sal_uInt16 nFlags, bool bAsLink )
2147 OSL_ENSURE( bIsClip && pTransClip && pTransClip->bIsClip,
2148 "TransposeClip with wrong Document" );
2150 // initialisieren
2151 // -> pTransClip muss vor dem Original-Dokument geloescht werden!
2153 pTransClip->ResetClip(this, (ScMarkData*)NULL); // alle
2155 // Bereiche uebernehmen
2157 if (pRangeName)
2159 pTransClip->GetRangeName()->clear();
2160 ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
2161 for (; itr != itrEnd; ++itr)
2163 sal_uInt16 nIndex = itr->second->GetIndex();
2164 ScRangeData* pData = new ScRangeData(*itr->second);
2165 if (pTransClip->pRangeName->insert(pData))
2166 pData->SetIndex(nIndex);
2170 // The data
2172 ScRange aClipRange = GetClipParam().getWholeRange();
2173 if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
2175 for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
2176 if (maTabs[i])
2178 OSL_ENSURE( pTransClip->maTabs[i], "TransposeClip: Table not there" );
2179 maTabs[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
2180 aClipRange.aEnd.Col(), aClipRange.aEnd.Row(),
2181 pTransClip->maTabs[i], nFlags, bAsLink );
2183 if ( pDrawLayer && ( nFlags & IDF_OBJECTS ) )
2185 // Drawing objects are copied to the new area without transposing.
2186 // CopyFromClip is used to adjust the objects to the transposed block's
2187 // cell range area.
2188 // (pDrawLayer in the original clipboard document is set only if there
2189 // are drawing objects to copy)
2191 pTransClip->InitDrawLayer();
2192 Rectangle aSourceRect = GetMMRect( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
2193 aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i );
2194 Rectangle aDestRect = pTransClip->GetMMRect( 0, 0,
2195 static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()),
2196 static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()), i );
2197 pTransClip->pDrawLayer->CopyFromClip( pDrawLayer, i, aSourceRect, ScAddress(0,0,i), aDestRect );
2201 pTransClip->SetClipParam(GetClipParam());
2202 pTransClip->GetClipParam().transpose();
2204 else
2206 OSL_TRACE("TransposeClip: Too big");
2209 // Dies passiert erst beim Einfuegen...
2211 GetClipParam().mbCutMode = false;
2214 namespace {
2216 void copyUsedNamesToClip(ScRangeName* pClipRangeName, ScRangeName* pRangeName, const std::set<sal_uInt16>& rUsedNames)
2218 pClipRangeName->clear();
2219 ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
2220 for (; itr != itrEnd; ++itr) //! DB-Bereiche Pivot-Bereiche auch !!!
2222 sal_uInt16 nIndex = itr->second->GetIndex();
2223 bool bInUse = (rUsedNames.count(nIndex) > 0);
2224 if (!bInUse)
2225 continue;
2227 ScRangeData* pData = new ScRangeData(*itr->second);
2228 if (pClipRangeName->insert(pData))
2229 pData->SetIndex(nIndex);
2235 void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs)
2237 if (!pRangeName || pRangeName->empty())
2238 return;
2240 std::set<sal_uInt16> aUsedNames; // indexes of named ranges that are used in the copied cells
2241 SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pClipDoc->maTabs.size()));
2242 for (SCTAB i = 0; i < nMinSizeBothTabs; ++i)
2243 if (maTabs[i] && pClipDoc->maTabs[i])
2244 if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
2245 maTabs[i]->FindRangeNamesInUse(
2246 rClipRange.aStart.Col(), rClipRange.aStart.Row(),
2247 rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames);
2249 copyUsedNamesToClip(pClipDoc->GetRangeName(), pRangeName, aUsedNames);
2252 ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) :
2253 mpDoc(pDoc)
2255 mpDoc->MergeNumberFormatter(pSrcDoc);
2258 ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
2260 mpDoc->pFormatExchangeList = NULL;
2263 SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos )
2265 ScTable* pTab = FetchTable(rPos.Tab());
2266 if (!pTab)
2267 return NULL;
2269 return pTab->GetBroadcaster(rPos.Col(), rPos.Row());
2272 const SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos ) const
2274 const ScTable* pTab = FetchTable(rPos.Tab());
2275 if (!pTab)
2276 return NULL;
2278 return pTab->GetBroadcaster(rPos.Col(), rPos.Row());
2281 void ScDocument::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rTopPos, SCROW nLength )
2283 ScTable* pTab = FetchTable(rTopPos.Tab());
2284 if (!pTab || nLength <= 0)
2285 return;
2287 pTab->DeleteBroadcasters(rBlockPos, rTopPos.Col(), rTopPos.Row(), rTopPos.Row()+nLength-1);
2290 bool ScDocument::HasBroadcaster( SCTAB nTab, SCCOL nCol ) const
2292 const ScTable* pTab = FetchTable(nTab);
2293 if (!pTab)
2294 return false;
2296 return pTab->HasBroadcaster(nCol);
2299 bool ScDocument::TableExists( SCTAB nTab ) const
2301 return ValidTab(nTab) && static_cast<size_t>(nTab) < maTabs.size() && maTabs[nTab];
2304 ScTable* ScDocument::FetchTable( SCTAB nTab )
2306 if (!TableExists(nTab))
2307 return NULL;
2309 return maTabs[nTab];
2312 const ScTable* ScDocument::FetchTable( SCTAB nTab ) const
2314 if (!TableExists(nTab))
2315 return NULL;
2317 return maTabs[nTab];
2320 void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
2322 SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
2323 SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
2324 if (pOtherFormatter && pOtherFormatter != pThisFormatter)
2326 SvNumberFormatterIndexTable* pExchangeList =
2327 pThisFormatter->MergeFormatter(*(pOtherFormatter));
2328 if (!pExchangeList->empty())
2329 pFormatExchangeList = pExchangeList;
2333 ScClipParam& ScDocument::GetClipParam()
2335 if (!mpClipParam.get())
2336 mpClipParam.reset(new ScClipParam);
2338 return *mpClipParam;
2341 void ScDocument::SetClipParam(const ScClipParam& rParam)
2343 mpClipParam.reset(new ScClipParam(rParam));
2346 bool ScDocument::IsClipboardSource() const
2348 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
2349 return pClipDoc && pClipDoc->xPoolHelper.is() &&
2350 xPoolHelper->GetDocPool() == pClipDoc->xPoolHelper->GetDocPool();
2354 void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
2355 SCCOL nCol2, SCROW nRow2,
2356 const ScMarkData& rMark, sal_uInt16 nInsFlag )
2358 if (nInsFlag & IDF_CONTENTS)
2360 sc::StartListeningContext aCxt(*this);
2361 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
2362 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
2363 for (; itr != itrEnd && *itr < nMax; ++itr)
2364 if (maTabs[*itr])
2365 maTabs[*itr]->StartListeningInArea(aCxt, nCol1, nRow1, nCol2, nRow2);
2370 void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
2371 SCCOL nCol2, SCROW nRow2,
2372 const ScMarkData& rMark, sal_uInt16 nInsFlag )
2374 if (nInsFlag & IDF_CONTENTS)
2376 ScBulkBroadcast aBulkBroadcast( GetBASM());
2377 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
2378 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
2379 for (; itr != itrEnd && *itr < nMax; ++itr)
2380 if (maTabs[*itr])
2381 maTabs[*itr]->BroadcastInArea( nCol1, nRow1, nCol2, nRow2 );
2385 bool ScDocument::InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol )
2387 if (!TableExists(nTab))
2388 return false;
2390 return maTabs[nTab]->InitColumnBlockPosition(rBlockPos, nCol);
2393 void ScDocument::CopyBlockFromClip(
2394 sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
2395 const ScMarkData& rMark, SCsCOL nDx, SCsROW nDy )
2397 TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs;
2398 SCTAB nTabEnd = rCxt.getTabEnd();
2399 SCTAB nClipTab = 0;
2400 for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++)
2402 if (maTabs[i] && rMark.GetTableSelect(i) )
2404 while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
2406 maTabs[i]->CopyFromClip(
2407 rCxt, nCol1, nRow1, nCol2, nRow2, nDx, nDy, rClipTabs[nClipTab]);
2409 if (rCxt.getClipDoc()->pDrawLayer && (rCxt.getInsertFlag() & IDF_OBJECTS))
2411 // also copy drawing objects
2413 // drawing layer must be created before calling CopyFromClip
2414 // (ScDocShell::MakeDrawLayer also does InitItems etc.)
2415 OSL_ENSURE( pDrawLayer, "CopyBlockFromClip: No drawing layer" );
2416 if ( pDrawLayer )
2418 // For GetMMRect, the row heights in the target document must already be valid
2419 // (copied in an extra step before pasting, or updated after pasting cells, but
2420 // before pasting objects).
2422 Rectangle aSourceRect = rCxt.getClipDoc()->GetMMRect(
2423 nCol1-nDx, nRow1-nDy, nCol2-nDx, nRow2-nDy, nClipTab );
2424 Rectangle aDestRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, i );
2425 pDrawLayer->CopyFromClip(rCxt.getClipDoc()->pDrawLayer, nClipTab, aSourceRect,
2426 ScAddress( nCol1, nRow1, i ), aDestRect );
2430 nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
2433 if (rCxt.getInsertFlag() & IDF_CONTENTS)
2435 nClipTab = 0;
2436 for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++)
2438 if (maTabs[i] && rMark.GetTableSelect(i) )
2440 while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
2441 SCsTAB nDz = ((SCsTAB)i) - nClipTab;
2443 // ranges of consecutive selected tables (in clipboard and dest. doc)
2444 // must be handled in one UpdateReference call
2445 SCTAB nFollow = 0;
2446 while ( i + nFollow < nTabEnd
2447 && rMark.GetTableSelect( i + nFollow + 1 )
2448 && nClipTab + nFollow < MAXTAB
2449 && rClipTabs[(nClipTab + nFollow + 1) % static_cast<SCTAB>(rClipTabs.size())] )
2450 ++nFollow;
2452 if (rCxt.getClipDoc()->GetClipParam().mbCutMode)
2454 bool bOldInserting = IsInsertingFromOtherDoc();
2455 SetInsertingFromOtherDoc( true);
2456 UpdateReference( URM_MOVE,
2457 nCol1, nRow1, i, nCol2, nRow2, i+nFollow,
2458 nDx, nDy, nDz, rCxt.getUndoDoc(), false );
2459 SetInsertingFromOtherDoc( bOldInserting);
2461 else
2462 UpdateReference( URM_COPY,
2463 nCol1, nRow1, i, nCol2, nRow2, i+nFollow,
2464 nDx, nDy, nDz, rCxt.getUndoDoc(), false );
2466 nClipTab = (nClipTab+nFollow+1) % (static_cast<SCTAB>(rClipTabs.size()));
2467 i = sal::static_int_cast<SCTAB>( i + nFollow );
2474 void ScDocument::CopyNonFilteredFromClip(
2475 sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
2476 const ScMarkData& rMark, SCsCOL nDx, SCROW & rClipStartRow )
2478 // call CopyBlockFromClip for ranges of consecutive non-filtered rows
2479 // nCol1/nRow1 etc. is in target doc
2481 // filtered state is taken from first used table in clipboard (as in GetClipArea)
2482 SCTAB nFlagTab = 0;
2483 TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs;
2484 while ( nFlagTab < static_cast<SCTAB>(rClipTabs.size()) && !rClipTabs[nFlagTab] )
2485 ++nFlagTab;
2487 SCROW nSourceRow = rClipStartRow;
2488 SCROW nSourceEnd = 0;
2489 if (!rCxt.getClipDoc()->GetClipParam().maRanges.empty())
2490 nSourceEnd = rCxt.getClipDoc()->GetClipParam().maRanges.front()->aEnd.Row();
2491 SCROW nDestRow = nRow1;
2493 while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
2495 // skip filtered rows
2496 nSourceRow = rCxt.getClipDoc()->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab);
2498 if ( nSourceRow <= nSourceEnd )
2500 // look for more non-filtered rows following
2501 SCROW nLastRow = nSourceRow;
2502 rCxt.getClipDoc()->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow);
2503 SCROW nFollow = nLastRow - nSourceRow;
2505 if (nFollow > nSourceEnd - nSourceRow)
2506 nFollow = nSourceEnd - nSourceRow;
2507 if (nFollow > nRow2 - nDestRow)
2508 nFollow = nRow2 - nDestRow;
2510 SCsROW nNewDy = ((SCsROW)nDestRow) - nSourceRow;
2511 CopyBlockFromClip(
2512 rCxt, nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy);
2514 nSourceRow += nFollow + 1;
2515 nDestRow += nFollow + 1;
2518 rClipStartRow = nSourceRow;
2522 void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
2523 sal_uInt16 nInsFlag,
2524 ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut,
2525 bool bAsLink, bool bIncludeFiltered, bool bSkipAttrForEmpty,
2526 const ScRangeList * pDestRanges )
2528 if (bIsClip)
2529 return;
2531 if (!pClipDoc)
2533 OSL_FAIL("CopyFromClip: no ClipDoc");
2534 pClipDoc = SC_MOD()->GetClipDoc();
2537 if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
2538 return;
2540 bool bOldAutoCalc = GetAutoCalc();
2541 SetAutoCalc( false ); // avoid multiple recalculations
2543 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2545 SCCOL nAllCol1 = rDestRange.aStart.Col();
2546 SCROW nAllRow1 = rDestRange.aStart.Row();
2547 SCCOL nAllCol2 = rDestRange.aEnd.Col();
2548 SCROW nAllRow2 = rDestRange.aEnd.Row();
2550 SCCOL nXw = 0;
2551 SCROW nYw = 0;
2552 ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
2553 for (SCTAB nTab = 0; nTab < static_cast<SCTAB>(pClipDoc->maTabs.size()); nTab++) // find largest merge overlap
2554 if (pClipDoc->maTabs[nTab]) // all sheets of the clipboard content
2556 SCCOL nThisEndX = aClipRange.aEnd.Col();
2557 SCROW nThisEndY = aClipRange.aEnd.Row();
2558 pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
2559 aClipRange.aStart.Row(),
2560 nThisEndX, nThisEndY, nTab );
2561 // only extra value from ExtendMerge
2562 nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
2563 nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
2564 if ( nThisEndX > nXw )
2565 nXw = nThisEndX;
2566 if ( nThisEndY > nYw )
2567 nYw = nThisEndY;
2570 SCCOL nDestAddX;
2571 SCROW nDestAddY;
2572 pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered );
2573 nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX );
2574 nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value
2576 /* Decide which contents to delete before copying. Delete all
2577 contents if nInsFlag contains any real content flag.
2578 #i102056# Notes are pasted from clipboard in a second pass,
2579 together with the special flag IDF_ADDNOTES that states to not
2580 overwrite/delete existing cells but to insert the notes into
2581 these cells. In this case, just delete old notes from the
2582 destination area. */
2583 sal_uInt16 nDelFlag = IDF_NONE;
2584 if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) )
2585 nDelFlag |= IDF_NOTE;
2586 else if ( nInsFlag & IDF_CONTENTS )
2587 nDelFlag |= IDF_CONTENTS;
2588 // With bSkipAttrForEmpty, don't remove attributes, copy
2589 // on top of existing attributes instead.
2590 if ( ( nInsFlag & IDF_ATTRIB ) && !bSkipAttrForEmpty )
2591 nDelFlag |= IDF_ATTRIB;
2593 sc::CopyFromClipContext aCxt(*this, pRefUndoDoc, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
2594 std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark);
2595 aCxt.setTabRange(aTabRanges.first, aTabRanges.second);
2597 ScRangeList aLocalRangeList;
2598 if (!pDestRanges)
2600 aLocalRangeList.Append( rDestRange);
2601 pDestRanges = &aLocalRangeList;
2604 bInsertingFromOtherDoc = true; // kein Broadcast/Listener aufbauen bei Insert
2606 SCCOL nClipStartCol = aClipRange.aStart.Col();
2607 SCROW nClipStartRow = aClipRange.aStart.Row();
2608 SCROW nClipEndRow = aClipRange.aEnd.Row();
2609 for ( size_t nRange = 0; nRange < pDestRanges->size(); ++nRange )
2611 const ScRange* pRange = (*pDestRanges)[nRange];
2612 SCCOL nCol1 = pRange->aStart.Col();
2613 SCROW nRow1 = pRange->aStart.Row();
2614 SCCOL nCol2 = pRange->aEnd.Col();
2615 SCROW nRow2 = pRange->aEnd.Row();
2617 DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
2619 SCCOL nC1 = nCol1;
2620 SCROW nR1 = nRow1;
2621 SCCOL nC2 = nC1 + nXw;
2622 if (nC2 > nCol2)
2623 nC2 = nCol2;
2624 SCROW nR2 = nR1 + nYw;
2625 if (nR2 > nRow2)
2626 nR2 = nRow2;
2630 // Pasting is done column-wise, when pasting to a filtered
2631 // area this results in partitioning and we have to
2632 // remember and reset the start row for each column until
2633 // it can be advanced for the next chunk of unfiltered
2634 // rows.
2635 SCROW nSaveClipStartRow = nClipStartRow;
2638 nClipStartRow = nSaveClipStartRow;
2639 SCsCOL nDx = ((SCsCOL)nC1) - nClipStartCol;
2640 SCsROW nDy = ((SCsROW)nR1) - nClipStartRow;
2641 if ( bIncludeFiltered )
2643 CopyBlockFromClip(
2644 aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nDy);
2645 nClipStartRow += nR2 - nR1 + 1;
2647 else
2649 CopyNonFilteredFromClip(
2650 aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nClipStartRow);
2652 nC1 = nC2 + 1;
2653 nC2 = std::min((SCCOL)(nC1 + nXw), nCol2);
2654 } while (nC1 <= nCol2);
2655 if (nClipStartRow > nClipEndRow)
2656 nClipStartRow = aClipRange.aStart.Row();
2657 nC1 = nCol1;
2658 nC2 = nC1 + nXw;
2659 if (nC2 > nCol2)
2660 nC2 = nCol2;
2661 nR1 = nR2 + 1;
2662 nR2 = std::min((SCROW)(nR1 + nYw), nRow2);
2663 } while (nR1 <= nRow2);
2666 bInsertingFromOtherDoc = false;
2668 // Listener aufbauen nachdem alles inserted wurde
2669 StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
2670 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2671 BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
2672 if (bResetCut)
2673 pClipDoc->GetClipParam().mbCutMode = false;
2674 SetAutoCalc( bOldAutoCalc );
2677 static SCROW lcl_getLastNonFilteredRow(
2678 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags, SCROW nBegRow, SCROW nEndRow,
2679 SCROW nRowCount)
2681 SCROW nFilteredRow = rFlags.GetFirstForCondition(
2682 nBegRow, nEndRow, CR_FILTERED, CR_FILTERED);
2684 SCROW nRow = nFilteredRow - 1;
2685 if (nRow - nBegRow + 1 > nRowCount)
2686 // make sure the row range stays within the data size.
2687 nRow = nBegRow + nRowCount - 1;
2689 return nRow;
2692 void ScDocument::CopyMultiRangeFromClip(
2693 const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
2694 bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
2696 if (bIsClip)
2697 return;
2699 if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
2700 // There is nothing in the clip doc to copy.
2701 return;
2703 bool bOldAutoCalc = GetAutoCalc();
2704 SetAutoCalc( false ); // avoid multiple recalculations
2706 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2708 SCCOL nCol1 = rDestPos.Col();
2709 SCROW nRow1 = rDestPos.Row();
2710 ScClipParam& rClipParam = pClipDoc->GetClipParam();
2712 sc::CopyFromClipContext aCxt(*this, NULL, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
2713 std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark);
2714 aCxt.setTabRange(aTabRanges.first, aTabRanges.second);
2716 ScRange aDestRange;
2717 rMark.GetMarkArea(aDestRange);
2718 SCROW nLastMarkedRow = aDestRange.aEnd.Row();
2720 bInsertingFromOtherDoc = true; // kein Broadcast/Listener aufbauen bei Insert
2722 SCROW nBegRow = nRow1;
2723 sal_uInt16 nDelFlag = IDF_CONTENTS;
2724 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags = GetRowFlagsArray(aCxt.getTabStart());
2726 for ( size_t i = 0, n = rClipParam.maRanges.size(); i < n; ++i )
2728 ScRange* p = rClipParam.maRanges[ i ];
2729 // The begin row must not be filtered.
2731 SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1;
2733 SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
2734 SCsROW nDy = static_cast<SCsROW>(nBegRow - p->aStart.Row());
2735 SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
2737 SCROW nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
2739 if (!bSkipAttrForEmpty)
2740 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
2742 CopyBlockFromClip(aCxt, nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy);
2743 nRowCount -= nEndRow - nBegRow + 1;
2745 while (nRowCount > 0)
2747 // Get the first non-filtered row.
2748 SCROW nNonFilteredRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
2749 if (nNonFilteredRow > nLastMarkedRow)
2750 return;
2752 SCROW nRowsSkipped = nNonFilteredRow - nEndRow - 1;
2753 nDy += nRowsSkipped;
2755 nBegRow = nNonFilteredRow;
2756 nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
2758 if (!bSkipAttrForEmpty)
2759 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
2761 CopyBlockFromClip(aCxt, nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy);
2762 nRowCount -= nEndRow - nBegRow + 1;
2765 if (rClipParam.meDirection == ScClipParam::Row)
2766 // Begin row for the next range being pasted.
2767 nBegRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
2768 else
2769 nBegRow = nRow1;
2771 if (rClipParam.meDirection == ScClipParam::Column)
2772 nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
2775 bInsertingFromOtherDoc = false;
2777 ScRangeList aRanges;
2778 aRanges.Append(aDestRange);
2780 // Listener aufbauen nachdem alles inserted wurde
2781 StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
2782 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
2783 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2784 BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
2785 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
2787 if (bResetCut)
2788 pClipDoc->GetClipParam().mbCutMode = false;
2789 SetAutoCalc( bOldAutoCalc );
2792 void ScDocument::SetClipArea( const ScRange& rArea, bool bCut )
2794 if (bIsClip)
2796 ScClipParam& rClipParam = GetClipParam();
2797 rClipParam.maRanges.RemoveAll();
2798 rClipParam.maRanges.Append(rArea);
2799 rClipParam.mbCutMode = bCut;
2801 else
2803 OSL_FAIL("SetClipArea: No Clip");
2808 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, bool bIncludeFiltered)
2810 if (!bIsClip)
2812 OSL_FAIL("GetClipArea: No Clip");
2813 return;
2816 ScRangeList& rClipRanges = GetClipParam().maRanges;
2817 if (rClipRanges.empty())
2818 // No clip range. Bail out.
2819 return;
2821 ScRange* p = rClipRanges.front();
2822 SCCOL nStartCol = p->aStart.Col();
2823 SCCOL nEndCol = p->aEnd.Col();
2824 SCROW nStartRow = p->aStart.Row();
2825 SCROW nEndRow = p->aEnd.Row();
2826 for ( size_t i = 1, n = rClipRanges.size(); i < n; ++i )
2828 p = rClipRanges[ i ];
2829 if (p->aStart.Col() < nStartCol)
2830 nStartCol = p->aStart.Col();
2831 if (p->aStart.Row() < nStartRow)
2832 nStartRow = p->aStart.Row();
2833 if (p->aEnd.Col() > nEndCol)
2834 nEndCol = p->aEnd.Col();
2835 if (p->aEnd.Row() < nEndRow)
2836 nEndRow = p->aEnd.Row();
2839 nClipX = nEndCol - nStartCol;
2841 if ( bIncludeFiltered )
2842 nClipY = nEndRow - nStartRow;
2843 else
2845 // count non-filtered rows
2846 // count on first used table in clipboard
2847 SCTAB nCountTab = 0;
2848 while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] )
2849 ++nCountTab;
2851 SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab);
2853 if ( nResult > 0 )
2854 nClipY = nResult - 1;
2855 else
2856 nClipY = 0; // always return at least 1 row
2861 void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
2863 if (bIsClip)
2865 ScRangeList& rClipRanges = GetClipParam().maRanges;
2866 if ( !rClipRanges.empty() )
2868 nClipX = rClipRanges.front()->aStart.Col();
2869 nClipY = rClipRanges.front()->aStart.Row();
2872 else
2874 OSL_FAIL("GetClipStart: No Clip");
2879 bool ScDocument::HasClipFilteredRows()
2881 // count on first used table in clipboard
2882 SCTAB nCountTab = 0;
2883 while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] )
2884 ++nCountTab;
2886 ScRangeList& rClipRanges = GetClipParam().maRanges;
2887 if ( rClipRanges.empty() )
2888 return false;
2890 for ( size_t i = 0, n = rClipRanges.size(); i < n; ++i )
2892 ScRange* p = rClipRanges[ i ];
2893 bool bAnswer = maTabs[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row());
2894 if (bAnswer)
2895 return true;
2897 return false;
2901 void ScDocument::MixDocument( const ScRange& rRange, sal_uInt16 nFunction, bool bSkipEmpty,
2902 ScDocument* pSrcDoc )
2904 SCTAB nTab1 = rRange.aStart.Tab();
2905 SCTAB nTab2 = rRange.aEnd.Tab();
2906 sc::MixDocContext aCxt(*this);
2907 SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pSrcDoc->maTabs.size()));
2908 for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
2910 ScTable* pTab = FetchTable(i);
2911 const ScTable* pSrcTab = pSrcDoc->FetchTable(i);
2912 if (!pTab || !pSrcTab)
2913 continue;
2915 pTab->MixData(
2916 aCxt, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(),
2917 nFunction, bSkipEmpty, pSrcTab);
2922 void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark,
2923 sal_uInt16 nFlags, sal_uInt16 nFunction,
2924 bool bSkipEmpty, bool bAsLink )
2926 sal_uInt16 nDelFlags = nFlags;
2927 if (nDelFlags & IDF_CONTENTS)
2928 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
2930 SCTAB nSrcTab = rSrcArea.aStart.Tab();
2932 if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
2934 SCCOL nStartCol = rSrcArea.aStart.Col();
2935 SCROW nStartRow = rSrcArea.aStart.Row();
2936 SCCOL nEndCol = rSrcArea.aEnd.Col();
2937 SCROW nEndRow = rSrcArea.aEnd.Row();
2938 boost::scoped_ptr<ScDocument> pMixDoc;
2939 bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
2941 bool bOldAutoCalc = GetAutoCalc();
2942 SetAutoCalc( false ); // avoid multiple calculations
2944 sc::CopyToDocContext aCxt(*this);
2945 sc::MixDocContext aMixDocCxt(*this);
2947 SCTAB nCount = static_cast<SCTAB>(maTabs.size());
2948 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
2949 for (; itr != itrEnd && *itr < nCount; ++itr)
2950 if ( *itr!=nSrcTab && maTabs[*itr])
2952 SCTAB i = *itr;
2953 if (bDoMix)
2955 if (!pMixDoc)
2957 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
2958 pMixDoc->InitUndo( this, i, i );
2960 else
2961 pMixDoc->AddUndoTab( i, i );
2963 // context used for copying content to the temporary mix document.
2964 sc::CopyToDocContext aMixCxt(*pMixDoc);
2965 maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow,
2966 IDF_CONTENTS, false, pMixDoc->maTabs[i] );
2968 maTabs[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags);
2969 maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow,
2970 nFlags, false, maTabs[i], NULL, bAsLink );
2972 if (bDoMix)
2973 maTabs[i]->MixData(aMixDocCxt, nStartCol,nStartRow, nEndCol,nEndRow,
2974 nFunction, bSkipEmpty, pMixDoc->maTabs[i] );
2977 SetAutoCalc( bOldAutoCalc );
2979 else
2981 OSL_FAIL("wrong table");
2986 void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark,
2987 sal_uInt16 nFlags, sal_uInt16 nFunction,
2988 bool bSkipEmpty, bool bAsLink )
2990 sal_uInt16 nDelFlags = nFlags;
2991 if (nDelFlags & IDF_CONTENTS)
2992 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
2994 if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
2996 boost::scoped_ptr<ScDocument> pMixDoc;
2997 bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
2999 bool bOldAutoCalc = GetAutoCalc();
3000 SetAutoCalc( false ); // avoid multiple calculations
3002 ScRange aArea;
3003 rMark.GetMultiMarkArea( aArea );
3004 SCCOL nStartCol = aArea.aStart.Col();
3005 SCROW nStartRow = aArea.aStart.Row();
3006 SCCOL nEndCol = aArea.aEnd.Col();
3007 SCROW nEndRow = aArea.aEnd.Row();
3009 sc::CopyToDocContext aCxt(*this);
3010 sc::MixDocContext aMixDocCxt(*this);
3011 SCTAB nCount = static_cast<SCTAB>(maTabs.size());
3012 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
3013 for (; itr != itrEnd && *itr < nCount; ++itr)
3014 if ( *itr!=nSrcTab && maTabs[*itr] )
3016 SCTAB i = *itr;
3017 if (bDoMix)
3019 if (!pMixDoc)
3021 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
3022 pMixDoc->InitUndo( this, i, i );
3024 else
3025 pMixDoc->AddUndoTab( i, i );
3027 sc::CopyToDocContext aMixCxt(*pMixDoc);
3028 maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow,
3029 IDF_CONTENTS, true, pMixDoc->maTabs[i], &rMark );
3032 maTabs[i]->DeleteSelection( nDelFlags, rMark );
3033 maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow,
3034 nFlags, true, maTabs[i], &rMark, bAsLink );
3036 if (bDoMix)
3037 maTabs[i]->MixMarked(aMixDocCxt, rMark, nFunction, bSkipEmpty, pMixDoc->maTabs[i]);
3040 SetAutoCalc( bOldAutoCalc );
3042 else
3044 OSL_FAIL("wrong table");
3048 void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell, bool bForceTab )
3050 SCTAB nTab = rPos.Tab();
3051 if ( bForceTab && ( nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) )
3053 bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
3055 if (nTab >= static_cast<SCTAB>(maTabs.size()))
3056 maTabs.resize(nTab + 1,NULL);
3057 maTabs[nTab] = new ScTable(this, nTab,
3058 OUString("temp"),
3059 bExtras, bExtras);
3062 if (maTabs[nTab])
3063 maTabs[nTab]->PutCell( rPos, pCell );
3067 bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rString,
3068 ScSetStringParam* pParam )
3070 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3071 return maTabs[nTab]->SetString( nCol, nRow, nTab, rString, pParam );
3072 else
3073 return false;
3076 bool ScDocument::SetString(
3077 const ScAddress& rPos, const OUString& rString, ScSetStringParam* pParam )
3079 return SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rString, pParam);
3082 void ScDocument::SetEditText( const ScAddress& rPos, EditTextObject* pEditText )
3084 if (!TableExists(rPos.Tab()))
3086 delete pEditText;
3087 return;
3090 maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), pEditText);
3093 void ScDocument::SetEditText( const ScAddress& rPos, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
3095 if (!TableExists(rPos.Tab()))
3096 return;
3098 maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEditText, pEditPool);
3101 void ScDocument::SetEditText( const ScAddress& rPos, const OUString& rStr )
3103 if (!TableExists(rPos.Tab()))
3104 return;
3106 ScFieldEditEngine& rEngine = GetEditEngine();
3107 rEngine.SetText(rStr);
3108 maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject());
3111 void ScDocument::SetTextCell( const ScAddress& rPos, const OUString& rStr )
3113 if (!TableExists(rPos.Tab()))
3114 return;
3116 if (ScStringUtil::isMultiline(rStr))
3118 ScFieldEditEngine& rEngine = GetEditEngine();
3119 rEngine.SetText(rStr);
3120 maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject());
3122 else
3124 ScSetStringParam aParam;
3125 aParam.setTextInput();
3126 maTabs[rPos.Tab()]->SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rStr, &aParam);
3130 void ScDocument::SetEmptyCell( const ScAddress& rPos )
3132 if (!TableExists(rPos.Tab()))
3133 return;
3135 maTabs[rPos.Tab()]->SetEmptyCell(rPos.Col(), rPos.Row());
3138 void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal )
3140 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
3141 if (maTabs[nTab])
3142 maTabs[nTab]->SetValue( nCol, nRow, rVal );
3145 void ScDocument::SetValue( const ScAddress& rPos, double fVal )
3147 if (!TableExists(rPos.Tab()))
3148 return;
3150 maTabs[rPos.Tab()]->SetValue(rPos.Col(), rPos.Row(), fVal);
3153 OUString ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3155 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
3157 OUString aStr;
3158 maTabs[nTab]->GetString(nCol, nRow, aStr);
3159 return aStr;
3161 else
3162 return EMPTY_OUSTRING;
3165 OUString ScDocument::GetString( const ScAddress& rPos ) const
3167 if (!TableExists(rPos.Tab()))
3168 return EMPTY_OUSTRING;
3170 OUString aStr;
3171 maTabs[rPos.Tab()]->GetString(rPos.Col(), rPos.Row(), aStr);
3172 return aStr;
3175 const OUString* ScDocument::GetStringCell( const ScAddress& rPos ) const
3177 if (!TableExists(rPos.Tab()))
3178 return NULL;
3180 return maTabs[rPos.Tab()]->GetStringCell(rPos.Col(), rPos.Row());
3183 double* ScDocument::GetValueCell( const ScAddress& rPos )
3185 if (!TableExists(rPos.Tab()))
3186 return NULL;
3188 return maTabs[rPos.Tab()]->GetValueCell(rPos.Col(), rPos.Row());
3191 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rString )
3193 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3194 maTabs[nTab]->GetInputString( nCol, nRow, rString );
3195 else
3196 rString = OUString();
3199 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString )
3201 OUString aString;
3202 GetInputString( nCol, nRow, nTab, aString);
3203 rString = aString;
3206 sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, OUString& rString )
3208 // Used in formulas (add-in parameters etc), so it must use the same semantics as
3209 // ScInterpreter::GetCellString: always format values as numbers.
3210 // The return value is the error code.
3212 ScRefCellValue aCell;
3213 aCell.assign(*this, rPos);
3214 if (aCell.isEmpty())
3216 rString = EMPTY_OUSTRING;
3217 return 0;
3220 sal_uInt16 nErr = 0;
3221 OUString aStr;
3222 SvNumberFormatter* pFormatter = GetFormatTable();
3223 switch (aCell.meType)
3225 case CELLTYPE_STRING:
3226 case CELLTYPE_EDIT:
3227 aStr = aCell.getString(this);
3228 break;
3229 case CELLTYPE_FORMULA:
3231 ScFormulaCell* pFCell = aCell.mpFormula;
3232 nErr = pFCell->GetErrCode();
3233 if (pFCell->IsValue())
3235 double fVal = pFCell->GetValue();
3236 sal_uInt32 nIndex = pFormatter->GetStandardFormat(
3237 NUMBERFORMAT_NUMBER,
3238 ScGlobal::eLnge);
3239 pFormatter->GetInputLineString(fVal, nIndex, aStr);
3241 else
3242 aStr = pFCell->GetString();
3244 break;
3245 case CELLTYPE_VALUE:
3247 double fVal = aCell.mfValue;
3248 sal_uInt32 nIndex = pFormatter->GetStandardFormat(
3249 NUMBERFORMAT_NUMBER,
3250 ScGlobal::eLnge);
3251 pFormatter->GetInputLineString(fVal, nIndex, aStr);
3253 break;
3254 default:
3258 rString = aStr;
3259 return nErr;
3263 void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue ) const
3265 if (TableExists(nTab))
3266 rValue = maTabs[nTab]->GetValue( nCol, nRow );
3267 else
3268 rValue = 0.0;
3271 const EditTextObject* ScDocument::GetEditText( const ScAddress& rPos ) const
3273 SCTAB nTab = rPos.Tab();
3274 if (!TableExists(nTab))
3275 return NULL;
3277 return maTabs[nTab]->GetEditText(rPos.Col(), rPos.Row());
3280 void ScDocument::RemoveEditTextCharAttribs( const ScAddress& rPos, const ScPatternAttr& rAttr )
3282 if (!TableExists(rPos.Tab()))
3283 return;
3285 return maTabs[rPos.Tab()]->RemoveEditTextCharAttribs(rPos.Col(), rPos.Row(), rAttr);
3288 double ScDocument::GetValue( const ScAddress& rPos ) const
3290 SCTAB nTab = rPos.Tab();
3291 if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3292 return maTabs[nTab]->GetValue(rPos.Col(), rPos.Row());
3293 return 0.0;
3297 void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
3298 sal_uInt32& rFormat ) const
3300 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
3301 if (maTabs[nTab])
3303 rFormat = maTabs[nTab]->GetNumberFormat( nCol, nRow );
3304 return ;
3306 rFormat = 0;
3309 sal_uInt32 ScDocument::GetNumberFormat( const ScRange& rRange ) const
3311 SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
3312 SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
3313 SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
3315 if (!ValidTab(nTab1) || !ValidTab(nTab2) || !maTabs[nTab1] || !maTabs[nTab2])
3316 return 0;
3318 sal_uInt32 nFormat = 0;
3319 bool bFirstItem = true;
3320 for (SCTAB nTab = nTab1; nTab <= nTab2 && nTab < static_cast<SCTAB>(maTabs.size()) ; ++nTab)
3321 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
3323 sal_uInt32 nThisFormat = maTabs[nTab]->GetNumberFormat(nCol, nRow1, nRow2);
3324 if (bFirstItem)
3326 nFormat = nThisFormat;
3327 bFirstItem = false;
3329 else if (nThisFormat != nFormat)
3330 return 0;
3333 return nFormat;
3336 sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const
3338 SCTAB nTab = rPos.Tab();
3339 if ( maTabs[nTab] )
3340 return maTabs[nTab]->GetNumberFormat( rPos );
3341 return 0;
3344 void ScDocument::SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat )
3346 if (!TableExists(rPos.Tab()))
3347 return;
3349 maTabs[rPos.Tab()]->SetNumberFormat(rPos.Col(), rPos.Row(), nNumberFormat);
3352 void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex,
3353 const ScAddress& rPos ) const
3355 SCTAB nTab = rPos.Tab();
3356 if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3358 nIndex = maTabs[nTab]->GetNumberFormat( rPos );
3359 nType = GetFormatTable()->GetType( nIndex );
3361 else
3363 nType = NUMBERFORMAT_UNDEFINED;
3364 nIndex = 0;
3369 void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rFormula ) const
3371 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3372 maTabs[nTab]->GetFormula( nCol, nRow, rFormula );
3373 else
3374 rFormula = OUString();
3378 void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rFormula ) const
3380 OUString aString;
3381 GetFormula( nCol, nRow, nTab, aString);
3382 rFormula = aString;
3385 const ScTokenArray* ScDocument::GetFormulaTokens( const ScAddress& rPos ) const
3387 if (!TableExists(rPos.Tab()))
3388 return NULL;
3390 return maTabs[rPos.Tab()]->GetFormulaTokens(rPos.Col(), rPos.Row());
3393 const ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos ) const
3395 if (!TableExists(rPos.Tab()))
3396 return NULL;
3398 return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row());
3401 ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos )
3403 if (!TableExists(rPos.Tab()))
3404 return NULL;
3406 return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row());
3409 CellType ScDocument::GetCellType( const ScAddress& rPos ) const
3411 SCTAB nTab = rPos.Tab();
3412 if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3413 return maTabs[nTab]->GetCellType( rPos );
3414 return CELLTYPE_NONE;
3418 void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab,
3419 CellType& rCellType ) const
3421 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
3422 rCellType = maTabs[nTab]->GetCellType( nCol, nRow );
3423 else
3424 rCellType = CELLTYPE_NONE;
3427 bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3429 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3430 return maTabs[nTab]->HasStringData( nCol, nRow );
3431 else
3432 return false;
3436 bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3438 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3439 return maTabs[nTab]->HasValueData( nCol, nRow );
3440 else
3441 return false;
3444 bool ScDocument::HasValueData( const ScAddress& rPos ) const
3446 return HasValueData(rPos.Col(), rPos.Row(), rPos.Tab());
3449 bool ScDocument::HasStringCells( const ScRange& rRange ) const
3451 // true, wenn String- oder Editzellen im Bereich
3453 SCCOL nStartCol = rRange.aStart.Col();
3454 SCROW nStartRow = rRange.aStart.Row();
3455 SCTAB nStartTab = rRange.aStart.Tab();
3456 SCCOL nEndCol = rRange.aEnd.Col();
3457 SCROW nEndRow = rRange.aEnd.Row();
3458 SCTAB nEndTab = rRange.aEnd.Tab();
3460 for ( SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
3461 if ( maTabs[nTab] && maTabs[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) )
3462 return true;
3464 return false;
3468 bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3470 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
3471 if( nValidation )
3473 const ScValidationData* pData = GetValidationEntry( nValidation );
3474 if( pData && pData->HasSelectionList() )
3475 return true;
3477 return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) );
3481 void ScDocument::InitializeNoteCaptions( SCTAB nTab, bool bForced )
3483 if( ValidTab( nTab ) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[ nTab ] )
3484 maTabs[ nTab ]->InitializeNoteCaptions( bForced );
3487 void ScDocument::SetDirty()
3489 bool bOldAutoCalc = GetAutoCalc();
3490 bAutoCalc = false; // keine Mehrfachberechnung
3491 { // scope for bulk broadcast
3492 ScBulkBroadcast aBulkBroadcast( GetBASM());
3493 TableContainer::iterator it = maTabs.begin();
3494 for (;it != maTabs.end(); ++it)
3495 if (*it)
3496 (*it)->SetDirty();
3499 // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt,
3500 // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt
3501 // (#45205#) - darum alle Charts nochmal explizit
3502 if (pChartListenerCollection)
3503 pChartListenerCollection->SetDirty();
3505 SetAutoCalc( bOldAutoCalc );
3509 void ScDocument::SetDirty( const ScRange& rRange )
3511 bool bOldAutoCalc = GetAutoCalc();
3512 bAutoCalc = false; // keine Mehrfachberechnung
3513 { // scope for bulk broadcast
3514 ScBulkBroadcast aBulkBroadcast( GetBASM());
3515 SCTAB nTab2 = rRange.aEnd.Tab();
3516 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++)
3517 if (maTabs[i]) maTabs[i]->SetDirty( rRange );
3519 SetAutoCalc( bOldAutoCalc );
3523 void ScDocument::SetTableOpDirty( const ScRange& rRange )
3525 bool bOldAutoCalc = GetAutoCalc();
3526 bAutoCalc = false; // no multiple recalculation
3527 SCTAB nTab2 = rRange.aEnd.Tab();
3528 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++)
3529 if (maTabs[i]) maTabs[i]->SetTableOpDirty( rRange );
3530 SetAutoCalc( bOldAutoCalc );
3534 void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
3536 for (size_t nPos=0, nRangeCount = rRanges.size(); nPos < nRangeCount; nPos++)
3538 ScCellIterator aIter( this, *rRanges[ nPos ] );
3539 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
3541 if (aIter.getType() != CELLTYPE_FORMULA)
3542 continue;
3544 ScFormulaCell* p = aIter.getFormulaCell();
3545 if (p->GetDirty() && GetAutoCalc())
3546 p->Interpret();
3552 void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
3554 if ( !aTableOpList.empty() )
3556 ScInterpreterTableOpParams* p = &aTableOpList.back();
3557 if ( p->bCollectNotifications )
3559 if ( p->bRefresh )
3560 { // refresh pointers only
3561 p->aNotifiedFormulaCells.push_back( pCell );
3563 else
3564 { // init both, address and pointer
3565 p->aNotifiedFormulaCells.push_back( pCell );
3566 p->aNotifiedFormulaPos.push_back( pCell->aPos );
3573 void ScDocument::CalcAll()
3575 ClearLookupCaches(); // Ensure we don't deliver zombie data.
3576 bool bOldAutoCalc = GetAutoCalc();
3577 SetAutoCalc( true );
3578 TableContainer::iterator it = maTabs.begin();
3579 for (; it != maTabs.end(); ++it)
3580 if (*it)
3581 (*it)->SetDirtyVar();
3582 for (it = maTabs.begin(); it != maTabs.end(); ++it)
3583 if (*it)
3584 (*it)->CalcAll();
3585 ClearFormulaTree();
3586 SetAutoCalc( bOldAutoCalc );
3590 void ScDocument::CompileAll()
3592 TableContainer::iterator it = maTabs.begin();
3593 for (; it != maTabs.end(); ++it)
3594 if (*it)
3595 (*it)->CompileAll();
3596 SetDirty();
3600 void ScDocument::CompileXML()
3602 bool bOldAutoCalc = GetAutoCalc();
3603 SetAutoCalc( false );
3604 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(
3605 STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() );
3607 // set AutoNameCache to speed up automatic name lookup
3608 OSL_ENSURE( !pAutoNameCache, "AutoNameCache already set" );
3609 pAutoNameCache = new ScAutoNameCache( this );
3611 if (pRangeName)
3612 pRangeName->CompileUnresolvedXML();
3614 TableContainer::iterator it = maTabs.begin();
3615 for (; it != maTabs.end(); ++it)
3616 if (*it)
3617 (*it)->CompileXML( aProgress );
3619 DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change
3621 if ( pValidationList )
3622 pValidationList->CompileXML();
3624 SetAutoCalc( bOldAutoCalc );
3627 bool ScDocument::CompileErrorCells(sal_uInt16 nErrCode)
3629 bool bCompiled = false;
3630 TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
3631 for (; it != itEnd; ++it)
3633 ScTable* pTab = *it;
3634 if (!pTab)
3635 continue;
3637 if (pTab->CompileErrorCells(nErrCode))
3638 bCompiled = true;
3641 return bCompiled;
3644 void ScDocument::CalcAfterLoad()
3646 if (bIsClip) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen
3647 return; // dann wird erst beim Einfuegen in das richtige Doc berechnet
3649 bCalcingAfterLoad = true;
3651 TableContainer::iterator it = maTabs.begin();
3652 for (; it != maTabs.end(); ++it)
3653 if (*it)
3654 (*it)->CalcAfterLoad();
3655 for (it = maTabs.begin(); it != maTabs.end(); ++it)
3656 if (*it)
3657 (*it)->SetDirtyAfterLoad();
3659 bCalcingAfterLoad = false;
3661 SetDetectiveDirty(false); // noch keine wirklichen Aenderungen
3663 // #i112436# If formula cells are already dirty, they don't broadcast further changes.
3664 // So the source ranges of charts must be interpreted even if they are not visible,
3665 // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899).
3666 if (pChartListenerCollection)
3668 const ScChartListenerCollection::ListenersType& rListeners = pChartListenerCollection->getListeners();
3669 ScChartListenerCollection::ListenersType::const_iterator it = rListeners.begin(), itEnd = rListeners.end();
3670 for (; it != itEnd; ++it)
3672 const ScChartListener* p = it->second;
3673 InterpretDirtyCells(*p->GetRangeList());
3679 sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const
3681 SCTAB nTab = rPos.Tab();
3682 if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3683 return maTabs[nTab]->GetErrCode( rPos );
3684 return 0;
3688 void ScDocument::ResetChanged( const ScRange& rRange )
3690 SCTAB nTabSize = static_cast<SCTAB>(maTabs.size());
3691 SCTAB nTab1 = rRange.aStart.Tab();
3692 SCTAB nTab2 = rRange.aEnd.Tab();
3693 for (SCTAB nTab = nTab1; nTab1 <= nTab2 && nTab < nTabSize; ++nTab)
3694 if (maTabs[nTab])
3695 maTabs[nTab]->ResetChanged(rRange);
3699 // Spaltenbreiten / Zeilenhoehen --------------------------------------
3703 void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3705 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3706 maTabs[nTab]->SetColWidth( nCol, nNewWidth );
3709 void ScDocument::SetColWidthOnly( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3711 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3712 maTabs[nTab]->SetColWidthOnly( nCol, nNewWidth );
3715 void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight )
3717 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3718 maTabs[nTab]->SetRowHeight( nRow, nNewHeight );
3722 void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3724 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3725 maTabs[nTab]->SetRowHeightRange
3726 ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 );
3729 void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3731 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3732 maTabs[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight );
3735 void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bManual )
3737 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3738 maTabs[nTab]->SetManualHeight( nStartRow, nEndRow, bManual );
3742 sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const
3744 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3745 return maTabs[nTab]->GetColWidth( nCol, bHiddenAsZero );
3746 OSL_FAIL("wrong table number");
3747 return 0;
3751 sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const
3753 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3754 return maTabs[nTab]->GetOriginalWidth( nCol );
3755 OSL_FAIL("wrong table number");
3756 return 0;
3760 sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const
3762 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3763 return maTabs[nTab]->GetCommonWidth( nEndCol );
3764 OSL_FAIL("Wrong table number");
3765 return 0;
3769 sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const
3771 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3772 return maTabs[nTab]->GetOriginalHeight( nRow );
3773 OSL_FAIL("Wrong table number");
3774 return 0;
3778 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
3780 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3781 return maTabs[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero );
3782 OSL_FAIL("Wrong sheet number");
3783 return 0;
3787 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
3789 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3790 return maTabs[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero );
3791 OSL_FAIL("Wrong sheet number");
3792 return 0;
3796 sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero ) const
3798 if (nStartRow == nEndRow)
3799 return GetRowHeight( nStartRow, nTab, bHiddenAsZero ); // faster for a single row
3801 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3802 if (nStartRow > nEndRow)
3803 return 0;
3805 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3806 return maTabs[nTab]->GetRowHeight( nStartRow, nEndRow, bHiddenAsZero );
3808 OSL_FAIL("wrong sheet number");
3809 return 0;
3812 SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const
3814 return maTabs[nTab]->GetRowForHeight(nHeight);
3817 sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow,
3818 SCTAB nTab, double fScale ) const
3820 // faster for a single row
3821 if (nStartRow == nEndRow)
3822 return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale);
3824 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3825 if (nStartRow > nEndRow)
3826 return 0;
3828 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3829 return maTabs[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale);
3831 OSL_FAIL("wrong sheet number");
3832 return 0;
3835 SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const
3837 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3838 return maTabs[nTab]->GetHiddenRowCount( nRow );
3839 OSL_FAIL("wrong table number");
3840 return 0;
3844 sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const
3846 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3847 return maTabs[nTab]->GetColOffset( nCol, bHiddenAsZero );
3848 OSL_FAIL("wrong table number");
3849 return 0;
3853 sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
3855 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3856 return maTabs[nTab]->GetRowOffset( nRow, bHiddenAsZero );
3857 OSL_FAIL("wrong table number");
3858 return 0;
3862 sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev,
3863 double nPPTX, double nPPTY,
3864 const Fraction& rZoomX, const Fraction& rZoomY,
3865 bool bFormula, const ScMarkData* pMarkData,
3866 const ScColWidthParam* pParam )
3868 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3869 return maTabs[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY,
3870 rZoomX, rZoomY, bFormula, pMarkData, pParam );
3871 OSL_FAIL("wrong table number");
3872 return 0;
3876 long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab,
3877 OutputDevice* pDev,
3878 double nPPTX, double nPPTY,
3879 const Fraction& rZoomX, const Fraction& rZoomY,
3880 bool bWidth, bool bTotalSize )
3882 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3883 return maTabs[nTab]->GetNeededSize
3884 ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize );
3885 OSL_FAIL("wrong table number");
3886 return 0;
3890 bool ScDocument::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nExtra,
3891 OutputDevice* pDev,
3892 double nPPTX, double nPPTY,
3893 const Fraction& rZoomX, const Fraction& rZoomY,
3894 bool bShrink )
3896 //! MarkToMulti();
3897 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3898 return maTabs[nTab]->SetOptimalHeight( nStartRow, nEndRow, nExtra,
3899 pDev, nPPTX, nPPTY, rZoomX, rZoomY, bShrink );
3900 OSL_FAIL("wrong table number");
3901 return false;
3905 void ScDocument::UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY,
3906 const Fraction& rZoomX, const Fraction& rZoomY, const ScMarkData* pTabMark )
3908 // one progress across all (selected) sheets
3910 sal_uLong nCellCount = 0;
3911 for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ )
3912 if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
3913 nCellCount += maTabs[nTab]->GetWeightedCount();
3915 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount );
3917 sal_uLong nProgressStart = 0;
3918 for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ )
3919 if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
3921 maTabs[nTab]->SetOptimalHeightOnly( 0, MAXROW, 0,
3922 pDev, nPPTX, nPPTY, rZoomX, rZoomY, false, &aProgress, nProgressStart );
3923 maTabs[nTab]->SetDrawPageSize(true, true);
3924 nProgressStart += maTabs[nTab]->GetWeightedCount();
3930 // Spalten-/Zeilen-Flags ----------------------------------------------
3933 void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, bool bShow)
3935 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3936 maTabs[nTab]->ShowCol( nCol, bShow );
3940 void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, bool bShow)
3942 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3943 maTabs[nTab]->ShowRow( nRow, bShow );
3947 void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, bool bShow)
3949 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3950 maTabs[nTab]->ShowRows( nRow1, nRow2, bShow );
3954 void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags )
3956 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3957 maTabs[nTab]->SetRowFlags( nRow, nNewFlags );
3961 void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags )
3963 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3964 maTabs[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags );
3968 sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const
3970 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3971 return maTabs[nTab]->GetColFlags( nCol );
3972 OSL_FAIL("wrong table number");
3973 return 0;
3976 sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const
3978 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3979 return maTabs[nTab]->GetRowFlags( nRow );
3980 OSL_FAIL("wrong table number");
3981 return 0;
3984 const ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArray(
3985 SCTAB nTab ) const
3987 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pFlags;
3988 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3989 pFlags = maTabs[nTab]->GetRowFlagsArray();
3990 else
3992 OSL_FAIL("wrong sheet number");
3993 pFlags = 0;
3995 if (!pFlags)
3997 OSL_FAIL("no row flags at sheet");
3998 static ScBitMaskCompressedArray< SCROW, sal_uInt8> aDummy( MAXROW, 0);
3999 pFlags = &aDummy;
4001 return *pFlags;
4004 void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
4006 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4007 return;
4008 maTabs[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual);
4011 void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
4013 if (!ValidTab(nTab) || !maTabs[nTab])
4014 return;
4016 maTabs[nTab]->GetAllColBreaks(rBreaks, bPage, bManual);
4019 ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const
4021 ScBreakType nType = BREAK_NONE;
4022 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
4023 return nType;
4025 if (maTabs[nTab]->HasRowPageBreak(nRow))
4026 nType |= BREAK_PAGE;
4028 if (maTabs[nTab]->HasRowManualBreak(nRow))
4029 nType |= BREAK_MANUAL;
4031 return nType;
4034 ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const
4036 ScBreakType nType = BREAK_NONE;
4037 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
4038 return nType;
4040 if (maTabs[nTab]->HasColPageBreak(nCol))
4041 nType |= BREAK_PAGE;
4043 if (maTabs[nTab]->HasColManualBreak(nCol))
4044 nType |= BREAK_MANUAL;
4046 return nType;
4049 void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
4051 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
4052 return;
4054 maTabs[nTab]->SetRowBreak(nRow, bPage, bManual);
4057 void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
4059 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
4060 return;
4062 maTabs[nTab]->SetColBreak(nCol, bPage, bManual);
4065 void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
4067 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
4068 return;
4070 maTabs[nTab]->RemoveRowBreak(nRow, bPage, bManual);
4073 void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
4075 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
4076 return;
4078 maTabs[nTab]->RemoveColBreak(nCol, bPage, bManual);
4081 Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const
4083 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4084 return Sequence<TablePageBreakData>();
4086 return maTabs[nTab]->GetRowBreakData();
4089 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const
4091 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4092 return false;
4094 return maTabs[nTab]->RowHidden(nRow, pFirstRow, pLastRow);
4097 bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4099 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4100 return false;
4102 return maTabs[nTab]->HasHiddenRows(nStartRow, nEndRow);
4105 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) const
4107 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4109 if (pFirstCol)
4110 *pFirstCol = nCol;
4111 if (pLastCol)
4112 *pLastCol = nCol;
4113 return false;
4116 return maTabs[nTab]->ColHidden(nCol, pFirstCol, pLastCol);
4119 void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden)
4121 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4122 return;
4124 maTabs[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden);
4127 void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden)
4129 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4130 return;
4132 maTabs[nTab]->SetColHidden(nStartCol, nEndCol, bHidden);
4135 SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4137 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4138 return ::std::numeric_limits<SCROW>::max();;
4140 return maTabs[nTab]->FirstVisibleRow(nStartRow, nEndRow);
4143 SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4145 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4146 return ::std::numeric_limits<SCROW>::max();;
4148 return maTabs[nTab]->LastVisibleRow(nStartRow, nEndRow);
4151 SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4153 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4154 return 0;
4156 return maTabs[nTab]->CountVisibleRows(nStartRow, nEndRow);
4159 bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const
4161 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4162 return false;
4164 return maTabs[nTab]->RowFiltered(nRow, pFirstRow, pLastRow);
4167 bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4169 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4170 return false;
4172 return maTabs[nTab]->HasFilteredRows(nStartRow, nEndRow);
4175 bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) const
4177 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4178 return false;
4180 return maTabs[nTab]->ColFiltered(nCol, pFirstCol, pLastCol);
4183 void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered)
4185 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4186 return;
4188 maTabs[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered);
4192 SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4194 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4195 return ::std::numeric_limits<SCROW>::max();;
4197 return maTabs[nTab]->FirstNonFilteredRow(nStartRow, nEndRow);
4200 SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4202 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4203 return ::std::numeric_limits<SCROW>::max();;
4205 return maTabs[nTab]->LastNonFilteredRow(nStartRow, nEndRow);
4208 SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4210 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4211 return 0;
4213 return maTabs[nTab]->CountNonFilteredRows(nStartRow, nEndRow);
4216 bool ScDocument::IsManualRowHeight(SCROW nRow, SCTAB nTab) const
4218 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4219 return false;
4221 return maTabs[nTab]->IsManualRowHeight(nRow);
4224 void ScDocument::SyncColRowFlags()
4226 TableContainer::iterator it = maTabs.begin();
4227 for (; it != maTabs.end(); ++it)
4229 if (*it)
4230 (*it)->SyncColRowFlags();
4234 SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const
4236 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4237 return maTabs[nTab]->GetLastFlaggedRow();
4238 return 0;
4242 SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const
4244 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4245 return maTabs[nTab]->GetLastChangedCol();
4246 return 0;
4249 SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const
4251 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4252 return maTabs[nTab]->GetLastChangedRow();
4253 return 0;
4257 SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const
4259 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4261 sal_uInt8 nStartFlags = maTabs[nTab]->GetColFlags(nStart);
4262 sal_uInt16 nStartWidth = maTabs[nTab]->GetOriginalWidth(nStart);
4263 for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++)
4265 if (((nStartFlags & CR_MANUALBREAK) != (maTabs[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) ||
4266 (nStartWidth != maTabs[nTab]->GetOriginalWidth(nCol)) ||
4267 ((nStartFlags & CR_HIDDEN) != (maTabs[nTab]->GetColFlags(nCol) & CR_HIDDEN)) )
4268 return nCol;
4270 return MAXCOL+1;
4272 return 0;
4275 SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const
4277 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4278 return 0;
4280 const ScBitMaskCompressedArray<SCROW, sal_uInt8>* pRowFlagsArray = maTabs[nTab]->GetRowFlagsArray();
4281 if (!pRowFlagsArray)
4282 return 0;
4284 if (!maTabs[nTab]->mpRowHeights || !maTabs[nTab]->mpHiddenRows)
4285 return 0;
4287 size_t nIndex; // ignored
4288 SCROW nFlagsEndRow;
4289 SCROW nHiddenEndRow;
4290 SCROW nHeightEndRow;
4291 sal_uInt8 nFlags;
4292 bool bHidden;
4293 sal_uInt16 nHeight;
4294 sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow);
4295 bool bStartHidden = bHidden = maTabs[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow);
4296 sal_uInt16 nStartHeight = nHeight = maTabs[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false);
4297 SCROW nRow;
4298 while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW)
4300 if (nFlagsEndRow < nRow)
4301 nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow);
4302 if (nHiddenEndRow < nRow)
4303 bHidden = maTabs[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow);
4304 if (nHeightEndRow < nRow)
4305 nHeight = maTabs[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false);
4307 if (((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) ||
4308 ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) ||
4309 (bStartHidden != bHidden) ||
4310 (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) ||
4311 (!bCareManualSize && ((nStartHeight != nHeight))))
4312 return nRow;
4315 return MAXROW+1;
4318 bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault)
4320 bool bRet(false);
4321 nDefault = 0;
4322 ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow);
4323 SCCOL nColumn;
4324 SCROW nStartRow;
4325 SCROW nEndRow;
4326 const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
4327 if (nEndRow < nLastRow)
4329 ScDefaultAttrSet aSet;
4330 ScDefaultAttrSet::iterator aItr = aSet.end();
4331 while (pAttr)
4333 ScDefaultAttr aAttr(pAttr);
4334 aItr = aSet.find(aAttr);
4335 if (aItr == aSet.end())
4337 aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
4338 aAttr.nFirst = nStartRow;
4339 aSet.insert(aAttr);
4341 else
4343 aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1);
4344 aAttr.nFirst = aItr->nFirst;
4345 aSet.erase(aItr);
4346 aSet.insert(aAttr);
4348 pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
4350 ScDefaultAttrSet::iterator aDefaultItr = aSet.begin();
4351 aItr = aDefaultItr;
4352 ++aItr;
4353 while (aItr != aSet.end())
4355 // for entries with equal count, use the one with the lowest start row,
4356 // don't use the random order of pointer comparisons
4357 if ( aItr->nCount > aDefaultItr->nCount ||
4358 ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) )
4359 aDefaultItr = aItr;
4360 ++aItr;
4362 nDefault = aDefaultItr->nFirst;
4363 bRet = true;
4365 else
4366 bRet = true;
4367 return bRet;
4370 bool ScDocument::GetRowDefault( SCTAB /* nTab */, SCROW /* nRow */, SCCOL /* nLastCol */, SCCOL& /* nDefault */ )
4372 return false;
4375 void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
4377 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4378 maTabs[nTab]->StripHidden( rX1, rY1, rX2, rY2 );
4382 void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
4384 if ( ValidTab(nTab) && maTabs[nTab] )
4385 maTabs[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 );
4389 // Attribute ----------------------------------------------------------
4392 const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
4394 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4396 const SfxPoolItem* pTemp = maTabs[nTab]->GetAttr( nCol, nRow, nWhich );
4397 if (pTemp)
4398 return pTemp;
4399 else
4401 OSL_FAIL( "Attribut Null" );
4404 return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich );
4407 const SfxPoolItem* ScDocument::GetAttr( const ScAddress& rPos, sal_uInt16 nWhich ) const
4409 return GetAttr(rPos.Col(), rPos.Row(), rPos.Tab(), nWhich);
4412 const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4414 if (TableExists(nTab))
4415 return maTabs[nTab]->GetPattern( nCol, nRow );
4416 return NULL;
4419 const ScPatternAttr* ScDocument::GetPattern( const ScAddress& rPos ) const
4421 if (TableExists(rPos.Tab()))
4422 return maTabs[rPos.Tab()]->GetPattern(rPos.Col(), rPos.Row());
4424 return NULL;
4427 const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const
4429 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4430 return maTabs[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow );
4431 return NULL;
4435 void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr )
4437 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4438 maTabs[nTab]->ApplyAttr( nCol, nRow, rAttr );
4442 void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr )
4444 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4445 maTabs[nTab]->ApplyPattern( nCol, nRow, rAttr );
4449 void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow,
4450 SCCOL nEndCol, SCROW nEndRow,
4451 const ScMarkData& rMark,
4452 const ScPatternAttr& rAttr,
4453 ScEditDataArray* pDataArray )
4455 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4456 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4457 for (; itr != itrEnd && *itr < nMax; ++itr)
4458 if (maTabs[*itr])
4459 maTabs[*itr]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr, pDataArray );
4463 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow,
4464 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr )
4466 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4467 if (maTabs[nTab])
4468 maTabs[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
4471 bool ScDocument::SetAttrEntries(SCCOL nCol, SCTAB nTab, ScAttrEntry* pData, SCSIZE nSize)
4473 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4474 return false;
4476 return maTabs[nTab]->SetAttrEntries(nCol, pData, nSize);
4479 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
4480 const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType )
4482 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4483 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4484 for (; itr != itrEnd && *itr < nMax; ++itr)
4485 if (maTabs[*itr])
4486 maTabs[*itr]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
4489 void ScDocument::AddCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex )
4491 if(!(static_cast<size_t>(nTab) < maTabs.size()))
4492 return;
4494 if(!maTabs[nTab])
4495 return;
4497 maTabs[nTab]->AddCondFormatData(rRange, nIndex);
4500 void ScDocument::RemoveCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex )
4502 if(!(static_cast<size_t>(nTab) < maTabs.size()))
4503 return;
4505 if(!maTabs[nTab])
4506 return;
4508 maTabs[nTab]->RemoveCondFormatData(rRange, nIndex);
4512 void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle)
4514 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4515 if (maTabs[nTab])
4516 maTabs[nTab]->ApplyStyle( nCol, nRow, rStyle );
4520 void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow,
4521 SCCOL nEndCol, SCROW nEndRow,
4522 const ScMarkData& rMark,
4523 const ScStyleSheet& rStyle)
4525 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4526 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4527 for (; itr != itrEnd && *itr < nMax; ++itr)
4528 if (maTabs[*itr])
4529 maTabs[*itr]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4533 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow,
4534 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle)
4536 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4537 if (maTabs[nTab])
4538 maTabs[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4542 void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
4544 // ApplySelectionStyle needs multi mark
4545 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
4547 ScRange aRange;
4548 rMark.GetMarkArea( aRange );
4549 ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(),
4550 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle );
4552 else
4554 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4555 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4556 for (; itr != itrEnd && *itr < nMax; ++itr)
4557 if ( maTabs[*itr] )
4558 maTabs[*itr]->ApplySelectionStyle( rStyle, rMark );
4563 void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark,
4564 const SvxBorderLine* pLine, bool bColorOnly )
4566 if ( bColorOnly && !pLine )
4567 return;
4569 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4570 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4571 for (; itr != itrEnd && *itr < nMax; ++itr)
4572 if (maTabs[*itr])
4573 maTabs[*itr]->ApplySelectionLineStyle( rMark, pLine, bColorOnly );
4577 const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4579 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4580 return maTabs[nTab]->GetStyle(nCol, nRow);
4581 else
4582 return NULL;
4586 const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const
4588 bool bEqual = true;
4589 bool bFound;
4591 const ScStyleSheet* pStyle = NULL;
4592 const ScStyleSheet* pNewStyle;
4594 if ( rMark.IsMultiMarked() )
4596 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4597 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4598 for (; itr != itrEnd && *itr < nMax; ++itr)
4599 if (maTabs[*itr])
4601 pNewStyle = maTabs[*itr]->GetSelectionStyle( rMark, bFound );
4602 if (bFound)
4604 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4605 bEqual = false; // unterschiedliche
4606 pStyle = pNewStyle;
4610 if ( rMark.IsMarked() )
4612 ScRange aRange;
4613 rMark.GetMarkArea( aRange );
4614 for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual && i < static_cast<SCTAB>(maTabs.size()); i++)
4615 if (maTabs[i] && rMark.GetTableSelect(i))
4617 pNewStyle = maTabs[i]->GetAreaStyle( bFound,
4618 aRange.aStart.Col(), aRange.aStart.Row(),
4619 aRange.aEnd.Col(), aRange.aEnd.Row() );
4620 if (bFound)
4622 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4623 bEqual = false; // unterschiedliche
4624 pStyle = pNewStyle;
4629 return bEqual ? pStyle : NULL;
4633 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved,
4634 OutputDevice* pDev,
4635 double nPPTX, double nPPTY,
4636 const Fraction& rZoomX, const Fraction& rZoomY )
4638 TableContainer::iterator it = maTabs.begin();
4639 for (; it != maTabs.end(); ++it)
4640 if (*it)
4641 (*it)->StyleSheetChanged
4642 ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY );
4644 if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
4646 // update attributes for all note objects
4647 ScDetectiveFunc::UpdateAllComments( *this );
4652 bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
4654 if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN )
4656 if ( bGatherAllStyles )
4658 SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(),
4659 SFX_STYLE_FAMILY_PARA );
4660 for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle;
4661 pStyle = aIter.Next() )
4663 const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle );
4664 if ( pScStyle )
4665 pScStyle->SetUsage( ScStyleSheet::NOTUSED );
4669 bool bIsUsed = false;
4671 TableContainer::const_iterator it = maTabs.begin();
4672 for (; it != maTabs.end(); ++it)
4673 if (*it)
4675 if ( (*it)->IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
4677 if ( !bGatherAllStyles )
4678 return true;
4679 bIsUsed = true;
4683 if ( bGatherAllStyles )
4684 bStyleSheetUsageInvalid = false;
4686 return bIsUsed;
4689 return rStyle.GetUsage() == ScStyleSheet::USED;
4693 bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4694 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4696 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4697 if (maTabs[nTab])
4698 return maTabs[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4700 OSL_FAIL("ApplyFlags: wrong table");
4701 return false;
4705 bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4706 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4708 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4709 if (maTabs[nTab])
4710 return maTabs[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4712 OSL_FAIL("RemoveFlags: wrong table");
4713 return false;
4717 void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr,
4718 bool bPutToPool )
4720 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4721 if (maTabs[nTab])
4722 maTabs[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool );
4726 void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr,
4727 bool bPutToPool )
4729 SCTAB nTab = rPos.Tab();
4730 if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
4731 maTabs[nTab]->SetPattern( rPos, rAttr, bPutToPool );
4735 ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, bool bDeep )
4737 ScMergePatternState aState;
4739 if ( rMark.IsMultiMarked() ) // multi selection
4741 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4742 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4743 for (; itr != itrEnd && *itr < nMax; ++itr)
4744 if (maTabs[*itr])
4745 maTabs[*itr]->MergeSelectionPattern( aState, rMark, bDeep );
4747 if ( rMark.IsMarked() ) // simle selection
4749 ScRange aRange;
4750 rMark.GetMarkArea(aRange);
4751 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4752 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4753 for (; itr != itrEnd && *itr < nMax; ++itr)
4754 if (maTabs[*itr])
4755 maTabs[*itr]->MergePatternArea( aState,
4756 aRange.aStart.Col(), aRange.aStart.Row(),
4757 aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep );
4760 OSL_ENSURE( aState.pItemSet, "SelectionPattern Null" );
4761 if (aState.pItemSet)
4762 return new ScPatternAttr( aState.pItemSet );
4763 else
4764 return new ScPatternAttr( GetPool() ); // empty
4768 const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, bool bDeep )
4770 delete pSelectionAttr;
4771 pSelectionAttr = CreateSelectionPattern( rMark, bDeep );
4772 return pSelectionAttr;
4776 void ScDocument::GetSelectionFrame( const ScMarkData& rMark,
4777 SvxBoxItem& rLineOuter,
4778 SvxBoxInfoItem& rLineInner )
4780 rLineOuter.SetLine(NULL, BOX_LINE_TOP);
4781 rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM);
4782 rLineOuter.SetLine(NULL, BOX_LINE_LEFT);
4783 rLineOuter.SetLine(NULL, BOX_LINE_RIGHT);
4784 rLineOuter.SetDistance(0);
4786 rLineInner.SetLine(NULL, BOXINFO_LINE_HORI);
4787 rLineInner.SetLine(NULL, BOXINFO_LINE_VERT);
4788 rLineInner.SetTable(true);
4789 rLineInner.SetDist(true);
4790 rLineInner.SetMinDist(false);
4792 ScLineFlags aFlags;
4794 if (rMark.IsMarked())
4796 ScRange aRange;
4797 rMark.GetMarkArea(aRange);
4798 rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() );
4799 rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() );
4800 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4801 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4802 for (; itr != itrEnd && *itr < nMax; ++itr)
4803 if (maTabs[*itr])
4804 maTabs[*itr]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags,
4805 aRange.aStart.Col(), aRange.aStart.Row(),
4806 aRange.aEnd.Col(), aRange.aEnd.Row() );
4809 // Don't care Status auswerten
4811 rLineInner.SetValid( VALID_LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) );
4812 rLineInner.SetValid( VALID_RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) );
4813 rLineInner.SetValid( VALID_TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) );
4814 rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) );
4815 rLineInner.SetValid( VALID_HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) );
4816 rLineInner.SetValid( VALID_VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) );
4820 bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
4821 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask ) const
4823 if ( nMask & HASATTR_ROTATE )
4825 // Attribut im Dokument ueberhaupt verwendet?
4826 // (wie in fillinfo)
4828 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4830 bool bAnyItem = false;
4831 sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE );
4832 for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++)
4834 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem );
4835 if ( pItem )
4837 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
4838 // (see ScPatternAttr::GetCellOrientation)
4839 sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue();
4840 if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
4842 bAnyItem = true;
4843 break;
4847 if (!bAnyItem)
4848 nMask &= ~HASATTR_ROTATE;
4851 if ( nMask & HASATTR_RTL )
4853 // first check if right-to left is in the pool at all
4854 // (the same item is used in cell and page format)
4856 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4858 bool bHasRtl = false;
4859 sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR );
4860 for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++)
4862 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem );
4863 if ( pItem && ((const SvxFrameDirectionItem*)pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP )
4865 bHasRtl = true;
4866 break;
4869 if (!bHasRtl)
4870 nMask &= ~HASATTR_RTL;
4873 if (!nMask)
4874 return false;
4876 bool bFound = false;
4877 for (SCTAB i=nTab1; i<=nTab2 && !bFound && i < static_cast<SCTAB>(maTabs.size()); i++)
4878 if (maTabs[i])
4880 if ( nMask & HASATTR_RTL )
4882 if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L ) // sheet default
4883 bFound = true;
4885 if ( nMask & HASATTR_RIGHTORCENTER )
4887 // On a RTL sheet, don't start to look for the default left value
4888 // (which is then logically right), instead always assume true.
4889 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets.
4891 if ( IsLayoutRTL(i) )
4892 bFound = true;
4895 if ( !bFound )
4896 bFound = maTabs[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask );
4899 return bFound;
4902 bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask ) const
4904 return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
4905 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(),
4906 nMask );
4909 void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
4910 SCCOL nX1, SCCOL nX2 ) const
4912 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4913 maTabs[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 );
4914 else
4916 OSL_FAIL("FindMaxRotCol: wrong table");
4920 void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab,
4921 const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop,
4922 const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const
4924 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
4926 const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER );
4927 OSL_ENSURE(pThisAttr,"where is the attribute?");
4929 const SvxBorderLine* pLeftLine = pThisAttr->GetLeft();
4930 const SvxBorderLine* pTopLine = pThisAttr->GetTop();
4931 const SvxBorderLine* pRightLine = pThisAttr->GetRight();
4932 const SvxBorderLine* pBottomLine = pThisAttr->GetBottom();
4934 if ( nCol > 0 )
4936 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4937 GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight();
4938 if ( ScHasPriority( pOther, pLeftLine ) )
4939 pLeftLine = pOther;
4941 if ( nRow > 0 )
4943 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4944 GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom();
4945 if ( ScHasPriority( pOther, pTopLine ) )
4946 pTopLine = pOther;
4948 if ( nCol < MAXCOL )
4950 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4951 GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft();
4952 if ( ScHasPriority( pOther, pRightLine ) )
4953 pRightLine = pOther;
4955 if ( nRow < MAXROW )
4957 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4958 GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
4959 if ( ScHasPriority( pOther, pBottomLine ) )
4960 pBottomLine = pOther;
4963 if (ppLeft)
4964 *ppLeft = pLeftLine;
4965 if (ppTop)
4966 *ppTop = pTopLine;
4967 if (ppRight)
4968 *ppRight = pRightLine;
4969 if (ppBottom)
4970 *ppBottom = pBottomLine;
4973 bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
4974 SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const
4976 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4977 if (maTabs[nTab])
4978 return maTabs[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes );
4980 OSL_FAIL("wrong table number");
4981 return false;
4985 void ScDocument::LockTable(SCTAB nTab)
4987 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4988 maTabs[nTab]->LockTable();
4989 else
4991 OSL_FAIL("wrong table number");
4996 void ScDocument::UnlockTable(SCTAB nTab)
4998 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4999 maTabs[nTab]->UnlockTable();
5000 else
5002 OSL_FAIL("wrong table number");
5007 bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
5008 SCCOL nEndCol, SCROW nEndRow,
5009 bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
5011 // import into read-only document is possible
5012 if (!bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly())
5014 if ( pOnlyNotBecauseOfMatrix )
5015 *pOnlyNotBecauseOfMatrix = false;
5016 return false;
5019 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
5020 if (maTabs[nTab])
5021 return maTabs[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol,
5022 nEndRow, pOnlyNotBecauseOfMatrix );
5024 OSL_FAIL("wrong table number");
5025 if ( pOnlyNotBecauseOfMatrix )
5026 *pOnlyNotBecauseOfMatrix = false;
5027 return false;
5031 bool ScDocument::IsSelectionEditable( const ScMarkData& rMark,
5032 bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
5034 // import into read-only document is possible
5035 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() )
5037 if ( pOnlyNotBecauseOfMatrix )
5038 *pOnlyNotBecauseOfMatrix = false;
5039 return false;
5042 ScRange aRange;
5043 rMark.GetMarkArea(aRange);
5045 bool bOk = true;
5046 bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL );
5047 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5048 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5049 for (; itr != itrEnd && *itr < nMax && (bOk || bMatrix); ++itr)
5051 if ( maTabs[*itr] )
5053 if (rMark.IsMarked())
5055 if ( !maTabs[*itr]->IsBlockEditable( aRange.aStart.Col(),
5056 aRange.aStart.Row(), aRange.aEnd.Col(),
5057 aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) )
5059 bOk = false;
5060 if ( pOnlyNotBecauseOfMatrix )
5061 bMatrix = *pOnlyNotBecauseOfMatrix;
5064 if (rMark.IsMultiMarked())
5066 if ( !maTabs[*itr]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) )
5068 bOk = false;
5069 if ( pOnlyNotBecauseOfMatrix )
5070 bMatrix = *pOnlyNotBecauseOfMatrix;
5076 if ( pOnlyNotBecauseOfMatrix )
5077 *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix );
5079 return bOk;
5083 bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow,
5084 SCCOL nEndCol, SCROW nEndRow,
5085 const ScMarkData& rMark ) const
5087 bool bOk = true;
5088 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5089 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5090 for (; itr != itrEnd && *itr < nMax && bOk; ++itr)
5091 if (maTabs[*itr])
5092 if (maTabs[*itr]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow ))
5093 bOk = false;
5095 return !bOk;
5098 bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix )
5100 // if rCell is part of a matrix formula, return its complete range
5102 ScFormulaCell* pFCell = GetFormulaCell(rCellPos);
5103 if (!pFCell)
5104 // not a formula cell. Bail out.
5105 return false;
5107 ScAddress aOrigin = rCellPos;
5108 if (!pFCell->GetMatrixOrigin(aOrigin))
5109 // Failed to get the address of the matrix origin.
5110 return false;
5112 if (aOrigin != rCellPos)
5114 pFCell = GetFormulaCell(aOrigin);
5115 if (!pFCell)
5116 // The matrix origin cell is not a formula cell !? Something is up...
5117 return false;
5120 SCCOL nSizeX;
5121 SCROW nSizeY;
5122 pFCell->GetMatColsRows(nSizeX, nSizeY);
5123 if (nSizeX <= 0 || nSizeY <= 0)
5125 // GetMatrixEdge computes also dimensions of the matrix
5126 // if not already done (may occur if document is loaded
5127 // from old file format).
5128 // Needs an "invalid" initialized address.
5129 aOrigin.SetInvalid();
5130 pFCell->GetMatrixEdge(aOrigin);
5131 pFCell->GetMatColsRows(nSizeX, nSizeY);
5134 if (nSizeX <= 0 || nSizeY <= 0)
5135 // Matrix size is still invalid. Give up.
5136 return false;
5138 ScAddress aEnd( aOrigin.Col() + nSizeX - 1,
5139 aOrigin.Row() + nSizeY - 1,
5140 aOrigin.Tab() );
5142 rMatrix.aStart = aOrigin;
5143 rMatrix.aEnd = aEnd;
5145 return true;
5149 bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
5150 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) const
5152 bool bFound = false;
5153 if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) )
5155 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5157 SCCOL nCol;
5158 SCCOL nOldCol = rStartCol;
5159 SCROW nOldRow = rStartRow;
5160 for (nCol=nOldCol; nCol<=nEndCol; nCol++)
5161 while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))->
5162 IsVerOverlapped())
5163 --rStartRow;
5165 //! weiterreichen ?
5167 ScAttrArray* pAttrArray = maTabs[nTab]->aCol[nOldCol].pAttrArray;
5168 SCSIZE nIndex;
5169 pAttrArray->Search( nOldRow, nIndex );
5170 SCROW nAttrPos = nOldRow;
5171 while (nAttrPos<=nEndRow)
5173 OSL_ENSURE( nIndex < pAttrArray->nCount, "Wrong index in AttrArray" );
5175 if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern->
5176 GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped())
5178 SCROW nLoopEndRow = std::min( nEndRow, pAttrArray->pData[nIndex].nRow );
5179 for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++)
5181 SCCOL nTempCol = nOldCol;
5183 --nTempCol;
5184 while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG))
5185 ->IsHorOverlapped());
5186 if (nTempCol < rStartCol)
5187 rStartCol = nTempCol;
5190 nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
5191 ++nIndex;
5195 else
5197 OSL_FAIL("ExtendOverlapped: invalid range");
5200 return bFound;
5204 bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow,
5205 SCCOL& rEndCol, SCROW& rEndRow,
5206 const ScMarkData& rMark, bool bRefresh )
5208 // use all selected sheets from rMark
5210 bool bFound = false;
5211 SCCOL nOldEndCol = rEndCol;
5212 SCROW nOldEndRow = rEndRow;
5214 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5215 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5216 for (; itr != itrEnd && *itr < nMax; ++itr)
5217 if ( maTabs[*itr] )
5219 SCCOL nThisEndCol = nOldEndCol;
5220 SCROW nThisEndRow = nOldEndRow;
5221 if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, *itr, bRefresh ) )
5222 bFound = true;
5223 if ( nThisEndCol > rEndCol )
5224 rEndCol = nThisEndCol;
5225 if ( nThisEndRow > rEndRow )
5226 rEndRow = nThisEndRow;
5229 return bFound;
5233 bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
5234 SCCOL& rEndCol, SCROW& rEndRow,
5235 SCTAB nTab, bool bRefresh )
5237 bool bFound = false;
5238 if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) )
5240 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5241 bFound = maTabs[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh );
5243 if (bRefresh)
5244 RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab );
5246 else
5248 OSL_FAIL("ExtendMerge: invalid range");
5251 return bFound;
5255 bool ScDocument::ExtendMerge( ScRange& rRange, bool bRefresh )
5257 bool bFound = false;
5258 SCTAB nStartTab = rRange.aStart.Tab();
5259 SCTAB nEndTab = rRange.aEnd.Tab();
5260 SCCOL nEndCol = rRange.aEnd.Col();
5261 SCROW nEndRow = rRange.aEnd.Row();
5263 PutInOrder( nStartTab, nEndTab );
5264 for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
5266 SCCOL nExtendCol = rRange.aEnd.Col();
5267 SCROW nExtendRow = rRange.aEnd.Row();
5268 if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(),
5269 nExtendCol, nExtendRow,
5270 nTab, bRefresh ) )
5272 bFound = true;
5273 if (nExtendCol > nEndCol) nEndCol = nExtendCol;
5274 if (nExtendRow > nEndRow) nEndRow = nExtendRow;
5278 rRange.aEnd.SetCol(nEndCol);
5279 rRange.aEnd.SetRow(nEndRow);
5281 return bFound;
5284 bool ScDocument::ExtendTotalMerge( ScRange& rRange ) const
5286 // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn
5287 // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden
5289 bool bRet = false;
5290 ScRange aExt = rRange;
5291 // ExtendMerge() is non-const, but called withouth refresh.
5292 if (const_cast<ScDocument*>(this)->ExtendMerge( aExt, false))
5294 if ( aExt.aEnd.Row() > rRange.aEnd.Row() )
5296 ScRange aTest = aExt;
5297 aTest.aStart.SetRow( rRange.aEnd.Row() + 1 );
5298 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
5299 aExt.aEnd.SetRow(rRange.aEnd.Row());
5301 if ( aExt.aEnd.Col() > rRange.aEnd.Col() )
5303 ScRange aTest = aExt;
5304 aTest.aStart.SetCol( rRange.aEnd.Col() + 1 );
5305 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
5306 aExt.aEnd.SetCol(rRange.aEnd.Col());
5309 bRet = ( aExt.aEnd != rRange.aEnd );
5310 rRange = aExt;
5312 return bRet;
5315 bool ScDocument::ExtendOverlapped( ScRange& rRange ) const
5317 bool bFound = false;
5318 SCTAB nStartTab = rRange.aStart.Tab();
5319 SCTAB nEndTab = rRange.aEnd.Tab();
5320 SCCOL nStartCol = rRange.aStart.Col();
5321 SCROW nStartRow = rRange.aStart.Row();
5323 PutInOrder( nStartTab, nEndTab );
5324 for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
5326 SCCOL nExtendCol = rRange.aStart.Col();
5327 SCROW nExtendRow = rRange.aStart.Row();
5328 ExtendOverlapped( nExtendCol, nExtendRow,
5329 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab );
5330 if (nExtendCol < nStartCol)
5332 nStartCol = nExtendCol;
5333 bFound = true;
5335 if (nExtendRow < nStartRow)
5337 nStartRow = nExtendRow;
5338 bFound = true;
5342 rRange.aStart.SetCol(nStartCol);
5343 rRange.aStart.SetRow(nStartRow);
5345 return bFound;
5348 bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow,
5349 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
5351 SCTAB nDBTab;
5352 SCCOL nDBStartCol;
5353 SCROW nDBStartRow;
5354 SCCOL nDBEndCol;
5355 SCROW nDBEndRow;
5357 // Autofilter loeschen
5359 bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO );
5361 // Autofilter setzen
5363 const ScDBData* pData = NULL;
5364 ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs();
5365 ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
5366 for (; itr != itrEnd; ++itr)
5368 if (itr->HasAutoFilter())
5370 itr->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
5371 if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
5372 nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
5374 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
5375 nDBTab, SC_MF_AUTO ))
5376 bChange = true;
5380 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5381 pData = maTabs[nTab]->GetAnonymousDBData();
5382 else
5383 pData=NULL;
5384 if (pData)
5386 if (pData->HasAutoFilter())
5388 pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
5389 if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
5390 nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
5392 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
5393 nDBTab, SC_MF_AUTO ))
5394 bChange = true;
5398 return bChange;
5401 void ScDocument::SkipOverlapped( SCCOL& rCol, SCROW& rRow, SCTAB nTab ) const
5403 while (IsHorOverlapped(rCol, rRow, nTab))
5404 --rCol;
5405 while (IsVerOverlapped(rCol, rRow, nTab))
5406 --rRow;
5409 bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
5411 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
5412 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
5413 if (pAttr)
5414 return pAttr->IsHorOverlapped();
5415 else
5417 OSL_FAIL("Overlapped: Attr==0");
5418 return false;
5423 bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
5425 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
5426 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
5427 if (pAttr)
5428 return pAttr->IsVerOverlapped();
5429 else
5431 OSL_FAIL("Overlapped: Attr==0");
5432 return false;
5437 void ScDocument::ApplySelectionFrame( const ScMarkData& rMark,
5438 const SvxBoxItem* pLineOuter,
5439 const SvxBoxInfoItem* pLineInner )
5441 ScRangeList aRangeList;
5442 rMark.FillRangeListWithMarks( &aRangeList, false );
5443 size_t nRangeCount = aRangeList.size();
5444 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5445 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5446 for (; itr != itrEnd && *itr < nMax; ++itr)
5448 if (maTabs[*itr])
5450 for ( size_t j=0; j < nRangeCount; j++ )
5452 ScRange aRange = *aRangeList[ j ];
5453 maTabs[*itr]->ApplyBlockFrame( pLineOuter, pLineInner,
5454 aRange.aStart.Col(), aRange.aStart.Row(),
5455 aRange.aEnd.Col(), aRange.aEnd.Row() );
5462 void ScDocument::ApplyFrameAreaTab( const ScRange& rRange,
5463 const SvxBoxItem* pLineOuter,
5464 const SvxBoxInfoItem* pLineInner )
5466 SCTAB nStartTab = rRange.aStart.Tab();
5467 SCTAB nEndTab = rRange.aStart.Tab();
5468 for (SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++)
5469 if (maTabs[nTab])
5470 maTabs[nTab]->ApplyBlockFrame( pLineOuter, pLineInner,
5471 rRange.aStart.Col(), rRange.aStart.Row(),
5472 rRange.aEnd.Col(), rRange.aEnd.Row() );
5476 void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark, ScEditDataArray* pDataArray )
5478 const SfxItemSet* pSet = &rAttr.GetItemSet();
5479 bool bSet = false;
5480 sal_uInt16 i;
5481 for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++)
5482 if (pSet->GetItemState(i) == SFX_ITEM_SET)
5483 bSet = true;
5485 if (bSet)
5487 // ApplySelectionCache needs multi mark
5488 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
5490 ScRange aRange;
5491 rMark.GetMarkArea( aRange );
5492 ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(),
5493 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr, pDataArray );
5495 else
5497 SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet );
5498 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5499 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5500 for (; itr != itrEnd && *itr < nMax; ++itr)
5501 if (maTabs[*itr])
5502 maTabs[*itr]->ApplySelectionCache( &aCache, rMark, pDataArray );
5508 void ScDocument::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
5510 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5511 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5512 for (; itr != itrEnd && *itr < nMax; ++itr)
5513 if (maTabs[*itr])
5514 maTabs[*itr]->ChangeSelectionIndent( bIncrement, rMark );
5518 void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
5520 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5521 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5522 for (; itr != itrEnd && *itr < nMax; ++itr)
5523 if (maTabs[*itr])
5524 maTabs[*itr]->ClearSelectionItems( pWhich, rMark );
5528 void ScDocument::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
5530 SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5531 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5532 for (; itr != itrEnd && *itr < nMax; ++itr)
5533 if (maTabs[*itr])
5534 maTabs[*itr]->DeleteSelection( nDelFlag, rMark );
5538 void ScDocument::DeleteSelectionTab( SCTAB nTab, sal_uInt16 nDelFlag, const ScMarkData& rMark )
5540 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5541 maTabs[nTab]->DeleteSelection( nDelFlag, rMark );
5542 else
5544 OSL_FAIL("wrong table");
5549 ScPatternAttr* ScDocument::GetDefPattern() const
5551 return (ScPatternAttr*) &xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN);
5555 ScDocumentPool* ScDocument::GetPool()
5557 return xPoolHelper->GetDocPool();
5562 ScStyleSheetPool* ScDocument::GetStyleSheetPool() const
5564 return xPoolHelper->GetStylePool();
5568 SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
5569 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir )
5571 PutInOrder(nStartCol, nEndCol);
5572 PutInOrder(nStartRow, nEndRow);
5573 PutInOrder(nStartTab, nEndTab);
5574 if (ValidTab(nStartTab) && nStartTab < static_cast<SCTAB>(maTabs.size()))
5576 if (maTabs[nStartTab])
5577 return maTabs[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir);
5578 else
5579 return 0;
5581 else
5582 return 0;
5586 void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, ScMoveDirection eDirection ) const
5588 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5589 maTabs[nTab]->FindAreaPos( rCol, rRow, eDirection );
5593 void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
5594 bool bMarked, bool bUnprotected, const ScMarkData& rMark ) const
5596 OSL_ENSURE( !nMovX || !nMovY, "GetNextPos: only X or Y" );
5598 ScMarkData aCopyMark = rMark;
5599 aCopyMark.SetMarking(false);
5600 aCopyMark.MarkToMulti();
5602 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5603 maTabs[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
5607 // Datei-Operationen
5611 void ScDocument::UpdStlShtPtrsFrmNms()
5613 ScPatternAttr::pDoc = this;
5615 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5617 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5618 ScPatternAttr* pPattern;
5619 for (sal_uInt32 i=0; i<nCount; i++)
5621 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
5622 if (pPattern)
5623 pPattern->UpdateStyleSheet();
5625 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet();
5629 void ScDocument::StylesToNames()
5631 ScPatternAttr::pDoc = this;
5633 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5635 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5636 ScPatternAttr* pPattern;
5637 for (sal_uInt32 i=0; i<nCount; i++)
5639 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
5640 if (pPattern)
5641 pPattern->StyleToName();
5643 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName();
5647 sal_uLong ScDocument::GetCellCount() const
5649 sal_uLong nCellCount = 0L;
5651 TableContainer::const_iterator it = maTabs.begin();
5652 for (; it != maTabs.end(); ++it)
5653 if ( *it )
5654 nCellCount += (*it)->GetCellCount();
5656 return nCellCount;
5659 SCSIZE ScDocument::GetCellCount(SCTAB nTab, SCCOL nCol) const
5661 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
5662 return 0;
5664 return maTabs[nTab]->GetCellCount(nCol);
5667 sal_uLong ScDocument::GetCodeCount() const
5669 sal_uLong nCodeCount = 0;
5671 TableContainer::const_iterator it = maTabs.begin();
5672 for (; it != maTabs.end(); ++it)
5673 if ( *it )
5674 nCodeCount += (*it)->GetCodeCount();
5676 return nCodeCount;
5680 void ScDocument::PageStyleModified( SCTAB nTab, const OUString& rNewName )
5682 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5683 maTabs[nTab]->PageStyleModified( rNewName );
5687 void ScDocument::SetPageStyle( SCTAB nTab, const OUString& rName )
5689 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5690 maTabs[nTab]->SetPageStyle( rName );
5694 const OUString ScDocument::GetPageStyle( SCTAB nTab ) const
5696 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5697 return maTabs[nTab]->GetPageStyle();
5699 return OUString();
5703 void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize )
5705 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5706 maTabs[nTab]->SetPageSize( rSize );
5709 Size ScDocument::GetPageSize( SCTAB nTab ) const
5711 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5712 return maTabs[nTab]->GetPageSize();
5714 OSL_FAIL("invalid tab");
5715 return Size();
5719 void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
5721 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5722 maTabs[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow );
5725 void ScDocument::InvalidatePageBreaks(SCTAB nTab)
5727 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5728 maTabs[nTab]->InvalidatePageBreaks();
5731 void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea )
5733 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5734 maTabs[nTab]->UpdatePageBreaks( pUserArea );
5737 void ScDocument::RemoveManualBreaks( SCTAB nTab )
5739 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5740 maTabs[nTab]->RemoveManualBreaks();
5743 bool ScDocument::HasManualBreaks( SCTAB nTab ) const
5745 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5746 return maTabs[nTab]->HasManualBreaks();
5748 OSL_FAIL("invalid tab");
5749 return false;
5753 void ScDocument::GetDocStat( ScDocStat& rDocStat )
5755 rDocStat.nTableCount = GetTableCount();
5756 rDocStat.aDocName = aDocName;
5757 rDocStat.nCellCount = GetCellCount();
5761 bool ScDocument::HasPrintRange()
5763 bool bResult = false;
5765 TableContainer::iterator it = maTabs.begin();
5766 for (; it != maTabs.end() && !bResult; ++it)
5767 if ( *it )
5768 bResult = (*it)->IsPrintEntireSheet() || ((*it)->GetPrintRangeCount() > 0);
5770 return bResult;
5774 bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const
5776 return (ValidTab(nTab) ) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsPrintEntireSheet();
5780 sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab )
5782 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5783 return maTabs[nTab]->GetPrintRangeCount();
5785 return 0;
5789 const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos )
5791 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5792 return maTabs[nTab]->GetPrintRange(nPos);
5794 return NULL;
5798 const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab )
5800 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5801 return maTabs[nTab]->GetRepeatColRange();
5803 return NULL;
5807 const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab )
5809 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5810 return maTabs[nTab]->GetRepeatRowRange();
5812 return NULL;
5816 void ScDocument::ClearPrintRanges( SCTAB nTab )
5818 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5819 maTabs[nTab]->ClearPrintRanges();
5823 void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew )
5825 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5826 maTabs[nTab]->AddPrintRange( rNew );
5830 void ScDocument::SetPrintEntireSheet( SCTAB nTab )
5832 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5833 maTabs[nTab]->SetPrintEntireSheet();
5837 void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew )
5839 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5840 maTabs[nTab]->SetRepeatColRange( pNew );
5844 void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew )
5846 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5847 maTabs[nTab]->SetRepeatRowRange( pNew );
5851 ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const
5853 SCTAB nCount = static_cast<SCTAB>(maTabs.size());
5854 ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount );
5855 for (SCTAB i=0; i<nCount; i++)
5856 if (maTabs[i])
5857 maTabs[i]->FillPrintSaver( pNew->GetTabData(i) );
5858 return pNew;
5862 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver )
5864 SCTAB nCount = rSaver.GetTabCount();
5865 for (SCTAB i=0; i<nCount && i < static_cast<SCTAB>(maTabs.size()); i++)
5866 if (maTabs[i])
5867 maTabs[i]->RestorePrintRanges( rSaver.GetTabData(i) );
5871 bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const
5873 // Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine
5874 // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen)
5875 // und eine Seitennummer angegeben ist (nicht 0)
5877 if ( nTab + 1 < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab+1] )
5879 OUString aNew = maTabs[nTab+1]->GetPageStyle();
5880 if ( aNew != maTabs[nTab]->GetPageStyle() )
5882 SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE );
5883 if ( pStyle )
5885 const SfxItemSet& rSet = pStyle->GetItemSet();
5886 sal_uInt16 nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue();
5887 if ( nFirst != 0 )
5888 return true; // Seitennummer in neuer Vorlage angegeben
5893 return false; // sonst nicht
5896 SfxUndoManager* ScDocument::GetUndoManager()
5898 if (!mpUndoManager)
5899 mpUndoManager = new SfxUndoManager;
5900 return mpUndoManager;
5903 ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const
5905 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5906 return new ScRowBreakIterator(maTabs[nTab]->maRowPageBreaks);
5907 return NULL;
5910 void ScDocument::AddSubTotalCell(ScFormulaCell* pCell)
5912 maSubTotalCells.insert(pCell);
5915 void ScDocument::RemoveSubTotalCell(ScFormulaCell* pCell)
5917 maSubTotalCells.erase(pCell);
5920 namespace {
5922 bool lcl_hasDirtyRange(ScFormulaCell* pCell, const ScRange& rDirtyRange)
5924 ScDetectiveRefIter aRefIter(pCell);
5925 ScRange aRange;
5926 while (aRefIter.GetNextRef(aRange))
5928 if (aRange.Intersects(rDirtyRange))
5929 return true;
5931 return false;
5936 void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
5938 // to update the list by skipping cells that no longer contain subtotal function.
5939 set<ScFormulaCell*> aNewSet;
5941 bool bOldRecalc = GetAutoCalc();
5942 SetAutoCalc(false);
5943 set<ScFormulaCell*>::iterator itr = maSubTotalCells.begin(), itrEnd = maSubTotalCells.end();
5944 for (; itr != itrEnd; ++itr)
5946 ScFormulaCell* pCell = *itr;
5947 if (pCell->IsSubTotal())
5949 aNewSet.insert(pCell);
5950 if (lcl_hasDirtyRange(pCell, rDirtyRange))
5951 pCell->SetDirty();
5955 SetAutoCalc(bOldRecalc);
5956 maSubTotalCells.swap(aNewSet); // update the list.
5959 sal_uInt16 ScDocument::GetTextWidth( const ScAddress& rPos ) const
5961 SCTAB nTab = rPos.Tab();
5962 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5963 return maTabs[nTab]->GetTextWidth(rPos.Col(), rPos.Row());
5965 return 0;
5968 void ScDocument::SetTextWidth( const ScAddress& rPos, sal_uInt16 nWidth )
5970 SCTAB nTab = rPos.Tab();
5971 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5972 maTabs[nTab]->SetTextWidth(rPos.Col(), rPos.Row(), nWidth);
5975 sal_uInt8 ScDocument::GetScriptType( const ScAddress& rPos ) const
5977 SCTAB nTab = rPos.Tab();
5978 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5979 return maTabs[nTab]->GetScriptType(rPos.Col(), rPos.Row());
5981 return 0;
5984 void ScDocument::SetScriptType( const ScAddress& rPos, sal_uInt8 nType )
5986 SCTAB nTab = rPos.Tab();
5987 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5988 maTabs[nTab]->SetScriptType(rPos.Col(), rPos.Row(), nType);
5991 void ScDocument::EnableUndo( bool bVal )
5993 // The undo manager increases lock count every time undo is disabled.
5994 // Because of this, we shouldn't disable undo unless it's currently
5995 // enabled, or else re-enabling it may not actually re-enable undo unless
5996 // the lock count becomes zero.
5998 if (bVal != GetUndoManager()->IsUndoEnabled())
6000 GetUndoManager()->EnableUndo(bVal);
6001 if( pDrawLayer ) pDrawLayer->EnableUndo(bVal);
6004 mbUndoEnabled = bVal;
6007 bool ScDocument::IsUserInteractionEnabled() const
6009 return mbUserInteractionEnabled;
6012 void ScDocument::EnableUserInteraction( bool bVal )
6014 mbUserInteractionEnabled = bVal;
6017 bool ScDocument::IsInVBAMode() const
6019 if (!pShell)
6020 return false;
6024 uno::Reference<script::vba::XVBACompatibility> xVBA(
6025 pShell->GetBasicContainer(), uno::UNO_QUERY);
6027 return xVBA.is() && xVBA->getVBACompatibilityMode();
6029 catch (const lang::NotInitializedException&) {}
6031 return false;
6034 ScNotes* ScDocument::GetNotes(SCTAB nTab)
6036 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
6037 return maTabs[nTab]->GetNotes();
6039 return NULL;
6042 void ScDocument::SetAutoNameCache( ScAutoNameCache* pCache )
6044 delete pAutoNameCache;
6045 pAutoNameCache = pCache;
6048 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */