1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
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/sdrundomanager.hxx>
29 #include <svx/svditer.hxx>
30 #include <svx/svdpage.hxx>
31 #include <svx/svdocapt.hxx>
32 #include <sfx2/app.hxx>
33 #include <sfx2/objsh.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <svl/poolcach.hxx>
36 #include <unotools/saveopt.hxx>
37 #include <svl/zforlist.hxx>
38 #include <unotools/charclass.hxx>
39 #include <unotools/transliterationwrapper.hxx>
40 #include <tools/tenccvt.hxx>
41 #include <tools/urlobj.hxx>
43 #include <com/sun/star/text/WritingMode2.hpp>
44 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
45 #include <com/sun/star/sheet/TablePageBreakData.hpp>
46 #include <com/sun/star/lang/NotInitializedException.hpp>
48 #include "document.hxx"
51 #include "attarray.hxx"
52 #include "markarr.hxx"
53 #include "patattr.hxx"
54 #include "rangenam.hxx"
55 #include "poolhelp.hxx"
56 #include "docpool.hxx"
57 #include "stlpool.hxx"
58 #include "stlsheet.hxx"
59 #include "globstr.hrc"
60 #include "rechead.hxx"
63 #include "chartlis.hxx"
64 #include "rangelst.hxx"
65 #include "markdata.hxx"
66 #include "drwlayer.hxx"
67 #include "conditio.hxx"
68 #include "colorscale.hxx"
69 #include "validat.hxx"
70 #include "prnsave.hxx"
71 #include "chgtrack.hxx"
73 #include "scresid.hxx"
75 #include "detdata.hxx"
76 #include "dpobject.hxx"
77 #include "detfunc.hxx"
79 #include "dociter.hxx"
80 #include "progress.hxx"
81 #include "autonamecache.hxx"
82 #include "bcaslot.hxx"
84 #include "externalrefmgr.hxx"
85 #include "tabprotection.hxx"
86 #include "clipparam.hxx"
87 #include "defaultsoptions.hxx"
88 #include "editutil.hxx"
89 #include "stringutil.hxx"
90 #include "formulaiter.hxx"
91 #include "formulacell.hxx"
92 #include "clipcontext.hxx"
93 #include "listenercontext.hxx"
94 #include "scopetools.hxx"
95 #include "refupdatecontext.hxx"
96 #include "formulagroup.hxx"
97 #include <tokenarray.hxx>
98 #include <tokenstringcontext.hxx>
100 #include <formula/vectortoken.hxx>
104 #include <boost/checked_delete.hpp>
105 #include <boost/scoped_ptr.hpp>
107 #include "mtvelements.hxx"
109 using ::editeng::SvxBorderLine
;
110 using namespace ::com::sun::star
;
112 namespace WritingMode2
= ::com::sun::star::text::WritingMode2
;
113 using ::com::sun::star::uno::Sequence
;
114 using ::com::sun::star::sheet::TablePageBreakData
;
119 std::pair
<SCTAB
,SCTAB
> getMarkedTableRange(const std::vector
<ScTable
*>& rTables
, const ScMarkData
& rMark
)
121 SCTAB nTabStart
= MAXTAB
;
123 SCTAB nMax
= static_cast<SCTAB
>(rTables
.size());
124 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
125 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
130 if (*itr
< nTabStart
)
135 return std::pair
<SCTAB
,SCTAB
>(nTabStart
,nTabEnd
);
142 const ScPatternAttr
* pAttr
;
145 ScDefaultAttr(const ScPatternAttr
* pPatAttr
) : pAttr(pPatAttr
), nFirst(0), nCount(0) {}
148 struct ScLessDefaultAttr
150 bool operator() (const ScDefaultAttr
& rValue1
, const ScDefaultAttr
& rValue2
) const
152 return rValue1
.pAttr
< rValue2
.pAttr
;
156 typedef std::set
<ScDefaultAttr
, ScLessDefaultAttr
> ScDefaultAttrSet
;
158 void ScDocument::MakeTable( SCTAB nTab
,bool _bNeedsNameCheck
)
160 if ( ValidTab(nTab
) && ( nTab
>= static_cast<SCTAB
>(maTabs
.size()) ||!maTabs
[nTab
]) )
163 const ScDefaultsOptions
& rOpt
= SC_MOD()->GetDefaultsOptions();
164 OUString aString
= rOpt
.GetInitTabPrefix();
166 aString
+= OUString::number(nTab
+1);
167 if ( _bNeedsNameCheck
)
168 CreateValidTabName( aString
); // no doubles
169 if (nTab
< static_cast<SCTAB
>(maTabs
.size()))
171 maTabs
[nTab
] = new ScTable(this, nTab
, aString
);
175 while(nTab
> static_cast<SCTAB
>(maTabs
.size()))
176 maTabs
.push_back(NULL
);
177 maTabs
.push_back( new ScTable(this, nTab
, aString
) );
179 maTabs
[nTab
]->SetLoadingMedium(bLoadingMedium
);
183 bool ScDocument::HasTable( SCTAB nTab
) const
185 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
192 bool ScDocument::GetName( SCTAB nTab
, OUString
& rName
) const
194 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
198 maTabs
[nTab
]->GetName( rName
);
206 OUString
ScDocument::GetCopyTabName( SCTAB nTab
) const
208 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabNames
.size()))
209 return maTabNames
[nTab
];
213 bool ScDocument::SetCodeName( SCTAB nTab
, const OUString
& rName
)
215 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
219 maTabs
[nTab
]->SetCodeName( rName
);
223 OSL_TRACE( "**** can't set code name %s", OUStringToOString( rName
, RTL_TEXTENCODING_UTF8
).getStr() );
227 bool ScDocument::GetCodeName( SCTAB nTab
, OUString
& rName
) const
229 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
232 maTabs
[nTab
]->GetCodeName( rName
);
239 bool ScDocument::GetTable( const OUString
& rName
, SCTAB
& rTab
) const
242 static OUString aCacheName
, aCacheUpperName
;
244 if (aCacheName
!= rName
)
247 // surprisingly slow ...
248 aCacheUpperName
= ScGlobal::pCharClass
->uppercase(rName
);
250 aUpperName
= aCacheUpperName
;
252 for (SCTAB i
=0; i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
255 if (aUpperName
.equals(maTabs
[i
]->GetUpperName()))
265 std::vector
<OUString
> ScDocument::GetAllTableNames() const
267 std::vector
<OUString
> aNames
;
268 aNames
.reserve(maTabs
.size());
269 TableContainer::const_iterator it
= maTabs
.begin(), itEnd
= maTabs
.end();
270 for (; it
!= itEnd
; ++it
)
272 // Positions need to be preserved for ScCompiler and address convention
273 // context, so still push an empty string for NULL tabs.
277 const ScTable
& rTab
= **it
;
280 aNames
.push_back(aName
);
286 ScDBData
* ScDocument::GetAnonymousDBData(SCTAB nTab
)
288 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
289 return maTabs
[nTab
]->GetAnonymousDBData();
293 SCTAB
ScDocument::GetTableCount() const
295 return static_cast<SCTAB
>(maTabs
.size());
298 void ScDocument::SetAnonymousDBData(SCTAB nTab
, ScDBData
* pDBData
)
300 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
301 maTabs
[nTab
]->SetAnonymousDBData(pDBData
);
304 bool ScDocument::ValidTabName( const OUString
& rName
)
308 sal_Int32 nLen
= rName
.getLength();
311 // Restrict sheet names to what Excel accepts.
312 /* TODO: We may want to remove this restriction for full ODFF compliance.
313 * Merely loading and calculating ODF documents using these characters in
314 * sheet names is not affected by this, but all sheet name editing and
315 * copying functionality is, maybe falling back to "Sheet4" or similar. */
316 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
318 const sal_Unicode c
= rName
[i
];
328 // these characters are not allowed to match XL's convention.
331 if (i
== 0 || i
== nLen
- 1)
332 // single quote is not allowed at the first or last
333 // character position.
343 bool ScDocument::ValidNewTabName( const OUString
& rName
) const
345 bool bValid
= ValidTabName(rName
);
346 TableContainer::const_iterator it
= maTabs
.begin();
347 for (; it
!= maTabs
.end() && bValid
; ++it
)
351 (*it
)->GetName(aOldName
);
352 bValid
= !ScGlobal::GetpTransliteration()->isEqual( rName
, aOldName
);
357 void ScDocument::CreateValidTabName(OUString
& rName
) const
359 if ( !ValidTabName(rName
) )
364 const ScDefaultsOptions
& rOpt
= SC_MOD()->GetDefaultsOptions();
365 OUString aStrTable
= rOpt
.GetInitTabPrefix();
369 // First test if the prefix is valid, if so only avoid doubles
370 bool bPrefix
= ValidTabName( aStrTable
);
371 OSL_ENSURE(bPrefix
, "Invalid Table Name");
374 for ( SCTAB i
= static_cast<SCTAB
>(maTabs
.size())+1; !bOk
; i
++ )
377 aBuf
.append(aStrTable
);
378 aBuf
.append(static_cast<sal_Int32
>(i
));
379 rName
= aBuf
.makeStringAndClear();
381 bOk
= ValidNewTabName( rName
);
383 bOk
= !GetTable( rName
, nDummy
);
388 // testing the supplied Name
390 if ( !ValidNewTabName(rName
) )
393 OUStringBuffer aName
;
399 aName
.append(static_cast<sal_Int32
>(i
));
401 while (!ValidNewTabName(aName
.toString()) && (i
< MAXTAB
+1));
402 rName
= aName
.makeStringAndClear();
407 void ScDocument::CreateValidTabNames(std::vector
<OUString
>& aNames
, SCTAB nCount
) const
409 aNames
.clear();//ensure that the vector is empty
412 const ScDefaultsOptions
& rOpt
= SC_MOD()->GetDefaultsOptions();
413 OUString aStrTable
= rOpt
.GetInitTabPrefix();
415 OUStringBuffer rName
;
418 // First test if the prefix is valid, if so only avoid doubles
419 bool bPrefix
= ValidTabName( aStrTable
);
420 OSL_ENSURE(bPrefix
, "Invalid Table Name");
422 SCTAB i
= static_cast<SCTAB
>(maTabs
.size())+1;
424 for (SCTAB j
= 0; j
< nCount
; ++j
)
430 rName
.append(static_cast<sal_Int32
>(i
));
432 bOk
= ValidNewTabName( rName
.toString() );
434 bOk
= !GetTable( rName
.toString(), nDummy
);
437 aNames
.push_back(rName
.makeStringAndClear());
441 void ScDocument::AppendTabOnLoad(const OUString
& rName
)
443 SCTAB nTabCount
= static_cast<SCTAB
>(maTabs
.size());
444 if (!ValidTab(nTabCount
))
445 // max table count reached. No more tables.
448 OUString aName
= rName
;
449 CreateValidTabName(aName
);
450 maTabs
.push_back( new ScTable(this, nTabCount
, aName
) );
453 void ScDocument::SetTabNameOnLoad(SCTAB nTab
, const OUString
& rName
)
455 if (!ValidTab(nTab
) || static_cast<SCTAB
>(maTabs
.size()) <= nTab
)
458 if (!ValidTabName(rName
))
461 maTabs
[nTab
]->SetName(rName
);
464 void ScDocument::InvalidateStreamOnSave()
466 TableContainer::iterator it
= maTabs
.begin(), itEnd
= maTabs
.end();
467 for (; it
!= itEnd
; ++it
)
471 pTab
->SetStreamValid(false);
475 bool ScDocument::InsertTab(
476 SCTAB nPos
, const OUString
& rName
, bool bExternalDocument
, bool bUndoDeleteTab
)
478 SCTAB nTabCount
= static_cast<SCTAB
>(maTabs
.size());
479 bool bValid
= ValidTab(nTabCount
);
480 if ( !bExternalDocument
) // else test rName == "'Doc'!Tab" first
481 bValid
= (bValid
&& ValidNewTabName(rName
));
484 if (nPos
== SC_TAB_APPEND
|| nPos
>= nTabCount
)
486 nPos
= maTabs
.size();
487 maTabs
.push_back( new ScTable(this, nTabCount
, rName
) );
488 if ( bExternalDocument
)
489 maTabs
[nTabCount
]->SetVisible( false );
493 if (ValidTab(nPos
) && (nPos
< nTabCount
))
495 sc::RefUpdateInsertTabContext
aCxt( *this, nPos
, 1);
497 ScRange
aRange( 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
);
498 xColNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,1 );
499 xRowNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,1 );
501 pRangeName
->UpdateInsertTab(aCxt
);
502 pDBCollection
->UpdateReference(
503 URM_INSDEL
, 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,1 );
505 pDPCollection
->UpdateReference( URM_INSDEL
, aRange
, 0,0,1 );
507 pDetOpList
->UpdateReference( this, URM_INSDEL
, aRange
, 0,0,1 );
508 UpdateChartRef( URM_INSDEL
, 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,1 );
509 UpdateRefAreaLinks( URM_INSDEL
, aRange
, 0,0,1 );
510 if ( pUnoBroadcaster
)
511 pUnoBroadcaster
->Broadcast( ScUpdateRefHint( URM_INSDEL
, aRange
, 0,0,1 ) );
514 TableContainer::iterator it
= maTabs
.begin();
515 for (; it
!= maTabs
.end(); ++it
)
517 (*it
)->UpdateInsertTab(aCxt
);
518 maTabs
.push_back(NULL
);
519 for (i
= nTabCount
; i
> nPos
; i
--)
521 maTabs
[i
] = maTabs
[i
- 1];
524 maTabs
[nPos
] = new ScTable(this, nPos
, rName
);
526 // UpdateBroadcastAreas must be called between UpdateInsertTab,
527 // which ends listening, and StartAllListeners, to not modify
528 // areas that are to be inserted by starting listeners.
529 UpdateBroadcastAreas( URM_INSDEL
, aRange
, 0,0,1);
531 for (; it
!= maTabs
.end(); ++it
)
533 (*it
)->UpdateCompile();
538 pValidationList
->UpdateInsertTab(aCxt
);
540 // sheet names of references are not valid until sheet is inserted
541 if ( pChartListenerCollection
)
542 pChartListenerCollection
->UpdateScheduledSeriesRanges();
553 sc::SetFormulaDirtyContext aCxt
;
554 aCxt
.mbClearTabDeletedFlag
= bUndoDeleteTab
;
555 aCxt
.mnTabDeletedStart
= nPos
;
556 aCxt
.mnTabDeletedEnd
= nPos
;
557 SetAllFormulasDirty(aCxt
);
563 bool ScDocument::InsertTabs( SCTAB nPos
, const std::vector
<OUString
>& rNames
,
564 bool bExternalDocument
, bool bNamesValid
)
566 SCTAB nNewSheets
= static_cast<SCTAB
>(rNames
.size());
567 SCTAB nTabCount
= static_cast<SCTAB
>(maTabs
.size());
568 bool bValid
= bNamesValid
|| ValidTab(nTabCount
+nNewSheets
);
572 if (nPos
== SC_TAB_APPEND
|| nPos
>= nTabCount
)
574 for ( SCTAB i
= 0; i
< nNewSheets
; ++i
)
576 maTabs
.push_back( new ScTable(this, nTabCount
+ i
, rNames
.at(i
)) );
577 if ( bExternalDocument
)
578 maTabs
[nTabCount
+i
]->SetVisible( false );
583 if (ValidTab(nPos
) && (nPos
< nTabCount
))
585 sc::RefUpdateInsertTabContext
aCxt( *this, nPos
, nNewSheets
);
586 ScRange
aRange( 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
);
587 xColNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,nNewSheets
);
588 xRowNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,nNewSheets
);
590 pRangeName
->UpdateInsertTab(aCxt
);
591 pDBCollection
->UpdateReference(
592 URM_INSDEL
, 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,nNewSheets
);
594 pDPCollection
->UpdateReference( URM_INSDEL
, aRange
, 0,0,nNewSheets
);
596 pDetOpList
->UpdateReference( this, URM_INSDEL
, aRange
, 0,0,nNewSheets
);
597 UpdateChartRef( URM_INSDEL
, 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,nNewSheets
);
598 UpdateRefAreaLinks( URM_INSDEL
, aRange
, 0,0, nNewSheets
);
599 if ( pUnoBroadcaster
)
600 pUnoBroadcaster
->Broadcast( ScUpdateRefHint( URM_INSDEL
, aRange
, 0,0,nNewSheets
) );
602 TableContainer::iterator it
= maTabs
.begin();
603 for (; it
!= maTabs
.end(); ++it
)
605 (*it
)->UpdateInsertTab(aCxt
);
607 maTabs
.insert(it
+nPos
,nNewSheets
, NULL
);
608 for (SCTAB i
= 0; i
< nNewSheets
; ++i
)
610 maTabs
[nPos
+ i
] = new ScTable(this, nPos
+ i
, rNames
.at(i
));
613 // UpdateBroadcastAreas must be called between UpdateInsertTab,
614 // which ends listening, and StartAllListeners, to not modify
615 // areas that are to be inserted by starting listeners.
616 UpdateBroadcastAreas( URM_INSDEL
, aRange
, 0,0,nNewSheets
);
618 for (; it
!= maTabs
.end(); ++it
)
621 (*it
)->UpdateCompile();
627 pValidationList
->UpdateInsertTab(aCxt
);
629 // sheet names of references are not valid until sheet is inserted
630 if ( pChartListenerCollection
)
631 pChartListenerCollection
->UpdateScheduledSeriesRanges();
642 sc::SetFormulaDirtyContext aCxt
;
643 SetAllFormulasDirty(aCxt
);
649 bool ScDocument::DeleteTab( SCTAB nTab
)
652 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
656 SCTAB nTabCount
= static_cast<SCTAB
>(maTabs
.size());
659 sc::AutoCalcSwitch
aACSwitch(*this, false);
660 sc::RefUpdateDeleteTabContext
aCxt( *this, nTab
, 1);
662 ScRange
aRange( 0, 0, nTab
, MAXCOL
, MAXROW
, nTab
);
663 DelBroadcastAreasInRange( aRange
);
665 // #i8180# remove database ranges etc. that are on the deleted tab
666 // (restored in undo with ScRefUndoData)
668 xColNameRanges
->DeleteOnTab( nTab
);
669 xRowNameRanges
->DeleteOnTab( nTab
);
670 pDBCollection
->DeleteOnTab( nTab
);
672 pDPCollection
->DeleteOnTab( nTab
);
674 pDetOpList
->DeleteOnTab( nTab
);
675 DeleteAreaLinksOnTab( nTab
);
677 // normal reference update
679 aRange
.aEnd
.SetTab( static_cast<SCTAB
>(maTabs
.size())-1 );
680 xColNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,-1 );
681 xRowNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,-1 );
683 pRangeName
->UpdateDeleteTab(aCxt
);
684 pDBCollection
->UpdateReference(
685 URM_INSDEL
, 0,0,nTab
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,-1 );
687 pDPCollection
->UpdateReference( URM_INSDEL
, aRange
, 0,0,-1 );
689 pDetOpList
->UpdateReference( this, URM_INSDEL
, aRange
, 0,0,-1 );
690 UpdateChartRef( URM_INSDEL
, 0,0,nTab
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,-1 );
691 UpdateRefAreaLinks( URM_INSDEL
, aRange
, 0,0,-1 );
693 pValidationList
->UpdateDeleteTab(aCxt
);
694 if ( pUnoBroadcaster
)
695 pUnoBroadcaster
->Broadcast( ScUpdateRefHint( URM_INSDEL
, aRange
, 0,0,-1 ) );
697 for (SCTAB i
= 0, n
= static_cast<SCTAB
>(maTabs
.size()); i
< n
; ++i
)
699 maTabs
[i
]->UpdateDeleteTab(aCxt
);
701 TableContainer::iterator it
= maTabs
.begin() + nTab
;
704 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
705 // which ends listening, and StartAllListeners, to not modify
706 // areas that are to be inserted by starting listeners.
707 UpdateBroadcastAreas( URM_INSDEL
, aRange
, 0,0,-1);
709 for (; it
!= maTabs
.end(); ++it
)
711 (*it
)->UpdateCompile();
712 // Excel-Filter deletes some Tables while loading, Listeners will
713 // only be triggered after the loading is done.
714 if ( !bInsertingFromOtherDoc
)
718 sc::SetFormulaDirtyContext aFormulaDirtyCxt
;
719 SetAllFormulasDirty(aFormulaDirtyCxt
);
721 // sheet names of references are not valid until sheet is deleted
722 pChartListenerCollection
->UpdateScheduledSeriesRanges();
731 bool ScDocument::DeleteTabs( SCTAB nTab
, SCTAB nSheets
)
734 if (ValidTab(nTab
) && (nTab
+ nSheets
) < static_cast<SCTAB
>(maTabs
.size()))
738 SCTAB nTabCount
= static_cast<SCTAB
>(maTabs
.size());
739 if (nTabCount
> nSheets
)
741 sc::AutoCalcSwitch
aACSwitch(*this, false);
742 sc::RefUpdateDeleteTabContext
aCxt( *this, nTab
, nSheets
);
744 for (SCTAB aTab
= 0; aTab
< nSheets
; ++aTab
)
746 ScRange
aRange( 0, 0, nTab
, MAXCOL
, MAXROW
, nTab
+ aTab
);
747 DelBroadcastAreasInRange( aRange
);
749 // #i8180# remove database ranges etc. that are on the deleted tab
750 // (restored in undo with ScRefUndoData)
752 xColNameRanges
->DeleteOnTab( nTab
+ aTab
);
753 xRowNameRanges
->DeleteOnTab( nTab
+ aTab
);
754 pDBCollection
->DeleteOnTab( nTab
+ aTab
);
756 pDPCollection
->DeleteOnTab( nTab
+ aTab
);
758 pDetOpList
->DeleteOnTab( nTab
+ aTab
);
759 DeleteAreaLinksOnTab( nTab
+ aTab
);
763 pRangeName
->UpdateDeleteTab(aCxt
);
765 // normal reference update
767 ScRange
aRange( 0, 0, nTab
, MAXCOL
, MAXROW
, nTabCount
- 1 );
768 xColNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,-1*nSheets
);
769 xRowNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,-1*nSheets
);
770 pDBCollection
->UpdateReference(
771 URM_INSDEL
, 0,0,nTab
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,-1*nSheets
);
773 pDPCollection
->UpdateReference( URM_INSDEL
, aRange
, 0,0,-1*nSheets
);
775 pDetOpList
->UpdateReference( this, URM_INSDEL
, aRange
, 0,0,-1*nSheets
);
776 UpdateChartRef( URM_INSDEL
, 0,0,nTab
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,-1*nSheets
);
777 UpdateRefAreaLinks( URM_INSDEL
, aRange
, 0,0,-1*nSheets
);
779 pValidationList
->UpdateDeleteTab(aCxt
);
780 if ( pUnoBroadcaster
)
781 pUnoBroadcaster
->Broadcast( ScUpdateRefHint( URM_INSDEL
, aRange
, 0,0,-1*nSheets
) );
783 for (SCTAB i
= 0, n
= static_cast<SCTAB
>(maTabs
.size()); i
< n
; ++i
)
785 maTabs
[i
]->UpdateDeleteTab(aCxt
);
787 TableContainer::iterator it
= maTabs
.begin() + nTab
;
788 TableContainer::iterator itEnd
= it
+ nSheets
;
789 std::for_each(it
, itEnd
, boost::checked_deleter
<ScTable
>());
790 maTabs
.erase(it
, itEnd
);
791 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
792 // which ends listening, and StartAllListeners, to not modify
793 // areas that are to be inserted by starting listeners.
794 UpdateBroadcastAreas( URM_INSDEL
, aRange
, 0,0,-1*nSheets
);
796 for (; it
!= maTabs
.end(); ++it
)
798 (*it
)->UpdateCompile();
799 // Excel-Filter deletes some Tables while loading, Listeners will
800 // only be triggered after the loading is done.
801 if ( !bInsertingFromOtherDoc
)
805 sc::SetFormulaDirtyContext aFormulaDirtyCxt
;
806 SetAllFormulasDirty(aFormulaDirtyCxt
);
808 // sheet names of references are not valid until sheet is deleted
809 pChartListenerCollection
->UpdateScheduledSeriesRanges();
818 bool ScDocument::RenameTab( SCTAB nTab
, const OUString
& rName
, bool /* bUpdateRef */,
819 bool bExternalDocument
)
827 if ( bExternalDocument
)
828 bValid
= true; // composed name
830 bValid
= ValidTabName(rName
);
831 for (i
=0; (i
< static_cast<SCTAB
>(maTabs
.size())) && bValid
; i
++)
832 if (maTabs
[i
] && (i
!= nTab
))
835 maTabs
[i
]->GetName(aOldName
);
836 bValid
= !ScGlobal::GetpTransliteration()->isEqual( rName
, aOldName
);
840 // #i75258# update charts before renaming, so they can get their live data objects.
841 // Once the charts are live, the sheet can be renamed without problems.
842 if ( pChartListenerCollection
)
843 pChartListenerCollection
->UpdateChartsContainingTab( nTab
);
844 maTabs
[nTab
]->SetName(rName
);
846 // If formulas refer to the renamed sheet, the TokenArray remains valid,
847 // but the XML stream must be re-generated.
848 TableContainer::iterator it
= maTabs
.begin();
849 for (; it
!= maTabs
.end(); ++it
)
850 if ( *it
&& (*it
)->IsStreamValid())
851 (*it
)->SetStreamValid( false );
858 void ScDocument::SetVisible( SCTAB nTab
, bool bVisible
)
860 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()))
862 maTabs
[nTab
]->SetVisible(bVisible
);
865 bool ScDocument::IsVisible( SCTAB nTab
) const
867 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()))
869 return maTabs
[nTab
]->IsVisible();
874 bool ScDocument::IsStreamValid( SCTAB nTab
) const
876 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
] )
877 return maTabs
[nTab
]->IsStreamValid();
882 void ScDocument::SetStreamValid( SCTAB nTab
, bool bSet
, bool bIgnoreLock
)
884 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
] )
885 maTabs
[nTab
]->SetStreamValid( bSet
, bIgnoreLock
);
888 void ScDocument::LockStreamValid( bool bLock
)
890 mbStreamValidLocked
= bLock
;
893 bool ScDocument::IsPendingRowHeights( SCTAB nTab
) const
895 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
] )
896 return maTabs
[nTab
]->IsPendingRowHeights();
901 void ScDocument::SetPendingRowHeights( SCTAB nTab
, bool bSet
)
903 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
] )
904 maTabs
[nTab
]->SetPendingRowHeights( bSet
);
907 void ScDocument::SetLayoutRTL( SCTAB nTab
, bool bRTL
)
909 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
] )
913 // #i57869# only set the LoadingRTL flag, the real setting (including mirroring)
914 // is applied in SetImportingXML(false). This is so the shapes can be loaded in
917 maTabs
[nTab
]->SetLoadingRTL( bRTL
);
921 maTabs
[nTab
]->SetLayoutRTL( bRTL
); // only sets the flag
922 maTabs
[nTab
]->SetDrawPageSize();
924 // mirror existing objects:
928 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
929 OSL_ENSURE(pPage
,"Page ?");
932 SdrObjListIter
aIter( *pPage
, IM_DEEPNOGROUPS
);
933 SdrObject
* pObject
= aIter
.Next();
936 // objects with ScDrawObjData are re-positioned in SetPageSize,
937 // don't mirror again
938 ScDrawObjData
* pData
= ScDrawLayer::GetObjData( pObject
);
940 pDrawLayer
->MirrorRTL( pObject
);
942 pObject
->SetContextWritingMode( bRTL
? WritingMode2::RL_TB
: WritingMode2::LR_TB
);
944 pObject
= aIter
.Next();
951 bool ScDocument::IsLayoutRTL( SCTAB nTab
) const
953 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
] )
954 return maTabs
[nTab
]->IsLayoutRTL();
959 bool ScDocument::IsNegativePage( SCTAB nTab
) const
961 // Negative page area is always used for RTL layout.
962 // The separate method is used to find all RTL handling of drawing objects.
963 return IsLayoutRTL( nTab
);
966 /* ----------------------------------------------------------------------------
969 GetCellArea - Only Data
970 GetTableArea - Data / Attributes
971 GetPrintArea - intended for character objects,
972 sweeps attributes all the way to bottom / right
973 ---------------------------------------------------------------------------- */
975 bool ScDocument::GetCellArea( SCTAB nTab
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
977 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()))
979 return maTabs
[nTab
]->GetCellArea( rEndCol
, rEndRow
);
986 bool ScDocument::GetTableArea( SCTAB nTab
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
988 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()))
990 return maTabs
[nTab
]->GetTableArea( rEndCol
, rEndRow
);
997 bool ScDocument::ShrinkToDataArea(SCTAB nTab
, SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
999 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
> (maTabs
.size()) || !maTabs
[nTab
])
1004 maTabs
[nTab
]->GetFirstDataPos(nCol1
, nRow1
);
1005 maTabs
[nTab
]->GetLastDataPos(nCol2
, nRow2
);
1007 if (nCol1
> nCol2
|| nRow1
> nRow2
)
1011 // Make sure the area only shrinks, and doesn't grow.
1012 if (rStartCol
< nCol1
)
1014 if (nCol2
< rEndCol
)
1016 if (rStartRow
< nRow1
)
1018 if (nRow2
< rEndRow
)
1021 if (rStartCol
> rEndCol
|| rStartRow
> rEndRow
)
1025 return true; // success!
1028 bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk
, SCTAB nTab
, SCCOL
& rStartCol
,
1029 SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bColumnsOnly
,
1030 bool bStickyTopRow
, bool bStickyLeftCol
) const
1032 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
> (maTabs
.size()) || !maTabs
[nTab
])
1037 return maTabs
[nTab
]->ShrinkToUsedDataArea( o_bShrunk
, rStartCol
, rStartRow
, rEndCol
, rEndRow
,
1038 bColumnsOnly
, bStickyTopRow
, bStickyLeftCol
);
1041 SCROW
ScDocument::GetLastDataRow( SCTAB nTab
, SCCOL nCol1
, SCCOL nCol2
, SCROW nLastRow
) const
1043 const ScTable
* pTab
= FetchTable(nTab
);
1047 return pTab
->GetLastDataRow(nCol1
, nCol2
, nLastRow
);
1050 ScAddress
ScDocument::GetLastDataPos( SCTAB nTab
) const
1052 const ScTable
* pTab
= FetchTable(nTab
);
1054 return ScAddress(ScAddress::INITIALIZE_INVALID
);
1058 pTab
->GetLastDataPos(nCol
, nRow
);
1059 return ScAddress(nCol
, nRow
, nTab
);
1064 void ScDocument::GetDataArea( SCTAB nTab
, SCCOL
& rStartCol
, SCROW
& rStartRow
,
1065 SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bIncludeOld
, bool bOnlyDown
) const
1067 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
])
1068 maTabs
[nTab
]->GetDataArea( rStartCol
, rStartRow
, rEndCol
, rEndRow
, bIncludeOld
, bOnlyDown
);
1071 void ScDocument::LimitChartArea( SCTAB nTab
, SCCOL
& rStartCol
, SCROW
& rStartRow
,
1072 SCCOL
& rEndCol
, SCROW
& rEndRow
)
1074 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
> (maTabs
.size()))
1076 maTabs
[nTab
]->LimitChartArea( rStartCol
, rStartRow
, rEndCol
, rEndRow
);
1079 void ScDocument::LimitChartIfAll( ScRangeListRef
& rRangeList
)
1081 ScRangeListRef aNew
= new ScRangeList
;
1082 if (rRangeList
.Is())
1084 for ( size_t i
= 0, nCount
= rRangeList
->size(); i
< nCount
; i
++ )
1086 ScRange
aRange( *(*rRangeList
)[i
] );
1087 if ( ( aRange
.aStart
.Col() == 0 && aRange
.aEnd
.Col() == MAXCOL
) ||
1088 ( aRange
.aStart
.Row() == 0 && aRange
.aEnd
.Row() == MAXROW
) )
1090 SCCOL nStartCol
= aRange
.aStart
.Col();
1091 SCROW nStartRow
= aRange
.aStart
.Row();
1092 SCCOL nEndCol
= aRange
.aEnd
.Col();
1093 SCROW nEndRow
= aRange
.aEnd
.Row();
1094 SCTAB nTab
= aRange
.aStart
.Tab();
1095 if ( nTab
< static_cast<SCTAB
> (maTabs
.size()) && maTabs
[nTab
])
1096 maTabs
[nTab
]->LimitChartArea(nStartCol
, nStartRow
, nEndCol
, nEndRow
);
1097 aRange
.aStart
.SetCol( nStartCol
);
1098 aRange
.aStart
.SetRow( nStartRow
);
1099 aRange
.aEnd
.SetCol( nEndCol
);
1100 aRange
.aEnd
.SetRow( nEndRow
);
1102 aNew
->Append(aRange
);
1107 OSL_FAIL("LimitChartIfAll: Ref==0");
1112 static void lcl_GetFirstTabRange( SCTAB
& rTabRangeStart
, SCTAB
& rTabRangeEnd
, const ScMarkData
* pTabMark
, SCTAB aMaxTab
)
1114 // without ScMarkData, leave start/end unchanged
1117 for (SCTAB nTab
=0; nTab
< aMaxTab
; ++nTab
)
1118 if (pTabMark
->GetTableSelect(nTab
))
1120 // find first range of consecutive selected sheets
1121 rTabRangeStart
= pTabMark
->GetFirstSelected();
1122 while ( nTab
+1 < aMaxTab
&& pTabMark
->GetTableSelect(nTab
+1) )
1124 rTabRangeEnd
= nTab
;
1130 static bool lcl_GetNextTabRange( SCTAB
& rTabRangeStart
, SCTAB
& rTabRangeEnd
, const ScMarkData
* pTabMark
, SCTAB aMaxTab
)
1134 // find next range of consecutive selected sheets after rTabRangeEnd
1135 for (SCTAB nTab
=rTabRangeEnd
+1; nTab
< aMaxTab
; ++nTab
)
1136 if (pTabMark
->GetTableSelect(nTab
))
1138 rTabRangeStart
= nTab
;
1139 while ( nTab
+1 < aMaxTab
&& pTabMark
->GetTableSelect(nTab
+1) )
1141 rTabRangeEnd
= nTab
;
1148 bool ScDocument::CanInsertRow( const ScRange
& rRange
) const
1150 SCCOL nStartCol
= rRange
.aStart
.Col();
1151 SCROW nStartRow
= rRange
.aStart
.Row();
1152 SCTAB nStartTab
= rRange
.aStart
.Tab();
1153 SCCOL nEndCol
= rRange
.aEnd
.Col();
1154 SCROW nEndRow
= rRange
.aEnd
.Row();
1155 SCTAB nEndTab
= rRange
.aEnd
.Tab();
1156 PutInOrder( nStartCol
, nEndCol
);
1157 PutInOrder( nStartRow
, nEndRow
);
1158 PutInOrder( nStartTab
, nEndTab
);
1159 SCSIZE nSize
= static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
1162 for (SCTAB i
=nStartTab
; i
<=nEndTab
&& bTest
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1164 bTest
&= maTabs
[i
]->TestInsertRow( nStartCol
, nEndCol
, nStartRow
, nSize
);
1171 struct SetDirtyIfPostponedHandler
: std::unary_function
<ScTable
*, void>
1173 void operator() (ScTable
* p
)
1176 p
->SetDirtyIfPostponed();
1180 struct BroadcastRecalcOnRefMoveHandler
: std::unary_function
<ScTable
*, void>
1182 void operator() (ScTable
* p
)
1185 p
->BroadcastRecalcOnRefMove();
1191 bool ScDocument::InsertRow( SCCOL nStartCol
, SCTAB nStartTab
,
1192 SCCOL nEndCol
, SCTAB nEndTab
,
1193 SCROW nStartRow
, SCSIZE nSize
, ScDocument
* pRefUndoDoc
,
1194 const ScMarkData
* pTabMark
)
1198 PutInOrder( nStartCol
, nEndCol
);
1199 PutInOrder( nStartTab
, nEndTab
);
1203 nEndTab
= static_cast<SCTAB
>(maTabs
.size()) -1;
1208 bool bOldAutoCalc
= GetAutoCalc();
1209 SetAutoCalc( false ); // avoid mulitple calculations
1210 for ( i
= nStartTab
; i
<= nEndTab
&& bTest
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1211 if (maTabs
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1212 bTest
&= maTabs
[i
]->TestInsertRow(nStartCol
, nEndCol
, nStartRow
, nSize
);
1215 // UpdateBroadcastAreas have to be called before UpdateReference, so that entries
1216 // aren't shifted that would be rebuild at UpdateReference
1218 // handle chunks of consecutive selected sheets together
1219 SCTAB nTabRangeStart
= nStartTab
;
1220 SCTAB nTabRangeEnd
= nEndTab
;
1221 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1222 ScRange
aShiftedRange(nStartCol
, nStartRow
, nTabRangeStart
, nEndCol
, MAXROW
, nTabRangeEnd
);
1223 sc::EndListeningContext
aEndListenCxt(*this);
1225 std::vector
<ScAddress
> aGroupPos
;
1228 aShiftedRange
.aStart
.SetTab(nTabRangeStart
);
1229 aShiftedRange
.aEnd
.SetTab(nTabRangeEnd
);
1231 // Collect all formula groups that will get split by the shifting,
1232 // and end all their listening. Record the position of the top
1233 // cell of the topmost group, and the position of the bottom cell
1234 // of the bottommost group.
1235 EndListeningIntersectedGroups(aEndListenCxt
, aShiftedRange
, &aGroupPos
);
1237 UpdateBroadcastAreas(URM_INSDEL
, aShiftedRange
, 0, static_cast<SCsROW
>(nSize
), 0);
1239 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1241 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1243 sc::RefUpdateContext
aCxt(*this);
1244 aCxt
.meMode
= URM_INSDEL
;
1245 aCxt
.maRange
= aShiftedRange
;
1246 aCxt
.mnRowDelta
= nSize
;
1249 aCxt
.maRange
.aStart
.SetTab(nTabRangeStart
);
1250 aCxt
.maRange
.aEnd
.SetTab(nTabRangeEnd
);
1251 UpdateReference(aCxt
, pRefUndoDoc
, false); // without drawing objects
1253 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1255 // UpdateReference should have set "needs listening" flags to those
1256 // whose references have been modified. We also need to set this flag
1257 // to those that were in the groups that got split by shifting.
1258 SetNeedsListeningGroups(aGroupPos
);
1260 for (i
=nStartTab
; i
<=nEndTab
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1261 if (maTabs
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1262 maTabs
[i
]->InsertRow( nStartCol
, nEndCol
, nStartRow
, nSize
);
1264 // UpdateRef for drawing layer must be after inserting,
1265 // when the new row heights are known.
1266 for (i
=nStartTab
; i
<=nEndTab
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1267 if (maTabs
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1268 maTabs
[i
]->UpdateDrawRef( URM_INSDEL
,
1269 nStartCol
, nStartRow
, nStartTab
, nEndCol
, MAXROW
, nEndTab
,
1270 0, static_cast<SCsROW
>(nSize
), 0 );
1272 if ( pChangeTrack
&& pChangeTrack
->IsInDeleteUndo() )
1273 { // A new Listening is needed when references to deleted ranges are restored,
1274 // previous Listeners were removed in FormulaCell UpdateReference.
1275 StartAllListeners();
1278 { // Listeners have been removed in UpdateReference
1279 StartNeededListeners();
1281 // At least all cells using range names pointing relative to the
1282 // moved range must be recalculated, and all cells marked postponed
1284 TableContainer::iterator it
= maTabs
.begin();
1285 for (; it
!= maTabs
.end(); ++it
)
1287 (*it
)->SetDirtyIfPostponed();
1289 std::for_each(maTabs
.begin(), maTabs
.end(), BroadcastRecalcOnRefMoveHandler());
1293 SetAutoCalc( bOldAutoCalc
);
1295 pChartListenerCollection
->UpdateDirtyCharts();
1299 bool ScDocument::InsertRow( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
)
1301 return InsertRow( rRange
.aStart
.Col(), rRange
.aStart
.Tab(),
1302 rRange
.aEnd
.Col(), rRange
.aEnd
.Tab(),
1303 rRange
.aStart
.Row(), static_cast<SCSIZE
>(rRange
.aEnd
.Row()-rRange
.aStart
.Row()+1),
1307 void ScDocument::DeleteRow( SCCOL nStartCol
, SCTAB nStartTab
,
1308 SCCOL nEndCol
, SCTAB nEndTab
,
1309 SCROW nStartRow
, SCSIZE nSize
,
1310 ScDocument
* pRefUndoDoc
, bool* pUndoOutline
,
1311 const ScMarkData
* pTabMark
)
1315 PutInOrder( nStartCol
, nEndCol
);
1316 PutInOrder( nStartTab
, nEndTab
);
1320 nEndTab
= static_cast<SCTAB
>(maTabs
.size())-1;
1323 sc::AutoCalcSwitch
aACSwitch(*this, false); // avoid multiple calculations
1325 // handle chunks of consecutive selected sheets together
1326 SCTAB nTabRangeStart
= nStartTab
;
1327 SCTAB nTabRangeEnd
= nEndTab
;
1328 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1331 if ( ValidRow(nStartRow
+nSize
) )
1333 DelBroadcastAreasInRange( ScRange(
1334 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1335 ScAddress( nEndCol
, nStartRow
+nSize
-1, nTabRangeEnd
) ) );
1336 UpdateBroadcastAreas( URM_INSDEL
, ScRange(
1337 ScAddress( nStartCol
, nStartRow
+nSize
, nTabRangeStart
),
1338 ScAddress( nEndCol
, MAXROW
, nTabRangeEnd
)), 0, -(static_cast<SCsROW
>(nSize
)), 0 );
1341 DelBroadcastAreasInRange( ScRange(
1342 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1343 ScAddress( nEndCol
, MAXROW
, nTabRangeEnd
) ) );
1345 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1347 sc::RefUpdateContext
aCxt(*this);
1348 if ( ValidRow(nStartRow
+nSize
) )
1350 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1351 aCxt
.meMode
= URM_INSDEL
;
1352 aCxt
.maRange
= ScRange(nStartCol
, nStartRow
+nSize
, nTabRangeStart
, nEndCol
, MAXROW
, nTabRangeEnd
);
1353 aCxt
.mnRowDelta
= -(static_cast<SCROW
>(nSize
));
1356 UpdateReference(aCxt
, pRefUndoDoc
, true, false);
1358 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1362 *pUndoOutline
= false;
1364 // Keep track of the positions of all formula groups that have been joined
1365 // during row deletion.
1366 std::vector
<ScAddress
> aGroupPos
;
1368 for ( i
= nStartTab
; i
<= nEndTab
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1369 if (maTabs
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1370 maTabs
[i
]->DeleteRow(aCxt
.maRegroupCols
, nStartCol
, nEndCol
, nStartRow
, nSize
, pUndoOutline
, &aGroupPos
);
1372 // Newly joined groups have some of their members still listening. We
1373 // need to make sure none of them are listening.
1374 EndListeningGroups(aGroupPos
);
1376 // Mark all joined groups for group listening.
1377 SetNeedsListeningGroups(aGroupPos
);
1379 if ( ValidRow(nStartRow
+nSize
) )
1381 // Listeners have been removed in UpdateReference
1382 StartNeededListeners();
1384 // At least all cells using range names pointing relative to the moved
1385 // range must be recalculated, and all cells marked postponed dirty.
1386 TableContainer::iterator it
= maTabs
.begin();
1387 for (; it
!= maTabs
.end(); ++it
)
1389 (*it
)->SetDirtyIfPostponed();
1391 std::for_each(maTabs
.begin(), maTabs
.end(), BroadcastRecalcOnRefMoveHandler());
1394 pChartListenerCollection
->UpdateDirtyCharts();
1397 void ScDocument::DeleteRow( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
, bool* pUndoOutline
)
1399 DeleteRow( rRange
.aStart
.Col(), rRange
.aStart
.Tab(),
1400 rRange
.aEnd
.Col(), rRange
.aEnd
.Tab(),
1401 rRange
.aStart
.Row(), static_cast<SCSIZE
>(rRange
.aEnd
.Row()-rRange
.aStart
.Row()+1),
1402 pRefUndoDoc
, pUndoOutline
);
1405 bool ScDocument::CanInsertCol( const ScRange
& rRange
) const
1407 SCCOL nStartCol
= rRange
.aStart
.Col();
1408 SCROW nStartRow
= rRange
.aStart
.Row();
1409 SCTAB nStartTab
= rRange
.aStart
.Tab();
1410 SCCOL nEndCol
= rRange
.aEnd
.Col();
1411 SCROW nEndRow
= rRange
.aEnd
.Row();
1412 SCTAB nEndTab
= rRange
.aEnd
.Tab();
1413 PutInOrder( nStartCol
, nEndCol
);
1414 PutInOrder( nStartRow
, nEndRow
);
1415 PutInOrder( nStartTab
, nEndTab
);
1416 SCSIZE nSize
= static_cast<SCSIZE
>(nEndCol
- nStartCol
+ 1);
1419 for (SCTAB i
=nStartTab
; i
<=nEndTab
&& bTest
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1421 bTest
&= maTabs
[i
]->TestInsertCol( nStartRow
, nEndRow
, nSize
);
1426 bool ScDocument::InsertCol( SCROW nStartRow
, SCTAB nStartTab
,
1427 SCROW nEndRow
, SCTAB nEndTab
,
1428 SCCOL nStartCol
, SCSIZE nSize
, ScDocument
* pRefUndoDoc
,
1429 const ScMarkData
* pTabMark
)
1433 PutInOrder( nStartRow
, nEndRow
);
1434 PutInOrder( nStartTab
, nEndTab
);
1438 nEndTab
= static_cast<SCTAB
>(maTabs
.size())-1;
1443 bool bOldAutoCalc
= GetAutoCalc();
1444 SetAutoCalc( false ); // avoid multiple calculations
1445 for ( i
= nStartTab
; i
<= nEndTab
&& bTest
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1446 if (maTabs
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1447 bTest
&= maTabs
[i
]->TestInsertCol( nStartRow
, nEndRow
, nSize
);
1450 // handle chunks of consecutive selected sheets together
1451 SCTAB nTabRangeStart
= nStartTab
;
1452 SCTAB nTabRangeEnd
= nEndTab
;
1453 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1456 UpdateBroadcastAreas( URM_INSDEL
, ScRange(
1457 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1458 ScAddress( MAXCOL
, nEndRow
, nTabRangeEnd
)), static_cast<SCsCOL
>(nSize
), 0, 0 );
1460 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1462 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1464 sc::RefUpdateContext
aCxt(*this);
1465 aCxt
.meMode
= URM_INSDEL
;
1466 aCxt
.maRange
= ScRange(nStartCol
, nStartRow
, nTabRangeStart
, MAXCOL
, nEndRow
, nTabRangeEnd
);
1467 aCxt
.mnColDelta
= nSize
;
1470 UpdateReference(aCxt
, pRefUndoDoc
, true, false);
1472 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1474 for (i
=nStartTab
; i
<=nEndTab
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1475 if (maTabs
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1476 maTabs
[i
]->InsertCol(aCxt
.maRegroupCols
, nStartCol
, nStartRow
, nEndRow
, nSize
);
1478 if ( pChangeTrack
&& pChangeTrack
->IsInDeleteUndo() )
1479 { // A new Listening is needed when references to deleted ranges are restored,
1480 // previous Listeners were removed in FormulaCell UpdateReference.
1481 StartAllListeners();
1485 // Listeners have been removed in UpdateReference
1486 StartNeededListeners();
1487 // At least all cells using range names pointing relative to the
1488 // moved range must be recalculated, and all cells marked postponed
1490 std::for_each(maTabs
.begin(), maTabs
.end(), SetDirtyIfPostponedHandler());
1491 // Cells containing functions such as CELL, COLUMN or ROW may have
1492 // changed their values on relocation. Broadcast them.
1493 std::for_each(maTabs
.begin(), maTabs
.end(), BroadcastRecalcOnRefMoveHandler());
1497 SetAutoCalc( bOldAutoCalc
);
1499 pChartListenerCollection
->UpdateDirtyCharts();
1503 bool ScDocument::InsertCol( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
)
1505 return InsertCol( rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
1506 rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(),
1507 rRange
.aStart
.Col(), static_cast<SCSIZE
>(rRange
.aEnd
.Col()-rRange
.aStart
.Col()+1),
1511 void ScDocument::DeleteCol(SCROW nStartRow
, SCTAB nStartTab
, SCROW nEndRow
, SCTAB nEndTab
,
1512 SCCOL nStartCol
, SCSIZE nSize
, ScDocument
* pRefUndoDoc
,
1513 bool* pUndoOutline
, const ScMarkData
* pTabMark
)
1517 PutInOrder( nStartRow
, nEndRow
);
1518 PutInOrder( nStartTab
, nEndTab
);
1522 nEndTab
= static_cast<SCTAB
>(maTabs
.size())-1;
1525 sc::AutoCalcSwitch
aACSwitch(*this, false); // avoid multiple calculations
1527 // handle chunks of consecutive selected sheets together
1528 SCTAB nTabRangeStart
= nStartTab
;
1529 SCTAB nTabRangeEnd
= nEndTab
;
1530 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1533 if ( ValidCol(sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
)) )
1535 DelBroadcastAreasInRange( ScRange(
1536 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1537 ScAddress( sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
-1), nEndRow
, nTabRangeEnd
) ) );
1538 UpdateBroadcastAreas( URM_INSDEL
, ScRange(
1539 ScAddress( sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
), nStartRow
, nTabRangeStart
),
1540 ScAddress( MAXCOL
, nEndRow
, nTabRangeEnd
)), -static_cast<SCsCOL
>(nSize
), 0, 0 );
1543 DelBroadcastAreasInRange( ScRange(
1544 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1545 ScAddress( MAXCOL
, nEndRow
, nTabRangeEnd
) ) );
1547 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1549 sc::RefUpdateContext
aCxt(*this);
1550 if ( ValidCol(sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
)) )
1552 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) );
1553 aCxt
.meMode
= URM_INSDEL
;
1554 aCxt
.maRange
= ScRange(sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
), nStartRow
, nTabRangeStart
, MAXCOL
, nEndRow
, nTabRangeEnd
);
1555 aCxt
.mnColDelta
= -(static_cast<SCCOL
>(nSize
));
1558 UpdateReference(aCxt
, pRefUndoDoc
, true, false);
1560 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
, static_cast<SCTAB
>(maTabs
.size()) ) );
1564 *pUndoOutline
= false;
1566 for (i
= nStartTab
; i
<= nEndTab
&& i
< static_cast<SCTAB
>(maTabs
.size()); ++i
)
1568 if (maTabs
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1569 maTabs
[i
]->DeleteCol(aCxt
.maRegroupCols
, nStartCol
, nStartRow
, nEndRow
, nSize
, pUndoOutline
);
1572 if ( ValidCol(sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
)) )
1574 // Listeners have been removed in UpdateReference
1575 StartNeededListeners();
1577 // At least all cells using range names pointing relative to the moved
1578 // range must be recalculated, and all cells marked postponed dirty.
1579 TableContainer::iterator it
= maTabs
.begin();
1580 for (; it
!= maTabs
.end(); ++it
)
1582 (*it
)->SetDirtyIfPostponed();
1584 std::for_each(maTabs
.begin(), maTabs
.end(), BroadcastRecalcOnRefMoveHandler());
1587 pChartListenerCollection
->UpdateDirtyCharts();
1590 void ScDocument::DeleteCol( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
, bool* pUndoOutline
)
1592 DeleteCol( rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
1593 rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(),
1594 rRange
.aStart
.Col(), static_cast<SCSIZE
>(rRange
.aEnd
.Col()-rRange
.aStart
.Col()+1),
1595 pRefUndoDoc
, pUndoOutline
);
1598 // for Area-Links: Insert/delete cells, when the range is changed.
1601 static void lcl_GetInsDelRanges( const ScRange
& rOld
, const ScRange
& rNew
,
1602 ScRange
& rColRange
, bool& rInsCol
, bool& rDelCol
,
1603 ScRange
& rRowRange
, bool& rInsRow
, bool& rDelRow
)
1605 OSL_ENSURE( rOld
.aStart
== rNew
.aStart
, "FitBlock: Beginning is different" );
1607 rInsCol
= rDelCol
= rInsRow
= rDelRow
= false;
1609 SCCOL nStartX
= rOld
.aStart
.Col();
1610 SCROW nStartY
= rOld
.aStart
.Row();
1611 SCCOL nOldEndX
= rOld
.aEnd
.Col();
1612 SCROW nOldEndY
= rOld
.aEnd
.Row();
1613 SCCOL nNewEndX
= rNew
.aEnd
.Col();
1614 SCROW nNewEndY
= rNew
.aEnd
.Row();
1615 SCTAB nTab
= rOld
.aStart
.Tab();
1617 // if more rows, columns are inserted/deleted at the old height.
1618 bool bGrowY
= ( nNewEndY
> nOldEndY
);
1619 SCROW nColEndY
= bGrowY
? nOldEndY
: nNewEndY
;
1620 SCCOL nRowEndX
= bGrowY
? nNewEndX
: nOldEndX
;
1624 if ( nNewEndX
> nOldEndX
) // Insert columns
1626 rColRange
= ScRange( nOldEndX
+1, nStartY
, nTab
, nNewEndX
, nColEndY
, nTab
);
1629 else if ( nNewEndX
< nOldEndX
) // Delete columns
1631 rColRange
= ScRange( nNewEndX
+1, nStartY
, nTab
, nOldEndX
, nColEndY
, nTab
);
1637 if ( nNewEndY
> nOldEndY
) // Insert rows
1639 rRowRange
= ScRange( nStartX
, nOldEndY
+1, nTab
, nRowEndX
, nNewEndY
, nTab
);
1642 else if ( nNewEndY
< nOldEndY
) // Delete rows
1644 rRowRange
= ScRange( nStartX
, nNewEndY
+1, nTab
, nRowEndX
, nOldEndY
, nTab
);
1649 bool ScDocument::HasPartOfMerged( const ScRange
& rRange
)
1652 SCTAB nTab
= rRange
.aStart
.Tab();
1654 SCCOL nStartX
= rRange
.aStart
.Col();
1655 SCROW nStartY
= rRange
.aStart
.Row();
1656 SCCOL nEndX
= rRange
.aEnd
.Col();
1657 SCROW nEndY
= rRange
.aEnd
.Row();
1659 if (HasAttrib( nStartX
, nStartY
, nTab
, nEndX
, nEndY
, nTab
,
1660 HASATTR_MERGED
| HASATTR_OVERLAPPED
))
1662 ExtendMerge( nStartX
, nStartY
, nEndX
, nEndY
, nTab
);
1663 ExtendOverlapped( nStartX
, nStartY
, nEndX
, nEndY
, nTab
);
1665 bPart
= ( nStartX
!= rRange
.aStart
.Col() || nEndX
!= rRange
.aEnd
.Col() ||
1666 nStartY
!= rRange
.aStart
.Row() || nEndY
!= rRange
.aEnd
.Row() );
1671 size_t ScDocument::GetFormulaHash( const ScAddress
& rPos
) const
1673 SCTAB nTab
= rPos
.Tab();
1674 if (!ValidTab(nTab
) || static_cast<size_t>(nTab
) >= maTabs
.size() || !maTabs
[nTab
])
1677 return maTabs
[nTab
]->GetFormulaHash(rPos
.Col(), rPos
.Row());
1680 ScFormulaVectorState
ScDocument::GetFormulaVectorState( const ScAddress
& rPos
) const
1682 SCTAB nTab
= rPos
.Tab();
1683 if (!ValidTab(nTab
) || static_cast<size_t>(nTab
) >= maTabs
.size() || !maTabs
[nTab
])
1684 return FormulaVectorUnknown
;
1686 return maTabs
[nTab
]->GetFormulaVectorState(rPos
.Col(), rPos
.Row());
1689 formula::FormulaTokenRef
ScDocument::ResolveStaticReference( const ScAddress
& rPos
)
1691 SCTAB nTab
= rPos
.Tab();
1692 if (!TableExists(nTab
))
1693 return formula::FormulaTokenRef();
1695 return maTabs
[nTab
]->ResolveStaticReference(rPos
.Col(), rPos
.Row());
1698 formula::FormulaTokenRef
ScDocument::ResolveStaticReference( const ScRange
& rRange
)
1700 SCTAB nTab
= rRange
.aStart
.Tab();
1701 if (nTab
!= rRange
.aEnd
.Tab() || !TableExists(nTab
))
1702 return formula::FormulaTokenRef();
1704 return maTabs
[nTab
]->ResolveStaticReference(
1705 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row());
1708 formula::VectorRefArray
ScDocument::FetchVectorRefArray( const ScAddress
& rPos
, SCROW nLength
)
1710 SCTAB nTab
= rPos
.Tab();
1711 if (!TableExists(nTab
))
1712 return formula::VectorRefArray();
1714 return maTabs
[nTab
]->FetchVectorRefArray(rPos
.Col(), rPos
.Row(), rPos
.Row()+nLength
-1);
1717 bool ScDocument::CanFitBlock( const ScRange
& rOld
, const ScRange
& rNew
)
1723 bool bInsCol
,bDelCol
,bInsRow
,bDelRow
;
1724 ScRange aColRange
,aRowRange
;
1725 lcl_GetInsDelRanges( rOld
, rNew
, aColRange
,bInsCol
,bDelCol
, aRowRange
,bInsRow
,bDelRow
);
1727 if ( bInsCol
&& !CanInsertCol( aColRange
) ) // Cells at the edge ?
1729 if ( bInsRow
&& !CanInsertRow( aRowRange
) ) // Cells at the edge ?
1732 if ( bInsCol
|| bDelCol
)
1734 aColRange
.aEnd
.SetCol(MAXCOL
);
1735 if ( HasPartOfMerged(aColRange
) )
1738 if ( bInsRow
|| bDelRow
)
1740 aRowRange
.aEnd
.SetRow(MAXROW
);
1741 if ( HasPartOfMerged(aRowRange
) )
1748 void ScDocument::FitBlock( const ScRange
& rOld
, const ScRange
& rNew
, bool bClear
)
1751 DeleteAreaTab( rOld
, IDF_ALL
);
1753 bool bInsCol
,bDelCol
,bInsRow
,bDelRow
;
1754 ScRange aColRange
,aRowRange
;
1755 lcl_GetInsDelRanges( rOld
, rNew
, aColRange
,bInsCol
,bDelCol
, aRowRange
,bInsRow
,bDelRow
);
1758 InsertCol( aColRange
); // First insert columns
1760 InsertRow( aRowRange
);
1763 DeleteRow( aRowRange
); // First delete rows
1765 DeleteCol( aColRange
);
1767 // Expand references to inserted rows
1769 if ( bInsCol
|| bInsRow
)
1771 ScRange aGrowSource
= rOld
;
1772 aGrowSource
.aEnd
.SetCol(std::min( rOld
.aEnd
.Col(), rNew
.aEnd
.Col() ));
1773 aGrowSource
.aEnd
.SetRow(std::min( rOld
.aEnd
.Row(), rNew
.aEnd
.Row() ));
1774 SCCOL nGrowX
= bInsCol
? ( rNew
.aEnd
.Col() - rOld
.aEnd
.Col() ) : 0;
1775 SCROW nGrowY
= bInsRow
? ( rNew
.aEnd
.Row() - rOld
.aEnd
.Row() ) : 0;
1776 UpdateGrow( aGrowSource
, nGrowX
, nGrowY
);
1780 void ScDocument::DeleteArea(
1781 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, const ScMarkData
& rMark
,
1782 InsertDeleteFlags nDelFlag
, bool bBroadcast
, sc::ColumnSpanSet
* pBroadcastSpans
)
1784 sc::AutoCalcSwitch
aACSwitch(*this, false);
1786 PutInOrder( nCol1
, nCol2
);
1787 PutInOrder( nRow1
, nRow2
);
1789 std::vector
<ScAddress
> aGroupPos
;
1790 // Destroy and reconstruct listeners only if content is affected.
1791 bool bDelContent
= ((nDelFlag
& ~IDF_CONTENTS
) != nDelFlag
);
1794 // Record the positions of top and/or bottom formula groups that intersect
1795 // the area borders.
1796 sc::EndListeningContext
aCxt(*this);
1797 ScRange
aRange(nCol1
, nRow1
, 0, nCol2
, nRow2
, 0);
1798 for (SCTAB i
= 0; i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1800 if (rMark
.GetTableSelect(i
))
1802 aRange
.aStart
.SetTab(i
);
1803 aRange
.aEnd
.SetTab(i
);
1805 EndListeningIntersectedGroups(aCxt
, aRange
, &aGroupPos
);
1808 aCxt
.purgeEmptyBroadcasters();
1811 for (SCTAB i
= 0; i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
1813 if ( rMark
.GetTableSelect(i
) || bIsUndo
)
1814 maTabs
[i
]->DeleteArea(nCol1
, nRow1
, nCol2
, nRow2
, nDelFlag
, bBroadcast
, pBroadcastSpans
);
1818 // Re-start listeners on those top bottom groups that have been split.
1819 SetNeedsListeningGroups(aGroupPos
);
1820 StartNeededListeners();
1824 void ScDocument::DeleteAreaTab(SCCOL nCol1
, SCROW nRow1
,
1825 SCCOL nCol2
, SCROW nRow2
,
1826 SCTAB nTab
, InsertDeleteFlags nDelFlag
)
1828 PutInOrder( nCol1
, nCol2
);
1829 PutInOrder( nRow1
, nRow2
);
1830 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
1832 bool bOldAutoCalc
= GetAutoCalc();
1833 SetAutoCalc( false ); // avoid multiple calculations
1834 maTabs
[nTab
]->DeleteArea(nCol1
, nRow1
, nCol2
, nRow2
, nDelFlag
);
1835 SetAutoCalc( bOldAutoCalc
);
1839 void ScDocument::DeleteAreaTab( const ScRange
& rRange
, InsertDeleteFlags nDelFlag
)
1841 for ( SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); nTab
++ )
1842 DeleteAreaTab( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
1843 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(),
1847 void ScDocument::InitUndoSelected( ScDocument
* pSrcDoc
, const ScMarkData
& rTabSelection
,
1848 bool bColInfo
, bool bRowInfo
)
1854 SharePooledResources(pSrcDoc
);
1857 for (SCTAB nTab
= 0; nTab
<= rTabSelection
.GetLastSelected(); nTab
++)
1858 if ( rTabSelection
.GetTableSelect( nTab
) )
1860 ScTable
* pTable
= new ScTable(this, nTab
, aString
, bColInfo
, bRowInfo
);
1861 if (nTab
< static_cast<SCTAB
>(maTabs
.size()))
1862 maTabs
[nTab
] = pTable
;
1864 maTabs
.push_back(pTable
);
1868 if (nTab
< static_cast<SCTAB
>(maTabs
.size()))
1871 maTabs
.push_back(NULL
);
1876 OSL_FAIL("InitUndo");
1880 void ScDocument::InitUndo( ScDocument
* pSrcDoc
, SCTAB nTab1
, SCTAB nTab2
,
1881 bool bColInfo
, bool bRowInfo
)
1885 OSL_FAIL("InitUndo");
1891 // Undo document shares its pooled resources with the source document.
1892 SharePooledResources(pSrcDoc
);
1894 if (pSrcDoc
->pShell
->GetMedium())
1895 maFileURL
= pSrcDoc
->pShell
->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI
);
1898 if ( nTab2
>= static_cast<SCTAB
>(maTabs
.size()))
1899 maTabs
.resize(nTab2
+ 1, NULL
);
1900 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; nTab
++)
1902 ScTable
* pTable
= new ScTable(this, nTab
, aString
, bColInfo
, bRowInfo
);
1903 maTabs
[nTab
] = pTable
;
1907 void ScDocument::AddUndoTab( SCTAB nTab1
, SCTAB nTab2
, bool bColInfo
, bool bRowInfo
)
1911 OSL_FAIL("AddUndoTab");
1916 if (nTab2
>= static_cast<SCTAB
>(maTabs
.size()))
1918 maTabs
.resize(nTab2
+1,NULL
);
1921 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; nTab
++)
1924 maTabs
[nTab
] = new ScTable(this, nTab
, aString
, bColInfo
, bRowInfo
);
1928 void ScDocument::SetCutMode( bool bVal
)
1931 GetClipParam().mbCutMode
= bVal
;
1934 OSL_FAIL("SetCutMode without bIsClip");
1938 bool ScDocument::IsCutMode()
1941 return GetClipParam().mbCutMode
;
1944 OSL_FAIL("IsCutMode without bIsClip");
1949 void ScDocument::CopyToDocument(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1950 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
1951 InsertDeleteFlags nFlags
, bool bOnlyMarked
, ScDocument
* pDestDoc
,
1952 const ScMarkData
* pMarks
, bool bColRowFlags
)
1954 PutInOrder( nCol1
, nCol2
);
1955 PutInOrder( nRow1
, nRow2
);
1956 PutInOrder( nTab1
, nTab2
);
1957 if( pDestDoc
->aDocName
.isEmpty() )
1958 pDestDoc
->aDocName
= aDocName
;
1959 if (ValidTab(nTab1
) && ValidTab(nTab2
))
1961 sc::CopyToDocContext
aCxt(*pDestDoc
);
1962 bool bOldAutoCalc
= pDestDoc
->GetAutoCalc();
1963 pDestDoc
->SetAutoCalc( false ); // avoid multiple calculations
1964 SCTAB nMinSizeBothTabs
= static_cast<SCTAB
>(std::min(maTabs
.size(), pDestDoc
->maTabs
.size()));
1965 for (SCTAB i
= nTab1
; i
<= nTab2
&& i
< nMinSizeBothTabs
; i
++)
1967 if (maTabs
[i
] && pDestDoc
->maTabs
[i
])
1968 maTabs
[i
]->CopyToTable(aCxt
, nCol1
, nRow1
, nCol2
, nRow2
, nFlags
,
1969 bOnlyMarked
, pDestDoc
->maTabs
[i
], pMarks
,
1970 false, bColRowFlags
);
1972 pDestDoc
->SetAutoCalc( bOldAutoCalc
);
1976 void ScDocument::UndoToDocument(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1977 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
1978 InsertDeleteFlags nFlags
, bool bOnlyMarked
, ScDocument
* pDestDoc
,
1979 const ScMarkData
* pMarks
)
1981 PutInOrder( nCol1
, nCol2
);
1982 PutInOrder( nRow1
, nRow2
);
1983 PutInOrder( nTab1
, nTab2
);
1984 if (ValidTab(nTab1
) && ValidTab(nTab2
))
1986 sc::AutoCalcSwitch
aACSwitch(*pDestDoc
, false); // avoid multiple calculations
1989 CopyToDocument( 0,0,0, MAXCOL
,MAXROW
,nTab1
-1, IDF_FORMULA
, false, pDestDoc
, pMarks
);
1991 sc::CopyToDocContext
aCxt(*pDestDoc
);
1992 OSL_ASSERT( nTab2
< static_cast<SCTAB
>(maTabs
.size()) && nTab2
< static_cast<SCTAB
>(pDestDoc
->maTabs
.size()));
1993 for (SCTAB i
= nTab1
; i
<= nTab2
; i
++)
1995 if (maTabs
[i
] && pDestDoc
->maTabs
[i
])
1996 maTabs
[i
]->UndoToTable(aCxt
, nCol1
, nRow1
, nCol2
, nRow2
, nFlags
,
1997 bOnlyMarked
, pDestDoc
->maTabs
[i
], pMarks
);
2001 CopyToDocument( 0,0,nTab2
+1, MAXCOL
,MAXROW
,MAXTAB
, IDF_FORMULA
, false, pDestDoc
, pMarks
);
2005 void ScDocument::CopyToDocument(const ScRange
& rRange
,
2006 InsertDeleteFlags nFlags
, bool bOnlyMarked
, ScDocument
* pDestDoc
,
2007 const ScMarkData
* pMarks
, bool bColRowFlags
)
2009 ScRange aNewRange
= rRange
;
2010 aNewRange
.Justify();
2012 if( pDestDoc
->aDocName
.isEmpty() )
2013 pDestDoc
->aDocName
= aDocName
;
2015 sc::AutoCalcSwitch
aACSwitch(*pDestDoc
, false); // avoid multiple calculations
2017 sc::CopyToDocContext
aCxt(*pDestDoc
);
2018 aCxt
.setStartListening(false);
2020 SCTAB nMinSizeBothTabs
= static_cast<SCTAB
>(std::min(maTabs
.size(), pDestDoc
->maTabs
.size()));
2021 for (SCTAB i
= aNewRange
.aStart
.Tab(); i
<= aNewRange
.aEnd
.Tab() && i
< nMinSizeBothTabs
; i
++)
2023 ScTable
* pTab
= FetchTable(i
);
2024 ScTable
* pDestTab
= pDestDoc
->FetchTable(i
);
2025 if (!pTab
|| !pDestTab
)
2029 aCxt
, aNewRange
.aStart
.Col(), aNewRange
.aStart
.Row(), aNewRange
.aEnd
.Col(), aNewRange
.aEnd
.Row(),
2030 nFlags
, bOnlyMarked
, pDestTab
, pMarks
, false, bColRowFlags
);
2033 pDestDoc
->StartAllListeners(aNewRange
);
2036 void ScDocument::UndoToDocument(const ScRange
& rRange
,
2037 InsertDeleteFlags nFlags
, bool bOnlyMarked
, ScDocument
* pDestDoc
,
2038 const ScMarkData
* pMarks
)
2040 sc::AutoCalcSwitch
aAutoCalcSwitch(*this, false);
2042 ScRange aNewRange
= rRange
;
2043 aNewRange
.Justify();
2044 SCTAB nTab1
= aNewRange
.aStart
.Tab();
2045 SCTAB nTab2
= aNewRange
.aEnd
.Tab();
2047 sc::CopyToDocContext
aCxt(*pDestDoc
);
2049 CopyToDocument( 0,0,0, MAXCOL
,MAXROW
,nTab1
-1, IDF_FORMULA
, false, pDestDoc
, pMarks
);
2051 SCTAB nMinSizeBothTabs
= static_cast<SCTAB
>(std::min(maTabs
.size(), pDestDoc
->maTabs
.size()));
2052 for (SCTAB i
= nTab1
; i
<= nTab2
&& i
< nMinSizeBothTabs
; i
++)
2054 if (maTabs
[i
] && pDestDoc
->maTabs
[i
])
2055 maTabs
[i
]->UndoToTable(aCxt
, aNewRange
.aStart
.Col(), aNewRange
.aStart
.Row(),
2056 aNewRange
.aEnd
.Col(), aNewRange
.aEnd
.Row(),
2057 nFlags
, bOnlyMarked
, pDestDoc
->maTabs
[i
], pMarks
);
2060 if (nTab2
< static_cast<SCTAB
>(maTabs
.size()))
2061 CopyToDocument( 0,0,nTab2
+1, MAXCOL
,MAXROW
,maTabs
.size(), IDF_FORMULA
, false, pDestDoc
, pMarks
);
2064 // bUseRangeForVBA added for VBA api support to allow content of a specified
2065 // range to be copied ( e.g. don't use marked data but the just the range
2066 // specified by rClipParam
2067 void ScDocument::CopyToClip(const ScClipParam
& rClipParam
,
2068 ScDocument
* pClipDoc
, const ScMarkData
* pMarks
,
2069 bool bAllTabs
, bool bKeepScenarioFlags
, bool bIncludeObjects
, bool bCloneNoteCaptions
, bool bUseRangeForVBA
)
2071 OSL_ENSURE( !bUseRangeForVBA
&& ( bAllTabs
|| pMarks
), "CopyToClip: ScMarkData fails" );
2078 OSL_TRACE("CopyToClip: no ClipDoc");
2079 pClipDoc
= ScModule::GetClipDoc();
2082 if (pShell
->GetMedium())
2084 pClipDoc
->maFileURL
= pShell
->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI
);
2085 // for unsaved files use the title name and adjust during save of file
2086 if (pClipDoc
->maFileURL
.isEmpty())
2087 pClipDoc
->maFileURL
= pShell
->GetName();
2091 pClipDoc
->maFileURL
= pShell
->GetName();
2095 for (TableContainer::iterator itr
= maTabs
.begin(); itr
!= maTabs
.end(); ++itr
)
2100 (*itr
)->GetName(aTabName
);
2101 pClipDoc
->maTabNames
.push_back(aTabName
);
2104 pClipDoc
->maTabNames
.push_back(OUString());
2107 pClipDoc
->aDocName
= aDocName
;
2108 pClipDoc
->SetClipParam(rClipParam
);
2109 ScRange aClipRange
= rClipParam
.getWholeRange();
2110 SCTAB nTab
= aClipRange
.aStart
.Tab();
2112 SCTAB nEndTab
= static_cast<SCTAB
>(maTabs
.size());
2114 if ( bUseRangeForVBA
)
2116 pClipDoc
->ResetClip( this, nTab
);
2121 pClipDoc
->ResetClip(this, pMarks
);
2123 sc::CopyToClipContext
aCxt(*pClipDoc
, bKeepScenarioFlags
, bCloneNoteCaptions
);
2124 CopyRangeNamesToClip(pClipDoc
, aClipRange
, pMarks
, bAllTabs
);
2126 for ( ; i
< nEndTab
; ++i
)
2128 if (!maTabs
[i
] || i
>= static_cast<SCTAB
>(pClipDoc
->maTabs
.size()) || !pClipDoc
->maTabs
[i
])
2131 if ( !bUseRangeForVBA
&& ( pMarks
&& !pMarks
->GetTableSelect(i
) ) )
2134 maTabs
[i
]->CopyToClip(aCxt
, rClipParam
.maRanges
, pClipDoc
->maTabs
[i
]);
2136 if (pDrawLayer
&& bIncludeObjects
)
2138 // also copy drawing objects
2139 Rectangle aObjRect
= GetMMRect(
2140 aClipRange
.aStart
.Col(), aClipRange
.aStart
.Row(), aClipRange
.aEnd
.Col(), aClipRange
.aEnd
.Row(), i
);
2141 pDrawLayer
->CopyToClip(pClipDoc
, i
, aObjRect
);
2145 // Make sure to mark overlapped cells.
2146 pClipDoc
->ExtendMerge(aClipRange
, true);
2149 void ScDocument::CopyStaticToDocument(const ScRange
& rSrcRange
, SCTAB nDestTab
, ScDocument
* pDestDoc
)
2154 ScTable
* pSrcTab
= rSrcRange
.aStart
.Tab() < static_cast<SCTAB
>(maTabs
.size()) ? maTabs
[rSrcRange
.aStart
.Tab()] : NULL
;
2155 ScTable
* pDestTab
= nDestTab
< static_cast<SCTAB
>(pDestDoc
->maTabs
.size()) ? pDestDoc
->maTabs
[nDestTab
] : NULL
;
2157 if (!pSrcTab
|| !pDestTab
)
2160 pDestDoc
->GetFormatTable()->MergeFormatter(*GetFormatTable());
2161 SvNumberFormatterMergeMap aMap
= pDestDoc
->GetFormatTable()->ConvertMergeTableToMap();
2163 pSrcTab
->CopyStaticToDocument(
2164 rSrcRange
.aStart
.Col(), rSrcRange
.aStart
.Row(), rSrcRange
.aEnd
.Col(), rSrcRange
.aEnd
.Row(),
2168 void ScDocument::CopyCellToDocument( const ScAddress
& rSrcPos
, const ScAddress
& rDestPos
, ScDocument
& rDestDoc
)
2170 if (!TableExists(rSrcPos
.Tab()) || !rDestDoc
.TableExists(rDestPos
.Tab()))
2173 ScTable
& rSrcTab
= *maTabs
[rSrcPos
.Tab()];
2174 ScTable
& rDestTab
= *rDestDoc
.maTabs
[rDestPos
.Tab()];
2176 rSrcTab
.CopyCellToDocument(rSrcPos
.Col(), rSrcPos
.Row(), rDestPos
.Col(), rDestPos
.Row(), rDestTab
);
2179 void ScDocument::CopyTabToClip(SCCOL nCol1
, SCROW nRow1
,
2180 SCCOL nCol2
, SCROW nRow2
,
2181 SCTAB nTab
, ScDocument
* pClipDoc
)
2187 OSL_TRACE("CopyTabToClip: no ClipDoc");
2188 pClipDoc
= ScModule::GetClipDoc();
2191 if (pShell
->GetMedium())
2193 pClipDoc
->maFileURL
= pShell
->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI
);
2194 // for unsaved files use the title name and adjust during save of file
2195 if (pClipDoc
->maFileURL
.isEmpty())
2196 pClipDoc
->maFileURL
= pShell
->GetName();
2200 pClipDoc
->maFileURL
= pShell
->GetName();
2204 for (TableContainer::iterator itr
= maTabs
.begin(); itr
!= maTabs
.end(); ++itr
)
2209 (*itr
)->GetName(aTabName
);
2210 pClipDoc
->maTabNames
.push_back(aTabName
);
2213 pClipDoc
->maTabNames
.push_back(OUString());
2216 PutInOrder( nCol1
, nCol2
);
2217 PutInOrder( nRow1
, nRow2
);
2219 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
2220 pClipDoc
->aDocName
= aDocName
;
2221 rClipParam
.maRanges
.RemoveAll();
2222 rClipParam
.maRanges
.Append(ScRange(nCol1
, nRow1
, 0, nCol2
, nRow2
, 0));
2223 pClipDoc
->ResetClip( this, nTab
);
2225 sc::CopyToClipContext
aCxt(*pClipDoc
, false, true);
2226 if (nTab
< static_cast<SCTAB
>(maTabs
.size()) && nTab
< static_cast<SCTAB
>(pClipDoc
->maTabs
.size()))
2227 if (maTabs
[nTab
] && pClipDoc
->maTabs
[nTab
])
2228 maTabs
[nTab
]->CopyToClip(aCxt
, nCol1
, nRow1
, nCol2
, nRow2
, pClipDoc
->maTabs
[nTab
]);
2230 pClipDoc
->GetClipParam().mbCutMode
= false;
2234 void ScDocument::TransposeClip( ScDocument
* pTransClip
, InsertDeleteFlags nFlags
, bool bAsLink
)
2236 OSL_ENSURE( bIsClip
&& pTransClip
&& pTransClip
->bIsClip
,
2237 "TransposeClip with wrong Document" );
2240 // -> pTransClip has to be delted before the original document!
2242 pTransClip
->ResetClip(this, (ScMarkData
*)NULL
); // all
2248 pTransClip
->GetRangeName()->clear();
2249 ScRangeName::const_iterator itr
= pRangeName
->begin(), itrEnd
= pRangeName
->end();
2250 for (; itr
!= itrEnd
; ++itr
)
2252 sal_uInt16 nIndex
= itr
->second
->GetIndex();
2253 ScRangeData
* pData
= new ScRangeData(*itr
->second
);
2254 if (pTransClip
->pRangeName
->insert(pData
))
2255 pData
->SetIndex(nIndex
);
2261 ScRange aClipRange
= GetClipParam().getWholeRange();
2262 if ( ValidRow(aClipRange
.aEnd
.Row()-aClipRange
.aStart
.Row()) )
2264 for (SCTAB i
=0; i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
2267 OSL_ENSURE( pTransClip
->maTabs
[i
], "TransposeClip: Table not there" );
2268 maTabs
[i
]->TransposeClip( aClipRange
.aStart
.Col(), aClipRange
.aStart
.Row(),
2269 aClipRange
.aEnd
.Col(), aClipRange
.aEnd
.Row(),
2270 pTransClip
->maTabs
[i
], nFlags
, bAsLink
);
2272 if ( pDrawLayer
&& ( nFlags
& IDF_OBJECTS
) )
2274 // Drawing objects are copied to the new area without transposing.
2275 // CopyFromClip is used to adjust the objects to the transposed block's
2277 // (pDrawLayer in the original clipboard document is set only if there
2278 // are drawing objects to copy)
2280 pTransClip
->InitDrawLayer();
2281 Rectangle aSourceRect
= GetMMRect( aClipRange
.aStart
.Col(), aClipRange
.aStart
.Row(),
2282 aClipRange
.aEnd
.Col(), aClipRange
.aEnd
.Row(), i
);
2283 Rectangle aDestRect
= pTransClip
->GetMMRect( 0, 0,
2284 static_cast<SCCOL
>(aClipRange
.aEnd
.Row() - aClipRange
.aStart
.Row()),
2285 static_cast<SCROW
>(aClipRange
.aEnd
.Col() - aClipRange
.aStart
.Col()), i
);
2286 pTransClip
->pDrawLayer
->CopyFromClip( pDrawLayer
, i
, aSourceRect
, ScAddress(0,0,i
), aDestRect
);
2290 pTransClip
->SetClipParam(GetClipParam());
2291 pTransClip
->GetClipParam().transpose();
2295 OSL_TRACE("TransposeClip: Too big");
2298 // This happens only when inserting...
2300 GetClipParam().mbCutMode
= false;
2305 void copyUsedNamesToClip(ScRangeName
* pClipRangeName
, ScRangeName
* pRangeName
, const std::set
<sal_uInt16
>& rUsedNames
)
2307 pClipRangeName
->clear();
2308 ScRangeName::const_iterator itr
= pRangeName
->begin(), itrEnd
= pRangeName
->end();
2309 for (; itr
!= itrEnd
; ++itr
) //TODO: also DB and Pivot regions!!!
2311 sal_uInt16 nIndex
= itr
->second
->GetIndex();
2312 bool bInUse
= (rUsedNames
.count(nIndex
) > 0);
2316 ScRangeData
* pData
= new ScRangeData(*itr
->second
);
2317 if (pClipRangeName
->insert(pData
))
2318 pData
->SetIndex(nIndex
);
2324 void ScDocument::CopyRangeNamesToClip(ScDocument
* pClipDoc
, const ScRange
& rClipRange
, const ScMarkData
* pMarks
, bool bAllTabs
)
2326 if (!pRangeName
|| pRangeName
->empty())
2329 std::set
<sal_uInt16
> aUsedNames
; // indexes of named ranges that are used in the copied cells
2330 SCTAB nMinSizeBothTabs
= static_cast<SCTAB
>(std::min(maTabs
.size(), pClipDoc
->maTabs
.size()));
2331 for (SCTAB i
= 0; i
< nMinSizeBothTabs
; ++i
)
2332 if (maTabs
[i
] && pClipDoc
->maTabs
[i
])
2333 if ( bAllTabs
|| !pMarks
|| pMarks
->GetTableSelect(i
) )
2334 maTabs
[i
]->FindRangeNamesInUse(
2335 rClipRange
.aStart
.Col(), rClipRange
.aStart
.Row(),
2336 rClipRange
.aEnd
.Col(), rClipRange
.aEnd
.Row(), aUsedNames
);
2338 copyUsedNamesToClip(pClipDoc
->GetRangeName(), pRangeName
, aUsedNames
);
2341 ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument
* pDoc
, ScDocument
* pSrcDoc
) :
2344 mpDoc
->MergeNumberFormatter(pSrcDoc
);
2347 ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
2349 mpDoc
->pFormatExchangeList
= NULL
;
2352 void ScDocument::ClearFormulaContext()
2354 mpFormulaGroupCxt
.reset();
2357 SvtBroadcaster
* ScDocument::GetBroadcaster( const ScAddress
& rPos
)
2359 ScTable
* pTab
= FetchTable(rPos
.Tab());
2363 return pTab
->GetBroadcaster(rPos
.Col(), rPos
.Row());
2366 const SvtBroadcaster
* ScDocument::GetBroadcaster( const ScAddress
& rPos
) const
2368 const ScTable
* pTab
= FetchTable(rPos
.Tab());
2372 return pTab
->GetBroadcaster(rPos
.Col(), rPos
.Row());
2375 void ScDocument::DeleteBroadcasters( sc::ColumnBlockPosition
& rBlockPos
, const ScAddress
& rTopPos
, SCROW nLength
)
2377 ScTable
* pTab
= FetchTable(rTopPos
.Tab());
2378 if (!pTab
|| nLength
<= 0)
2381 pTab
->DeleteBroadcasters(rBlockPos
, rTopPos
.Col(), rTopPos
.Row(), rTopPos
.Row()+nLength
-1);
2384 bool ScDocument::HasBroadcaster( SCTAB nTab
, SCCOL nCol
) const
2386 const ScTable
* pTab
= FetchTable(nTab
);
2390 return pTab
->HasBroadcaster(nCol
);
2393 #if DEBUG_COLUMN_STORAGE
2394 void ScDocument::DumpFormulaGroups( SCTAB nTab
, SCCOL nCol
) const
2396 const ScTable
* pTab
= FetchTable(nTab
);
2400 pTab
->DumpFormulaGroups(nCol
);
2404 #if DEBUG_AREA_BROADCASTER
2405 void ScDocument::DumpAreaBroadcasters() const
2412 bool ScDocument::TableExists( SCTAB nTab
) const
2414 return ValidTab(nTab
) && static_cast<size_t>(nTab
) < maTabs
.size() && maTabs
[nTab
];
2417 ScTable
* ScDocument::FetchTable( SCTAB nTab
)
2419 if (!TableExists(nTab
))
2422 return maTabs
[nTab
];
2425 const ScTable
* ScDocument::FetchTable( SCTAB nTab
) const
2427 if (!TableExists(nTab
))
2430 return maTabs
[nTab
];
2433 void ScDocument::MergeNumberFormatter(ScDocument
* pSrcDoc
)
2435 SvNumberFormatter
* pThisFormatter
= xPoolHelper
->GetFormTable();
2436 SvNumberFormatter
* pOtherFormatter
= pSrcDoc
->xPoolHelper
->GetFormTable();
2437 if (pOtherFormatter
&& pOtherFormatter
!= pThisFormatter
)
2439 SvNumberFormatterIndexTable
* pExchangeList
=
2440 pThisFormatter
->MergeFormatter(*(pOtherFormatter
));
2441 if (!pExchangeList
->empty())
2442 pFormatExchangeList
= pExchangeList
;
2446 ScClipParam
& ScDocument::GetClipParam()
2448 if (!mpClipParam
.get())
2449 mpClipParam
.reset(new ScClipParam
);
2451 return *mpClipParam
;
2454 void ScDocument::SetClipParam(const ScClipParam
& rParam
)
2456 mpClipParam
.reset(new ScClipParam(rParam
));
2459 bool ScDocument::IsClipboardSource() const
2461 ScDocument
* pClipDoc
= ScModule::GetClipDoc();
2462 return pClipDoc
&& pClipDoc
->xPoolHelper
.is() &&
2463 xPoolHelper
->GetDocPool() == pClipDoc
->xPoolHelper
->GetDocPool();
2466 void ScDocument::StartListeningFromClip( SCCOL nCol1
, SCROW nRow1
,
2467 SCCOL nCol2
, SCROW nRow2
,
2468 const ScMarkData
& rMark
, InsertDeleteFlags nInsFlag
)
2470 if (nInsFlag
& IDF_CONTENTS
)
2472 boost::shared_ptr
<sc::ColumnBlockPositionSet
> pSet(
2473 new sc::ColumnBlockPositionSet(*this));
2475 sc::StartListeningContext
aStartCxt(*this, pSet
);
2476 sc::EndListeningContext
aEndCxt(*this, pSet
, NULL
);
2478 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
2479 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2480 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
2482 maTabs
[*itr
]->StartListeningFormulaCells(aStartCxt
, aEndCxt
, nCol1
, nRow1
, nCol2
, nRow2
);
2486 void ScDocument::SetDirtyFromClip(
2487 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, const ScMarkData
& rMark
,
2488 InsertDeleteFlags nInsFlag
, sc::ColumnSpanSet
& rBroadcastSpans
)
2490 if (nInsFlag
& IDF_CONTENTS
)
2492 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
2493 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
2494 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
2496 maTabs
[*itr
]->SetDirtyFromClip(nCol1
, nRow1
, nCol2
, nRow2
, rBroadcastSpans
);
2500 bool ScDocument::InitColumnBlockPosition( sc::ColumnBlockPosition
& rBlockPos
, SCTAB nTab
, SCCOL nCol
)
2502 if (!TableExists(nTab
))
2505 return maTabs
[nTab
]->InitColumnBlockPosition(rBlockPos
, nCol
);
2508 void ScDocument::CopyBlockFromClip(
2509 sc::CopyFromClipContext
& rCxt
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
2510 const ScMarkData
& rMark
, SCsCOL nDx
, SCsROW nDy
)
2512 TableContainer
& rClipTabs
= rCxt
.getClipDoc()->maTabs
;
2513 SCTAB nTabEnd
= rCxt
.getTabEnd();
2515 for (SCTAB i
= rCxt
.getTabStart(); i
<= nTabEnd
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
2517 if (maTabs
[i
] && rMark
.GetTableSelect(i
) )
2519 while (!rClipTabs
[nClipTab
]) nClipTab
= (nClipTab
+1) % (static_cast<SCTAB
>(rClipTabs
.size()));
2521 maTabs
[i
]->CopyFromClip(
2522 rCxt
, nCol1
, nRow1
, nCol2
, nRow2
, nDx
, nDy
, rClipTabs
[nClipTab
]);
2524 if (rCxt
.getClipDoc()->pDrawLayer
&& (rCxt
.getInsertFlag() & IDF_OBJECTS
))
2526 // also copy drawing objects
2528 // drawing layer must be created before calling CopyFromClip
2529 // (ScDocShell::MakeDrawLayer also does InitItems etc.)
2530 OSL_ENSURE( pDrawLayer
, "CopyBlockFromClip: No drawing layer" );
2533 // For GetMMRect, the row heights in the target document must already be valid
2534 // (copied in an extra step before pasting, or updated after pasting cells, but
2535 // before pasting objects).
2537 Rectangle aSourceRect
= rCxt
.getClipDoc()->GetMMRect(
2538 nCol1
-nDx
, nRow1
-nDy
, nCol2
-nDx
, nRow2
-nDy
, nClipTab
);
2539 Rectangle aDestRect
= GetMMRect( nCol1
, nRow1
, nCol2
, nRow2
, i
);
2540 pDrawLayer
->CopyFromClip(rCxt
.getClipDoc()->pDrawLayer
, nClipTab
, aSourceRect
,
2541 ScAddress( nCol1
, nRow1
, i
), aDestRect
);
2545 nClipTab
= (nClipTab
+1) % (static_cast<SCTAB
>(rClipTabs
.size()));
2548 if (rCxt
.getInsertFlag() & IDF_CONTENTS
)
2551 for (SCTAB i
= rCxt
.getTabStart(); i
<= nTabEnd
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
2553 if (maTabs
[i
] && rMark
.GetTableSelect(i
) )
2555 while (!rClipTabs
[nClipTab
]) nClipTab
= (nClipTab
+1) % (static_cast<SCTAB
>(rClipTabs
.size()));
2556 SCsTAB nDz
= ((SCsTAB
)i
) - nClipTab
;
2558 // ranges of consecutive selected tables (in clipboard and dest. doc)
2559 // must be handled in one UpdateReference call
2561 while ( i
+ nFollow
< nTabEnd
2562 && rMark
.GetTableSelect( i
+ nFollow
+ 1 )
2563 && nClipTab
+ nFollow
< MAXTAB
2564 && rClipTabs
[(nClipTab
+ nFollow
+ 1) % static_cast<SCTAB
>(rClipTabs
.size())] )
2567 sc::RefUpdateContext
aRefCxt(*this);
2568 aRefCxt
.maRange
= ScRange(nCol1
, nRow1
, i
, nCol2
, nRow2
, i
+nFollow
);
2569 aRefCxt
.mnColDelta
= nDx
;
2570 aRefCxt
.mnRowDelta
= nDy
;
2571 aRefCxt
.mnTabDelta
= nDz
;
2572 if (rCxt
.getClipDoc()->GetClipParam().mbCutMode
)
2574 // Update references only if cut originates from the same
2575 // document we are pasting into.
2576 if (rCxt
.getClipDoc()->GetPool() == GetPool())
2578 bool bOldInserting
= IsInsertingFromOtherDoc();
2579 SetInsertingFromOtherDoc( true);
2580 aRefCxt
.meMode
= URM_MOVE
;
2581 UpdateReference(aRefCxt
, rCxt
.getUndoDoc(), false);
2582 SetInsertingFromOtherDoc( bOldInserting
);
2587 aRefCxt
.meMode
= URM_COPY
;
2588 UpdateReference(aRefCxt
, rCxt
.getUndoDoc(), false);
2591 nClipTab
= (nClipTab
+nFollow
+1) % (static_cast<SCTAB
>(rClipTabs
.size()));
2592 i
= sal::static_int_cast
<SCTAB
>( i
+ nFollow
);
2598 void ScDocument::CopyNonFilteredFromClip(
2599 sc::CopyFromClipContext
& rCxt
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
2600 const ScMarkData
& rMark
, SCsCOL nDx
, SCROW
& rClipStartRow
)
2602 // call CopyBlockFromClip for ranges of consecutive non-filtered rows
2603 // nCol1/nRow1 etc. is in target doc
2605 // filtered state is taken from first used table in clipboard (as in GetClipArea)
2607 TableContainer
& rClipTabs
= rCxt
.getClipDoc()->maTabs
;
2608 while ( nFlagTab
< static_cast<SCTAB
>(rClipTabs
.size()) && !rClipTabs
[nFlagTab
] )
2611 SCROW nSourceRow
= rClipStartRow
;
2612 SCROW nSourceEnd
= 0;
2613 if (!rCxt
.getClipDoc()->GetClipParam().maRanges
.empty())
2614 nSourceEnd
= rCxt
.getClipDoc()->GetClipParam().maRanges
.front()->aEnd
.Row();
2615 SCROW nDestRow
= nRow1
;
2617 while ( nSourceRow
<= nSourceEnd
&& nDestRow
<= nRow2
)
2619 // skip filtered rows
2620 nSourceRow
= rCxt
.getClipDoc()->FirstNonFilteredRow(nSourceRow
, nSourceEnd
, nFlagTab
);
2622 if ( nSourceRow
<= nSourceEnd
)
2624 // look for more non-filtered rows following
2625 SCROW nLastRow
= nSourceRow
;
2626 rCxt
.getClipDoc()->RowFiltered(nSourceRow
, nFlagTab
, NULL
, &nLastRow
);
2627 SCROW nFollow
= nLastRow
- nSourceRow
;
2629 if (nFollow
> nSourceEnd
- nSourceRow
)
2630 nFollow
= nSourceEnd
- nSourceRow
;
2631 if (nFollow
> nRow2
- nDestRow
)
2632 nFollow
= nRow2
- nDestRow
;
2634 SCsROW nNewDy
= ((SCsROW
)nDestRow
) - nSourceRow
;
2636 rCxt
, nCol1
, nDestRow
, nCol2
, nDestRow
+ nFollow
, rMark
, nDx
, nNewDy
);
2638 nSourceRow
+= nFollow
+ 1;
2639 nDestRow
+= nFollow
+ 1;
2642 rClipStartRow
= nSourceRow
;
2647 class BroadcastAction
: public sc::ColumnSpanSet::ColumnAction
2653 BroadcastAction( ScDocument
& rDoc
) : mrDoc(rDoc
), mpCol(NULL
) {}
2655 virtual void startColumn( ScColumn
* pCol
) SAL_OVERRIDE
2660 virtual void execute( SCROW nRow1
, SCROW nRow2
, bool bVal
) SAL_OVERRIDE
2666 ScRange
aRange(mpCol
->GetCol(), nRow1
, mpCol
->GetTab());
2667 aRange
.aEnd
.SetRow(nRow2
);
2668 mrDoc
.BroadcastCells(aRange
, SC_HINT_DATACHANGED
);
2674 void ScDocument::CopyFromClip( const ScRange
& rDestRange
, const ScMarkData
& rMark
,
2675 InsertDeleteFlags nInsFlag
,
2676 ScDocument
* pRefUndoDoc
, ScDocument
* pClipDoc
, bool bResetCut
,
2677 bool bAsLink
, bool bIncludeFiltered
, bool bSkipAttrForEmpty
,
2678 const ScRangeList
* pDestRanges
)
2685 OSL_FAIL("CopyFromClip: no ClipDoc");
2686 pClipDoc
= ScModule::GetClipDoc();
2689 if (!pClipDoc
->bIsClip
|| !pClipDoc
->GetTableCount())
2692 sc::AutoCalcSwitch
aACSwitch(*this, false); // temporarily turn off auto calc.
2694 NumFmtMergeHandler
aNumFmtMergeHdl(this, pClipDoc
);
2696 SCCOL nAllCol1
= rDestRange
.aStart
.Col();
2697 SCROW nAllRow1
= rDestRange
.aStart
.Row();
2698 SCCOL nAllCol2
= rDestRange
.aEnd
.Col();
2699 SCROW nAllRow2
= rDestRange
.aEnd
.Row();
2703 ScRange aClipRange
= pClipDoc
->GetClipParam().getWholeRange();
2704 for (SCTAB nTab
= 0; nTab
< static_cast<SCTAB
>(pClipDoc
->maTabs
.size()); nTab
++) // find largest merge overlap
2705 if (pClipDoc
->maTabs
[nTab
]) // all sheets of the clipboard content
2707 SCCOL nThisEndX
= aClipRange
.aEnd
.Col();
2708 SCROW nThisEndY
= aClipRange
.aEnd
.Row();
2709 pClipDoc
->ExtendMerge( aClipRange
.aStart
.Col(),
2710 aClipRange
.aStart
.Row(),
2711 nThisEndX
, nThisEndY
, nTab
);
2712 // only extra value from ExtendMerge
2713 nThisEndX
= sal::static_int_cast
<SCCOL
>( nThisEndX
- aClipRange
.aEnd
.Col() );
2714 nThisEndY
= sal::static_int_cast
<SCROW
>( nThisEndY
- aClipRange
.aEnd
.Row() );
2715 if ( nThisEndX
> nXw
)
2717 if ( nThisEndY
> nYw
)
2723 pClipDoc
->GetClipArea( nDestAddX
, nDestAddY
, bIncludeFiltered
);
2724 nXw
= sal::static_int_cast
<SCCOL
>( nXw
+ nDestAddX
);
2725 nYw
= sal::static_int_cast
<SCROW
>( nYw
+ nDestAddY
); // ClipArea, plus ExtendMerge value
2727 /* Decide which contents to delete before copying. Delete all
2728 contents if nInsFlag contains any real content flag.
2729 #i102056# Notes are pasted from clipboard in a second pass,
2730 together with the special flag IDF_ADDNOTES that states to not
2731 overwrite/delete existing cells but to insert the notes into
2732 these cells. In this case, just delete old notes from the
2733 destination area. */
2734 InsertDeleteFlags nDelFlag
= IDF_NONE
;
2735 if ( (nInsFlag
& (IDF_CONTENTS
| IDF_ADDNOTES
)) == (IDF_NOTE
| IDF_ADDNOTES
) )
2736 nDelFlag
|= IDF_NOTE
;
2737 else if ( nInsFlag
& IDF_CONTENTS
)
2738 nDelFlag
|= IDF_CONTENTS
;
2740 if (nInsFlag
& IDF_ATTRIB
)
2741 nDelFlag
|= IDF_ATTRIB
;
2743 sc::CopyFromClipContext
aCxt(*this, pRefUndoDoc
, pClipDoc
, nInsFlag
, bAsLink
, bSkipAttrForEmpty
);
2744 std::pair
<SCTAB
,SCTAB
> aTabRanges
= getMarkedTableRange(maTabs
, rMark
);
2745 aCxt
.setTabRange(aTabRanges
.first
, aTabRanges
.second
);
2746 aCxt
.setDeleteFlag(nDelFlag
);
2748 ScRangeList aLocalRangeList
;
2751 aLocalRangeList
.Append( rDestRange
);
2752 pDestRanges
= &aLocalRangeList
;
2755 bInsertingFromOtherDoc
= true; // kein Broadcast/Listener aufbauen bei Insert
2757 sc::ColumnSpanSet
aBroadcastSpans(false);
2759 SCCOL nClipStartCol
= aClipRange
.aStart
.Col();
2760 SCROW nClipStartRow
= aClipRange
.aStart
.Row();
2761 SCROW nClipEndRow
= aClipRange
.aEnd
.Row();
2762 for ( size_t nRange
= 0; nRange
< pDestRanges
->size(); ++nRange
)
2764 const ScRange
* pRange
= (*pDestRanges
)[nRange
];
2765 SCCOL nCol1
= pRange
->aStart
.Col();
2766 SCROW nRow1
= pRange
->aStart
.Row();
2767 SCCOL nCol2
= pRange
->aEnd
.Col();
2768 SCROW nRow2
= pRange
->aEnd
.Row();
2770 if (bSkipAttrForEmpty
)
2772 // Delete cells in the destination only if their corresponding clip cells are not empty.
2773 aCxt
.setDestRange(nCol1
, nRow1
, nCol2
, nRow2
);
2774 DeleteBeforeCopyFromClip(aCxt
, rMark
, aBroadcastSpans
);
2777 DeleteArea(nCol1
, nRow1
, nCol2
, nRow2
, rMark
, nDelFlag
, false, &aBroadcastSpans
);
2779 if (CopyOneCellFromClip(aCxt
, nCol1
, nRow1
, nCol2
, nRow2
))
2784 SCCOL nC2
= nC1
+ nXw
;
2787 SCROW nR2
= nR1
+ nYw
;
2791 const SCCOLROW nThreshold
= 8192;
2792 bool bPreallocatePattern
= ((nInsFlag
& IDF_ATTRIB
) && (nRow2
- nRow1
> nThreshold
));
2793 std::vector
< SCTAB
> vTables
;
2795 if (bPreallocatePattern
)
2797 for (SCTAB i
= aCxt
.getTabStart(); i
<= aCxt
.getTabEnd(); ++i
)
2798 if (maTabs
[i
] && rMark
.GetTableSelect( i
) )
2799 vTables
.push_back( i
);
2804 // Pasting is done column-wise, when pasting to a filtered
2805 // area this results in partitioning and we have to
2806 // remember and reset the start row for each column until
2807 // it can be advanced for the next chunk of unfiltered
2809 SCROW nSaveClipStartRow
= nClipStartRow
;
2812 nClipStartRow
= nSaveClipStartRow
;
2813 SCsCOL nDx
= ((SCsCOL
)nC1
) - nClipStartCol
;
2814 SCsROW nDy
= ((SCsROW
)nR1
) - nClipStartRow
;
2815 if ( bIncludeFiltered
)
2818 aCxt
, nC1
, nR1
, nC2
, nR2
, rMark
, nDx
, nDy
);
2819 nClipStartRow
+= nR2
- nR1
+ 1;
2823 CopyNonFilteredFromClip(
2824 aCxt
, nC1
, nR1
, nC2
, nR2
, rMark
, nDx
, nClipStartRow
);
2827 nC2
= std::min((SCCOL
)(nC1
+ nXw
), nCol2
);
2828 } while (nC1
<= nCol2
);
2829 if (nClipStartRow
> nClipEndRow
)
2830 nClipStartRow
= aClipRange
.aStart
.Row();
2836 // Preallocate pattern memory once if further chunks are to be pasted.
2837 if (bPreallocatePattern
&& (nR2
+1) <= nRow2
)
2839 SCROW nR3
= nR2
+ 1;
2840 for (size_t j
= 0; j
< vTables
.size(); ++j
)
2842 SCTAB nTab
= vTables
[j
];
2843 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
2845 // Pattern count of the first chunk pasted.
2846 SCSIZE nChunk
= GetPatternCount( nTab
, nCol
, nR1
, nR2
);
2847 // If it is only one pattern per chunk and chunks are
2848 // pasted consecutively then it will get its range
2849 // enlarged for each chunk and no further allocation
2850 // happens. For non-consecutive chunks we're out of
2851 // luck in this case.
2854 SCSIZE nNeeded
= nChunk
* (nRow2
- nR3
+ 1) / (nYw
+ 1);
2855 SCSIZE nRemain
= GetPatternCount( nTab
, nCol
, nR3
, nRow2
);
2856 if (nNeeded
> nRemain
)
2858 SCSIZE nCurr
= GetPatternCount( nTab
, nCol
);
2859 ReservePatternCount( nTab
, nCol
, nCurr
+ nNeeded
);
2864 bPreallocatePattern
= false;
2868 nR2
= std::min((SCROW
)(nR1
+ nYw
), nRow2
);
2869 } while (nR1
<= nRow2
);
2872 bInsertingFromOtherDoc
= false;
2874 // Create Listener after everything has been inserted
2875 StartListeningFromClip( nAllCol1
, nAllRow1
, nAllCol2
, nAllRow2
, rMark
, nInsFlag
);
2878 ScBulkBroadcast
aBulkBroadcast( GetBASM());
2880 // Set all formula cells dirty, and collect non-empty non-formula cell
2881 // positions so that we can broadcast on them below.
2882 SetDirtyFromClip(nAllCol1
, nAllRow1
, nAllCol2
, nAllRow2
, rMark
, nInsFlag
, aBroadcastSpans
);
2884 BroadcastAction
aAction(*this);
2885 aBroadcastSpans
.executeColumnAction(*this, aAction
);
2889 pClipDoc
->GetClipParam().mbCutMode
= false;
2892 void ScDocument::CopyMultiRangeFromClip(
2893 const ScAddress
& rDestPos
, const ScMarkData
& rMark
, InsertDeleteFlags nInsFlag
, ScDocument
* pClipDoc
,
2894 bool bResetCut
, bool bAsLink
, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty
)
2899 if (!pClipDoc
->bIsClip
|| !pClipDoc
->GetTableCount())
2900 // There is nothing in the clip doc to copy.
2903 // Right now, we don't allow pasting into filtered rows, so we don't even handle it here.
2905 sc::AutoCalcSwitch
aACSwitch(*this, false); // turn of auto calc temporarily.
2906 NumFmtMergeHandler
aNumFmtMergeHdl(this, pClipDoc
);
2909 rMark
.GetMarkArea(aDestRange
);
2911 bInsertingFromOtherDoc
= true; // No Broadcast/Listener created at Insert
2913 SCCOL nCol1
= rDestPos
.Col();
2914 SCROW nRow1
= rDestPos
.Row();
2915 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
2917 sc::ColumnSpanSet
aBroadcastSpans(false);
2919 if (!bSkipAttrForEmpty
)
2921 // Do the deletion first.
2922 InsertDeleteFlags nDelFlag
= IDF_CONTENTS
;
2923 SCCOL nColSize
= rClipParam
.getPasteColSize();
2924 SCROW nRowSize
= rClipParam
.getPasteRowSize();
2926 DeleteArea(nCol1
, nRow1
, nCol1
+nColSize
-1, nRow1
+nRowSize
-1, rMark
, nDelFlag
, false, &aBroadcastSpans
);
2929 sc::CopyFromClipContext
aCxt(*this, NULL
, pClipDoc
, nInsFlag
, bAsLink
, bSkipAttrForEmpty
);
2930 std::pair
<SCTAB
,SCTAB
> aTabRanges
= getMarkedTableRange(maTabs
, rMark
);
2931 aCxt
.setTabRange(aTabRanges
.first
, aTabRanges
.second
);
2933 for (size_t i
= 0, n
= rClipParam
.maRanges
.size(); i
< n
; ++i
)
2935 ScRange
* p
= rClipParam
.maRanges
[i
];
2937 SCROW nRowCount
= p
->aEnd
.Row() - p
->aStart
.Row() + 1;
2938 SCsCOL nDx
= static_cast<SCsCOL
>(nCol1
- p
->aStart
.Col());
2939 SCsROW nDy
= static_cast<SCsROW
>(nRow1
- p
->aStart
.Row());
2940 SCCOL nCol2
= nCol1
+ p
->aEnd
.Col() - p
->aStart
.Col();
2941 SCROW nEndRow
= nRow1
+ nRowCount
- 1;
2943 CopyBlockFromClip(aCxt
, nCol1
, nRow1
, nCol2
, nEndRow
, rMark
, nDx
, nDy
);
2945 switch (rClipParam
.meDirection
)
2947 case ScClipParam::Row
:
2948 // Begin row for the next range being pasted.
2951 case ScClipParam::Column
:
2952 nCol1
+= p
->aEnd
.Col() - p
->aStart
.Col() + 1;
2959 bInsertingFromOtherDoc
= false;
2961 // Create Listener after everything has been inserted
2962 StartListeningFromClip(aDestRange
.aStart
.Col(), aDestRange
.aStart
.Row(),
2963 aDestRange
.aEnd
.Col(), aDestRange
.aEnd
.Row(), rMark
, nInsFlag
);
2966 ScBulkBroadcast
aBulkBroadcast( GetBASM());
2968 // Set formula cells dirty and collect non-formula cells.
2970 aDestRange
.aStart
.Col(), aDestRange
.aStart
.Row(), aDestRange
.aEnd
.Col(), aDestRange
.aEnd
.Row(),
2971 rMark
, nInsFlag
, aBroadcastSpans
);
2973 BroadcastAction
aAction(*this);
2974 aBroadcastSpans
.executeColumnAction(*this, aAction
);
2978 pClipDoc
->GetClipParam().mbCutMode
= false;
2981 void ScDocument::SetClipArea( const ScRange
& rArea
, bool bCut
)
2985 ScClipParam
& rClipParam
= GetClipParam();
2986 rClipParam
.maRanges
.RemoveAll();
2987 rClipParam
.maRanges
.Append(rArea
);
2988 rClipParam
.mbCutMode
= bCut
;
2992 OSL_FAIL("SetClipArea: No Clip");
2996 void ScDocument::GetClipArea(SCCOL
& nClipX
, SCROW
& nClipY
, bool bIncludeFiltered
)
3000 OSL_FAIL("GetClipArea: No Clip");
3004 ScRangeList
& rClipRanges
= GetClipParam().maRanges
;
3005 if (rClipRanges
.empty())
3006 // No clip range. Bail out.
3009 ScRange
* p
= rClipRanges
.front();
3010 SCCOL nStartCol
= p
->aStart
.Col();
3011 SCCOL nEndCol
= p
->aEnd
.Col();
3012 SCROW nStartRow
= p
->aStart
.Row();
3013 SCROW nEndRow
= p
->aEnd
.Row();
3014 for ( size_t i
= 1, n
= rClipRanges
.size(); i
< n
; ++i
)
3016 p
= rClipRanges
[ i
];
3017 if (p
->aStart
.Col() < nStartCol
)
3018 nStartCol
= p
->aStart
.Col();
3019 if (p
->aStart
.Row() < nStartRow
)
3020 nStartRow
= p
->aStart
.Row();
3021 if (p
->aEnd
.Col() > nEndCol
)
3022 nEndCol
= p
->aEnd
.Col();
3023 if (p
->aEnd
.Row() < nEndRow
)
3024 nEndRow
= p
->aEnd
.Row();
3027 nClipX
= nEndCol
- nStartCol
;
3029 if ( bIncludeFiltered
)
3030 nClipY
= nEndRow
- nStartRow
;
3033 // count non-filtered rows
3034 // count on first used table in clipboard
3035 SCTAB nCountTab
= 0;
3036 while ( nCountTab
< static_cast<SCTAB
>(maTabs
.size()) && !maTabs
[nCountTab
] )
3039 SCROW nResult
= CountNonFilteredRows(nStartRow
, nEndRow
, nCountTab
);
3042 nClipY
= nResult
- 1;
3044 nClipY
= 0; // always return at least 1 row
3048 void ScDocument::GetClipStart(SCCOL
& nClipX
, SCROW
& nClipY
)
3052 ScRangeList
& rClipRanges
= GetClipParam().maRanges
;
3053 if ( !rClipRanges
.empty() )
3055 nClipX
= rClipRanges
.front()->aStart
.Col();
3056 nClipY
= rClipRanges
.front()->aStart
.Row();
3061 OSL_FAIL("GetClipStart: No Clip");
3065 bool ScDocument::HasClipFilteredRows()
3067 // count on first used table in clipboard
3068 SCTAB nCountTab
= 0;
3069 while ( nCountTab
< static_cast<SCTAB
>(maTabs
.size()) && !maTabs
[nCountTab
] )
3072 ScRangeList
& rClipRanges
= GetClipParam().maRanges
;
3073 if ( rClipRanges
.empty() )
3076 for ( size_t i
= 0, n
= rClipRanges
.size(); i
< n
; ++i
)
3078 ScRange
* p
= rClipRanges
[ i
];
3079 bool bAnswer
= maTabs
[nCountTab
]->HasFilteredRows(p
->aStart
.Row(), p
->aEnd
.Row());
3086 void ScDocument::MixDocument( const ScRange
& rRange
, sal_uInt16 nFunction
, bool bSkipEmpty
,
3087 ScDocument
* pSrcDoc
)
3089 SCTAB nTab1
= rRange
.aStart
.Tab();
3090 SCTAB nTab2
= rRange
.aEnd
.Tab();
3091 sc::MixDocContext
aCxt(*this);
3092 SCTAB nMinSizeBothTabs
= static_cast<SCTAB
>(std::min(maTabs
.size(), pSrcDoc
->maTabs
.size()));
3093 for (SCTAB i
= nTab1
; i
<= nTab2
&& i
< nMinSizeBothTabs
; i
++)
3095 ScTable
* pTab
= FetchTable(i
);
3096 const ScTable
* pSrcTab
= pSrcDoc
->FetchTable(i
);
3097 if (!pTab
|| !pSrcTab
)
3101 aCxt
, rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row(),
3102 nFunction
, bSkipEmpty
, pSrcTab
);
3106 void ScDocument::FillTab( const ScRange
& rSrcArea
, const ScMarkData
& rMark
,
3107 InsertDeleteFlags nFlags
, sal_uInt16 nFunction
,
3108 bool bSkipEmpty
, bool bAsLink
)
3110 InsertDeleteFlags nDelFlags
= nFlags
;
3111 if (nDelFlags
& IDF_CONTENTS
)
3112 nDelFlags
|= IDF_CONTENTS
; // Either all contents or delete nothing!
3114 SCTAB nSrcTab
= rSrcArea
.aStart
.Tab();
3116 if (ValidTab(nSrcTab
) && nSrcTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nSrcTab
])
3118 SCCOL nStartCol
= rSrcArea
.aStart
.Col();
3119 SCROW nStartRow
= rSrcArea
.aStart
.Row();
3120 SCCOL nEndCol
= rSrcArea
.aEnd
.Col();
3121 SCROW nEndRow
= rSrcArea
.aEnd
.Row();
3122 boost::scoped_ptr
<ScDocument
> pMixDoc
;
3123 bool bDoMix
= ( bSkipEmpty
|| nFunction
) && ( nFlags
& IDF_CONTENTS
);
3125 bool bOldAutoCalc
= GetAutoCalc();
3126 SetAutoCalc( false ); // avoid multiple calculations
3128 sc::CopyToDocContext
aCxt(*this);
3129 sc::MixDocContext
aMixDocCxt(*this);
3131 SCTAB nCount
= static_cast<SCTAB
>(maTabs
.size());
3132 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
3133 for (; itr
!= itrEnd
&& *itr
< nCount
; ++itr
)
3134 if ( *itr
!=nSrcTab
&& maTabs
[*itr
])
3141 pMixDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
3142 pMixDoc
->InitUndo( this, i
, i
);
3145 pMixDoc
->AddUndoTab( i
, i
);
3147 // context used for copying content to the temporary mix document.
3148 sc::CopyToDocContext
aMixCxt(*pMixDoc
);
3149 maTabs
[i
]->CopyToTable(aMixCxt
, nStartCol
,nStartRow
, nEndCol
,nEndRow
,
3150 IDF_CONTENTS
, false, pMixDoc
->maTabs
[i
] );
3152 maTabs
[i
]->DeleteArea( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nDelFlags
);
3153 maTabs
[nSrcTab
]->CopyToTable(aCxt
, nStartCol
,nStartRow
, nEndCol
,nEndRow
,
3154 nFlags
, false, maTabs
[i
], NULL
, bAsLink
);
3157 maTabs
[i
]->MixData(aMixDocCxt
, nStartCol
,nStartRow
, nEndCol
,nEndRow
,
3158 nFunction
, bSkipEmpty
, pMixDoc
->maTabs
[i
] );
3161 SetAutoCalc( bOldAutoCalc
);
3165 OSL_FAIL("wrong table");
3169 void ScDocument::FillTabMarked( SCTAB nSrcTab
, const ScMarkData
& rMark
,
3170 InsertDeleteFlags nFlags
, sal_uInt16 nFunction
,
3171 bool bSkipEmpty
, bool bAsLink
)
3173 InsertDeleteFlags nDelFlags
= nFlags
;
3174 if (nDelFlags
& IDF_CONTENTS
)
3175 nDelFlags
|= IDF_CONTENTS
; // Either all contents or delete nothing!
3177 if (ValidTab(nSrcTab
) && nSrcTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nSrcTab
])
3179 boost::scoped_ptr
<ScDocument
> pMixDoc
;
3180 bool bDoMix
= ( bSkipEmpty
|| nFunction
) && ( nFlags
& IDF_CONTENTS
);
3182 bool bOldAutoCalc
= GetAutoCalc();
3183 SetAutoCalc( false ); // avoid multiple calculations
3186 rMark
.GetMultiMarkArea( aArea
);
3187 SCCOL nStartCol
= aArea
.aStart
.Col();
3188 SCROW nStartRow
= aArea
.aStart
.Row();
3189 SCCOL nEndCol
= aArea
.aEnd
.Col();
3190 SCROW nEndRow
= aArea
.aEnd
.Row();
3192 sc::CopyToDocContext
aCxt(*this);
3193 sc::MixDocContext
aMixDocCxt(*this);
3194 SCTAB nCount
= static_cast<SCTAB
>(maTabs
.size());
3195 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
3196 for (; itr
!= itrEnd
&& *itr
< nCount
; ++itr
)
3197 if ( *itr
!=nSrcTab
&& maTabs
[*itr
] )
3204 pMixDoc
.reset(new ScDocument(SCDOCMODE_UNDO
));
3205 pMixDoc
->InitUndo( this, i
, i
);
3208 pMixDoc
->AddUndoTab( i
, i
);
3210 sc::CopyToDocContext
aMixCxt(*pMixDoc
);
3211 maTabs
[i
]->CopyToTable(aMixCxt
, nStartCol
,nStartRow
, nEndCol
,nEndRow
,
3212 IDF_CONTENTS
, true, pMixDoc
->maTabs
[i
], &rMark
);
3215 maTabs
[i
]->DeleteSelection( nDelFlags
, rMark
);
3216 maTabs
[nSrcTab
]->CopyToTable(aCxt
, nStartCol
,nStartRow
, nEndCol
,nEndRow
,
3217 nFlags
, true, maTabs
[i
], &rMark
, bAsLink
);
3220 maTabs
[i
]->MixMarked(aMixDocCxt
, rMark
, nFunction
, bSkipEmpty
, pMixDoc
->maTabs
[i
]);
3223 SetAutoCalc( bOldAutoCalc
);
3227 OSL_FAIL("wrong table");
3231 bool ScDocument::SetString( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const OUString
& rString
,
3232 ScSetStringParam
* pParam
)
3234 ScTable
* pTab
= FetchTable(nTab
);
3238 bool bNumFmtSet
= false;
3240 const ScFormulaCell
* pCurCellFormula
= pTab
->GetFormulaCell(nCol
, nRow
);
3241 if (pCurCellFormula
&& pCurCellFormula
->IsShared())
3243 // In case setting this string affects an existing formula group, record
3244 // its above and below position for later listening.
3246 std::vector
<ScAddress
> aGroupPos
;
3247 sc::EndListeningContext
aCxt(*this);
3248 ScAddress
aPos(nCol
, nRow
, nTab
);
3249 EndListeningIntersectedGroup(aCxt
, aPos
, &aGroupPos
);
3250 aCxt
.purgeEmptyBroadcasters();
3252 bNumFmtSet
= pTab
->SetString(nCol
, nRow
, nTab
, rString
, pParam
);
3254 SetNeedsListeningGroups(aGroupPos
);
3255 StartNeededListeners();
3259 bNumFmtSet
= pTab
->SetString(nCol
, nRow
, nTab
, rString
, pParam
);
3265 bool ScDocument::SetString(
3266 const ScAddress
& rPos
, const OUString
& rString
, ScSetStringParam
* pParam
)
3268 return SetString(rPos
.Col(), rPos
.Row(), rPos
.Tab(), rString
, pParam
);
3271 bool ScDocument::SetEditText( const ScAddress
& rPos
, EditTextObject
* pEditText
)
3273 if (!TableExists(rPos
.Tab()))
3279 return maTabs
[rPos
.Tab()]->SetEditText(rPos
.Col(), rPos
.Row(), pEditText
);
3282 void ScDocument::SetEditText( const ScAddress
& rPos
, const EditTextObject
& rEditText
, const SfxItemPool
* pEditPool
)
3284 if (!TableExists(rPos
.Tab()))
3287 maTabs
[rPos
.Tab()]->SetEditText(rPos
.Col(), rPos
.Row(), rEditText
, pEditPool
);
3290 void ScDocument::SetEditText( const ScAddress
& rPos
, const OUString
& rStr
)
3292 if (!TableExists(rPos
.Tab()))
3295 ScFieldEditEngine
& rEngine
= GetEditEngine();
3296 rEngine
.SetText(rStr
);
3297 maTabs
[rPos
.Tab()]->SetEditText(rPos
.Col(), rPos
.Row(), rEngine
.CreateTextObject());
3300 SCROW
ScDocument::GetFirstEditTextRow( const ScRange
& rRange
) const
3302 const ScTable
* pTab
= FetchTable(rRange
.aStart
.Tab());
3306 return pTab
->GetFirstEditTextRow(rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row());
3309 void ScDocument::SetTextCell( const ScAddress
& rPos
, const OUString
& rStr
)
3311 if (!TableExists(rPos
.Tab()))
3314 if (ScStringUtil::isMultiline(rStr
))
3316 ScFieldEditEngine
& rEngine
= GetEditEngine();
3317 rEngine
.SetText(rStr
);
3318 maTabs
[rPos
.Tab()]->SetEditText(rPos
.Col(), rPos
.Row(), rEngine
.CreateTextObject());
3322 ScSetStringParam aParam
;
3323 aParam
.setTextInput();
3324 maTabs
[rPos
.Tab()]->SetString(rPos
.Col(), rPos
.Row(), rPos
.Tab(), rStr
, &aParam
);
3328 void ScDocument::SetEmptyCell( const ScAddress
& rPos
)
3330 if (!TableExists(rPos
.Tab()))
3333 maTabs
[rPos
.Tab()]->SetEmptyCell(rPos
.Col(), rPos
.Row());
3336 void ScDocument::SetValue( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const double& rVal
)
3338 SetValue(ScAddress(nCol
, nRow
, nTab
), rVal
);
3341 void ScDocument::SetValue( const ScAddress
& rPos
, double fVal
)
3343 ScTable
* pTab
= FetchTable(rPos
.Tab());
3347 const ScFormulaCell
* pCurCellFormula
= pTab
->GetFormulaCell(rPos
.Col(), rPos
.Row());
3348 if (pCurCellFormula
&& pCurCellFormula
->IsShared())
3350 // In case setting this string affects an existing formula group, record
3351 // its above and below position for later listening.
3353 std::vector
<ScAddress
> aGroupPos
;
3354 sc::EndListeningContext
aCxt(*this);
3355 EndListeningIntersectedGroup(aCxt
, rPos
, &aGroupPos
);
3356 aCxt
.purgeEmptyBroadcasters();
3358 pTab
->SetValue(rPos
.Col(), rPos
.Row(), fVal
);
3360 SetNeedsListeningGroups(aGroupPos
);
3361 StartNeededListeners();
3365 pTab
->SetValue(rPos
.Col(), rPos
.Row(), fVal
);
3369 OUString
ScDocument::GetString( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
3371 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
3374 maTabs
[nTab
]->GetString(nCol
, nRow
, aStr
);
3378 return EMPTY_OUSTRING
;
3381 OUString
ScDocument::GetString( const ScAddress
& rPos
) const
3383 if (!TableExists(rPos
.Tab()))
3384 return EMPTY_OUSTRING
;
3387 maTabs
[rPos
.Tab()]->GetString(rPos
.Col(), rPos
.Row(), aStr
);
3391 double* ScDocument::GetValueCell( const ScAddress
& rPos
)
3393 if (!TableExists(rPos
.Tab()))
3396 return maTabs
[rPos
.Tab()]->GetValueCell(rPos
.Col(), rPos
.Row());
3399 svl::SharedString
ScDocument::GetSharedString( const ScAddress
& rPos
) const
3401 if (!TableExists(rPos
.Tab()))
3402 return svl::SharedString();
3404 return maTabs
[rPos
.Tab()]->GetSharedString(rPos
.Col(), rPos
.Row());
3407 sc::FormulaGroupContext
& ScDocument::GetFormulaGroupContext()
3409 if (!mpFormulaGroupCxt
)
3410 mpFormulaGroupCxt
.reset(new sc::FormulaGroupContext
);
3412 return *mpFormulaGroupCxt
;
3415 void ScDocument::GetInputString( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, OUString
& rString
)
3417 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3418 maTabs
[nTab
]->GetInputString( nCol
, nRow
, rString
);
3423 sal_uInt16
ScDocument::GetStringForFormula( const ScAddress
& rPos
, OUString
& rString
)
3425 // Used in formulas (add-in parameters etc), so it must use the same semantics as
3426 // ScInterpreter::GetCellString: always format values as numbers.
3427 // The return value is the error code.
3429 ScRefCellValue aCell
;
3430 aCell
.assign(*this, rPos
);
3431 if (aCell
.isEmpty())
3433 rString
= EMPTY_OUSTRING
;
3437 sal_uInt16 nErr
= 0;
3439 SvNumberFormatter
* pFormatter
= GetFormatTable();
3440 switch (aCell
.meType
)
3442 case CELLTYPE_STRING
:
3444 aStr
= aCell
.getString(this);
3446 case CELLTYPE_FORMULA
:
3448 ScFormulaCell
* pFCell
= aCell
.mpFormula
;
3449 nErr
= pFCell
->GetErrCode();
3450 if (pFCell
->IsValue())
3452 double fVal
= pFCell
->GetValue();
3453 sal_uInt32 nIndex
= pFormatter
->GetStandardFormat(
3454 css::util::NumberFormat::NUMBER
,
3456 pFormatter
->GetInputLineString(fVal
, nIndex
, aStr
);
3459 aStr
= pFCell
->GetString().getString();
3462 case CELLTYPE_VALUE
:
3464 double fVal
= aCell
.mfValue
;
3465 sal_uInt32 nIndex
= pFormatter
->GetStandardFormat(
3466 css::util::NumberFormat::NUMBER
,
3468 pFormatter
->GetInputLineString(fVal
, nIndex
, aStr
);
3479 void ScDocument::GetValue( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, double& rValue
) const
3481 if (TableExists(nTab
))
3482 rValue
= maTabs
[nTab
]->GetValue( nCol
, nRow
);
3487 const EditTextObject
* ScDocument::GetEditText( const ScAddress
& rPos
) const
3489 SCTAB nTab
= rPos
.Tab();
3490 if (!TableExists(nTab
))
3493 return maTabs
[nTab
]->GetEditText(rPos
.Col(), rPos
.Row());
3496 void ScDocument::RemoveEditTextCharAttribs( const ScAddress
& rPos
, const ScPatternAttr
& rAttr
)
3498 if (!TableExists(rPos
.Tab()))
3501 return maTabs
[rPos
.Tab()]->RemoveEditTextCharAttribs(rPos
.Col(), rPos
.Row(), rAttr
);
3504 double ScDocument::GetValue( const ScAddress
& rPos
) const
3506 SCTAB nTab
= rPos
.Tab();
3507 if ( nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3508 return maTabs
[nTab
]->GetValue(rPos
.Col(), rPos
.Row());
3512 double ScDocument::GetValue( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
3514 ScAddress
aAdr(nCol
, nRow
, nTab
); return GetValue(aAdr
);
3517 void ScDocument::GetNumberFormat( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
3518 sal_uInt32
& rFormat
) const
3520 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
3523 rFormat
= maTabs
[nTab
]->GetNumberFormat( nCol
, nRow
);
3529 sal_uInt32
ScDocument::GetNumberFormat( const ScRange
& rRange
) const
3531 SCTAB nTab1
= rRange
.aStart
.Tab(), nTab2
= rRange
.aEnd
.Tab();
3532 SCCOL nCol1
= rRange
.aStart
.Col(), nCol2
= rRange
.aEnd
.Col();
3533 SCROW nRow1
= rRange
.aStart
.Row(), nRow2
= rRange
.aEnd
.Row();
3535 if (!ValidTab(nTab1
) || !ValidTab(nTab2
) || !maTabs
[nTab1
] || !maTabs
[nTab2
])
3538 sal_uInt32 nFormat
= 0;
3539 bool bFirstItem
= true;
3540 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
&& nTab
< static_cast<SCTAB
>(maTabs
.size()) ; ++nTab
)
3541 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
3543 sal_uInt32 nThisFormat
= maTabs
[nTab
]->GetNumberFormat(nCol
, nRow1
, nRow2
);
3546 nFormat
= nThisFormat
;
3549 else if (nThisFormat
!= nFormat
)
3556 sal_uInt32
ScDocument::GetNumberFormat( const ScAddress
& rPos
) const
3558 SCTAB nTab
= rPos
.Tab();
3559 if (!TableExists(nTab
))
3562 return maTabs
[nTab
]->GetNumberFormat( rPos
);
3565 void ScDocument::SetNumberFormat( const ScAddress
& rPos
, sal_uInt32 nNumberFormat
)
3567 SCTAB nTab
= rPos
.Tab();
3568 if (!TableExists(nTab
))
3571 maTabs
[nTab
]->SetNumberFormat(rPos
.Col(), rPos
.Row(), nNumberFormat
);
3574 void ScDocument::GetNumberFormatInfo( short& nType
, sal_uLong
& nIndex
,
3575 const ScAddress
& rPos
) const
3577 SCTAB nTab
= rPos
.Tab();
3578 if ( nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3580 nIndex
= maTabs
[nTab
]->GetNumberFormat( rPos
);
3581 nType
= GetFormatTable()->GetType( nIndex
);
3585 nType
= css::util::NumberFormat::UNDEFINED
;
3590 void ScDocument::GetFormula( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, OUString
& rFormula
) const
3592 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3593 maTabs
[nTab
]->GetFormula( nCol
, nRow
, rFormula
);
3598 const ScFormulaCell
* ScDocument::GetFormulaCell( const ScAddress
& rPos
) const
3600 if (!TableExists(rPos
.Tab()))
3603 return maTabs
[rPos
.Tab()]->GetFormulaCell(rPos
.Col(), rPos
.Row());
3606 ScFormulaCell
* ScDocument::GetFormulaCell( const ScAddress
& rPos
)
3608 if (!TableExists(rPos
.Tab()))
3611 return maTabs
[rPos
.Tab()]->GetFormulaCell(rPos
.Col(), rPos
.Row());
3614 CellType
ScDocument::GetCellType( const ScAddress
& rPos
) const
3616 SCTAB nTab
= rPos
.Tab();
3617 if ( nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3618 return maTabs
[nTab
]->GetCellType( rPos
);
3619 return CELLTYPE_NONE
;
3622 void ScDocument::GetCellType( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
3623 CellType
& rCellType
) const
3625 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
3626 rCellType
= maTabs
[nTab
]->GetCellType( nCol
, nRow
);
3628 rCellType
= CELLTYPE_NONE
;
3631 bool ScDocument::HasStringData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
3633 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3634 return maTabs
[nTab
]->HasStringData( nCol
, nRow
);
3639 bool ScDocument::HasValueData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
3641 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3642 return maTabs
[nTab
]->HasValueData( nCol
, nRow
);
3647 bool ScDocument::HasValueData( const ScAddress
& rPos
) const
3649 return HasValueData(rPos
.Col(), rPos
.Row(), rPos
.Tab());
3652 bool ScDocument::HasStringCells( const ScRange
& rRange
) const
3654 // true, if String- or Edit cells in range
3656 SCCOL nStartCol
= rRange
.aStart
.Col();
3657 SCROW nStartRow
= rRange
.aStart
.Row();
3658 SCTAB nStartTab
= rRange
.aStart
.Tab();
3659 SCCOL nEndCol
= rRange
.aEnd
.Col();
3660 SCROW nEndRow
= rRange
.aEnd
.Row();
3661 SCTAB nEndTab
= rRange
.aEnd
.Tab();
3663 for ( SCTAB nTab
=nStartTab
; nTab
<=nEndTab
&& nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++ )
3664 if ( maTabs
[nTab
] && maTabs
[nTab
]->HasStringCells( nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
3670 bool ScDocument::HasSelectionData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
3672 sal_uInt32 nValidation
= static_cast< const SfxUInt32Item
* >( GetAttr( nCol
, nRow
, nTab
, ATTR_VALIDDATA
) )->GetValue();
3675 const ScValidationData
* pData
= GetValidationEntry( nValidation
);
3676 if( pData
&& pData
->HasSelectionList() )
3679 return HasStringCells( ScRange( nCol
, 0, nTab
, nCol
, MAXROW
, nTab
) );
3682 void ScDocument::SetAllFormulasDirty( const sc::SetFormulaDirtyContext
& rCxt
)
3684 bool bOldAutoCalc
= GetAutoCalc();
3685 bAutoCalc
= false; // no mulitple calculations
3686 { // scope for bulk broadcast
3687 ScBulkBroadcast
aBulkBroadcast( GetBASM());
3688 TableContainer::iterator it
= maTabs
.begin();
3689 for (;it
!= maTabs
.end(); ++it
)
3691 (*it
)->SetAllFormulasDirty(rCxt
);
3694 // Allthough Charts are also set to dirty in Tracking without AutoCalc
3695 // if all formulas are dirty, the charts can no longer be caught
3696 // (#45205#) - that is why all Charts have to be explicitly handled again
3697 if (pChartListenerCollection
)
3698 pChartListenerCollection
->SetDirty();
3700 SetAutoCalc( bOldAutoCalc
);
3703 void ScDocument::SetDirty( const ScRange
& rRange
, bool bIncludeEmptyCells
)
3705 bool bOldAutoCalc
= GetAutoCalc();
3706 bAutoCalc
= false; // no mulitple calculations
3707 { // scope for bulk broadcast
3708 ScBulkBroadcast
aBulkBroadcast( GetBASM());
3709 SCTAB nTab2
= rRange
.aEnd
.Tab();
3710 for (SCTAB i
=rRange
.aStart
.Tab(); i
<=nTab2
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
3711 if (maTabs
[i
]) maTabs
[i
]->SetDirty( rRange
,
3712 (bIncludeEmptyCells
? ScColumn::BROADCAST_BROADCASTERS
: ScColumn::BROADCAST_DATA_POSITIONS
));
3714 /* TODO: this now also notifies conditional formatting and does an UNO
3715 * broadcast, which wasn't done here before. Is that an actually
3716 * desired side effect, or should we come up with a method that
3718 if (bIncludeEmptyCells
)
3719 BroadcastCells( rRange
, SC_HINT_DATACHANGED
, false);
3721 SetAutoCalc( bOldAutoCalc
);
3724 void ScDocument::SetTableOpDirty( const ScRange
& rRange
)
3726 bool bOldAutoCalc
= GetAutoCalc();
3727 bAutoCalc
= false; // no multiple recalculation
3728 SCTAB nTab2
= rRange
.aEnd
.Tab();
3729 for (SCTAB i
=rRange
.aStart
.Tab(); i
<=nTab2
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
3730 if (maTabs
[i
]) maTabs
[i
]->SetTableOpDirty( rRange
);
3731 SetAutoCalc( bOldAutoCalc
);
3734 void ScDocument::InterpretDirtyCells( const ScRangeList
& rRanges
)
3739 mpFormulaGroupCxt
.reset();
3741 for (size_t nPos
=0, nRangeCount
= rRanges
.size(); nPos
< nRangeCount
; nPos
++)
3743 const ScRange
& rRange
= *rRanges
[nPos
];
3744 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
3746 ScTable
* pTab
= FetchTable(nTab
);
3750 pTab
->InterpretDirtyCells(
3751 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row());
3755 mpFormulaGroupCxt
.reset();
3758 void ScDocument::AddTableOpFormulaCell( ScFormulaCell
* pCell
)
3760 if ( !aTableOpList
.empty() )
3762 ScInterpreterTableOpParams
* p
= &aTableOpList
.back();
3763 if ( p
->bCollectNotifications
)
3766 { // refresh pointers only
3767 p
->aNotifiedFormulaCells
.push_back( pCell
);
3770 { // init both, address and pointer
3771 p
->aNotifiedFormulaCells
.push_back( pCell
);
3772 p
->aNotifiedFormulaPos
.push_back( pCell
->aPos
);
3778 void ScDocument::CalcAll()
3780 ClearFormulaContext();
3781 ClearLookupCaches(); // Ensure we don't deliver zombie data.
3782 sc::AutoCalcSwitch
aSwitch(*this, true);
3783 TableContainer::iterator it
= maTabs
.begin();
3784 for (; it
!= maTabs
.end(); ++it
)
3786 (*it
)->SetDirtyVar();
3787 for (it
= maTabs
.begin(); it
!= maTabs
.end(); ++it
)
3792 // In hard recalc state caches were not added as listeners, invalidate them
3793 // so the next non-CalcAll() normal lookup will not be presented with
3795 /* TODO: come up with more detailed hard recalc states so we can
3796 * differentiate between hard recalc after load and others. */
3797 if (GetHardRecalcState())
3798 ClearLookupCaches();
3801 void ScDocument::CompileAll()
3803 sc::CompileFormulaContext
aCxt(this);
3804 TableContainer::iterator it
= maTabs
.begin();
3805 for (; it
!= maTabs
.end(); ++it
)
3807 (*it
)->CompileAll(aCxt
);
3809 sc::SetFormulaDirtyContext aFormulaDirtyCxt
;
3810 SetAllFormulasDirty(aFormulaDirtyCxt
);
3815 class CompileXMLHandler
: std::unary_function
<ScTable
*, void>
3817 sc::CompileFormulaContext
* mpCxt
;
3818 ScProgress
* mpProgress
;
3820 CompileXMLHandler( sc::CompileFormulaContext
& rCxt
, ScProgress
& rProgress
) :
3821 mpCxt(&rCxt
), mpProgress(&rProgress
) {} // Take pointers to make it copyable.
3823 void operator() ( ScTable
* pTab
)
3826 pTab
->CompileXML(*mpCxt
, *mpProgress
);
3832 void ScDocument::CompileXML()
3834 bool bOldAutoCalc
= GetAutoCalc();
3835 SetAutoCalc( false );
3836 ScProgress
aProgress( GetDocumentShell(), ScGlobal::GetRscString(
3837 STR_PROGRESS_CALCULATING
), GetXMLImportedFormulaCount() );
3839 sc::CompileFormulaContext
aCxt(this);
3841 // set AutoNameCache to speed up automatic name lookup
3842 OSL_ENSURE( !pAutoNameCache
, "AutoNameCache already set" );
3843 pAutoNameCache
= new ScAutoNameCache( this );
3846 pRangeName
->CompileUnresolvedXML(aCxt
);
3848 std::for_each(maTabs
.begin(), maTabs
.end(), CompileXMLHandler(aCxt
, aProgress
));
3849 StartAllListeners();
3851 DELETEZ( pAutoNameCache
); // valid only during CompileXML, where cell contents don't change
3853 if ( pValidationList
)
3854 pValidationList
->CompileXML();
3856 // Track all formula cells that were appended to the FormulaTrack during
3857 // import or CompileXML().
3860 SetAutoCalc( bOldAutoCalc
);
3863 bool ScDocument::CompileErrorCells(sal_uInt16 nErrCode
)
3865 bool bCompiled
= false;
3866 sc::CompileFormulaContext
aCxt(this);
3867 TableContainer::iterator it
= maTabs
.begin(), itEnd
= maTabs
.end();
3868 for (; it
!= itEnd
; ++it
)
3870 ScTable
* pTab
= *it
;
3874 if (pTab
->CompileErrorCells(aCxt
, nErrCode
))
3881 void ScDocument::CalcAfterLoad( bool bStartListening
)
3883 if (bIsClip
) // Excel data is loaded from the Clipboard to a Clip-Doc
3884 return; // the clculation is then only perfromed when inserting into the real document
3886 bCalcingAfterLoad
= true;
3887 sc::CompileFormulaContext
aCxt(this);
3889 TableContainer::iterator it
= maTabs
.begin();
3890 for (; it
!= maTabs
.end(); ++it
)
3892 (*it
)->CalcAfterLoad(aCxt
, bStartListening
);
3893 for (it
= maTabs
.begin(); it
!= maTabs
.end(); ++it
)
3895 (*it
)->SetDirtyAfterLoad();
3897 bCalcingAfterLoad
= false;
3899 SetDetectiveDirty(false); // No real changes yet
3901 // #i112436# If formula cells are already dirty, they don't broadcast further changes.
3902 // So the source ranges of charts must be interpreted even if they are not visible,
3903 // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899).
3904 if (pChartListenerCollection
)
3906 const ScChartListenerCollection::ListenersType
& rListeners
= pChartListenerCollection
->getListeners();
3907 ScChartListenerCollection::ListenersType::const_iterator it
= rListeners
.begin(), itEnd
= rListeners
.end();
3908 for (; it
!= itEnd
; ++it
)
3910 const ScChartListener
* p
= it
->second
;
3911 InterpretDirtyCells(*p
->GetRangeList());
3916 sal_uInt16
ScDocument::GetErrCode( const ScAddress
& rPos
) const
3918 SCTAB nTab
= rPos
.Tab();
3919 if ( nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3920 return maTabs
[nTab
]->GetErrCode( rPos
);
3924 void ScDocument::ResetChanged( const ScRange
& rRange
)
3926 SCTAB nTabSize
= static_cast<SCTAB
>(maTabs
.size());
3927 SCTAB nTab1
= rRange
.aStart
.Tab();
3928 SCTAB nTab2
= rRange
.aEnd
.Tab();
3929 for (SCTAB nTab
= nTab1
; nTab1
<= nTab2
&& nTab
< nTabSize
; ++nTab
)
3931 maTabs
[nTab
]->ResetChanged(rRange
);
3934 // Column widths / Row heights --------------------------------------
3936 void ScDocument::SetColWidth( SCCOL nCol
, SCTAB nTab
, sal_uInt16 nNewWidth
)
3938 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3939 maTabs
[nTab
]->SetColWidth( nCol
, nNewWidth
);
3942 void ScDocument::SetColWidthOnly( SCCOL nCol
, SCTAB nTab
, sal_uInt16 nNewWidth
)
3944 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3945 maTabs
[nTab
]->SetColWidthOnly( nCol
, nNewWidth
);
3948 void ScDocument::SetRowHeight( SCROW nRow
, SCTAB nTab
, sal_uInt16 nNewHeight
)
3950 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3951 maTabs
[nTab
]->SetRowHeight( nRow
, nNewHeight
);
3954 void ScDocument::SetRowHeightRange( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, sal_uInt16 nNewHeight
)
3956 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3957 maTabs
[nTab
]->SetRowHeightRange
3958 ( nStartRow
, nEndRow
, nNewHeight
, 1.0, 1.0 );
3961 void ScDocument::SetRowHeightOnly( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, sal_uInt16 nNewHeight
)
3963 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3964 maTabs
[nTab
]->SetRowHeightOnly( nStartRow
, nEndRow
, nNewHeight
);
3967 void ScDocument::SetManualHeight( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, bool bManual
)
3969 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3970 maTabs
[nTab
]->SetManualHeight( nStartRow
, nEndRow
, bManual
);
3973 sal_uInt16
ScDocument::GetColWidth( SCCOL nCol
, SCTAB nTab
, bool bHiddenAsZero
) const
3975 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3976 return maTabs
[nTab
]->GetColWidth( nCol
, bHiddenAsZero
);
3977 OSL_FAIL("wrong table number");
3981 sal_uLong
ScDocument::GetColWidth( SCCOL nStartCol
, SCCOL nEndCol
, SCTAB nTab
, bool bHiddenAsZero
) const
3983 const ScTable
* pTab
= FetchTable(nTab
);
3987 return pTab
->GetColWidth(nStartCol
, nEndCol
, bHiddenAsZero
);
3990 sal_uInt16
ScDocument::GetOriginalWidth( SCCOL nCol
, SCTAB nTab
) const
3992 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
3993 return maTabs
[nTab
]->GetOriginalWidth( nCol
);
3994 OSL_FAIL("wrong table number");
3998 sal_uInt16
ScDocument::GetCommonWidth( SCCOL nEndCol
, SCTAB nTab
) const
4000 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4001 return maTabs
[nTab
]->GetCommonWidth( nEndCol
);
4002 OSL_FAIL("Wrong table number");
4006 sal_uInt16
ScDocument::GetOriginalHeight( SCROW nRow
, SCTAB nTab
) const
4008 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4009 return maTabs
[nTab
]->GetOriginalHeight( nRow
);
4010 OSL_FAIL("Wrong table number");
4014 sal_uInt16
ScDocument::GetRowHeight( SCROW nRow
, SCTAB nTab
, bool bHiddenAsZero
) const
4016 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4017 return maTabs
[nTab
]->GetRowHeight( nRow
, NULL
, NULL
, bHiddenAsZero
);
4018 OSL_FAIL("Wrong sheet number");
4022 sal_uInt16
ScDocument::GetRowHeight( SCROW nRow
, SCTAB nTab
, SCROW
* pStartRow
, SCROW
* pEndRow
, bool bHiddenAsZero
) const
4024 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4025 return maTabs
[nTab
]->GetRowHeight( nRow
, pStartRow
, pEndRow
, bHiddenAsZero
);
4026 OSL_FAIL("Wrong sheet number");
4030 sal_uLong
ScDocument::GetRowHeight( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, bool bHiddenAsZero
) const
4032 if (nStartRow
== nEndRow
)
4033 return GetRowHeight( nStartRow
, nTab
, bHiddenAsZero
); // faster for a single row
4035 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
4036 if (nStartRow
> nEndRow
)
4039 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4040 return maTabs
[nTab
]->GetRowHeight( nStartRow
, nEndRow
, bHiddenAsZero
);
4042 OSL_FAIL("wrong sheet number");
4046 SCROW
ScDocument::GetRowForHeight( SCTAB nTab
, sal_uLong nHeight
) const
4048 return maTabs
[nTab
]->GetRowForHeight(nHeight
);
4051 sal_uLong
ScDocument::GetScaledRowHeight( SCROW nStartRow
, SCROW nEndRow
,
4052 SCTAB nTab
, double fScale
) const
4054 // faster for a single row
4055 if (nStartRow
== nEndRow
)
4056 return (sal_uLong
) (GetRowHeight( nStartRow
, nTab
) * fScale
);
4058 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
4059 if (nStartRow
> nEndRow
)
4062 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4063 return maTabs
[nTab
]->GetScaledRowHeight( nStartRow
, nEndRow
, fScale
);
4065 OSL_FAIL("wrong sheet number");
4069 SCROW
ScDocument::GetHiddenRowCount( SCROW nRow
, SCTAB nTab
) const
4071 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4072 return maTabs
[nTab
]->GetHiddenRowCount( nRow
);
4073 OSL_FAIL("wrong table number");
4077 sal_uLong
ScDocument::GetColOffset( SCCOL nCol
, SCTAB nTab
, bool bHiddenAsZero
) const
4079 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4080 return maTabs
[nTab
]->GetColOffset( nCol
, bHiddenAsZero
);
4081 OSL_FAIL("wrong table number");
4085 sal_uLong
ScDocument::GetRowOffset( SCROW nRow
, SCTAB nTab
, bool bHiddenAsZero
) const
4087 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4088 return maTabs
[nTab
]->GetRowOffset( nRow
, bHiddenAsZero
);
4089 OSL_FAIL("wrong table number");
4093 sal_uInt16
ScDocument::GetOptimalColWidth( SCCOL nCol
, SCTAB nTab
, OutputDevice
* pDev
,
4094 double nPPTX
, double nPPTY
,
4095 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
4096 bool bFormula
, const ScMarkData
* pMarkData
,
4097 const ScColWidthParam
* pParam
)
4099 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4100 return maTabs
[nTab
]->GetOptimalColWidth( nCol
, pDev
, nPPTX
, nPPTY
,
4101 rZoomX
, rZoomY
, bFormula
, pMarkData
, pParam
);
4102 OSL_FAIL("wrong table number");
4106 long ScDocument::GetNeededSize( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
4108 double nPPTX
, double nPPTY
,
4109 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
4110 bool bWidth
, bool bTotalSize
)
4112 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4113 return maTabs
[nTab
]->GetNeededSize
4114 ( nCol
, nRow
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bWidth
, bTotalSize
);
4115 OSL_FAIL("wrong table number");
4119 bool ScDocument::SetOptimalHeight( sc::RowHeightContext
& rCxt
, SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
)
4121 ScTable
* pTab
= FetchTable(nTab
);
4125 return pTab
->SetOptimalHeight(rCxt
, nStartRow
, nEndRow
);
4128 void ScDocument::UpdateAllRowHeights( sc::RowHeightContext
& rCxt
, const ScMarkData
* pTabMark
)
4130 // one progress across all (selected) sheets
4132 sal_uLong nCellCount
= 0;
4133 for ( SCTAB nTab
=0; nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++ )
4134 if ( maTabs
[nTab
] && ( !pTabMark
|| pTabMark
->GetTableSelect(nTab
) ) )
4135 nCellCount
+= maTabs
[nTab
]->GetWeightedCount();
4137 ScProgress
aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING
), nCellCount
);
4139 sal_uLong nProgressStart
= 0;
4140 for ( SCTAB nTab
=0; nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++ )
4141 if ( maTabs
[nTab
] && ( !pTabMark
|| pTabMark
->GetTableSelect(nTab
) ) )
4143 maTabs
[nTab
]->SetOptimalHeightOnly(rCxt
, 0, MAXROW
, &aProgress
, nProgressStart
);
4144 maTabs
[nTab
]->SetDrawPageSize(true, true);
4145 nProgressStart
+= maTabs
[nTab
]->GetWeightedCount();
4149 // Column/Row - Flags ----------------------------------------------
4151 void ScDocument::ShowCol(SCCOL nCol
, SCTAB nTab
, bool bShow
)
4153 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4154 maTabs
[nTab
]->ShowCol( nCol
, bShow
);
4157 void ScDocument::ShowRow(SCROW nRow
, SCTAB nTab
, bool bShow
)
4159 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4160 maTabs
[nTab
]->ShowRow( nRow
, bShow
);
4163 void ScDocument::ShowRows(SCROW nRow1
, SCROW nRow2
, SCTAB nTab
, bool bShow
)
4165 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4166 maTabs
[nTab
]->ShowRows( nRow1
, nRow2
, bShow
);
4169 void ScDocument::SetRowFlags( SCROW nRow
, SCTAB nTab
, sal_uInt8 nNewFlags
)
4171 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4172 maTabs
[nTab
]->SetRowFlags( nRow
, nNewFlags
);
4175 void ScDocument::SetRowFlags( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, sal_uInt8 nNewFlags
)
4177 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4178 maTabs
[nTab
]->SetRowFlags( nStartRow
, nEndRow
, nNewFlags
);
4181 sal_uInt8
ScDocument::GetColFlags( SCCOL nCol
, SCTAB nTab
) const
4183 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4184 return maTabs
[nTab
]->GetColFlags( nCol
);
4185 OSL_FAIL("wrong table number");
4189 sal_uInt8
ScDocument::GetRowFlags( SCROW nRow
, SCTAB nTab
) const
4191 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4192 return maTabs
[nTab
]->GetRowFlags( nRow
);
4193 OSL_FAIL("wrong table number");
4197 void ScDocument::GetAllRowBreaks(set
<SCROW
>& rBreaks
, SCTAB nTab
, bool bPage
, bool bManual
) const
4199 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4201 maTabs
[nTab
]->GetAllRowBreaks(rBreaks
, bPage
, bManual
);
4204 void ScDocument::GetAllColBreaks(set
<SCCOL
>& rBreaks
, SCTAB nTab
, bool bPage
, bool bManual
) const
4206 if (!ValidTab(nTab
) || !maTabs
[nTab
])
4209 maTabs
[nTab
]->GetAllColBreaks(rBreaks
, bPage
, bManual
);
4212 ScBreakType
ScDocument::HasRowBreak(SCROW nRow
, SCTAB nTab
) const
4214 ScBreakType nType
= BREAK_NONE
;
4215 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
] || !ValidRow(nRow
))
4218 if (maTabs
[nTab
]->HasRowPageBreak(nRow
))
4219 nType
|= BREAK_PAGE
;
4221 if (maTabs
[nTab
]->HasRowManualBreak(nRow
))
4222 nType
|= BREAK_MANUAL
;
4227 ScBreakType
ScDocument::HasColBreak(SCCOL nCol
, SCTAB nTab
) const
4229 ScBreakType nType
= BREAK_NONE
;
4230 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
] || !ValidCol(nCol
))
4233 if (maTabs
[nTab
]->HasColPageBreak(nCol
))
4234 nType
|= BREAK_PAGE
;
4236 if (maTabs
[nTab
]->HasColManualBreak(nCol
))
4237 nType
|= BREAK_MANUAL
;
4242 void ScDocument::SetRowBreak(SCROW nRow
, SCTAB nTab
, bool bPage
, bool bManual
)
4244 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
] || !ValidRow(nRow
))
4247 maTabs
[nTab
]->SetRowBreak(nRow
, bPage
, bManual
);
4250 void ScDocument::SetColBreak(SCCOL nCol
, SCTAB nTab
, bool bPage
, bool bManual
)
4252 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
] || !ValidCol(nCol
))
4255 maTabs
[nTab
]->SetColBreak(nCol
, bPage
, bManual
);
4258 void ScDocument::RemoveRowBreak(SCROW nRow
, SCTAB nTab
, bool bPage
, bool bManual
)
4260 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
] || !ValidRow(nRow
))
4263 maTabs
[nTab
]->RemoveRowBreak(nRow
, bPage
, bManual
);
4266 void ScDocument::RemoveColBreak(SCCOL nCol
, SCTAB nTab
, bool bPage
, bool bManual
)
4268 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
] || !ValidCol(nCol
))
4271 maTabs
[nTab
]->RemoveColBreak(nCol
, bPage
, bManual
);
4274 Sequence
<TablePageBreakData
> ScDocument::GetRowBreakData(SCTAB nTab
) const
4276 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4277 return Sequence
<TablePageBreakData
>();
4279 return maTabs
[nTab
]->GetRowBreakData();
4282 bool ScDocument::RowHidden(SCROW nRow
, SCTAB nTab
, SCROW
* pFirstRow
, SCROW
* pLastRow
) const
4284 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4287 return maTabs
[nTab
]->RowHidden(nRow
, pFirstRow
, pLastRow
);
4290 bool ScDocument::HasHiddenRows(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4292 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4295 return maTabs
[nTab
]->HasHiddenRows(nStartRow
, nEndRow
);
4298 bool ScDocument::ColHidden(SCCOL nCol
, SCTAB nTab
, SCCOL
* pFirstCol
, SCCOL
* pLastCol
) const
4300 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4309 return maTabs
[nTab
]->ColHidden(nCol
, pFirstCol
, pLastCol
);
4312 void ScDocument::SetRowHidden(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, bool bHidden
)
4314 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4317 maTabs
[nTab
]->SetRowHidden(nStartRow
, nEndRow
, bHidden
);
4320 void ScDocument::SetColHidden(SCCOL nStartCol
, SCCOL nEndCol
, SCTAB nTab
, bool bHidden
)
4322 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4325 maTabs
[nTab
]->SetColHidden(nStartCol
, nEndCol
, bHidden
);
4328 SCROW
ScDocument::FirstVisibleRow(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4330 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4331 return ::std::numeric_limits
<SCROW
>::max();
4333 return maTabs
[nTab
]->FirstVisibleRow(nStartRow
, nEndRow
);
4336 SCROW
ScDocument::LastVisibleRow(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4338 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4339 return ::std::numeric_limits
<SCROW
>::max();
4341 return maTabs
[nTab
]->LastVisibleRow(nStartRow
, nEndRow
);
4344 SCROW
ScDocument::CountVisibleRows(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4346 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4349 return maTabs
[nTab
]->CountVisibleRows(nStartRow
, nEndRow
);
4352 bool ScDocument::RowFiltered(SCROW nRow
, SCTAB nTab
, SCROW
* pFirstRow
, SCROW
* pLastRow
) const
4354 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4357 return maTabs
[nTab
]->RowFiltered(nRow
, pFirstRow
, pLastRow
);
4360 bool ScDocument::HasFilteredRows(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4362 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4365 return maTabs
[nTab
]->HasFilteredRows(nStartRow
, nEndRow
);
4368 bool ScDocument::ColFiltered(SCCOL nCol
, SCTAB nTab
, SCCOL
* pFirstCol
, SCCOL
* pLastCol
) const
4370 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4373 return maTabs
[nTab
]->ColFiltered(nCol
, pFirstCol
, pLastCol
);
4376 void ScDocument::SetRowFiltered(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, bool bFiltered
)
4378 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4381 maTabs
[nTab
]->SetRowFiltered(nStartRow
, nEndRow
, bFiltered
);
4384 SCROW
ScDocument::FirstNonFilteredRow(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4386 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4387 return ::std::numeric_limits
<SCROW
>::max();
4389 return maTabs
[nTab
]->FirstNonFilteredRow(nStartRow
, nEndRow
);
4392 SCROW
ScDocument::LastNonFilteredRow(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4394 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4395 return ::std::numeric_limits
<SCROW
>::max();
4397 return maTabs
[nTab
]->LastNonFilteredRow(nStartRow
, nEndRow
);
4400 SCROW
ScDocument::CountNonFilteredRows(SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4402 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4405 return maTabs
[nTab
]->CountNonFilteredRows(nStartRow
, nEndRow
);
4408 bool ScDocument::IsManualRowHeight(SCROW nRow
, SCTAB nTab
) const
4410 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4413 return maTabs
[nTab
]->IsManualRowHeight(nRow
);
4416 void ScDocument::SyncColRowFlags()
4418 TableContainer::iterator it
= maTabs
.begin();
4419 for (; it
!= maTabs
.end(); ++it
)
4422 (*it
)->SyncColRowFlags();
4426 SCROW
ScDocument::GetLastFlaggedRow( SCTAB nTab
) const
4428 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4429 return maTabs
[nTab
]->GetLastFlaggedRow();
4433 SCCOL
ScDocument::GetLastChangedCol( SCTAB nTab
) const
4435 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4436 return maTabs
[nTab
]->GetLastChangedCol();
4440 SCROW
ScDocument::GetLastChangedRow( SCTAB nTab
) const
4442 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4443 return maTabs
[nTab
]->GetLastChangedRow();
4447 SCCOL
ScDocument::GetNextDifferentChangedCol( SCTAB nTab
, SCCOL nStart
) const
4449 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4451 sal_uInt8 nStartFlags
= maTabs
[nTab
]->GetColFlags(nStart
);
4452 sal_uInt16 nStartWidth
= maTabs
[nTab
]->GetOriginalWidth(nStart
);
4453 for (SCCOL nCol
= nStart
+ 1; nCol
<= MAXCOL
; nCol
++)
4455 if (((nStartFlags
& CR_MANUALBREAK
) != (maTabs
[nTab
]->GetColFlags(nCol
) & CR_MANUALBREAK
)) ||
4456 (nStartWidth
!= maTabs
[nTab
]->GetOriginalWidth(nCol
)) ||
4457 ((nStartFlags
& CR_HIDDEN
) != (maTabs
[nTab
]->GetColFlags(nCol
) & CR_HIDDEN
)) )
4465 SCROW
ScDocument::GetNextDifferentChangedRow( SCTAB nTab
, SCROW nStart
, bool bCareManualSize
) const
4467 if (!ValidTab(nTab
) || nTab
>= static_cast<SCTAB
>(maTabs
.size()) || !maTabs
[nTab
])
4470 const ScBitMaskCompressedArray
<SCROW
, sal_uInt8
>* pRowFlagsArray
= maTabs
[nTab
]->GetRowFlagsArray();
4471 if (!pRowFlagsArray
)
4474 if (!maTabs
[nTab
]->mpRowHeights
|| !maTabs
[nTab
]->mpHiddenRows
)
4477 size_t nIndex
; // ignored
4479 SCROW nHiddenEndRow
;
4480 SCROW nHeightEndRow
;
4484 sal_uInt8 nStartFlags
= nFlags
= pRowFlagsArray
->GetValue( nStart
, nIndex
, nFlagsEndRow
);
4485 bool bStartHidden
= bHidden
= maTabs
[nTab
]->RowHidden( nStart
, NULL
, &nHiddenEndRow
);
4486 sal_uInt16 nStartHeight
= nHeight
= maTabs
[nTab
]->GetRowHeight( nStart
, NULL
, &nHeightEndRow
, false);
4488 while ((nRow
= std::min( nHiddenEndRow
, std::min( nFlagsEndRow
, nHeightEndRow
)) + 1) <= MAXROW
)
4490 if (nFlagsEndRow
< nRow
)
4491 nFlags
= pRowFlagsArray
->GetValue( nRow
, nIndex
, nFlagsEndRow
);
4492 if (nHiddenEndRow
< nRow
)
4493 bHidden
= maTabs
[nTab
]->RowHidden( nRow
, NULL
, &nHiddenEndRow
);
4494 if (nHeightEndRow
< nRow
)
4495 nHeight
= maTabs
[nTab
]->GetRowHeight( nRow
, NULL
, &nHeightEndRow
, false);
4497 if (((nStartFlags
& CR_MANUALBREAK
) != (nFlags
& CR_MANUALBREAK
)) ||
4498 ((nStartFlags
& CR_MANUALSIZE
) != (nFlags
& CR_MANUALSIZE
)) ||
4499 (bStartHidden
!= bHidden
) ||
4500 (bCareManualSize
&& (nStartFlags
& CR_MANUALSIZE
) && (nStartHeight
!= nHeight
)) ||
4501 (!bCareManualSize
&& ((nStartHeight
!= nHeight
))))
4508 bool ScDocument::GetColDefault( SCTAB nTab
, SCCOL nCol
, SCROW nLastRow
, SCROW
& nDefault
)
4512 ScDocAttrIterator
aDocAttrItr(this, nTab
, nCol
, 0, nCol
, nLastRow
);
4516 const ScPatternAttr
* pAttr
= aDocAttrItr
.GetNext(nColumn
, nStartRow
, nEndRow
);
4517 if (nEndRow
< nLastRow
)
4519 ScDefaultAttrSet aSet
;
4520 ScDefaultAttrSet::iterator aItr
= aSet
.end();
4523 ScDefaultAttr
aAttr(pAttr
);
4524 aItr
= aSet
.find(aAttr
);
4525 if (aItr
== aSet
.end())
4527 aAttr
.nCount
= static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
4528 aAttr
.nFirst
= nStartRow
;
4533 aAttr
.nCount
= aItr
->nCount
+ static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
4534 aAttr
.nFirst
= aItr
->nFirst
;
4538 pAttr
= aDocAttrItr
.GetNext(nColumn
, nStartRow
, nEndRow
);
4540 ScDefaultAttrSet::iterator aDefaultItr
= aSet
.begin();
4543 while (aItr
!= aSet
.end())
4545 // for entries with equal count, use the one with the lowest start row,
4546 // don't use the random order of pointer comparisons
4547 if ( aItr
->nCount
> aDefaultItr
->nCount
||
4548 ( aItr
->nCount
== aDefaultItr
->nCount
&& aItr
->nFirst
< aDefaultItr
->nFirst
) )
4552 nDefault
= aDefaultItr
->nFirst
;
4560 void ScDocument::StripHidden( SCCOL
& rX1
, SCROW
& rY1
, SCCOL
& rX2
, SCROW
& rY2
, SCTAB nTab
)
4562 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4563 maTabs
[nTab
]->StripHidden( rX1
, rY1
, rX2
, rY2
);
4566 void ScDocument::ExtendHidden( SCCOL
& rX1
, SCROW
& rY1
, SCCOL
& rX2
, SCROW
& rY2
, SCTAB nTab
)
4568 if ( ValidTab(nTab
) && maTabs
[nTab
] )
4569 maTabs
[nTab
]->ExtendHidden( rX1
, rY1
, rX2
, rY2
);
4572 // Attribute ----------------------------------------------------------
4574 const SfxPoolItem
* ScDocument::GetAttr( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, sal_uInt16 nWhich
) const
4576 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4578 const SfxPoolItem
* pTemp
= maTabs
[nTab
]->GetAttr( nCol
, nRow
, nWhich
);
4583 OSL_FAIL( "Attribut Null" );
4586 return &xPoolHelper
->GetDocPool()->GetDefaultItem( nWhich
);
4589 const SfxPoolItem
* ScDocument::GetAttr( const ScAddress
& rPos
, sal_uInt16 nWhich
) const
4591 return GetAttr(rPos
.Col(), rPos
.Row(), rPos
.Tab(), nWhich
);
4594 const ScPatternAttr
* ScDocument::GetPattern( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
4596 if (TableExists(nTab
))
4597 return maTabs
[nTab
]->GetPattern( nCol
, nRow
);
4601 const ScPatternAttr
* ScDocument::GetPattern( const ScAddress
& rPos
) const
4603 if (TableExists(rPos
.Tab()))
4604 return maTabs
[rPos
.Tab()]->GetPattern(rPos
.Col(), rPos
.Row());
4609 const ScPatternAttr
* ScDocument::GetMostUsedPattern( SCCOL nCol
, SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
4611 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4612 return maTabs
[nTab
]->GetMostUsedPattern( nCol
, nStartRow
, nEndRow
);
4616 void ScDocument::ApplyAttr( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const SfxPoolItem
& rAttr
)
4618 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4619 maTabs
[nTab
]->ApplyAttr( nCol
, nRow
, rAttr
);
4622 void ScDocument::ApplyPattern( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const ScPatternAttr
& rAttr
)
4624 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4625 maTabs
[nTab
]->ApplyPattern( nCol
, nRow
, rAttr
);
4628 void ScDocument::ApplyPatternArea( SCCOL nStartCol
, SCROW nStartRow
,
4629 SCCOL nEndCol
, SCROW nEndRow
,
4630 const ScMarkData
& rMark
,
4631 const ScPatternAttr
& rAttr
,
4632 ScEditDataArray
* pDataArray
)
4634 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4635 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4636 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4638 maTabs
[*itr
]->ApplyPatternArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rAttr
, pDataArray
);
4641 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol
, SCROW nStartRow
,
4642 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, const ScPatternAttr
& rAttr
)
4644 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
4646 maTabs
[nTab
]->ApplyPatternArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rAttr
);
4649 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange
& rRange
,
4650 const ScMarkData
& rMark
, const ScPatternAttr
& rPattern
, short nNewType
)
4652 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4653 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4654 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4656 maTabs
[*itr
]->ApplyPatternIfNumberformatIncompatible( rRange
, rPattern
, nNewType
);
4659 void ScDocument::AddCondFormatData( const ScRangeList
& rRange
, SCTAB nTab
, sal_uInt32 nIndex
)
4661 if(!(static_cast<size_t>(nTab
) < maTabs
.size()))
4667 maTabs
[nTab
]->AddCondFormatData(rRange
, nIndex
);
4670 void ScDocument::RemoveCondFormatData( const ScRangeList
& rRange
, SCTAB nTab
, sal_uInt32 nIndex
)
4672 if(!(static_cast<size_t>(nTab
) < maTabs
.size()))
4678 maTabs
[nTab
]->RemoveCondFormatData(rRange
, nIndex
);
4681 void ScDocument::ApplyStyle( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const ScStyleSheet
& rStyle
)
4683 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
4685 maTabs
[nTab
]->ApplyStyle( nCol
, nRow
, rStyle
);
4688 void ScDocument::ApplyStyleArea( SCCOL nStartCol
, SCROW nStartRow
,
4689 SCCOL nEndCol
, SCROW nEndRow
,
4690 const ScMarkData
& rMark
,
4691 const ScStyleSheet
& rStyle
)
4693 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4694 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4695 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4697 maTabs
[*itr
]->ApplyStyleArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rStyle
);
4700 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol
, SCROW nStartRow
,
4701 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, const ScStyleSheet
& rStyle
)
4703 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
4705 maTabs
[nTab
]->ApplyStyleArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rStyle
);
4708 void ScDocument::ApplySelectionStyle(const ScStyleSheet
& rStyle
, const ScMarkData
& rMark
)
4710 // ApplySelectionStyle needs multi mark
4711 if ( rMark
.IsMarked() && !rMark
.IsMultiMarked() )
4714 rMark
.GetMarkArea( aRange
);
4715 ApplyStyleArea( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
4716 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), rMark
, rStyle
);
4720 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4721 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4722 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4724 maTabs
[*itr
]->ApplySelectionStyle( rStyle
, rMark
);
4728 void ScDocument::ApplySelectionLineStyle( const ScMarkData
& rMark
,
4729 const SvxBorderLine
* pLine
, bool bColorOnly
)
4731 if ( bColorOnly
&& !pLine
)
4734 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4735 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4736 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4738 maTabs
[*itr
]->ApplySelectionLineStyle( rMark
, pLine
, bColorOnly
);
4741 const ScStyleSheet
* ScDocument::GetStyle( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
4743 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
4744 return maTabs
[nTab
]->GetStyle(nCol
, nRow
);
4749 const ScStyleSheet
* ScDocument::GetSelectionStyle( const ScMarkData
& rMark
) const
4754 const ScStyleSheet
* pStyle
= NULL
;
4755 const ScStyleSheet
* pNewStyle
;
4757 if ( rMark
.IsMultiMarked() )
4759 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4760 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4761 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4764 pNewStyle
= maTabs
[*itr
]->GetSelectionStyle( rMark
, bFound
);
4767 if ( !pNewStyle
|| ( pStyle
&& pNewStyle
!= pStyle
) )
4768 bEqual
= false; // different
4773 if ( rMark
.IsMarked() )
4776 rMark
.GetMarkArea( aRange
);
4777 for (SCTAB i
=aRange
.aStart
.Tab(); i
<=aRange
.aEnd
.Tab() && bEqual
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
4778 if (maTabs
[i
] && rMark
.GetTableSelect(i
))
4780 pNewStyle
= maTabs
[i
]->GetAreaStyle( bFound
,
4781 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
4782 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
4785 if ( !pNewStyle
|| ( pStyle
&& pNewStyle
!= pStyle
) )
4786 bEqual
= false; // different
4792 return bEqual
? pStyle
: NULL
;
4795 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase
* pStyleSheet
, bool bRemoved
,
4797 double nPPTX
, double nPPTY
,
4798 const Fraction
& rZoomX
, const Fraction
& rZoomY
)
4800 TableContainer::iterator it
= maTabs
.begin();
4801 for (; it
!= maTabs
.end(); ++it
)
4803 (*it
)->StyleSheetChanged
4804 ( pStyleSheet
, bRemoved
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
);
4806 if ( pStyleSheet
&& pStyleSheet
->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) )
4808 // update attributes for all note objects
4809 ScDetectiveFunc::UpdateAllComments( *this );
4813 bool ScDocument::IsStyleSheetUsed( const ScStyleSheet
& rStyle
, bool bGatherAllStyles
) const
4815 if ( bStyleSheetUsageInvalid
|| rStyle
.GetUsage() == ScStyleSheet::UNKNOWN
)
4817 if ( bGatherAllStyles
)
4819 SfxStyleSheetIterator
aIter( xPoolHelper
->GetStylePool(),
4820 SFX_STYLE_FAMILY_PARA
);
4821 for ( const SfxStyleSheetBase
* pStyle
= aIter
.First(); pStyle
;
4822 pStyle
= aIter
.Next() )
4824 const ScStyleSheet
* pScStyle
= PTR_CAST( ScStyleSheet
, pStyle
);
4826 pScStyle
->SetUsage( ScStyleSheet::NOTUSED
);
4830 bool bIsUsed
= false;
4832 TableContainer::const_iterator it
= maTabs
.begin();
4833 for (; it
!= maTabs
.end(); ++it
)
4836 if ( (*it
)->IsStyleSheetUsed( rStyle
, bGatherAllStyles
) )
4838 if ( !bGatherAllStyles
)
4844 if ( bGatherAllStyles
)
4845 bStyleSheetUsageInvalid
= false;
4850 return rStyle
.GetUsage() == ScStyleSheet::USED
;
4853 bool ScDocument::ApplyFlagsTab( SCCOL nStartCol
, SCROW nStartRow
,
4854 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, sal_Int16 nFlags
)
4856 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
4858 return maTabs
[nTab
]->ApplyFlags( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nFlags
);
4860 OSL_FAIL("ApplyFlags: wrong table");
4864 bool ScDocument::RemoveFlagsTab( SCCOL nStartCol
, SCROW nStartRow
,
4865 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, sal_Int16 nFlags
)
4867 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
4869 return maTabs
[nTab
]->RemoveFlags( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nFlags
);
4871 OSL_FAIL("RemoveFlags: wrong table");
4875 void ScDocument::SetPattern( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const ScPatternAttr
& rAttr
,
4878 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
4880 maTabs
[nTab
]->SetPattern( nCol
, nRow
, rAttr
, bPutToPool
);
4883 void ScDocument::SetPattern( const ScAddress
& rPos
, const ScPatternAttr
& rAttr
,
4886 SCTAB nTab
= rPos
.Tab();
4887 if ( nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
4888 maTabs
[nTab
]->SetPattern( rPos
, rAttr
, bPutToPool
);
4891 ScPatternAttr
* ScDocument::CreateSelectionPattern( const ScMarkData
& rMark
, bool bDeep
)
4893 ScMergePatternState aState
;
4895 if ( rMark
.IsMultiMarked() ) // multi selection
4897 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4898 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4899 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4901 maTabs
[*itr
]->MergeSelectionPattern( aState
, rMark
, bDeep
);
4903 if ( rMark
.IsMarked() ) // single selection
4906 rMark
.GetMarkArea(aRange
);
4907 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4908 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4909 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4911 maTabs
[*itr
]->MergePatternArea( aState
,
4912 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
4913 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), bDeep
);
4916 OSL_ENSURE( aState
.pItemSet
, "SelectionPattern Null" );
4917 if (aState
.pItemSet
)
4918 return new ScPatternAttr( aState
.pItemSet
);
4920 return new ScPatternAttr( GetPool() ); // empty
4923 const ScPatternAttr
* ScDocument::GetSelectionPattern( const ScMarkData
& rMark
, bool bDeep
)
4925 delete pSelectionAttr
;
4926 pSelectionAttr
= CreateSelectionPattern( rMark
, bDeep
);
4927 return pSelectionAttr
;
4930 void ScDocument::GetSelectionFrame( const ScMarkData
& rMark
,
4931 SvxBoxItem
& rLineOuter
,
4932 SvxBoxInfoItem
& rLineInner
)
4934 rLineOuter
.SetLine(NULL
, SvxBoxItemLine::TOP
);
4935 rLineOuter
.SetLine(NULL
, SvxBoxItemLine::BOTTOM
);
4936 rLineOuter
.SetLine(NULL
, SvxBoxItemLine::LEFT
);
4937 rLineOuter
.SetLine(NULL
, SvxBoxItemLine::RIGHT
);
4938 rLineOuter
.SetDistance(0);
4940 rLineInner
.SetLine(NULL
, SvxBoxInfoItemLine::HORI
);
4941 rLineInner
.SetLine(NULL
, SvxBoxInfoItemLine::VERT
);
4942 rLineInner
.SetTable(true);
4943 rLineInner
.SetDist(true);
4944 rLineInner
.SetMinDist(false);
4948 if (rMark
.IsMarked())
4951 rMark
.GetMarkArea(aRange
);
4952 rLineInner
.EnableHor( aRange
.aStart
.Row() != aRange
.aEnd
.Row() );
4953 rLineInner
.EnableVer( aRange
.aStart
.Col() != aRange
.aEnd
.Col() );
4954 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
4955 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
4956 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
4958 maTabs
[*itr
]->MergeBlockFrame( &rLineOuter
, &rLineInner
, aFlags
,
4959 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
4960 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
4963 // Evaluate don't care Status
4965 rLineInner
.SetValid( SvxBoxInfoItemValidFlags::LEFT
, ( aFlags
.nLeft
!= SC_LINE_DONTCARE
) );
4966 rLineInner
.SetValid( SvxBoxInfoItemValidFlags::RIGHT
, ( aFlags
.nRight
!= SC_LINE_DONTCARE
) );
4967 rLineInner
.SetValid( SvxBoxInfoItemValidFlags::TOP
, ( aFlags
.nTop
!= SC_LINE_DONTCARE
) );
4968 rLineInner
.SetValid( SvxBoxInfoItemValidFlags::BOTTOM
, ( aFlags
.nBottom
!= SC_LINE_DONTCARE
) );
4969 rLineInner
.SetValid( SvxBoxInfoItemValidFlags::HORI
, ( aFlags
.nHori
!= SC_LINE_DONTCARE
) );
4970 rLineInner
.SetValid( SvxBoxInfoItemValidFlags::VERT
, ( aFlags
.nVert
!= SC_LINE_DONTCARE
) );
4973 bool ScDocument::HasAttrib( SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
4974 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
, sal_uInt16 nMask
) const
4976 if ( nMask
& HASATTR_ROTATE
)
4978 // Is attribute used in document?
4981 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
4983 bool bAnyItem
= false;
4984 sal_uInt32 nRotCount
= pPool
->GetItemCount2( ATTR_ROTATE_VALUE
);
4985 for (sal_uInt32 nItem
=0; nItem
<nRotCount
; nItem
++)
4987 const SfxPoolItem
* pItem
= pPool
->GetItem2( ATTR_ROTATE_VALUE
, nItem
);
4990 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
4991 // (see ScPatternAttr::GetCellOrientation)
4992 sal_Int32 nAngle
= static_cast<const SfxInt32Item
*>(pItem
)->GetValue();
4993 if ( nAngle
!= 0 && nAngle
!= 9000 && nAngle
!= 27000 )
5001 nMask
&= ~HASATTR_ROTATE
;
5004 if ( nMask
& HASATTR_RTL
)
5006 // first check if right-to left is in the pool at all
5007 // (the same item is used in cell and page format)
5009 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
5011 bool bHasRtl
= false;
5012 sal_uInt32 nDirCount
= pPool
->GetItemCount2( ATTR_WRITINGDIR
);
5013 for (sal_uInt32 nItem
=0; nItem
<nDirCount
; nItem
++)
5015 const SfxPoolItem
* pItem
= pPool
->GetItem2( ATTR_WRITINGDIR
, nItem
);
5016 if ( pItem
&& static_cast<const SvxFrameDirectionItem
*>(pItem
)->GetValue() == FRMDIR_HORI_RIGHT_TOP
)
5023 nMask
&= ~HASATTR_RTL
;
5029 bool bFound
= false;
5030 for (SCTAB i
=nTab1
; i
<=nTab2
&& !bFound
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
5033 if ( nMask
& HASATTR_RTL
)
5035 if ( GetEditTextDirection(i
) == EE_HTEXTDIR_R2L
) // sheet default
5038 if ( nMask
& HASATTR_RIGHTORCENTER
)
5040 // On a RTL sheet, don't start to look for the default left value
5041 // (which is then logically right), instead always assume true.
5042 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets.
5044 if ( IsLayoutRTL(i
) )
5049 bFound
= maTabs
[i
]->HasAttrib( nCol1
, nRow1
, nCol2
, nRow2
, nMask
);
5055 bool ScDocument::HasAttrib( const ScRange
& rRange
, sal_uInt16 nMask
) const
5057 return HasAttrib( rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
5058 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(),
5062 void ScDocument::FindMaxRotCol( SCTAB nTab
, RowInfo
* pRowInfo
, SCSIZE nArrCount
,
5063 SCCOL nX1
, SCCOL nX2
) const
5065 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5066 maTabs
[nTab
]->FindMaxRotCol( pRowInfo
, nArrCount
, nX1
, nX2
);
5069 OSL_FAIL("FindMaxRotCol: wrong table");
5073 void ScDocument::GetBorderLines( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
5074 const SvxBorderLine
** ppLeft
, const SvxBorderLine
** ppTop
,
5075 const SvxBorderLine
** ppRight
, const SvxBorderLine
** ppBottom
) const
5077 //TODO: consider page limits for printing !!!!!
5079 const SvxBoxItem
* pThisAttr
= static_cast<const SvxBoxItem
*>( GetEffItem( nCol
, nRow
, nTab
, ATTR_BORDER
) );
5080 OSL_ENSURE(pThisAttr
,"where is the attribute?");
5082 const SvxBorderLine
* pLeftLine
= pThisAttr
->GetLeft();
5083 const SvxBorderLine
* pTopLine
= pThisAttr
->GetTop();
5084 const SvxBorderLine
* pRightLine
= pThisAttr
->GetRight();
5085 const SvxBorderLine
* pBottomLine
= pThisAttr
->GetBottom();
5089 const SvxBorderLine
* pOther
= static_cast<const SvxBoxItem
*>(
5090 GetEffItem( nCol
-1, nRow
, nTab
, ATTR_BORDER
))->GetRight();
5091 if ( ScHasPriority( pOther
, pLeftLine
) )
5096 const SvxBorderLine
* pOther
= static_cast<const SvxBoxItem
*>(
5097 GetEffItem( nCol
, nRow
-1, nTab
, ATTR_BORDER
))->GetBottom();
5098 if ( ScHasPriority( pOther
, pTopLine
) )
5101 if ( nCol
< MAXCOL
)
5103 const SvxBorderLine
* pOther
= static_cast<const SvxBoxItem
*>(
5104 GetEffItem( nCol
+1, nRow
, nTab
, ATTR_BORDER
))->GetLeft();
5105 if ( ScHasPriority( pOther
, pRightLine
) )
5106 pRightLine
= pOther
;
5108 if ( nRow
< MAXROW
)
5110 const SvxBorderLine
* pOther
= static_cast<const SvxBoxItem
*>(
5111 GetEffItem( nCol
, nRow
+1, nTab
, ATTR_BORDER
))->GetTop();
5112 if ( ScHasPriority( pOther
, pBottomLine
) )
5113 pBottomLine
= pOther
;
5117 *ppLeft
= pLeftLine
;
5121 *ppRight
= pRightLine
;
5123 *ppBottom
= pBottomLine
;
5126 bool ScDocument::IsBlockEmpty( SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
,
5127 SCCOL nEndCol
, SCROW nEndRow
, bool bIgnoreNotes
) const
5129 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
5131 return maTabs
[nTab
]->IsBlockEmpty( nStartCol
, nStartRow
, nEndCol
, nEndRow
, bIgnoreNotes
);
5133 OSL_FAIL("wrong table number");
5137 void ScDocument::LockTable(SCTAB nTab
)
5139 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5140 maTabs
[nTab
]->LockTable();
5143 OSL_FAIL("wrong table number");
5147 void ScDocument::UnlockTable(SCTAB nTab
)
5149 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5150 maTabs
[nTab
]->UnlockTable();
5153 OSL_FAIL("wrong table number");
5157 bool ScDocument::IsBlockEditable( SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
,
5158 SCCOL nEndCol
, SCROW nEndRow
,
5159 bool* pOnlyNotBecauseOfMatrix
/* = NULL */ ) const
5161 // import into read-only document is possible
5162 if (!bImportingXML
&& !mbChangeReadOnlyEnabled
&& pShell
&& pShell
->IsReadOnly())
5164 if ( pOnlyNotBecauseOfMatrix
)
5165 *pOnlyNotBecauseOfMatrix
= false;
5169 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
5171 return maTabs
[nTab
]->IsBlockEditable( nStartCol
, nStartRow
, nEndCol
,
5172 nEndRow
, pOnlyNotBecauseOfMatrix
);
5174 OSL_FAIL("wrong table number");
5175 if ( pOnlyNotBecauseOfMatrix
)
5176 *pOnlyNotBecauseOfMatrix
= false;
5180 bool ScDocument::IsSelectionEditable( const ScMarkData
& rMark
,
5181 bool* pOnlyNotBecauseOfMatrix
/* = NULL */ ) const
5183 // import into read-only document is possible
5184 if ( !bImportingXML
&& !mbChangeReadOnlyEnabled
&& pShell
&& pShell
->IsReadOnly() )
5186 if ( pOnlyNotBecauseOfMatrix
)
5187 *pOnlyNotBecauseOfMatrix
= false;
5192 rMark
.GetMarkArea(aRange
);
5195 bool bMatrix
= ( pOnlyNotBecauseOfMatrix
!= NULL
);
5196 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5197 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5198 for (; itr
!= itrEnd
&& *itr
< nMax
&& (bOk
|| bMatrix
); ++itr
)
5202 if (rMark
.IsMarked())
5204 if ( !maTabs
[*itr
]->IsBlockEditable( aRange
.aStart
.Col(),
5205 aRange
.aStart
.Row(), aRange
.aEnd
.Col(),
5206 aRange
.aEnd
.Row(), pOnlyNotBecauseOfMatrix
) )
5209 if ( pOnlyNotBecauseOfMatrix
)
5210 bMatrix
= *pOnlyNotBecauseOfMatrix
;
5213 if (rMark
.IsMultiMarked())
5215 if ( !maTabs
[*itr
]->IsSelectionEditable( rMark
, pOnlyNotBecauseOfMatrix
) )
5218 if ( pOnlyNotBecauseOfMatrix
)
5219 bMatrix
= *pOnlyNotBecauseOfMatrix
;
5225 if ( pOnlyNotBecauseOfMatrix
)
5226 *pOnlyNotBecauseOfMatrix
= ( !bOk
&& bMatrix
);
5231 bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol
, SCROW nStartRow
,
5232 SCCOL nEndCol
, SCROW nEndRow
,
5233 const ScMarkData
& rMark
) const
5236 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5237 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5238 for (; itr
!= itrEnd
&& *itr
< nMax
&& bOk
; ++itr
)
5240 if (maTabs
[*itr
]->HasBlockMatrixFragment( nStartCol
, nStartRow
, nEndCol
, nEndRow
))
5246 bool ScDocument::GetMatrixFormulaRange( const ScAddress
& rCellPos
, ScRange
& rMatrix
)
5248 // if rCell is part of a matrix formula, return its complete range
5250 ScFormulaCell
* pFCell
= GetFormulaCell(rCellPos
);
5252 // not a formula cell. Bail out.
5255 ScAddress aOrigin
= rCellPos
;
5256 if (!pFCell
->GetMatrixOrigin(aOrigin
))
5257 // Failed to get the address of the matrix origin.
5260 if (aOrigin
!= rCellPos
)
5262 pFCell
= GetFormulaCell(aOrigin
);
5264 // The matrix origin cell is not a formula cell !? Something is up...
5270 pFCell
->GetMatColsRows(nSizeX
, nSizeY
);
5271 if (nSizeX
<= 0 || nSizeY
<= 0)
5273 // GetMatrixEdge computes also dimensions of the matrix
5274 // if not already done (may occur if document is loaded
5275 // from old file format).
5276 // Needs an "invalid" initialized address.
5277 aOrigin
.SetInvalid();
5278 pFCell
->GetMatrixEdge(aOrigin
);
5279 pFCell
->GetMatColsRows(nSizeX
, nSizeY
);
5282 if (nSizeX
<= 0 || nSizeY
<= 0)
5283 // Matrix size is still invalid. Give up.
5286 ScAddress
aEnd( aOrigin
.Col() + nSizeX
- 1,
5287 aOrigin
.Row() + nSizeY
- 1,
5290 rMatrix
.aStart
= aOrigin
;
5291 rMatrix
.aEnd
= aEnd
;
5296 bool ScDocument::ExtendOverlapped( SCCOL
& rStartCol
, SCROW
& rStartRow
,
5297 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
) const
5299 bool bFound
= false;
5300 if ( ValidColRow(rStartCol
,rStartRow
) && ValidColRow(nEndCol
,nEndRow
) && ValidTab(nTab
) )
5302 if (nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5305 SCCOL nOldCol
= rStartCol
;
5306 SCROW nOldRow
= rStartRow
;
5307 for (nCol
=nOldCol
; nCol
<=nEndCol
; nCol
++)
5308 while (static_cast<const ScMergeFlagAttr
*>(GetAttr(nCol
,rStartRow
,nTab
,ATTR_MERGE_FLAG
))->
5314 ScAttrArray
* pAttrArray
= maTabs
[nTab
]->aCol
[nOldCol
].pAttrArray
;
5316 pAttrArray
->Search( nOldRow
, nIndex
);
5317 SCROW nAttrPos
= nOldRow
;
5318 while (nAttrPos
<=nEndRow
)
5320 OSL_ENSURE( nIndex
< pAttrArray
->nCount
, "Wrong index in AttrArray" );
5322 if (static_cast<const ScMergeFlagAttr
&>(pAttrArray
->pData
[nIndex
].pPattern
->
5323 GetItem(ATTR_MERGE_FLAG
)).IsHorOverlapped())
5325 SCROW nLoopEndRow
= std::min( nEndRow
, pAttrArray
->pData
[nIndex
].nRow
);
5326 for (SCROW nAttrRow
= nAttrPos
; nAttrRow
<= nLoopEndRow
; nAttrRow
++)
5328 SCCOL nTempCol
= nOldCol
;
5331 while (static_cast<const ScMergeFlagAttr
*>(GetAttr(nTempCol
,nAttrRow
,nTab
,ATTR_MERGE_FLAG
))
5332 ->IsHorOverlapped());
5333 if (nTempCol
< rStartCol
)
5334 rStartCol
= nTempCol
;
5337 nAttrPos
= pAttrArray
->pData
[nIndex
].nRow
+ 1;
5344 OSL_FAIL("ExtendOverlapped: invalid range");
5350 bool ScDocument::ExtendMergeSel( SCCOL nStartCol
, SCROW nStartRow
,
5351 SCCOL
& rEndCol
, SCROW
& rEndRow
,
5352 const ScMarkData
& rMark
, bool bRefresh
)
5354 // use all selected sheets from rMark
5356 bool bFound
= false;
5357 SCCOL nOldEndCol
= rEndCol
;
5358 SCROW nOldEndRow
= rEndRow
;
5360 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5361 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5362 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
5365 SCCOL nThisEndCol
= nOldEndCol
;
5366 SCROW nThisEndRow
= nOldEndRow
;
5367 if ( ExtendMerge( nStartCol
, nStartRow
, nThisEndCol
, nThisEndRow
, *itr
, bRefresh
) )
5369 if ( nThisEndCol
> rEndCol
)
5370 rEndCol
= nThisEndCol
;
5371 if ( nThisEndRow
> rEndRow
)
5372 rEndRow
= nThisEndRow
;
5378 bool ScDocument::ExtendMerge( SCCOL nStartCol
, SCROW nStartRow
,
5379 SCCOL
& rEndCol
, SCROW
& rEndRow
,
5380 SCTAB nTab
, bool bRefresh
)
5382 bool bFound
= false;
5383 if ( ValidColRow(nStartCol
,nStartRow
) && ValidColRow(rEndCol
,rEndRow
) && ValidTab(nTab
) )
5385 if (nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5386 bFound
= maTabs
[nTab
]->ExtendMerge( nStartCol
, nStartRow
, rEndCol
, rEndRow
, bRefresh
);
5389 RefreshAutoFilter( nStartCol
, nStartRow
, rEndCol
, rEndRow
, nTab
);
5393 OSL_FAIL("ExtendMerge: invalid range");
5399 bool ScDocument::ExtendMerge( ScRange
& rRange
, bool bRefresh
)
5401 bool bFound
= false;
5402 SCTAB nStartTab
= rRange
.aStart
.Tab();
5403 SCTAB nEndTab
= rRange
.aEnd
.Tab();
5404 SCCOL nEndCol
= rRange
.aEnd
.Col();
5405 SCROW nEndRow
= rRange
.aEnd
.Row();
5407 PutInOrder( nStartTab
, nEndTab
);
5408 for (SCTAB nTab
= nStartTab
; nTab
<= nEndTab
&& nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++ )
5410 SCCOL nExtendCol
= rRange
.aEnd
.Col();
5411 SCROW nExtendRow
= rRange
.aEnd
.Row();
5412 if (ExtendMerge( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
5413 nExtendCol
, nExtendRow
,
5417 if (nExtendCol
> nEndCol
) nEndCol
= nExtendCol
;
5418 if (nExtendRow
> nEndRow
) nEndRow
= nExtendRow
;
5422 rRange
.aEnd
.SetCol(nEndCol
);
5423 rRange
.aEnd
.SetRow(nEndRow
);
5428 bool ScDocument::ExtendTotalMerge( ScRange
& rRange
) const
5430 // Extend range to merged cells without including any new non-overlapped cells
5432 ScRange aExt
= rRange
;
5433 // ExtendMerge() is non-const, but called withouth refresh.
5434 if (const_cast<ScDocument
*>(this)->ExtendMerge( aExt
, false))
5436 if ( aExt
.aEnd
.Row() > rRange
.aEnd
.Row() )
5438 ScRange aTest
= aExt
;
5439 aTest
.aStart
.SetRow( rRange
.aEnd
.Row() + 1 );
5440 if ( HasAttrib( aTest
, HASATTR_NOTOVERLAPPED
) )
5441 aExt
.aEnd
.SetRow(rRange
.aEnd
.Row());
5443 if ( aExt
.aEnd
.Col() > rRange
.aEnd
.Col() )
5445 ScRange aTest
= aExt
;
5446 aTest
.aStart
.SetCol( rRange
.aEnd
.Col() + 1 );
5447 if ( HasAttrib( aTest
, HASATTR_NOTOVERLAPPED
) )
5448 aExt
.aEnd
.SetCol(rRange
.aEnd
.Col());
5451 bRet
= ( aExt
.aEnd
!= rRange
.aEnd
);
5457 bool ScDocument::ExtendOverlapped( ScRange
& rRange
) const
5459 bool bFound
= false;
5460 SCTAB nStartTab
= rRange
.aStart
.Tab();
5461 SCTAB nEndTab
= rRange
.aEnd
.Tab();
5462 SCCOL nStartCol
= rRange
.aStart
.Col();
5463 SCROW nStartRow
= rRange
.aStart
.Row();
5465 PutInOrder( nStartTab
, nEndTab
);
5466 for (SCTAB nTab
= nStartTab
; nTab
<= nEndTab
&& nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++ )
5468 SCCOL nExtendCol
= rRange
.aStart
.Col();
5469 SCROW nExtendRow
= rRange
.aStart
.Row();
5470 ExtendOverlapped( nExtendCol
, nExtendRow
,
5471 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), nTab
);
5472 if (nExtendCol
< nStartCol
)
5474 nStartCol
= nExtendCol
;
5477 if (nExtendRow
< nStartRow
)
5479 nStartRow
= nExtendRow
;
5484 rRange
.aStart
.SetCol(nStartCol
);
5485 rRange
.aStart
.SetRow(nStartRow
);
5490 bool ScDocument::RefreshAutoFilter( SCCOL nStartCol
, SCROW nStartRow
,
5491 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
)
5499 // Delete Autofilter
5501 bool bChange
= RemoveFlagsTab( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nTab
, SC_MF_AUTO
);
5505 const ScDBData
* pData
= NULL
;
5506 ScDBCollection::NamedDBs
& rDBs
= pDBCollection
->getNamedDBs();
5507 ScDBCollection::NamedDBs::const_iterator itr
= rDBs
.begin(), itrEnd
= rDBs
.end();
5508 for (; itr
!= itrEnd
; ++itr
)
5510 if (itr
->HasAutoFilter())
5512 itr
->GetArea( nDBTab
, nDBStartCol
,nDBStartRow
, nDBEndCol
,nDBEndRow
);
5513 if ( nDBTab
==nTab
&& nDBStartRow
<=nEndRow
&& nDBEndRow
>=nStartRow
&&
5514 nDBStartCol
<=nEndCol
&& nDBEndCol
>=nStartCol
)
5516 if (ApplyFlagsTab( nDBStartCol
,nDBStartRow
, nDBEndCol
,nDBStartRow
,
5517 nDBTab
, SC_MF_AUTO
))
5522 if (nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5523 pData
= maTabs
[nTab
]->GetAnonymousDBData();
5528 if (pData
->HasAutoFilter())
5530 pData
->GetArea( nDBTab
, nDBStartCol
,nDBStartRow
, nDBEndCol
,nDBEndRow
);
5531 if ( nDBTab
==nTab
&& nDBStartRow
<=nEndRow
&& nDBEndRow
>=nStartRow
&&
5532 nDBStartCol
<=nEndCol
&& nDBEndCol
>=nStartCol
)
5534 if (ApplyFlagsTab( nDBStartCol
,nDBStartRow
, nDBEndCol
,nDBStartRow
,
5535 nDBTab
, SC_MF_AUTO
))
5543 void ScDocument::SkipOverlapped( SCCOL
& rCol
, SCROW
& rRow
, SCTAB nTab
) const
5545 while (IsHorOverlapped(rCol
, rRow
, nTab
))
5547 while (IsVerOverlapped(rCol
, rRow
, nTab
))
5551 bool ScDocument::IsHorOverlapped( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
5553 const ScMergeFlagAttr
* pAttr
= static_cast<const ScMergeFlagAttr
*>(
5554 GetAttr( nCol
, nRow
, nTab
, ATTR_MERGE_FLAG
));
5556 return pAttr
->IsHorOverlapped();
5559 OSL_FAIL("Overlapped: Attr==0");
5564 bool ScDocument::IsVerOverlapped( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
5566 const ScMergeFlagAttr
* pAttr
= static_cast<const ScMergeFlagAttr
*>(
5567 GetAttr( nCol
, nRow
, nTab
, ATTR_MERGE_FLAG
));
5569 return pAttr
->IsVerOverlapped();
5572 OSL_FAIL("Overlapped: Attr==0");
5577 void ScDocument::ApplySelectionFrame( const ScMarkData
& rMark
,
5578 const SvxBoxItem
* pLineOuter
,
5579 const SvxBoxInfoItem
* pLineInner
)
5581 ScRangeList aRangeList
;
5582 rMark
.FillRangeListWithMarks( &aRangeList
, false );
5583 size_t nRangeCount
= aRangeList
.size();
5584 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5585 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5586 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
5590 for ( size_t j
=0; j
< nRangeCount
; j
++ )
5592 ScRange aRange
= *aRangeList
[ j
];
5593 maTabs
[*itr
]->ApplyBlockFrame( pLineOuter
, pLineInner
,
5594 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
5595 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
5601 void ScDocument::ApplyFrameAreaTab( const ScRange
& rRange
,
5602 const SvxBoxItem
* pLineOuter
,
5603 const SvxBoxInfoItem
* pLineInner
)
5605 SCTAB nStartTab
= rRange
.aStart
.Tab();
5606 SCTAB nEndTab
= rRange
.aStart
.Tab();
5607 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
&& nTab
< static_cast<SCTAB
>(maTabs
.size()); nTab
++)
5609 maTabs
[nTab
]->ApplyBlockFrame( pLineOuter
, pLineInner
,
5610 rRange
.aStart
.Col(), rRange
.aStart
.Row(),
5611 rRange
.aEnd
.Col(), rRange
.aEnd
.Row() );
5614 void ScDocument::ApplySelectionPattern( const ScPatternAttr
& rAttr
, const ScMarkData
& rMark
, ScEditDataArray
* pDataArray
)
5616 const SfxItemSet
* pSet
= &rAttr
.GetItemSet();
5619 for (i
=ATTR_PATTERN_START
; i
<=ATTR_PATTERN_END
&& !bSet
; i
++)
5620 if (pSet
->GetItemState(i
) == SfxItemState::SET
)
5625 // ApplySelectionCache needs multi mark
5626 if ( rMark
.IsMarked() && !rMark
.IsMultiMarked() )
5629 rMark
.GetMarkArea( aRange
);
5630 ApplyPatternArea( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
5631 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), rMark
, rAttr
, pDataArray
);
5635 SfxItemPoolCache
aCache( xPoolHelper
->GetDocPool(), pSet
);
5636 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5637 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5638 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
5640 maTabs
[*itr
]->ApplySelectionCache( &aCache
, rMark
, pDataArray
);
5645 void ScDocument::ChangeSelectionIndent( bool bIncrement
, const ScMarkData
& rMark
)
5647 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5648 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5649 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
5651 maTabs
[*itr
]->ChangeSelectionIndent( bIncrement
, rMark
);
5654 void ScDocument::ClearSelectionItems( const sal_uInt16
* pWhich
, const ScMarkData
& rMark
)
5656 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5657 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5658 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
5660 maTabs
[*itr
]->ClearSelectionItems( pWhich
, rMark
);
5663 void ScDocument::DeleteSelection( InsertDeleteFlags nDelFlag
, const ScMarkData
& rMark
, bool bBroadcast
)
5665 sc::AutoCalcSwitch
aACSwitch(*this, false);
5667 std::vector
<ScAddress
> aGroupPos
;
5668 // Destroy and reconstruct listeners only if content is affected.
5669 bool bDelContent
= ((nDelFlag
& ~IDF_CONTENTS
) != nDelFlag
);
5672 // Record the positions of top and/or bottom formula groups that
5673 // intersect the area borders.
5674 sc::EndListeningContext
aCxt(*this);
5675 ScRangeList aRangeList
;
5676 rMark
.FillRangeListWithMarks( &aRangeList
, false);
5677 for (size_t i
= 0; i
< aRangeList
.size(); ++i
)
5679 const ScRange
* pRange
= aRangeList
[i
];
5681 EndListeningIntersectedGroups( aCxt
, *pRange
, &aGroupPos
);
5683 aCxt
.purgeEmptyBroadcasters();
5686 SCTAB nMax
= static_cast<SCTAB
>(maTabs
.size());
5687 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
5688 for (; itr
!= itrEnd
&& *itr
< nMax
; ++itr
)
5690 maTabs
[*itr
]->DeleteSelection(nDelFlag
, rMark
, bBroadcast
);
5694 // Re-start listeners on those top bottom groups that have been split.
5695 SetNeedsListeningGroups(aGroupPos
);
5696 StartNeededListeners();
5700 void ScDocument::DeleteSelectionTab(
5701 SCTAB nTab
, InsertDeleteFlags nDelFlag
, const ScMarkData
& rMark
, bool bBroadcast
)
5703 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5705 sc::AutoCalcSwitch
aACSwitch(*this, false);
5707 std::vector
<ScAddress
> aGroupPos
;
5708 // Destroy and reconstruct listeners only if content is affected.
5709 bool bDelContent
= ((nDelFlag
& ~IDF_CONTENTS
) != nDelFlag
);
5712 // Record the positions of top and/or bottom formula groups that
5713 // intersect the area borders.
5714 sc::EndListeningContext
aCxt(*this);
5715 ScRangeList aRangeList
;
5716 rMark
.FillRangeListWithMarks( &aRangeList
, false);
5717 for (size_t i
= 0; i
< aRangeList
.size(); ++i
)
5719 const ScRange
* pRange
= aRangeList
[i
];
5720 if (pRange
&& pRange
->aStart
.Tab() <= nTab
&& nTab
<= pRange
->aEnd
.Tab())
5722 ScRange
aRange( *pRange
);
5723 aRange
.aStart
.SetTab( nTab
);
5724 aRange
.aEnd
.SetTab( nTab
);
5725 EndListeningIntersectedGroups( aCxt
, aRange
, &aGroupPos
);
5728 aCxt
.purgeEmptyBroadcasters();
5731 maTabs
[nTab
]->DeleteSelection(nDelFlag
, rMark
, bBroadcast
);
5735 // Re-start listeners on those top bottom groups that have been split.
5736 SetNeedsListeningGroups(aGroupPos
);
5737 StartNeededListeners();
5742 OSL_FAIL("wrong table");
5746 ScPatternAttr
* ScDocument::GetDefPattern() const
5748 return const_cast<ScPatternAttr
*>(static_cast<const ScPatternAttr
*>(&xPoolHelper
->GetDocPool()->GetDefaultItem(ATTR_PATTERN
)));
5751 ScDocumentPool
* ScDocument::GetPool()
5753 return xPoolHelper
->GetDocPool();
5756 ScStyleSheetPool
* ScDocument::GetStyleSheetPool() const
5758 return xPoolHelper
->GetStylePool();
5761 SCSIZE
ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol
, SCROW nStartRow
, SCTAB nStartTab
,
5762 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nEndTab
, ScDirection eDir
)
5764 PutInOrder(nStartCol
, nEndCol
);
5765 PutInOrder(nStartRow
, nEndRow
);
5766 PutInOrder(nStartTab
, nEndTab
);
5767 if (ValidTab(nStartTab
) && nStartTab
< static_cast<SCTAB
>(maTabs
.size()))
5769 if (maTabs
[nStartTab
])
5770 return maTabs
[nStartTab
]->GetEmptyLinesInBlock(nStartCol
, nStartRow
, nEndCol
, nEndRow
, eDir
);
5778 void ScDocument::FindAreaPos( SCCOL
& rCol
, SCROW
& rRow
, SCTAB nTab
, ScMoveDirection eDirection
) const
5780 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5781 maTabs
[nTab
]->FindAreaPos( rCol
, rRow
, eDirection
);
5784 void ScDocument::GetNextPos( SCCOL
& rCol
, SCROW
& rRow
, SCTAB nTab
, SCsCOL nMovX
, SCsROW nMovY
,
5785 bool bMarked
, bool bUnprotected
, const ScMarkData
& rMark
) const
5787 OSL_ENSURE( !nMovX
|| !nMovY
, "GetNextPos: only X or Y" );
5789 ScMarkData aCopyMark
= rMark
;
5790 aCopyMark
.SetMarking(false);
5791 aCopyMark
.MarkToMulti();
5793 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5794 maTabs
[nTab
]->GetNextPos( rCol
, rRow
, nMovX
, nMovY
, bMarked
, bUnprotected
, aCopyMark
);
5799 void ScDocument::UpdStlShtPtrsFrmNms()
5801 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
5803 sal_uInt32 nCount
= pPool
->GetItemCount2(ATTR_PATTERN
);
5804 ScPatternAttr
* pPattern
;
5805 for (sal_uInt32 i
=0; i
<nCount
; i
++)
5807 pPattern
= const_cast<ScPatternAttr
*>(static_cast<const ScPatternAttr
*>(pPool
->GetItem2(ATTR_PATTERN
, i
)));
5809 pPattern
->UpdateStyleSheet(this);
5811 const_cast<ScPatternAttr
&>(static_cast<const ScPatternAttr
&>(pPool
->GetDefaultItem(ATTR_PATTERN
))).UpdateStyleSheet(this);
5814 void ScDocument::StylesToNames()
5816 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
5818 sal_uInt32 nCount
= pPool
->GetItemCount2(ATTR_PATTERN
);
5819 ScPatternAttr
* pPattern
;
5820 for (sal_uInt32 i
=0; i
<nCount
; i
++)
5822 pPattern
= const_cast<ScPatternAttr
*>(static_cast<const ScPatternAttr
*>(pPool
->GetItem2(ATTR_PATTERN
, i
)));
5824 pPattern
->StyleToName();
5826 const_cast<ScPatternAttr
&>(static_cast<const ScPatternAttr
&>(pPool
->GetDefaultItem(ATTR_PATTERN
))).StyleToName();
5829 sal_uLong
ScDocument::GetCellCount() const
5831 sal_uLong nCellCount
= 0L;
5833 TableContainer::const_iterator it
= maTabs
.begin();
5834 for (; it
!= maTabs
.end(); ++it
)
5836 nCellCount
+= (*it
)->GetCellCount();
5841 sal_uLong
ScDocument::GetCodeCount() const
5843 sal_uLong nCodeCount
= 0;
5845 TableContainer::const_iterator it
= maTabs
.begin();
5846 for (; it
!= maTabs
.end(); ++it
)
5848 nCodeCount
+= (*it
)->GetCodeCount();
5853 void ScDocument::PageStyleModified( SCTAB nTab
, const OUString
& rNewName
)
5855 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5856 maTabs
[nTab
]->PageStyleModified( rNewName
);
5859 void ScDocument::SetPageStyle( SCTAB nTab
, const OUString
& rName
)
5861 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5862 maTabs
[nTab
]->SetPageStyle( rName
);
5865 const OUString
ScDocument::GetPageStyle( SCTAB nTab
) const
5867 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5868 return maTabs
[nTab
]->GetPageStyle();
5873 void ScDocument::SetPageSize( SCTAB nTab
, const Size
& rSize
)
5875 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5876 maTabs
[nTab
]->SetPageSize( rSize
);
5879 Size
ScDocument::GetPageSize( SCTAB nTab
) const
5881 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5882 return maTabs
[nTab
]->GetPageSize();
5884 OSL_FAIL("invalid tab");
5888 void ScDocument::SetRepeatArea( SCTAB nTab
, SCCOL nStartCol
, SCCOL nEndCol
, SCROW nStartRow
, SCROW nEndRow
)
5890 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5891 maTabs
[nTab
]->SetRepeatArea( nStartCol
, nEndCol
, nStartRow
, nEndRow
);
5894 void ScDocument::InvalidatePageBreaks(SCTAB nTab
)
5896 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5897 maTabs
[nTab
]->InvalidatePageBreaks();
5900 void ScDocument::UpdatePageBreaks( SCTAB nTab
, const ScRange
* pUserArea
)
5902 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5903 maTabs
[nTab
]->UpdatePageBreaks( pUserArea
);
5906 void ScDocument::RemoveManualBreaks( SCTAB nTab
)
5908 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5909 maTabs
[nTab
]->RemoveManualBreaks();
5912 bool ScDocument::HasManualBreaks( SCTAB nTab
) const
5914 if ( ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] )
5915 return maTabs
[nTab
]->HasManualBreaks();
5917 OSL_FAIL("invalid tab");
5921 void ScDocument::GetDocStat( ScDocStat
& rDocStat
)
5923 rDocStat
.nTableCount
= GetTableCount();
5924 rDocStat
.aDocName
= aDocName
;
5925 rDocStat
.nCellCount
= GetCellCount();
5928 bool ScDocument::HasPrintRange()
5930 bool bResult
= false;
5932 TableContainer::iterator it
= maTabs
.begin();
5933 for (; it
!= maTabs
.end() && !bResult
; ++it
)
5935 bResult
= (*it
)->IsPrintEntireSheet() || ((*it
)->GetPrintRangeCount() > 0);
5940 bool ScDocument::IsPrintEntireSheet( SCTAB nTab
) const
5942 return (ValidTab(nTab
) ) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] && maTabs
[nTab
]->IsPrintEntireSheet();
5945 sal_uInt16
ScDocument::GetPrintRangeCount( SCTAB nTab
)
5947 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5948 return maTabs
[nTab
]->GetPrintRangeCount();
5953 const ScRange
* ScDocument::GetPrintRange( SCTAB nTab
, sal_uInt16 nPos
)
5955 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5956 return maTabs
[nTab
]->GetPrintRange(nPos
);
5961 const ScRange
* ScDocument::GetRepeatColRange( SCTAB nTab
)
5963 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5964 return maTabs
[nTab
]->GetRepeatColRange();
5969 const ScRange
* ScDocument::GetRepeatRowRange( SCTAB nTab
)
5971 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5972 return maTabs
[nTab
]->GetRepeatRowRange();
5977 void ScDocument::ClearPrintRanges( SCTAB nTab
)
5979 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5980 maTabs
[nTab
]->ClearPrintRanges();
5983 void ScDocument::AddPrintRange( SCTAB nTab
, const ScRange
& rNew
)
5985 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5986 maTabs
[nTab
]->AddPrintRange( rNew
);
5989 void ScDocument::SetPrintEntireSheet( SCTAB nTab
)
5991 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5992 maTabs
[nTab
]->SetPrintEntireSheet();
5995 void ScDocument::SetRepeatColRange( SCTAB nTab
, const ScRange
* pNew
)
5997 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
5998 maTabs
[nTab
]->SetRepeatColRange( pNew
);
6001 void ScDocument::SetRepeatRowRange( SCTAB nTab
, const ScRange
* pNew
)
6003 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
6004 maTabs
[nTab
]->SetRepeatRowRange( pNew
);
6007 ScPrintRangeSaver
* ScDocument::CreatePrintRangeSaver() const
6009 SCTAB nCount
= static_cast<SCTAB
>(maTabs
.size());
6010 ScPrintRangeSaver
* pNew
= new ScPrintRangeSaver( nCount
);
6011 for (SCTAB i
=0; i
<nCount
; i
++)
6013 maTabs
[i
]->FillPrintSaver( pNew
->GetTabData(i
) );
6017 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver
& rSaver
)
6019 SCTAB nCount
= rSaver
.GetTabCount();
6020 for (SCTAB i
=0; i
<nCount
&& i
< static_cast<SCTAB
>(maTabs
.size()); i
++)
6022 maTabs
[i
]->RestorePrintRanges( rSaver
.GetTabData(i
) );
6025 bool ScDocument::NeedPageResetAfterTab( SCTAB nTab
) const
6027 // The page number count restarts at a sheet, if another template is set at
6028 // the preseding one (oly compare names) and if a pagenumber is specified (not 0)
6030 if ( nTab
+ 1 < static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
] && maTabs
[nTab
+1] )
6032 OUString aNew
= maTabs
[nTab
+1]->GetPageStyle();
6033 if ( aNew
!= maTabs
[nTab
]->GetPageStyle() )
6035 SfxStyleSheetBase
* pStyle
= xPoolHelper
->GetStylePool()->Find( aNew
, SFX_STYLE_FAMILY_PAGE
);
6038 const SfxItemSet
& rSet
= pStyle
->GetItemSet();
6039 sal_uInt16 nFirst
= static_cast<const SfxUInt16Item
&>(rSet
.Get(ATTR_PAGE_FIRSTPAGENO
)).GetValue();
6041 return true; // Specify page number in new template
6046 return false; // otherwise not
6049 SfxUndoManager
* ScDocument::GetUndoManager()
6053 // to support enhanced text edit for draw objects, use an SdrUndoManager
6054 mpUndoManager
= new SdrUndoManager
;
6057 return mpUndoManager
;
6060 ScRowBreakIterator
* ScDocument::GetRowBreakIterator(SCTAB nTab
) const
6062 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
6063 return new ScRowBreakIterator(maTabs
[nTab
]->maRowPageBreaks
);
6067 void ScDocument::AddSubTotalCell(ScFormulaCell
* pCell
)
6069 maSubTotalCells
.insert(pCell
);
6072 void ScDocument::RemoveSubTotalCell(ScFormulaCell
* pCell
)
6074 maSubTotalCells
.erase(pCell
);
6079 bool lcl_hasDirtyRange(ScFormulaCell
* pCell
, const ScRange
& rDirtyRange
)
6081 ScDetectiveRefIter
aRefIter(pCell
);
6083 while (aRefIter
.GetNextRef(aRange
))
6085 if (aRange
.Intersects(rDirtyRange
))
6093 void ScDocument::SetSubTotalCellsDirty(const ScRange
& rDirtyRange
)
6095 // to update the list by skipping cells that no longer contain subtotal function.
6096 set
<ScFormulaCell
*> aNewSet
;
6098 bool bOldRecalc
= GetAutoCalc();
6100 set
<ScFormulaCell
*>::iterator itr
= maSubTotalCells
.begin(), itrEnd
= maSubTotalCells
.end();
6101 for (; itr
!= itrEnd
; ++itr
)
6103 ScFormulaCell
* pCell
= *itr
;
6104 if (pCell
->IsSubTotal())
6106 aNewSet
.insert(pCell
);
6107 if (lcl_hasDirtyRange(pCell
, rDirtyRange
))
6112 SetAutoCalc(bOldRecalc
);
6113 maSubTotalCells
.swap(aNewSet
); // update the list.
6116 sal_uInt16
ScDocument::GetTextWidth( const ScAddress
& rPos
) const
6118 SCTAB nTab
= rPos
.Tab();
6119 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
6120 return maTabs
[nTab
]->GetTextWidth(rPos
.Col(), rPos
.Row());
6125 SvtScriptType
ScDocument::GetScriptType( const ScAddress
& rPos
) const
6127 SCTAB nTab
= rPos
.Tab();
6128 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
6129 return maTabs
[nTab
]->GetScriptType(rPos
.Col(), rPos
.Row());
6131 return SvtScriptType::NONE
;
6134 void ScDocument::SetScriptType( const ScAddress
& rPos
, SvtScriptType nType
)
6136 SCTAB nTab
= rPos
.Tab();
6137 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()) && maTabs
[nTab
])
6138 maTabs
[nTab
]->SetScriptType(rPos
.Col(), rPos
.Row(), nType
);
6141 void ScDocument::EnableUndo( bool bVal
)
6143 // The undo manager increases lock count every time undo is disabled.
6144 // Because of this, we shouldn't disable undo unless it's currently
6145 // enabled, or else re-enabling it may not actually re-enable undo unless
6146 // the lock count becomes zero.
6148 if (bVal
!= GetUndoManager()->IsUndoEnabled())
6150 GetUndoManager()->EnableUndo(bVal
);
6151 if( pDrawLayer
) pDrawLayer
->EnableUndo(bVal
);
6154 mbUndoEnabled
= bVal
;
6157 void ScDocument::EnableUserInteraction( bool bVal
)
6159 mbUserInteractionEnabled
= bVal
;
6162 bool ScDocument::IsInVBAMode() const
6169 uno::Reference
<script::vba::XVBACompatibility
> xVBA(
6170 pShell
->GetBasicContainer(), uno::UNO_QUERY
);
6172 return xVBA
.is() && xVBA
->getVBACompatibilityMode();
6174 catch (const lang::NotInitializedException
&) {}
6179 ScPostIt
* ScDocument::GetNote(const ScAddress
& rPos
)
6181 return GetNote(rPos
.Col(), rPos
.Row(), rPos
.Tab());
6184 ScPostIt
* ScDocument::GetNote(SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
6186 if (ValidTab(nTab
) && nTab
< static_cast<SCTAB
>(maTabs
.size()))
6187 return maTabs
[nTab
]->aCol
[nCol
].GetCellNote(nRow
);
6193 void ScDocument::SetNote(const ScAddress
& rPos
, ScPostIt
* pNote
)
6195 return SetNote(rPos
.Col(), rPos
.Row(), rPos
.Tab(), pNote
);
6198 void ScDocument::SetNote(SCCOL nCol
, SCROW nRow
, SCTAB nTab
, ScPostIt
* pNote
)
6200 return maTabs
[nTab
]->aCol
[nCol
].SetCellNote(nRow
, pNote
);
6203 bool ScDocument::HasNote(const ScAddress
& rPos
) const
6205 return HasNote(rPos
.Col(), rPos
.Row(), rPos
.Tab());
6208 bool ScDocument::HasNote(SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
6210 if (!ValidColRow(nCol
, nRow
))
6213 const ScTable
* pTab
= FetchTable(nTab
);
6217 const ScPostIt
* pNote
= pTab
->aCol
[nCol
].GetCellNote(nRow
);
6218 return pNote
!= NULL
;
6221 bool ScDocument::HasColNotes(SCCOL nCol
, SCTAB nTab
) const
6223 if (!ValidCol(nCol
))
6226 const ScTable
* pTab
= FetchTable(nTab
);
6230 return pTab
->aCol
[nCol
].HasCellNotes();
6233 bool ScDocument::HasTabNotes(SCTAB nTab
) const
6235 bool hasNotes
= false;
6236 for (SCCOL nCol
=0; nCol
<MAXCOLCOUNT
&& !hasNotes
; ++nCol
)
6237 hasNotes
= HasColNotes(nCol
, nTab
);
6242 bool ScDocument::HasNotes() const
6244 for (SCTAB i
= 0; i
<= MAXTAB
; ++i
)
6252 ScPostIt
* ScDocument::ReleaseNote(const ScAddress
& rPos
)
6254 ScTable
* pTab
= FetchTable(rPos
.Tab());
6258 return pTab
->ReleaseNote(rPos
.Col(), rPos
.Row());
6261 ScPostIt
* ScDocument::GetOrCreateNote(const ScAddress
& rPos
)
6264 return GetNote(rPos
);
6266 return CreateNote(rPos
);
6268 ScPostIt
* ScDocument::CreateNote(const ScAddress
& rPos
)
6270 ScPostIt
* pPostIt
= new ScPostIt(*this, rPos
, false);
6271 SetNote(rPos
, pPostIt
);
6275 size_t ScDocument::GetNoteCount( SCTAB nTab
, SCCOL nCol
) const
6277 const ScTable
* pTab
= FetchTable(nTab
);
6281 return pTab
->GetNoteCount(nCol
);
6284 void ScDocument::CreateAllNoteCaptions()
6286 TableContainer::iterator it
= maTabs
.begin(), itEnd
= maTabs
.end();
6287 for (; it
!= itEnd
; ++it
)
6291 p
->CreateAllNoteCaptions();
6295 void ScDocument::ForgetNoteCaptions( const ScRangeList
& rRanges
)
6297 for (size_t i
= 0, n
= rRanges
.size(); i
< n
; ++i
)
6299 const ScRange
* p
= rRanges
[i
];
6300 const ScAddress
& s
= p
->aStart
;
6301 const ScAddress
& e
= p
->aEnd
;
6302 for (SCTAB nTab
= s
.Tab(); nTab
<= e
.Tab(); ++nTab
)
6304 ScTable
* pTab
= FetchTable(nTab
);
6308 pTab
->ForgetNoteCaptions(s
.Col(), s
.Row(), e
.Col(), e
.Row());
6313 ScAddress
ScDocument::GetNotePosition( size_t nIndex
) const
6315 for (size_t nTab
= 0; nTab
< maTabs
.size(); ++nTab
)
6317 for (SCCOL nCol
=0; nCol
<MAXCOLCOUNT
; nCol
++)
6319 size_t nColNoteCount
= GetNoteCount(nTab
, nCol
);
6323 if (nIndex
>= nColNoteCount
)
6325 nIndex
-= nColNoteCount
;
6329 SCROW nRow
= GetNotePosition(nTab
, nCol
, nIndex
);
6331 return ScAddress(nCol
, nRow
, nTab
);
6333 OSL_FAIL("note not found");
6334 return ScAddress(ScAddress::INITIALIZE_INVALID
);
6338 OSL_FAIL("note not found");
6339 return ScAddress(ScAddress::INITIALIZE_INVALID
);
6342 ScAddress
ScDocument::GetNotePosition( size_t nIndex
, SCTAB nTab
) const
6344 for (SCCOL nCol
=0; nCol
<MAXCOLCOUNT
; nCol
++)
6346 size_t nColNoteCount
= GetNoteCount(nTab
, nCol
);
6350 if (nIndex
>= nColNoteCount
)
6352 nIndex
-= nColNoteCount
;
6356 SCROW nRow
= GetNotePosition(nTab
, nCol
, nIndex
);
6358 return ScAddress(nCol
, nRow
, nTab
);
6360 OSL_FAIL("note not found");
6361 return ScAddress(ScAddress::INITIALIZE_INVALID
);
6364 OSL_FAIL("note not found");
6365 return ScAddress(ScAddress::INITIALIZE_INVALID
);
6368 SCROW
ScDocument::GetNotePosition( SCTAB nTab
, SCCOL nCol
, size_t nIndex
) const
6370 const ScTable
* pTab
= FetchTable(nTab
);
6374 return pTab
->GetNotePosition(nCol
, nIndex
);
6377 void ScDocument::GetAllNoteEntries( std::vector
<sc::NoteEntry
>& rNotes
) const
6379 for (size_t nTab
= 0; nTab
< maTabs
.size(); ++nTab
)
6381 const ScTable
* pTab
= maTabs
[nTab
];
6385 pTab
->GetAllNoteEntries(rNotes
);
6389 void ScDocument::GetNotesInRange( const ScRangeList
& rRange
, std::vector
<sc::NoteEntry
>& rNotes
) const
6391 for( size_t i
= 0; i
< rRange
.size(); ++i
)
6393 const ScRange
* pRange
= rRange
[i
];
6394 for( SCTAB nTab
= pRange
->aStart
.Tab(); nTab
<= pRange
->aEnd
.Tab(); ++nTab
)
6396 maTabs
[nTab
]->GetNotesInRange( *pRange
, rNotes
);
6401 bool ScDocument::ContainsNotesInRange( const ScRangeList
& rRange
) const
6403 for( size_t i
= 0; i
< rRange
.size(); ++i
)
6405 const ScRange
* pRange
= rRange
[i
];
6406 for( SCTAB nTab
= pRange
->aStart
.Tab(); nTab
< pRange
->aEnd
.Tab(); ++nTab
)
6408 bool bContainsNote
= maTabs
[nTab
]->ContainsNotesInRange( *pRange
);
6417 void ScDocument::SetAutoNameCache( ScAutoNameCache
* pCache
)
6419 delete pAutoNameCache
;
6420 pAutoNameCache
= pCache
;
6423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */