1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: document.cxx,v $
10 * $Revision: 1.90.36.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #define _ZFORLIST_DECLARE_TABLE
37 #include "scitems.hxx"
38 #include <svx/eeitem.hxx>
40 #include <svx/boxitem.hxx>
41 #include <svx/frmdiritem.hxx>
42 #include <svx/pageitem.hxx>
43 #include <svx/editeng.hxx>
44 #include <svx/svditer.hxx>
45 #include <svx/svdpage.hxx>
46 #include <svx/svdocapt.hxx>
47 #include <sfx2/app.hxx>
48 #include <sfx2/objsh.hxx>
49 #include <svtools/poolcach.hxx>
50 #include <svtools/saveopt.hxx>
51 #include <svtools/zforlist.hxx>
52 #include <unotools/charclass.hxx>
53 #include <unotools/transliterationwrapper.hxx>
54 #include <tools/tenccvt.hxx>
56 #include <com/sun/star/text/WritingMode2.hpp>
58 #include "document.hxx"
61 #include "attarray.hxx"
62 #include "markarr.hxx"
63 #include "patattr.hxx"
64 #include "rangenam.hxx"
65 #include "poolhelp.hxx"
66 #include "docpool.hxx"
67 #include "stlpool.hxx"
68 #include "stlsheet.hxx"
69 #include "globstr.hrc"
70 #include "rechead.hxx"
71 #include "dbcolect.hxx"
73 #include "chartlis.hxx"
74 #include "rangelst.hxx"
75 #include "markdata.hxx"
76 #include "drwlayer.hxx"
77 #include "conditio.hxx"
78 #include "validat.hxx"
79 #include "prnsave.hxx"
80 #include "chgtrack.hxx"
82 #include "scresid.hxx"
84 #include "detdata.hxx"
86 #include "dpobject.hxx"
87 #include "indexmap.hxx"
88 #include "detfunc.hxx" // for UpdateAllComments
90 #include "dociter.hxx"
91 #include "progress.hxx"
92 #include "autonamecache.hxx"
93 #include "bcaslot.hxx"
95 #include "externalrefmgr.hxx"
96 #include "tabprotection.hxx"
97 #include "clipparam.hxx"
98 #include <basic/basmgr.hxx>
99 #include <com/sun/star/container/XContainer.hpp>
103 using namespace ::com::sun::star
;
105 namespace WritingMode2
= ::com::sun::star::text::WritingMode2
;
109 const ScPatternAttr
* pAttr
;
112 ScDefaultAttr(const ScPatternAttr
* pPatAttr
) : pAttr(pPatAttr
), nFirst(0), nCount(0) {}
115 struct ScLessDefaultAttr
117 sal_Bool
operator() (const ScDefaultAttr
& rValue1
, const ScDefaultAttr
& rValue2
) const
119 return rValue1
.pAttr
< rValue2
.pAttr
;
123 typedef std::set
<ScDefaultAttr
, ScLessDefaultAttr
> ScDefaultAttrSet
;
125 void ScDocument::MakeTable( SCTAB nTab
)
127 if ( ValidTab(nTab
) && !pTab
[nTab
] )
129 String aString
= ScGlobal::GetRscString(STR_TABLE_DEF
); //"Tabelle"
130 aString
+= String::CreateFromInt32(nTab
+1);
131 CreateValidTabName( aString
); // keine doppelten
133 pTab
[nTab
] = new ScTable(this, nTab
, aString
);
139 BOOL
ScDocument::HasTable( SCTAB nTab
) const
149 BOOL
ScDocument::GetName( SCTAB nTab
, String
& rName
) const
154 pTab
[nTab
]->GetName( rName
);
161 BOOL
ScDocument::SetCodeName( SCTAB nTab
, String
& rName
)
167 pTab
[nTab
]->SetCodeName( rName
);
171 OSL_TRACE( "**** can't set code name %s", rtl::OUStringToOString( rName
, RTL_TEXTENCODING_UTF8
).getStr() );
175 BOOL
ScDocument::GetCodeName( SCTAB nTab
, String
& rName
) const
180 pTab
[nTab
]->GetCodeName( rName
);
188 BOOL
ScDocument::GetTable( const String
& rName
, SCTAB
& rTab
) const
190 String aUpperName
= rName
;
191 ScGlobal::pCharClass
->toUpper(aUpperName
);
193 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
196 if ( pTab
[i
]->GetUpperName() == aUpperName
)
207 BOOL
ScDocument::ValidTabName( const String
& rName
) const
209 xub_StrLen nLen
= rName
.Len();
214 // Restrict sheet names to what Excel accepts.
215 /* TODO: We may want to remove this restriction for full ODFF compliance.
216 * Merely loading and calculating ODF documents using these characters in
217 * sheet names is not affected by this, but all sheet name editing and
218 * copying functionality is, maybe falling back to "Sheet4" or similar. */
219 for (xub_StrLen i
= 0; i
< nLen
; ++i
)
221 const sal_Unicode c
= rName
.GetChar(i
);
231 // these characters are not allowed to match XL's convention.
234 if (i
== 0 || i
== nLen
- 1)
235 // single quote is not allowed at the first or last
236 // character position.
247 BOOL
ScDocument::ValidNewTabName( const String
& rName
) const
249 BOOL bValid
= ValidTabName(rName
);
250 for (SCTAB i
=0; (i
<=MAXTAB
) && bValid
; i
++)
254 pTab
[i
]->GetName(aOldName
);
255 bValid
= !ScGlobal::pTransliteration
->isEqual( rName
, aOldName
);
261 void ScDocument::CreateValidTabName(String
& rName
) const
263 if ( !ValidTabName(rName
) )
267 const String
aStrTable( ScResId(SCSTR_TABLE
) );
270 // vorneweg testen, ob der Prefix als gueltig erkannt wird
271 // wenn nicht, nur doppelte vermeiden
272 BOOL bPrefix
= ValidTabName( aStrTable
);
273 DBG_ASSERT(bPrefix
, "ungueltiger Tabellenname");
276 SCTAB nLoops
= 0; // "zur Sicherheit"
277 for ( SCTAB i
= nMaxTableNumber
+1; !bOk
&& nLoops
<= MAXTAB
; i
++ )
280 rName
+= String::CreateFromInt32(i
);
282 bOk
= ValidNewTabName( rName
);
284 bOk
= !GetTable( rName
, nDummy
);
288 DBG_ASSERT(bOk
, "kein gueltiger Tabellenname gefunden");
294 // uebergebenen Namen ueberpruefen
296 if ( !ValidNewTabName(rName
) )
305 aName
+= String::CreateFromInt32(static_cast<sal_Int32
>(i
));
307 while (!ValidNewTabName(aName
) && (i
< MAXTAB
+1));
314 BOOL
ScDocument::InsertTab( SCTAB nPos
, const String
& rName
,
315 BOOL bExternalDocument
)
317 SCTAB nTabCount
= GetTableCount();
318 BOOL bValid
= ValidTab(nTabCount
);
319 if ( !bExternalDocument
) // sonst rName == "'Doc'!Tab", vorher pruefen
320 bValid
= (bValid
&& ValidNewTabName(rName
));
323 if (nPos
== SC_TAB_APPEND
|| nPos
== nTabCount
)
325 pTab
[nTabCount
] = new ScTable(this, nTabCount
, rName
);
326 pTab
[nTabCount
]->SetCodeName( rName
);
328 if ( bExternalDocument
)
329 pTab
[nTabCount
]->SetVisible( FALSE
);
333 if (VALIDTAB(nPos
) && (nPos
< nTabCount
))
335 ScRange
aRange( 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
);
336 xColNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,1 );
337 xRowNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,1 );
338 pRangeName
->UpdateTabRef( nPos
, 1 );
339 pDBCollection
->UpdateReference(
340 URM_INSDEL
, 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,1 );
342 pDPCollection
->UpdateReference( URM_INSDEL
, aRange
, 0,0,1 );
344 pDetOpList
->UpdateReference( this, URM_INSDEL
, aRange
, 0,0,1 );
345 UpdateChartRef( URM_INSDEL
, 0,0,nPos
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,1 );
346 UpdateRefAreaLinks( URM_INSDEL
, aRange
, 0,0,1 );
347 if ( pUnoBroadcaster
)
348 pUnoBroadcaster
->Broadcast( ScUpdateRefHint( URM_INSDEL
, aRange
, 0,0,1 ) );
351 for (i
= 0; i
<= MAXTAB
; i
++)
353 pTab
[i
]->UpdateInsertTab(nPos
);
355 for (i
= nTabCount
; i
> nPos
; i
--)
357 pTab
[i
] = pTab
[i
- 1];
360 pTab
[nPos
] = new ScTable(this, nPos
, rName
);
361 pTab
[nPos
]->SetCodeName( rName
);
364 // UpdateBroadcastAreas must be called between UpdateInsertTab,
365 // which ends listening, and StartAllListeners, to not modify
366 // areas that are to be inserted by starting listeners.
367 UpdateBroadcastAreas( URM_INSDEL
, aRange
, 0,0,1);
368 for (i
= 0; i
<= MAXTAB
; i
++)
370 pTab
[i
]->UpdateCompile();
371 for (i
= 0; i
<= MAXTAB
; i
++)
373 pTab
[i
]->StartAllListeners();
375 // update conditional formats after table is inserted
377 pCondFormList
->UpdateReference( URM_INSDEL
, aRange
, 0,0,1 );
378 if ( pValidationList
)
379 pValidationList
->UpdateReference( URM_INSDEL
, aRange
, 0,0,1 );
380 // #81844# sheet names of references are not valid until sheet is inserted
381 if ( pChartListenerCollection
)
382 pChartListenerCollection
->UpdateScheduledSeriesRanges();
384 // Update cells containing external references.
385 if (pExternalRefMgr
.get())
386 pExternalRefMgr
->updateRefInsertTable(nPos
);
399 BOOL
ScDocument::DeleteTab( SCTAB nTab
, ScDocument
* pRefUndoDoc
)
406 SCTAB nTabCount
= GetTableCount();
409 BOOL bOldAutoCalc
= GetAutoCalc();
410 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
411 ScRange
aRange( 0, 0, nTab
, MAXCOL
, MAXROW
, nTab
);
412 DelBroadcastAreasInRange( aRange
);
414 // #i8180# remove database ranges etc. that are on the deleted tab
415 // (restored in undo with ScRefUndoData)
417 xColNameRanges
->DeleteOnTab( nTab
);
418 xRowNameRanges
->DeleteOnTab( nTab
);
419 pDBCollection
->DeleteOnTab( nTab
);
421 pDPCollection
->DeleteOnTab( nTab
);
423 pDetOpList
->DeleteOnTab( nTab
);
424 DeleteAreaLinksOnTab( nTab
);
426 // normal reference update
428 aRange
.aEnd
.SetTab( MAXTAB
);
429 xColNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,-1 );
430 xRowNameRanges
->UpdateReference( URM_INSDEL
, this, aRange
, 0,0,-1 );
431 pRangeName
->UpdateTabRef( nTab
, 2 );
432 pDBCollection
->UpdateReference(
433 URM_INSDEL
, 0,0,nTab
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,-1 );
435 pDPCollection
->UpdateReference( URM_INSDEL
, aRange
, 0,0,-1 );
437 pDetOpList
->UpdateReference( this, URM_INSDEL
, aRange
, 0,0,-1 );
438 UpdateChartRef( URM_INSDEL
, 0,0,nTab
, MAXCOL
,MAXROW
,MAXTAB
, 0,0,-1 );
439 UpdateRefAreaLinks( URM_INSDEL
, aRange
, 0,0,-1 );
441 pCondFormList
->UpdateReference( URM_INSDEL
, aRange
, 0,0,-1 );
442 if ( pValidationList
)
443 pValidationList
->UpdateReference( URM_INSDEL
, aRange
, 0,0,-1 );
444 if ( pUnoBroadcaster
)
445 pUnoBroadcaster
->Broadcast( ScUpdateRefHint( URM_INSDEL
, aRange
, 0,0,-1 ) );
448 for (i
=0; i
<=MAXTAB
; i
++)
450 pTab
[i
]->UpdateDeleteTab(nTab
,FALSE
,
451 pRefUndoDoc
? pRefUndoDoc
->pTab
[i
] : 0);
453 for (i
=nTab
+ 1; i
< nTabCount
; i
++)
455 pTab
[i
- 1] = pTab
[i
];
458 pTab
[nTabCount
- 1] = NULL
;
460 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
461 // which ends listening, and StartAllListeners, to not modify
462 // areas that are to be inserted by starting listeners.
463 UpdateBroadcastAreas( URM_INSDEL
, aRange
, 0,0,-1);
464 for (i
= 0; i
<= MAXTAB
; i
++)
466 pTab
[i
]->UpdateCompile();
467 // Excel-Filter loescht einige Tables waehrend des Ladens,
468 // Listener werden erst nach dem Laden aufgesetzt
469 if ( !bInsertingFromOtherDoc
)
471 for (i
= 0; i
<= MAXTAB
; i
++)
473 pTab
[i
]->StartAllListeners();
476 // #81844# sheet names of references are not valid until sheet is deleted
477 pChartListenerCollection
->UpdateScheduledSeriesRanges();
480 // Update cells containing external references.
481 if (pExternalRefMgr
.get())
482 pExternalRefMgr
->updateRefDeleteTable(nTab
);
484 SetAutoCalc( bOldAutoCalc
);
493 BOOL
ScDocument::RenameTab( SCTAB nTab
, const String
& rName
, BOOL
/* bUpdateRef */,
494 BOOL bExternalDocument
)
501 if ( bExternalDocument
)
502 bValid
= TRUE
; // zusammengesetzter Name
504 bValid
= ValidTabName(rName
);
505 for (i
=0; (i
<=MAXTAB
) && bValid
; i
++)
506 if (pTab
[i
] && (i
!= nTab
))
509 pTab
[i
]->GetName(aOldName
);
510 bValid
= !ScGlobal::pTransliteration
->isEqual( rName
, aOldName
);
514 // #i75258# update charts before renaming, so they can get their live data objects.
515 // Once the charts are live, the sheet can be renamed without problems.
516 if ( pChartListenerCollection
)
517 pChartListenerCollection
->UpdateChartsContainingTab( nTab
);
518 pTab
[nTab
]->SetName(rName
);
525 void ScDocument::SetVisible( SCTAB nTab
, BOOL bVisible
)
529 pTab
[nTab
]->SetVisible(bVisible
);
533 BOOL
ScDocument::IsVisible( SCTAB nTab
) const
537 return pTab
[nTab
]->IsVisible();
543 BOOL
ScDocument::IsPendingRowHeights( SCTAB nTab
) const
545 if ( ValidTab(nTab
) && pTab
[nTab
] )
546 return pTab
[nTab
]->IsPendingRowHeights();
552 void ScDocument::SetPendingRowHeights( SCTAB nTab
, BOOL bSet
)
554 if ( ValidTab(nTab
) && pTab
[nTab
] )
555 pTab
[nTab
]->SetPendingRowHeights( bSet
);
559 void ScDocument::SetLayoutRTL( SCTAB nTab
, BOOL bRTL
)
561 if ( ValidTab(nTab
) && pTab
[nTab
] )
565 // #i57869# only set the LoadingRTL flag, the real setting (including mirroring)
566 // is applied in SetImportingXML(FALSE). This is so the shapes can be loaded in
569 pTab
[nTab
]->SetLoadingRTL( bRTL
);
573 pTab
[nTab
]->SetLayoutRTL( bRTL
); // only sets the flag
574 pTab
[nTab
]->SetDrawPageSize();
576 // mirror existing objects:
580 SdrPage
* pPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nTab
));
581 DBG_ASSERT(pPage
,"Page ?");
584 SdrObjListIter
aIter( *pPage
, IM_DEEPNOGROUPS
);
585 SdrObject
* pObject
= aIter
.Next();
588 // objects with ScDrawObjData are re-positioned in SetPageSize,
589 // don't mirror again
590 ScDrawObjData
* pData
= ScDrawLayer::GetObjData( pObject
);
592 pDrawLayer
->MirrorRTL( pObject
);
594 pObject
->SetContextWritingMode( bRTL
? WritingMode2::RL_TB
: WritingMode2::LR_TB
);
596 pObject
= aIter
.Next();
604 BOOL
ScDocument::IsLayoutRTL( SCTAB nTab
) const
606 if ( ValidTab(nTab
) && pTab
[nTab
] )
607 return pTab
[nTab
]->IsLayoutRTL();
613 BOOL
ScDocument::IsNegativePage( SCTAB nTab
) const
615 // Negative page area is always used for RTL layout.
616 // The separate method is used to find all RTL handling of drawing objects.
617 return IsLayoutRTL( nTab
);
621 /* ----------------------------------------------------------------------------
622 benutzten Bereich suchen:
624 GetCellArea - nur Daten
625 GetTableArea - Daten / Attribute
626 GetPrintArea - beruecksichtigt auch Zeichenobjekte,
627 streicht Attribute bis ganz rechts / unten
628 ---------------------------------------------------------------------------- */
631 BOOL
ScDocument::GetCellArea( SCTAB nTab
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
635 return pTab
[nTab
]->GetCellArea( rEndCol
, rEndRow
);
643 BOOL
ScDocument::GetTableArea( SCTAB nTab
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
647 return pTab
[nTab
]->GetTableArea( rEndCol
, rEndRow
);
654 bool ScDocument::ShrinkToDataArea(SCTAB nTab
, SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
656 if (!ValidTab(nTab
) || !pTab
[nTab
])
661 pTab
[nTab
]->GetFirstDataPos(nCol1
, nRow1
);
662 pTab
[nTab
]->GetLastDataPos(nCol2
, nRow2
);
664 if (nCol1
> nCol2
|| nRow1
> nRow2
)
668 // Make sure the area only shrinks, and doesn't grow.
669 if (rStartCol
< nCol1
)
673 if (rStartRow
< nRow1
)
678 return true; // success!
681 // zusammenhaengender Bereich
683 void ScDocument::GetDataArea( SCTAB nTab
, SCCOL
& rStartCol
, SCROW
& rStartRow
,
684 SCCOL
& rEndCol
, SCROW
& rEndRow
, BOOL bIncludeOld
) const
688 pTab
[nTab
]->GetDataArea( rStartCol
, rStartRow
, rEndCol
, rEndRow
, bIncludeOld
);
692 void ScDocument::LimitChartArea( SCTAB nTab
, SCCOL
& rStartCol
, SCROW
& rStartRow
,
693 SCCOL
& rEndCol
, SCROW
& rEndRow
)
697 pTab
[nTab
]->LimitChartArea( rStartCol
, rStartRow
, rEndCol
, rEndRow
);
701 void ScDocument::LimitChartIfAll( ScRangeListRef
& rRangeList
)
703 ScRangeListRef aNew
= new ScRangeList
;
706 ULONG nCount
= rRangeList
->Count();
707 for (ULONG i
=0; i
<nCount
; i
++)
709 ScRange
aRange(*rRangeList
->GetObject( i
));
710 if ( ( aRange
.aStart
.Col() == 0 && aRange
.aEnd
.Col() == MAXCOL
) ||
711 ( aRange
.aStart
.Row() == 0 && aRange
.aEnd
.Row() == MAXROW
) )
713 SCCOL nStartCol
= aRange
.aStart
.Col();
714 SCROW nStartRow
= aRange
.aStart
.Row();
715 SCCOL nEndCol
= aRange
.aEnd
.Col();
716 SCROW nEndRow
= aRange
.aEnd
.Row();
717 SCTAB nTab
= aRange
.aStart
.Tab();
719 pTab
[nTab
]->LimitChartArea(nStartCol
, nStartRow
, nEndCol
, nEndRow
);
720 aRange
.aStart
.SetCol( nStartCol
);
721 aRange
.aStart
.SetRow( nStartRow
);
722 aRange
.aEnd
.SetCol( nEndCol
);
723 aRange
.aEnd
.SetRow( nEndRow
);
725 aNew
->Append(aRange
);
730 DBG_ERROR("LimitChartIfAll: Ref==0");
736 void lcl_GetFirstTabRange( SCTAB
& rTabRangeStart
, SCTAB
& rTabRangeEnd
, const ScMarkData
* pTabMark
)
738 // without ScMarkData, leave start/end unchanged
741 for (SCTAB nTab
=0; nTab
<=MAXTAB
; ++nTab
)
742 if (pTabMark
->GetTableSelect(nTab
))
744 // find first range of consecutive selected sheets
745 rTabRangeStart
= nTab
;
746 while ( nTab
+1 <= MAXTAB
&& pTabMark
->GetTableSelect(nTab
+1) )
754 bool lcl_GetNextTabRange( SCTAB
& rTabRangeStart
, SCTAB
& rTabRangeEnd
, const ScMarkData
* pTabMark
)
758 // find next range of consecutive selected sheets after rTabRangeEnd
759 for (SCTAB nTab
=rTabRangeEnd
+1; nTab
<=MAXTAB
; ++nTab
)
760 if (pTabMark
->GetTableSelect(nTab
))
762 rTabRangeStart
= nTab
;
763 while ( nTab
+1 <= MAXTAB
&& pTabMark
->GetTableSelect(nTab
+1) )
773 BOOL
ScDocument::CanInsertRow( const ScRange
& rRange
) const
775 SCCOL nStartCol
= rRange
.aStart
.Col();
776 SCROW nStartRow
= rRange
.aStart
.Row();
777 SCTAB nStartTab
= rRange
.aStart
.Tab();
778 SCCOL nEndCol
= rRange
.aEnd
.Col();
779 SCROW nEndRow
= rRange
.aEnd
.Row();
780 SCTAB nEndTab
= rRange
.aEnd
.Tab();
781 PutInOrder( nStartCol
, nEndCol
);
782 PutInOrder( nStartRow
, nEndRow
);
783 PutInOrder( nStartTab
, nEndTab
);
784 SCSIZE nSize
= static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
787 for (SCTAB i
=nStartTab
; i
<=nEndTab
&& bTest
; i
++)
789 bTest
&= pTab
[i
]->TestInsertRow( nStartCol
, nEndCol
, nSize
);
795 BOOL
ScDocument::InsertRow( SCCOL nStartCol
, SCTAB nStartTab
,
796 SCCOL nEndCol
, SCTAB nEndTab
,
797 SCROW nStartRow
, SCSIZE nSize
, ScDocument
* pRefUndoDoc
,
798 const ScMarkData
* pTabMark
)
802 PutInOrder( nStartCol
, nEndCol
);
803 PutInOrder( nStartTab
, nEndTab
);
812 BOOL bOldAutoCalc
= GetAutoCalc();
813 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
814 for ( i
= nStartTab
; i
<= nEndTab
&& bTest
; i
++)
815 if (pTab
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
816 bTest
&= pTab
[i
]->TestInsertRow( nStartCol
, nEndCol
, nSize
);
819 // UpdateBroadcastAreas muss vor UpdateReference gerufen werden, damit nicht
820 // Eintraege verschoben werden, die erst bei UpdateReference neu erzeugt werden
822 // handle chunks of consecutive selected sheets together
823 SCTAB nTabRangeStart
= nStartTab
;
824 SCTAB nTabRangeEnd
= nEndTab
;
825 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
828 UpdateBroadcastAreas( URM_INSDEL
, ScRange(
829 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
830 ScAddress( nEndCol
, MAXROW
, nTabRangeEnd
)), 0, static_cast<SCsROW
>(nSize
), 0 );
832 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
834 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
837 UpdateReference( URM_INSDEL
, nStartCol
, nStartRow
, nTabRangeStart
,
838 nEndCol
, MAXROW
, nTabRangeEnd
,
839 0, static_cast<SCsROW
>(nSize
), 0, pRefUndoDoc
, FALSE
); // without drawing objects
841 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
843 for (i
=nStartTab
; i
<=nEndTab
; i
++)
844 if (pTab
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
845 pTab
[i
]->InsertRow( nStartCol
, nEndCol
, nStartRow
, nSize
);
847 // #82991# UpdateRef for drawing layer must be after inserting,
848 // when the new row heights are known.
849 for (i
=nStartTab
; i
<=nEndTab
; i
++)
850 if (pTab
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
851 pTab
[i
]->UpdateDrawRef( URM_INSDEL
,
852 nStartCol
, nStartRow
, nStartTab
, nEndCol
, MAXROW
, nEndTab
,
853 0, static_cast<SCsROW
>(nSize
), 0 );
855 if ( pChangeTrack
&& pChangeTrack
->IsInDeleteUndo() )
856 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
857 // ein neues Listening faellig, bisherige Listener wurden in
858 // FormulaCell UpdateReference abgehaengt
862 { // Listeners have been removed in UpdateReference
863 for (i
=0; i
<=MAXTAB
; i
++)
865 pTab
[i
]->StartNeededListeners();
866 // #69592# at least all cells using range names pointing relative
867 // to the moved range must recalculate
868 for (i
=0; i
<=MAXTAB
; i
++)
870 pTab
[i
]->SetRelNameDirty();
874 SetAutoCalc( bOldAutoCalc
);
876 pChartListenerCollection
->UpdateDirtyCharts();
881 BOOL
ScDocument::InsertRow( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
)
883 return InsertRow( rRange
.aStart
.Col(), rRange
.aStart
.Tab(),
884 rRange
.aEnd
.Col(), rRange
.aEnd
.Tab(),
885 rRange
.aStart
.Row(), static_cast<SCSIZE
>(rRange
.aEnd
.Row()-rRange
.aStart
.Row()+1),
890 void ScDocument::DeleteRow( SCCOL nStartCol
, SCTAB nStartTab
,
891 SCCOL nEndCol
, SCTAB nEndTab
,
892 SCROW nStartRow
, SCSIZE nSize
,
893 ScDocument
* pRefUndoDoc
, BOOL
* pUndoOutline
,
894 const ScMarkData
* pTabMark
)
898 PutInOrder( nStartCol
, nEndCol
);
899 PutInOrder( nStartTab
, nEndTab
);
906 BOOL bOldAutoCalc
= GetAutoCalc();
907 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
909 // handle chunks of consecutive selected sheets together
910 SCTAB nTabRangeStart
= nStartTab
;
911 SCTAB nTabRangeEnd
= nEndTab
;
912 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
915 if ( ValidRow(nStartRow
+nSize
) )
917 DelBroadcastAreasInRange( ScRange(
918 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
919 ScAddress( nEndCol
, nStartRow
+nSize
-1, nTabRangeEnd
) ) );
920 UpdateBroadcastAreas( URM_INSDEL
, ScRange(
921 ScAddress( nStartCol
, nStartRow
+nSize
, nTabRangeStart
),
922 ScAddress( nEndCol
, MAXROW
, nTabRangeEnd
)), 0, -(static_cast<SCsROW
>(nSize
)), 0 );
925 DelBroadcastAreasInRange( ScRange(
926 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
927 ScAddress( nEndCol
, MAXROW
, nTabRangeEnd
) ) );
929 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
931 if ( ValidRow(nStartRow
+nSize
) )
933 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
936 UpdateReference( URM_INSDEL
, nStartCol
, nStartRow
+nSize
, nTabRangeStart
,
937 nEndCol
, MAXROW
, nTabRangeEnd
,
938 0, -(static_cast<SCsROW
>(nSize
)), 0, pRefUndoDoc
);
940 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
944 *pUndoOutline
= FALSE
;
946 for ( i
= nStartTab
; i
<= nEndTab
; i
++)
947 if (pTab
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
948 pTab
[i
]->DeleteRow( nStartCol
, nEndCol
, nStartRow
, nSize
, pUndoOutline
);
950 if ( ValidRow(nStartRow
+nSize
) )
951 { // Listeners have been removed in UpdateReference
952 for (i
=0; i
<=MAXTAB
; i
++)
954 pTab
[i
]->StartNeededListeners();
955 // #69592# at least all cells using range names pointing relative to
956 // the moved range must recalculate
957 for (i
=0; i
<=MAXTAB
; i
++)
959 pTab
[i
]->SetRelNameDirty();
962 SetAutoCalc( bOldAutoCalc
);
963 pChartListenerCollection
->UpdateDirtyCharts();
967 void ScDocument::DeleteRow( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
, BOOL
* pUndoOutline
)
969 DeleteRow( rRange
.aStart
.Col(), rRange
.aStart
.Tab(),
970 rRange
.aEnd
.Col(), rRange
.aEnd
.Tab(),
971 rRange
.aStart
.Row(), static_cast<SCSIZE
>(rRange
.aEnd
.Row()-rRange
.aStart
.Row()+1),
972 pRefUndoDoc
, pUndoOutline
);
976 BOOL
ScDocument::CanInsertCol( const ScRange
& rRange
) const
978 SCCOL nStartCol
= rRange
.aStart
.Col();
979 SCROW nStartRow
= rRange
.aStart
.Row();
980 SCTAB nStartTab
= rRange
.aStart
.Tab();
981 SCCOL nEndCol
= rRange
.aEnd
.Col();
982 SCROW nEndRow
= rRange
.aEnd
.Row();
983 SCTAB nEndTab
= rRange
.aEnd
.Tab();
984 PutInOrder( nStartCol
, nEndCol
);
985 PutInOrder( nStartRow
, nEndRow
);
986 PutInOrder( nStartTab
, nEndTab
);
987 SCSIZE nSize
= static_cast<SCSIZE
>(nEndCol
- nStartCol
+ 1);
990 for (SCTAB i
=nStartTab
; i
<=nEndTab
&& bTest
; i
++)
992 bTest
&= pTab
[i
]->TestInsertCol( nStartRow
, nEndRow
, nSize
);
998 BOOL
ScDocument::InsertCol( SCROW nStartRow
, SCTAB nStartTab
,
999 SCROW nEndRow
, SCTAB nEndTab
,
1000 SCCOL nStartCol
, SCSIZE nSize
, ScDocument
* pRefUndoDoc
,
1001 const ScMarkData
* pTabMark
)
1005 PutInOrder( nStartRow
, nEndRow
);
1006 PutInOrder( nStartTab
, nEndTab
);
1015 BOOL bOldAutoCalc
= GetAutoCalc();
1016 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1017 for ( i
= nStartTab
; i
<= nEndTab
&& bTest
; i
++)
1018 if (pTab
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1019 bTest
&= pTab
[i
]->TestInsertCol( nStartRow
, nEndRow
, nSize
);
1022 // handle chunks of consecutive selected sheets together
1023 SCTAB nTabRangeStart
= nStartTab
;
1024 SCTAB nTabRangeEnd
= nEndTab
;
1025 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
1028 UpdateBroadcastAreas( URM_INSDEL
, ScRange(
1029 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1030 ScAddress( MAXCOL
, nEndRow
, nTabRangeEnd
)), static_cast<SCsCOL
>(nSize
), 0, 0 );
1032 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
1034 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
1037 UpdateReference( URM_INSDEL
, nStartCol
, nStartRow
, nTabRangeStart
,
1038 MAXCOL
, nEndRow
, nTabRangeEnd
,
1039 static_cast<SCsCOL
>(nSize
), 0, 0, pRefUndoDoc
);
1041 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
1043 for (i
=nStartTab
; i
<=nEndTab
; i
++)
1044 if (pTab
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1045 pTab
[i
]->InsertCol( nStartCol
, nStartRow
, nEndRow
, nSize
);
1047 if ( pChangeTrack
&& pChangeTrack
->IsInDeleteUndo() )
1048 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
1049 // ein neues Listening faellig, bisherige Listener wurden in
1050 // FormulaCell UpdateReference abgehaengt
1051 StartAllListeners();
1054 { // Listeners have been removed in UpdateReference
1055 for (i
=0; i
<=MAXTAB
; i
++)
1057 pTab
[i
]->StartNeededListeners();
1058 // #69592# at least all cells using range names pointing relative
1059 // to the moved range must recalculate
1060 for (i
=0; i
<=MAXTAB
; i
++)
1062 pTab
[i
]->SetRelNameDirty();
1066 SetAutoCalc( bOldAutoCalc
);
1068 pChartListenerCollection
->UpdateDirtyCharts();
1073 BOOL
ScDocument::InsertCol( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
)
1075 return InsertCol( rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
1076 rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(),
1077 rRange
.aStart
.Col(), static_cast<SCSIZE
>(rRange
.aEnd
.Col()-rRange
.aStart
.Col()+1),
1082 void ScDocument::DeleteCol(SCROW nStartRow
, SCTAB nStartTab
, SCROW nEndRow
, SCTAB nEndTab
,
1083 SCCOL nStartCol
, SCSIZE nSize
, ScDocument
* pRefUndoDoc
,
1084 BOOL
* pUndoOutline
, const ScMarkData
* pTabMark
)
1088 PutInOrder( nStartRow
, nEndRow
);
1089 PutInOrder( nStartTab
, nEndTab
);
1096 BOOL bOldAutoCalc
= GetAutoCalc();
1097 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1099 // handle chunks of consecutive selected sheets together
1100 SCTAB nTabRangeStart
= nStartTab
;
1101 SCTAB nTabRangeEnd
= nEndTab
;
1102 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
1105 if ( ValidCol(sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
)) )
1107 DelBroadcastAreasInRange( ScRange(
1108 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1109 ScAddress( sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
-1), nEndRow
, nTabRangeEnd
) ) );
1110 UpdateBroadcastAreas( URM_INSDEL
, ScRange(
1111 ScAddress( sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
), nStartRow
, nTabRangeStart
),
1112 ScAddress( MAXCOL
, nEndRow
, nTabRangeEnd
)), -static_cast<SCsCOL
>(nSize
), 0, 0 );
1115 DelBroadcastAreasInRange( ScRange(
1116 ScAddress( nStartCol
, nStartRow
, nTabRangeStart
),
1117 ScAddress( MAXCOL
, nEndRow
, nTabRangeEnd
) ) );
1119 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
1121 if ( ValidCol(sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
)) )
1123 lcl_GetFirstTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
);
1126 UpdateReference( URM_INSDEL
, sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
), nStartRow
, nTabRangeStart
,
1127 MAXCOL
, nEndRow
, nTabRangeEnd
,
1128 -static_cast<SCsCOL
>(nSize
), 0, 0, pRefUndoDoc
);
1130 while ( lcl_GetNextTabRange( nTabRangeStart
, nTabRangeEnd
, pTabMark
) );
1134 *pUndoOutline
= FALSE
;
1136 for ( i
= nStartTab
; i
<= nEndTab
; i
++)
1137 if (pTab
[i
] && (!pTabMark
|| pTabMark
->GetTableSelect(i
)))
1138 pTab
[i
]->DeleteCol( nStartCol
, nStartRow
, nEndRow
, nSize
, pUndoOutline
);
1140 if ( ValidCol(sal::static_int_cast
<SCCOL
>(nStartCol
+nSize
)) )
1141 { // Listeners have been removed in UpdateReference
1142 for (i
=0; i
<=MAXTAB
; i
++)
1144 pTab
[i
]->StartNeededListeners();
1145 // #69592# at least all cells using range names pointing relative to
1146 // the moved range must recalculate
1147 for (i
=0; i
<=MAXTAB
; i
++)
1149 pTab
[i
]->SetRelNameDirty();
1152 SetAutoCalc( bOldAutoCalc
);
1153 pChartListenerCollection
->UpdateDirtyCharts();
1157 void ScDocument::DeleteCol( const ScRange
& rRange
, ScDocument
* pRefUndoDoc
, BOOL
* pUndoOutline
)
1159 DeleteCol( rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
1160 rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(),
1161 rRange
.aStart
.Col(), static_cast<SCSIZE
>(rRange
.aEnd
.Col()-rRange
.aStart
.Col()+1),
1162 pRefUndoDoc
, pUndoOutline
);
1166 // fuer Area-Links: Zellen einuegen/loeschen, wenn sich der Bereich veraendert
1170 void lcl_GetInsDelRanges( const ScRange
& rOld
, const ScRange
& rNew
,
1171 ScRange
& rColRange
, BOOL
& rInsCol
, BOOL
& rDelCol
,
1172 ScRange
& rRowRange
, BOOL
& rInsRow
, BOOL
& rDelRow
)
1174 DBG_ASSERT( rOld
.aStart
== rNew
.aStart
, "FitBlock: Anfang unterschiedlich" );
1176 rInsCol
= rDelCol
= rInsRow
= rDelRow
= FALSE
;
1178 SCCOL nStartX
= rOld
.aStart
.Col();
1179 SCROW nStartY
= rOld
.aStart
.Row();
1180 SCCOL nOldEndX
= rOld
.aEnd
.Col();
1181 SCROW nOldEndY
= rOld
.aEnd
.Row();
1182 SCCOL nNewEndX
= rNew
.aEnd
.Col();
1183 SCROW nNewEndY
= rNew
.aEnd
.Row();
1184 SCTAB nTab
= rOld
.aStart
.Tab();
1186 // wenn es mehr Zeilen werden, werden Spalten auf der alten Hoehe eingefuegt/geloescht
1187 BOOL bGrowY
= ( nNewEndY
> nOldEndY
);
1188 SCROW nColEndY
= bGrowY
? nOldEndY
: nNewEndY
;
1189 SCCOL nRowEndX
= bGrowY
? nNewEndX
: nOldEndX
;
1193 if ( nNewEndX
> nOldEndX
) // Spalten einfuegen
1195 rColRange
= ScRange( nOldEndX
+1, nStartY
, nTab
, nNewEndX
, nColEndY
, nTab
);
1198 else if ( nNewEndX
< nOldEndX
) // Spalten loeschen
1200 rColRange
= ScRange( nNewEndX
+1, nStartY
, nTab
, nOldEndX
, nColEndY
, nTab
);
1206 if ( nNewEndY
> nOldEndY
) // Zeilen einfuegen
1208 rRowRange
= ScRange( nStartX
, nOldEndY
+1, nTab
, nRowEndX
, nNewEndY
, nTab
);
1211 else if ( nNewEndY
< nOldEndY
) // Zeilen loeschen
1213 rRowRange
= ScRange( nStartX
, nNewEndY
+1, nTab
, nRowEndX
, nOldEndY
, nTab
);
1219 BOOL
ScDocument::HasPartOfMerged( const ScRange
& rRange
)
1222 SCTAB nTab
= rRange
.aStart
.Tab();
1224 SCCOL nStartX
= rRange
.aStart
.Col();
1225 SCROW nStartY
= rRange
.aStart
.Row();
1226 SCCOL nEndX
= rRange
.aEnd
.Col();
1227 SCROW nEndY
= rRange
.aEnd
.Row();
1229 if (HasAttrib( nStartX
, nStartY
, nTab
, nEndX
, nEndY
, nTab
,
1230 HASATTR_MERGED
| HASATTR_OVERLAPPED
))
1232 ExtendMerge( nStartX
, nStartY
, nEndX
, nEndY
, nTab
);
1233 ExtendOverlapped( nStartX
, nStartY
, nEndX
, nEndY
, nTab
);
1235 bPart
= ( nStartX
!= rRange
.aStart
.Col() || nEndX
!= rRange
.aEnd
.Col() ||
1236 nStartY
!= rRange
.aStart
.Row() || nEndY
!= rRange
.aEnd
.Row() );
1242 BOOL
ScDocument::CanFitBlock( const ScRange
& rOld
, const ScRange
& rNew
)
1248 BOOL bInsCol
,bDelCol
,bInsRow
,bDelRow
;
1249 ScRange aColRange
,aRowRange
;
1250 lcl_GetInsDelRanges( rOld
, rNew
, aColRange
,bInsCol
,bDelCol
, aRowRange
,bInsRow
,bDelRow
);
1252 if ( bInsCol
&& !CanInsertCol( aColRange
) ) // Zellen am Rand ?
1254 if ( bInsRow
&& !CanInsertRow( aRowRange
) ) // Zellen am Rand ?
1257 if ( bInsCol
|| bDelCol
)
1259 aColRange
.aEnd
.SetCol(MAXCOL
);
1260 if ( HasPartOfMerged(aColRange
) )
1263 if ( bInsRow
|| bDelRow
)
1265 aRowRange
.aEnd
.SetRow(MAXROW
);
1266 if ( HasPartOfMerged(aRowRange
) )
1274 void ScDocument::FitBlock( const ScRange
& rOld
, const ScRange
& rNew
, BOOL bClear
)
1277 DeleteAreaTab( rOld
, IDF_ALL
);
1279 BOOL bInsCol
,bDelCol
,bInsRow
,bDelRow
;
1280 ScRange aColRange
,aRowRange
;
1281 lcl_GetInsDelRanges( rOld
, rNew
, aColRange
,bInsCol
,bDelCol
, aRowRange
,bInsRow
,bDelRow
);
1284 InsertCol( aColRange
); // Spalten zuerst einfuegen
1286 InsertRow( aRowRange
);
1289 DeleteRow( aRowRange
); // Zeilen zuerst loeschen
1291 DeleteCol( aColRange
);
1293 // Referenzen um eingefuegte Zeilen erweitern
1295 if ( bInsCol
|| bInsRow
)
1297 ScRange aGrowSource
= rOld
;
1298 aGrowSource
.aEnd
.SetCol(Min( rOld
.aEnd
.Col(), rNew
.aEnd
.Col() ));
1299 aGrowSource
.aEnd
.SetRow(Min( rOld
.aEnd
.Row(), rNew
.aEnd
.Row() ));
1300 SCCOL nGrowX
= bInsCol
? ( rNew
.aEnd
.Col() - rOld
.aEnd
.Col() ) : 0;
1301 SCROW nGrowY
= bInsRow
? ( rNew
.aEnd
.Row() - rOld
.aEnd
.Row() ) : 0;
1302 UpdateGrow( aGrowSource
, nGrowX
, nGrowY
);
1307 void ScDocument::DeleteArea(SCCOL nCol1
, SCROW nRow1
,
1308 SCCOL nCol2
, SCROW nRow2
,
1309 const ScMarkData
& rMark
, USHORT nDelFlag
)
1311 PutInOrder( nCol1
, nCol2
);
1312 PutInOrder( nRow1
, nRow2
);
1313 BOOL bOldAutoCalc
= GetAutoCalc();
1314 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1315 for (SCTAB i
= 0; i
<= MAXTAB
; i
++)
1317 if ( rMark
.GetTableSelect(i
) || bIsUndo
)
1318 pTab
[i
]->DeleteArea(nCol1
, nRow1
, nCol2
, nRow2
, nDelFlag
);
1319 SetAutoCalc( bOldAutoCalc
);
1323 void ScDocument::DeleteAreaTab(SCCOL nCol1
, SCROW nRow1
,
1324 SCCOL nCol2
, SCROW nRow2
,
1325 SCTAB nTab
, USHORT nDelFlag
)
1327 PutInOrder( nCol1
, nCol2
);
1328 PutInOrder( nRow1
, nRow2
);
1329 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
1331 BOOL bOldAutoCalc
= GetAutoCalc();
1332 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1333 pTab
[nTab
]->DeleteArea(nCol1
, nRow1
, nCol2
, nRow2
, nDelFlag
);
1334 SetAutoCalc( bOldAutoCalc
);
1339 void ScDocument::DeleteAreaTab( const ScRange
& rRange
, USHORT nDelFlag
)
1341 for ( SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); nTab
++ )
1342 DeleteAreaTab( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
1343 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(),
1348 void ScDocument::InitUndoSelected( ScDocument
* pSrcDoc
, const ScMarkData
& rTabSelection
,
1349 BOOL bColInfo
, BOOL bRowInfo
)
1355 xPoolHelper
= pSrcDoc
->xPoolHelper
;
1358 for (SCTAB nTab
= 0; nTab
<= MAXTAB
; nTab
++)
1359 if ( rTabSelection
.GetTableSelect( nTab
) )
1361 pTab
[nTab
] = new ScTable(this, nTab
, aString
, bColInfo
, bRowInfo
);
1362 nMaxTableNumber
= nTab
+ 1;
1367 DBG_ERROR("InitUndo");
1372 void ScDocument::InitUndo( ScDocument
* pSrcDoc
, SCTAB nTab1
, SCTAB nTab2
,
1373 BOOL bColInfo
, BOOL bRowInfo
)
1379 xPoolHelper
= pSrcDoc
->xPoolHelper
;
1382 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; nTab
++)
1383 pTab
[nTab
] = new ScTable(this, nTab
, aString
, bColInfo
, bRowInfo
);
1385 nMaxTableNumber
= nTab2
+ 1;
1389 DBG_ERROR("InitUndo");
1394 void ScDocument::AddUndoTab( SCTAB nTab1
, SCTAB nTab2
, BOOL bColInfo
, BOOL bRowInfo
)
1399 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; nTab
++)
1401 pTab
[nTab
] = new ScTable(this, nTab
, aString
, bColInfo
, bRowInfo
);
1403 if ( nMaxTableNumber
<= nTab2
)
1404 nMaxTableNumber
= nTab2
+ 1;
1408 DBG_ERROR("InitUndo");
1413 void ScDocument::SetCutMode( BOOL bVal
)
1416 GetClipParam().mbCutMode
= bVal
;
1419 DBG_ERROR("SetCutMode without bIsClip");
1424 BOOL
ScDocument::IsCutMode()
1427 return GetClipParam().mbCutMode
;
1430 DBG_ERROR("IsCutMode ohne bIsClip");
1436 void ScDocument::CopyToDocument(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1437 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
1438 USHORT nFlags
, BOOL bOnlyMarked
, ScDocument
* pDestDoc
,
1439 const ScMarkData
* pMarks
, BOOL bColRowFlags
)
1441 PutInOrder( nCol1
, nCol2
);
1442 PutInOrder( nRow1
, nRow2
);
1443 PutInOrder( nTab1
, nTab2
);
1444 if( !pDestDoc
->aDocName
.Len() )
1445 pDestDoc
->aDocName
= aDocName
;
1446 if (VALIDTAB(nTab1
) && VALIDTAB(nTab2
))
1448 BOOL bOldAutoCalc
= pDestDoc
->GetAutoCalc();
1449 pDestDoc
->SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1450 for (SCTAB i
= nTab1
; i
<= nTab2
; i
++)
1452 if (pTab
[i
] && pDestDoc
->pTab
[i
])
1453 pTab
[i
]->CopyToTable( nCol1
, nRow1
, nCol2
, nRow2
, nFlags
,
1454 bOnlyMarked
, pDestDoc
->pTab
[i
], pMarks
,
1455 FALSE
, bColRowFlags
);
1457 pDestDoc
->SetAutoCalc( bOldAutoCalc
);
1462 void ScDocument::UndoToDocument(SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1463 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
1464 USHORT nFlags
, BOOL bOnlyMarked
, ScDocument
* pDestDoc
,
1465 const ScMarkData
* pMarks
)
1467 PutInOrder( nCol1
, nCol2
);
1468 PutInOrder( nRow1
, nRow2
);
1469 PutInOrder( nTab1
, nTab2
);
1470 if (VALIDTAB(nTab1
) && VALIDTAB(nTab2
))
1472 BOOL bOldAutoCalc
= pDestDoc
->GetAutoCalc();
1473 pDestDoc
->SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1475 CopyToDocument( 0,0,0, MAXCOL
,MAXROW
,nTab1
-1, IDF_FORMULA
, FALSE
, pDestDoc
, pMarks
);
1477 for (SCTAB i
= nTab1
; i
<= nTab2
; i
++)
1479 if (pTab
[i
] && pDestDoc
->pTab
[i
])
1480 pTab
[i
]->UndoToTable(nCol1
, nRow1
, nCol2
, nRow2
, nFlags
,
1481 bOnlyMarked
, pDestDoc
->pTab
[i
], pMarks
);
1485 CopyToDocument( 0,0,nTab2
+1, MAXCOL
,MAXROW
,MAXTAB
, IDF_FORMULA
, FALSE
, pDestDoc
, pMarks
);
1486 pDestDoc
->SetAutoCalc( bOldAutoCalc
);
1491 void ScDocument::CopyToDocument(const ScRange
& rRange
,
1492 USHORT nFlags
, BOOL bOnlyMarked
, ScDocument
* pDestDoc
,
1493 const ScMarkData
* pMarks
, BOOL bColRowFlags
)
1495 ScRange aNewRange
= rRange
;
1496 aNewRange
.Justify();
1498 if( !pDestDoc
->aDocName
.Len() )
1499 pDestDoc
->aDocName
= aDocName
;
1500 BOOL bOldAutoCalc
= pDestDoc
->GetAutoCalc();
1501 pDestDoc
->SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1502 for (SCTAB i
= aNewRange
.aStart
.Tab(); i
<= aNewRange
.aEnd
.Tab(); i
++)
1503 if (pTab
[i
] && pDestDoc
->pTab
[i
])
1504 pTab
[i
]->CopyToTable(aNewRange
.aStart
.Col(), aNewRange
.aStart
.Row(),
1505 aNewRange
.aEnd
.Col(), aNewRange
.aEnd
.Row(),
1506 nFlags
, bOnlyMarked
, pDestDoc
->pTab
[i
],
1507 pMarks
, FALSE
, bColRowFlags
);
1508 pDestDoc
->SetAutoCalc( bOldAutoCalc
);
1512 void ScDocument::UndoToDocument(const ScRange
& rRange
,
1513 USHORT nFlags
, BOOL bOnlyMarked
, ScDocument
* pDestDoc
,
1514 const ScMarkData
* pMarks
)
1516 ScRange aNewRange
= rRange
;
1517 aNewRange
.Justify();
1518 SCTAB nTab1
= aNewRange
.aStart
.Tab();
1519 SCTAB nTab2
= aNewRange
.aEnd
.Tab();
1521 BOOL bOldAutoCalc
= pDestDoc
->GetAutoCalc();
1522 pDestDoc
->SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
1524 CopyToDocument( 0,0,0, MAXCOL
,MAXROW
,nTab1
-1, IDF_FORMULA
, FALSE
, pDestDoc
, pMarks
);
1526 for (SCTAB i
= nTab1
; i
<= nTab2
; i
++)
1528 if (pTab
[i
] && pDestDoc
->pTab
[i
])
1529 pTab
[i
]->UndoToTable(aNewRange
.aStart
.Col(), aNewRange
.aStart
.Row(),
1530 aNewRange
.aEnd
.Col(), aNewRange
.aEnd
.Row(),
1531 nFlags
, bOnlyMarked
, pDestDoc
->pTab
[i
], pMarks
);
1535 CopyToDocument( 0,0,nTab2
+1, MAXCOL
,MAXROW
,MAXTAB
, IDF_FORMULA
, FALSE
, pDestDoc
, pMarks
);
1536 pDestDoc
->SetAutoCalc( bOldAutoCalc
);
1540 void ScDocument::CopyToClip(SCCOL nCol1
, SCROW nRow1
,
1541 SCCOL nCol2
, SCROW nRow2
,
1542 BOOL bCut
, ScDocument
* pClipDoc
,
1543 BOOL bAllTabs
, const ScMarkData
* pMarks
,
1544 BOOL bKeepScenarioFlags
, BOOL bIncludeObjects
, BOOL bCloneNoteCaptions
)
1546 DBG_ASSERT( bAllTabs
|| pMarks
, "CopyToClip: ScMarkData fehlt" );
1550 PutInOrder( nCol1
, nCol2
);
1551 PutInOrder( nRow1
, nRow2
);
1554 DBG_ERROR("CopyToClip: no ClipDoc");
1555 pClipDoc
= SC_MOD()->GetClipDoc();
1558 ScRange
aClipRange(nCol1
, nRow1
, 0, nCol2
, nRow2
, 0);
1559 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
1560 rClipParam
.maRanges
.RemoveAll();
1561 rClipParam
.maRanges
.Append(aClipRange
);
1562 pClipDoc
->aDocName
= aDocName
;
1563 pClipDoc
->ResetClip( this, pMarks
);
1565 CopyRangeNamesToClip(pClipDoc
, aClipRange
, pMarks
, bAllTabs
);
1567 for (SCTAB j
= 0; j
<= MAXTAB
; j
++)
1568 if (pTab
[j
] && pClipDoc
->pTab
[j
])
1569 if ( bAllTabs
|| !pMarks
|| pMarks
->GetTableSelect(j
) )
1571 pTab
[j
]->CopyToClip(nCol1
, nRow1
, nCol2
, nRow2
, pClipDoc
->pTab
[j
], bKeepScenarioFlags
, bCloneNoteCaptions
);
1573 if ( pDrawLayer
&& bIncludeObjects
)
1575 // also copy drawing objects
1577 Rectangle aObjRect
= GetMMRect( nCol1
, nRow1
, nCol2
, nRow2
, j
);
1578 pDrawLayer
->CopyToClip( pClipDoc
, j
, aObjRect
);
1582 pClipDoc
->GetClipParam().mbCutMode
= bCut
;
1586 void ScDocument::CopyToClip(const ScClipParam
& rClipParam
,
1587 ScDocument
* pClipDoc
, const ScMarkData
* pMarks
,
1588 bool bKeepScenarioFlags
, bool bIncludeObjects
, bool bCloneNoteCaptions
)
1595 DBG_ERROR("CopyToClip: no ClipDoc");
1596 pClipDoc
= SC_MOD()->GetClipDoc();
1599 pClipDoc
->aDocName
= aDocName
;
1600 pClipDoc
->SetClipParam(rClipParam
);
1601 pClipDoc
->ResetClip(this, pMarks
);
1603 ScRange aClipRange
= rClipParam
.getWholeRange();
1604 CopyRangeNamesToClip(pClipDoc
, aClipRange
, pMarks
, false);
1606 for (SCTAB i
= 0; i
<= MAXTAB
; ++i
)
1608 if (!pTab
[i
] || !pClipDoc
->pTab
[i
])
1611 if (pMarks
&& !pMarks
->GetTableSelect(i
))
1614 pTab
[i
]->CopyToClip(rClipParam
.maRanges
, pClipDoc
->pTab
[i
], bKeepScenarioFlags
, bCloneNoteCaptions
);
1616 if (pDrawLayer
&& bIncludeObjects
)
1618 // also copy drawing objects
1619 const ScRange aRange
= rClipParam
.getWholeRange();
1620 Rectangle aObjRect
= GetMMRect(
1621 aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), i
);
1622 pDrawLayer
->CopyToClip(pClipDoc
, i
, aObjRect
);
1626 // Make sure to mark overlapped cells.
1627 pClipDoc
->ExtendMerge(aClipRange
, true);
1630 void ScDocument::CopyTabToClip(SCCOL nCol1
, SCROW nRow1
,
1631 SCCOL nCol2
, SCROW nRow2
,
1632 SCTAB nTab
, ScDocument
* pClipDoc
)
1636 PutInOrder( nCol1
, nCol2
);
1637 PutInOrder( nRow1
, nRow2
);
1640 DBG_ERROR("CopyTabToClip: no ClipDoc");
1641 pClipDoc
= SC_MOD()->GetClipDoc();
1644 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
1645 pClipDoc
->aDocName
= aDocName
;
1646 rClipParam
.maRanges
.RemoveAll();
1647 rClipParam
.maRanges
.Append(ScRange(nCol1
, nRow1
, 0, nCol2
, nRow2
, 0));
1648 pClipDoc
->ResetClip( this, nTab
);
1650 if (pTab
[nTab
] && pClipDoc
->pTab
[nTab
])
1651 pTab
[nTab
]->CopyToClip(nCol1
, nRow1
, nCol2
, nRow2
, pClipDoc
->pTab
[nTab
], FALSE
, TRUE
);
1653 pClipDoc
->GetClipParam().mbCutMode
= false;
1658 void ScDocument::TransposeClip( ScDocument
* pTransClip
, USHORT nFlags
, BOOL bAsLink
)
1660 DBG_ASSERT( bIsClip
&& pTransClip
&& pTransClip
->bIsClip
,
1661 "TransposeClip mit falschem Dokument" );
1664 // -> pTransClip muss vor dem Original-Dokument geloescht werden!
1666 pTransClip
->ResetClip(this, (ScMarkData
*)NULL
); // alle
1668 // Bereiche uebernehmen
1670 pTransClip
->pRangeName
->FreeAll();
1671 for (USHORT i
= 0; i
< pRangeName
->GetCount(); i
++) //! DB-Bereiche Pivot-Bereiche auch !!!
1673 USHORT nIndex
= ((ScRangeData
*)((*pRangeName
)[i
]))->GetIndex();
1674 ScRangeData
* pData
= new ScRangeData(*((*pRangeName
)[i
]));
1675 if (!pTransClip
->pRangeName
->Insert(pData
))
1678 pData
->SetIndex(nIndex
);
1683 ScRange aClipRange
= GetClipParam().getWholeRange();
1684 if ( ValidRow(aClipRange
.aEnd
.Row()-aClipRange
.aStart
.Row()) )
1686 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
1689 DBG_ASSERT( pTransClip
->pTab
[i
], "TransposeClip: Tabelle nicht da" );
1690 pTab
[i
]->TransposeClip( aClipRange
.aStart
.Col(), aClipRange
.aStart
.Row(),
1691 aClipRange
.aEnd
.Col(), aClipRange
.aEnd
.Row(),
1692 pTransClip
->pTab
[i
], nFlags
, bAsLink
);
1694 if ( pDrawLayer
&& ( nFlags
& IDF_OBJECTS
) )
1696 // Drawing objects are copied to the new area without transposing.
1697 // CopyFromClip is used to adjust the objects to the transposed block's
1699 // (pDrawLayer in the original clipboard document is set only if there
1700 // are drawing objects to copy)
1702 pTransClip
->InitDrawLayer();
1703 Rectangle aSourceRect
= GetMMRect( aClipRange
.aStart
.Col(), aClipRange
.aStart
.Row(),
1704 aClipRange
.aEnd
.Col(), aClipRange
.aEnd
.Row(), i
);
1705 Rectangle aDestRect
= pTransClip
->GetMMRect( 0, 0,
1706 static_cast<SCCOL
>(aClipRange
.aEnd
.Row() - aClipRange
.aStart
.Row()),
1707 static_cast<SCROW
>(aClipRange
.aEnd
.Col() - aClipRange
.aStart
.Col()), i
);
1708 pTransClip
->pDrawLayer
->CopyFromClip( pDrawLayer
, i
, aSourceRect
, ScAddress(0,0,i
), aDestRect
);
1712 pTransClip
->SetClipParam(GetClipParam());
1713 pTransClip
->GetClipParam().transpose();
1717 DBG_ERROR("TransposeClip: zu gross");
1720 // Dies passiert erst beim Einfuegen...
1722 GetClipParam().mbCutMode
= false;
1725 void ScDocument::CopyRangeNamesToClip(ScDocument
* pClipDoc
, const ScRange
& rClipRange
, const ScMarkData
* pMarks
, bool bAllTabs
)
1727 std::set
<USHORT
> aUsedNames
; // indexes of named ranges that are used in the copied cells
1728 for (SCTAB i
= 0; i
<= MAXTAB
; ++i
)
1729 if (pTab
[i
] && pClipDoc
->pTab
[i
])
1730 if ( bAllTabs
|| !pMarks
|| pMarks
->GetTableSelect(i
) )
1731 pTab
[i
]->FindRangeNamesInUse(
1732 rClipRange
.aStart
.Col(), rClipRange
.aStart
.Row(),
1733 rClipRange
.aEnd
.Col(), rClipRange
.aEnd
.Row(), aUsedNames
);
1735 pClipDoc
->pRangeName
->FreeAll();
1736 for (USHORT i
= 0; i
< pRangeName
->GetCount(); i
++) //! DB-Bereiche Pivot-Bereiche auch !!!
1738 USHORT nIndex
= ((ScRangeData
*)((*pRangeName
)[i
]))->GetIndex();
1739 bool bInUse
= ( aUsedNames
.find(nIndex
) != aUsedNames
.end() );
1742 ScRangeData
* pData
= new ScRangeData(*((*pRangeName
)[i
]));
1743 if (!pClipDoc
->pRangeName
->Insert(pData
))
1746 pData
->SetIndex(nIndex
);
1751 ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument
* pDoc
, ScDocument
* pSrcDoc
) :
1754 mpDoc
->MergeNumberFormatter(pSrcDoc
);
1757 ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
1759 mpDoc
->pFormatExchangeList
= NULL
;
1762 void ScDocument::MergeNumberFormatter(ScDocument
* pSrcDoc
)
1764 SvNumberFormatter
* pThisFormatter
= xPoolHelper
->GetFormTable();
1765 SvNumberFormatter
* pOtherFormatter
= pSrcDoc
->xPoolHelper
->GetFormTable();
1766 if (pOtherFormatter
&& pOtherFormatter
!= pThisFormatter
)
1768 SvNumberFormatterIndexTable
* pExchangeList
=
1769 pThisFormatter
->MergeFormatter(*(pOtherFormatter
));
1770 if (pExchangeList
->Count() > 0)
1771 pFormatExchangeList
= pExchangeList
;
1775 void ScDocument::CopyRangeNamesFromClip(ScDocument
* pClipDoc
, ScClipRangeNameData
& rRangeNames
)
1777 sal_uInt16 nClipRangeNameCount
= pClipDoc
->pRangeName
->GetCount();
1778 ScClipRangeNameData aClipRangeNames
;
1780 // array containing range names which might need update of indices
1781 aClipRangeNames
.mpRangeNames
.resize(nClipRangeNameCount
, NULL
);
1783 for (sal_uInt16 i
= 0; i
< nClipRangeNameCount
; ++i
) //! DB-Bereiche Pivot-Bereiche auch
1785 /* Copy only if the name doesn't exist in this document.
1786 If it exists we use the already existing name instead,
1787 another possibility could be to create new names if
1789 A proper solution would ask the user how to proceed.
1790 The adjustment of the indices in the formulas is done later.
1792 ScRangeData
* pClipRangeData
= (*pClipDoc
->pRangeName
)[i
];
1794 if ( pRangeName
->SearchName( pClipRangeData
->GetName(), k
) )
1796 aClipRangeNames
.mpRangeNames
[i
] = NULL
; // range name not inserted
1797 USHORT nOldIndex
= pClipRangeData
->GetIndex();
1798 USHORT nNewIndex
= ((*pRangeName
)[k
])->GetIndex();
1799 aClipRangeNames
.insert(nOldIndex
, nNewIndex
);
1800 if ( !aClipRangeNames
.mbReplace
)
1801 aClipRangeNames
.mbReplace
= ( nOldIndex
!= nNewIndex
);
1805 ScRangeData
* pData
= new ScRangeData( *pClipRangeData
);
1806 pData
->SetDocument(this);
1807 if ( pRangeName
->FindIndex( pData
->GetIndex() ) )
1808 pData
->SetIndex(0); // need new index, done in Insert
1809 if ( pRangeName
->Insert( pData
) )
1811 aClipRangeNames
.mpRangeNames
[i
] = pData
;
1812 USHORT nOldIndex
= pClipRangeData
->GetIndex();
1813 USHORT nNewIndex
= pData
->GetIndex();
1814 aClipRangeNames
.insert(nOldIndex
, nNewIndex
);
1815 if ( !aClipRangeNames
.mbReplace
)
1816 aClipRangeNames
.mbReplace
= ( nOldIndex
!= nNewIndex
);
1819 { // must be an overflow
1821 aClipRangeNames
.mpRangeNames
[i
] = NULL
;
1822 aClipRangeNames
.insert(pClipRangeData
->GetIndex(), 0);
1823 aClipRangeNames
.mbReplace
= true;
1827 rRangeNames
= aClipRangeNames
;
1830 void ScDocument::UpdateRangeNamesInFormulas(
1831 ScClipRangeNameData
& rRangeNames
, const ScRangeList
& rDestRanges
, const ScMarkData
& rMark
,
1832 SCCOL nXw
, SCROW nYw
)
1834 // nXw and nYw are the extra width and height of the destination range
1835 // extended due to presence of merged cell(s).
1837 if (!rRangeNames
.mbReplace
)
1840 // first update all inserted named formulas if they contain other
1841 // range names and used indices changed
1842 sal_uInt16 nRangeNameCount
= rRangeNames
.mpRangeNames
.size();
1843 for (sal_uInt16 i
= 0; i
< nRangeNameCount
; ++i
) //! DB-Bereiche Pivot-Bereiche auch
1845 if ( rRangeNames
.mpRangeNames
[i
] )
1846 rRangeNames
.mpRangeNames
[i
]->ReplaceRangeNamesInUse(rRangeNames
.maRangeMap
);
1848 // then update the formulas, they might need just the updated range names
1849 for (ULONG nRange
= 0; nRange
< rDestRanges
.Count(); ++nRange
)
1851 const ScRange
* pRange
= rDestRanges
.GetObject( nRange
);
1852 SCCOL nCol1
= pRange
->aStart
.Col();
1853 SCROW nRow1
= pRange
->aStart
.Row();
1854 SCCOL nCol2
= pRange
->aEnd
.Col();
1855 SCROW nRow2
= pRange
->aEnd
.Row();
1859 SCCOL nC2
= nC1
+ nXw
;
1862 SCROW nR2
= nR1
+ nYw
;
1869 for (SCTAB k
= 0; k
<= MAXTAB
; k
++)
1871 if ( pTab
[k
] && rMark
.GetTableSelect(k
) )
1872 pTab
[k
]->ReplaceRangeNamesInUse(nC1
, nR1
,
1873 nC2
, nR2
, rRangeNames
.maRangeMap
);
1876 nC2
= Min((SCCOL
)(nC1
+ nXw
), nCol2
);
1877 } while (nC1
<= nCol2
);
1883 nR2
= Min((SCROW
)(nR1
+ nYw
), nRow2
);
1884 } while (nR1
<= nRow2
);
1888 ScClipParam
& ScDocument::GetClipParam()
1890 if (!mpClipParam
.get())
1891 mpClipParam
.reset(new ScClipParam
);
1893 return *mpClipParam
;
1896 void ScDocument::SetClipParam(const ScClipParam
& rParam
)
1898 mpClipParam
.reset(new ScClipParam(rParam
));
1901 BOOL
ScDocument::IsClipboardSource() const
1903 ScDocument
* pClipDoc
= SC_MOD()->GetClipDoc();
1904 return pClipDoc
&& pClipDoc
->xPoolHelper
.isValid() &&
1905 xPoolHelper
->GetDocPool() == pClipDoc
->xPoolHelper
->GetDocPool();
1909 void ScDocument::StartListeningFromClip( SCCOL nCol1
, SCROW nRow1
,
1910 SCCOL nCol2
, SCROW nRow2
,
1911 const ScMarkData
& rMark
, USHORT nInsFlag
)
1913 if (nInsFlag
& IDF_CONTENTS
)
1915 for (SCTAB i
= 0; i
<= MAXTAB
; i
++)
1917 if (rMark
.GetTableSelect(i
))
1918 pTab
[i
]->StartListeningInArea( nCol1
, nRow1
, nCol2
, nRow2
);
1923 void ScDocument::BroadcastFromClip( SCCOL nCol1
, SCROW nRow1
,
1924 SCCOL nCol2
, SCROW nRow2
,
1925 const ScMarkData
& rMark
, USHORT nInsFlag
)
1927 if (nInsFlag
& IDF_CONTENTS
)
1929 ScBulkBroadcast
aBulkBroadcast( GetBASM());
1930 for (SCTAB i
= 0; i
<= MAXTAB
; i
++)
1932 if (rMark
.GetTableSelect(i
))
1933 pTab
[i
]->BroadcastInArea( nCol1
, nRow1
, nCol2
, nRow2
);
1938 void ScDocument::CopyBlockFromClip( SCCOL nCol1
, SCROW nRow1
,
1939 SCCOL nCol2
, SCROW nRow2
,
1940 const ScMarkData
& rMark
,
1941 SCsCOL nDx
, SCsROW nDy
,
1942 const ScCopyBlockFromClipParams
* pCBFCP
)
1944 ScTable
** ppClipTab
= pCBFCP
->pClipDoc
->pTab
;
1945 SCTAB nTabEnd
= pCBFCP
->nTabEnd
;
1947 for (SCTAB i
= pCBFCP
->nTabStart
; i
<= nTabEnd
; i
++)
1949 if (pTab
[i
] && rMark
.GetTableSelect(i
) )
1951 while (!ppClipTab
[nClipTab
]) nClipTab
= (nClipTab
+1) % (MAXTAB
+1);
1953 pTab
[i
]->CopyFromClip( nCol1
, nRow1
, nCol2
, nRow2
, nDx
, nDy
,
1954 pCBFCP
->nInsFlag
, pCBFCP
->bAsLink
, pCBFCP
->bSkipAttrForEmpty
, ppClipTab
[nClipTab
] );
1956 if ( pCBFCP
->pClipDoc
->pDrawLayer
&& ( pCBFCP
->nInsFlag
& IDF_OBJECTS
) )
1958 // also copy drawing objects
1960 // drawing layer must be created before calling CopyFromClip
1961 // (ScDocShell::MakeDrawLayer also does InitItems etc.)
1962 DBG_ASSERT( pDrawLayer
, "CopyBlockFromClip: No drawing layer" );
1965 // For GetMMRect, the row heights in the target document must already be valid
1966 // (copied in an extra step before pasting, or updated after pasting cells, but
1967 // before pasting objects).
1969 Rectangle aSourceRect
= pCBFCP
->pClipDoc
->GetMMRect(
1970 nCol1
-nDx
, nRow1
-nDy
, nCol2
-nDx
, nRow2
-nDy
, nClipTab
);
1971 Rectangle aDestRect
= GetMMRect( nCol1
, nRow1
, nCol2
, nRow2
, i
);
1972 pDrawLayer
->CopyFromClip( pCBFCP
->pClipDoc
->pDrawLayer
, nClipTab
, aSourceRect
,
1973 ScAddress( nCol1
, nRow1
, i
), aDestRect
);
1977 nClipTab
= (nClipTab
+1) % (MAXTAB
+1);
1980 if ( pCBFCP
->nInsFlag
& IDF_CONTENTS
)
1983 for (SCTAB i
= pCBFCP
->nTabStart
; i
<= nTabEnd
; i
++)
1985 if (pTab
[i
] && rMark
.GetTableSelect(i
) )
1987 while (!ppClipTab
[nClipTab
]) nClipTab
= (nClipTab
+1) % (MAXTAB
+1);
1988 SCsTAB nDz
= ((SCsTAB
)i
) - nClipTab
;
1990 // #89081# ranges of consecutive selected tables (in clipboard and dest. doc)
1991 // must be handled in one UpdateReference call
1993 while ( i
+ nFollow
< nTabEnd
1994 && rMark
.GetTableSelect( i
+ nFollow
+ 1 )
1995 && nClipTab
+ nFollow
< MAXTAB
1996 && ppClipTab
[nClipTab
+ nFollow
+ 1] )
1999 if ( pCBFCP
->pClipDoc
->GetClipParam().mbCutMode
)
2001 BOOL bOldInserting
= IsInsertingFromOtherDoc();
2002 SetInsertingFromOtherDoc( TRUE
);
2003 UpdateReference( URM_MOVE
,
2004 nCol1
, nRow1
, i
, nCol2
, nRow2
, i
+nFollow
,
2005 nDx
, nDy
, nDz
, pCBFCP
->pRefUndoDoc
);
2006 SetInsertingFromOtherDoc( bOldInserting
);
2009 UpdateReference( URM_COPY
,
2010 nCol1
, nRow1
, i
, nCol2
, nRow2
, i
+nFollow
,
2011 nDx
, nDy
, nDz
, pCBFCP
->pRefUndoDoc
, FALSE
);
2013 nClipTab
= (nClipTab
+nFollow
+1) % (MAXTAB
+1);
2014 i
= sal::static_int_cast
<SCTAB
>( i
+ nFollow
);
2021 void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1
, SCROW nRow1
,
2022 SCCOL nCol2
, SCROW nRow2
,
2023 const ScMarkData
& rMark
,
2024 SCsCOL nDx
, SCsROW
/* nDy */,
2025 const ScCopyBlockFromClipParams
* pCBFCP
,
2026 SCROW
& rClipStartRow
)
2028 // call CopyBlockFromClip for ranges of consecutive non-filtered rows
2029 // nCol1/nRow1 etc. is in target doc
2031 // filtered state is taken from first used table in clipboard (as in GetClipArea)
2033 ScTable
** ppClipTab
= pCBFCP
->pClipDoc
->pTab
;
2034 while ( nFlagTab
< MAXTAB
&& !ppClipTab
[nFlagTab
] )
2037 const ScBitMaskCompressedArray
< SCROW
, BYTE
> & rSourceFlags
=
2038 pCBFCP
->pClipDoc
->GetRowFlagsArray( nFlagTab
);
2040 SCROW nSourceRow
= rClipStartRow
;
2041 SCROW nSourceEnd
= 0;
2042 if (pCBFCP
->pClipDoc
->GetClipParam().maRanges
.Count())
2043 nSourceEnd
= pCBFCP
->pClipDoc
->GetClipParam().maRanges
.First()->aEnd
.Row();
2044 SCROW nDestRow
= nRow1
;
2046 while ( nSourceRow
<= nSourceEnd
&& nDestRow
<= nRow2
)
2048 // skip filtered rows
2049 nSourceRow
= rSourceFlags
.GetFirstForCondition( nSourceRow
, nSourceEnd
, CR_FILTERED
, 0);
2051 if ( nSourceRow
<= nSourceEnd
)
2053 // look for more non-filtered rows following
2054 SCROW nFollow
= rSourceFlags
.GetBitStateEnd( nSourceRow
, CR_FILTERED
, 0) - nSourceRow
;
2055 if (nFollow
> nSourceEnd
- nSourceRow
)
2056 nFollow
= nSourceEnd
- nSourceRow
;
2057 if (nFollow
> nRow2
- nDestRow
)
2058 nFollow
= nRow2
- nDestRow
;
2060 SCsROW nNewDy
= ((SCsROW
)nDestRow
) - nSourceRow
;
2061 CopyBlockFromClip( nCol1
, nDestRow
, nCol2
, nDestRow
+ nFollow
, rMark
, nDx
, nNewDy
, pCBFCP
);
2063 nSourceRow
+= nFollow
+ 1;
2064 nDestRow
+= nFollow
+ 1;
2067 rClipStartRow
= nSourceRow
;
2071 void ScDocument::CopyFromClip( const ScRange
& rDestRange
, const ScMarkData
& rMark
,
2073 ScDocument
* pRefUndoDoc
, ScDocument
* pClipDoc
, BOOL bResetCut
,
2074 BOOL bAsLink
, BOOL bIncludeFiltered
, BOOL bSkipAttrForEmpty
,
2075 const ScRangeList
* pDestRanges
)
2081 DBG_ERROR("CopyFromClip: no ClipDoc");
2082 pClipDoc
= SC_MOD()->GetClipDoc();
2084 if (pClipDoc
->bIsClip
&& pClipDoc
->GetTableCount())
2086 BOOL bOldAutoCalc
= GetAutoCalc();
2087 SetAutoCalc( FALSE
); // avoid multiple recalculations
2089 NumFmtMergeHandler
aNumFmtMergeHdl(this, pClipDoc
);
2091 ScClipRangeNameData aClipRangeNames
;
2092 CopyRangeNamesFromClip(pClipDoc
, aClipRangeNames
);
2094 SCCOL nAllCol1
= rDestRange
.aStart
.Col();
2095 SCROW nAllRow1
= rDestRange
.aStart
.Row();
2096 SCCOL nAllCol2
= rDestRange
.aEnd
.Col();
2097 SCROW nAllRow2
= rDestRange
.aEnd
.Row();
2101 ScRange aClipRange
= pClipDoc
->GetClipParam().getWholeRange();
2102 for (SCTAB nTab
= 0; nTab
<= MAXTAB
; nTab
++) // find largest merge overlap
2103 if (pClipDoc
->pTab
[nTab
]) // all sheets of the clipboard content
2105 SCCOL nThisEndX
= aClipRange
.aEnd
.Col();
2106 SCROW nThisEndY
= aClipRange
.aEnd
.Row();
2107 pClipDoc
->ExtendMerge( aClipRange
.aStart
.Col(),
2108 aClipRange
.aStart
.Row(),
2109 nThisEndX
, nThisEndY
, nTab
);
2110 // only extra value from ExtendMerge
2111 nThisEndX
= sal::static_int_cast
<SCCOL
>( nThisEndX
- aClipRange
.aEnd
.Col() );
2112 nThisEndY
= sal::static_int_cast
<SCROW
>( nThisEndY
- aClipRange
.aEnd
.Row() );
2113 if ( nThisEndX
> nXw
)
2115 if ( nThisEndY
> nYw
)
2121 pClipDoc
->GetClipArea( nDestAddX
, nDestAddY
, bIncludeFiltered
);
2122 nXw
= sal::static_int_cast
<SCCOL
>( nXw
+ nDestAddX
);
2123 nYw
= sal::static_int_cast
<SCROW
>( nYw
+ nDestAddY
); // ClipArea, plus ExtendMerge value
2125 /* Decide which contents to delete before copying. Delete all
2126 contents if nInsFlag contains any real content flag.
2127 #i102056# Notes are pasted from clipboard in a second pass,
2128 together with the special flag IDF_ADDNOTES that states to not
2129 overwrite/delete existing cells but to insert the notes into
2130 these cells. In this case, just delete old notes from the
2131 destination area. */
2132 USHORT nDelFlag
= IDF_NONE
;
2133 if ( (nInsFlag
& (IDF_CONTENTS
| IDF_ADDNOTES
)) == (IDF_NOTE
| IDF_ADDNOTES
) )
2134 nDelFlag
|= IDF_NOTE
;
2135 else if ( nInsFlag
& IDF_CONTENTS
)
2136 nDelFlag
|= IDF_CONTENTS
;
2137 // With bSkipAttrForEmpty, don't remove attributes, copy
2138 // on top of existing attributes instead.
2139 if ( ( nInsFlag
& IDF_ATTRIB
) && !bSkipAttrForEmpty
)
2140 nDelFlag
|= IDF_ATTRIB
;
2142 ScCopyBlockFromClipParams aCBFCP
;
2143 aCBFCP
.pRefUndoDoc
= pRefUndoDoc
;
2144 aCBFCP
.pClipDoc
= pClipDoc
;
2145 aCBFCP
.nInsFlag
= nInsFlag
;
2146 aCBFCP
.bAsLink
= bAsLink
;
2147 aCBFCP
.bSkipAttrForEmpty
= bSkipAttrForEmpty
;
2148 aCBFCP
.nTabStart
= MAXTAB
; // wird in der Schleife angepasst
2149 aCBFCP
.nTabEnd
= 0; // wird in der Schleife angepasst
2151 // Inc/DecRecalcLevel einmal aussen, damit nicht fuer jeden Block
2152 // die Draw-Seitengroesse neu berechnet werden muss
2153 //! nur wenn ganze Zeilen/Spalten kopiert werden?
2155 for (SCTAB j
= 0; j
<= MAXTAB
; j
++)
2156 if (pTab
[j
] && rMark
.GetTableSelect(j
))
2158 if ( j
< aCBFCP
.nTabStart
)
2159 aCBFCP
.nTabStart
= j
;
2161 pTab
[j
]->IncRecalcLevel();
2164 ScRangeList aLocalRangeList
;
2167 aLocalRangeList
.Append( rDestRange
);
2168 pDestRanges
= &aLocalRangeList
;
2171 bInsertingFromOtherDoc
= TRUE
; // kein Broadcast/Listener aufbauen bei Insert
2173 // bei mindestens 64 Zeilen wird in ScColumn::CopyFromClip voralloziert
2174 BOOL bDoDouble
= ( nYw
< 64 && nAllRow2
- nAllRow1
> 64);
2175 BOOL bOldDouble
= ScColumn::bDoubleAlloc
;
2177 ScColumn::bDoubleAlloc
= TRUE
;
2179 SCCOL nClipStartCol
= aClipRange
.aStart
.Col();
2180 SCROW nClipStartRow
= aClipRange
.aStart
.Row();
2181 // WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col();
2182 SCROW nClipEndRow
= aClipRange
.aEnd
.Row();
2183 for (ULONG nRange
= 0; nRange
< pDestRanges
->Count(); ++nRange
)
2185 const ScRange
* pRange
= pDestRanges
->GetObject( nRange
);
2186 SCCOL nCol1
= pRange
->aStart
.Col();
2187 SCROW nRow1
= pRange
->aStart
.Row();
2188 SCCOL nCol2
= pRange
->aEnd
.Col();
2189 SCROW nRow2
= pRange
->aEnd
.Row();
2191 DeleteArea(nCol1
, nRow1
, nCol2
, nRow2
, rMark
, nDelFlag
);
2195 SCCOL nC2
= nC1
+ nXw
;
2198 SCROW nR2
= nR1
+ nYw
;
2204 // Pasting is done column-wise, when pasting to a filtered
2205 // area this results in partitioning and we have to
2206 // remember and reset the start row for each column until
2207 // it can be advanced for the next chunk of unfiltered
2209 SCROW nSaveClipStartRow
= nClipStartRow
;
2212 nClipStartRow
= nSaveClipStartRow
;
2213 SCsCOL nDx
= ((SCsCOL
)nC1
) - nClipStartCol
;
2214 SCsROW nDy
= ((SCsROW
)nR1
) - nClipStartRow
;
2215 if ( bIncludeFiltered
)
2217 CopyBlockFromClip( nC1
, nR1
, nC2
, nR2
, rMark
, nDx
,
2219 nClipStartRow
+= nR2
- nR1
+ 1;
2223 CopyNonFilteredFromClip( nC1
, nR1
, nC2
, nR2
, rMark
,
2224 nDx
, nDy
, &aCBFCP
, nClipStartRow
);
2226 // Not needed for columns, but if it was this would be how to.
2227 //if (nClipStartCol > nClipEndCol)
2228 // nClipStartCol = pClipDoc->aClipRange.aStart.Col();
2230 nC2
= Min((SCCOL
)(nC1
+ nXw
), nCol2
);
2231 } while (nC1
<= nCol2
);
2232 if (nClipStartRow
> nClipEndRow
)
2233 nClipStartRow
= aClipRange
.aStart
.Row();
2239 nR2
= Min((SCROW
)(nR1
+ nYw
), nRow2
);
2240 } while (nR1
<= nRow2
);
2243 ScColumn::bDoubleAlloc
= bOldDouble
;
2245 for (SCTAB k
= 0; k
<= MAXTAB
; k
++)
2246 if (pTab
[k
] && rMark
.GetTableSelect(k
))
2247 pTab
[k
]->DecRecalcLevel();
2249 bInsertingFromOtherDoc
= FALSE
;
2251 UpdateRangeNamesInFormulas(aClipRangeNames
, *pDestRanges
, rMark
, nXw
, nYw
);
2253 // Listener aufbauen nachdem alles inserted wurde
2254 StartListeningFromClip( nAllCol1
, nAllRow1
, nAllCol2
, nAllRow2
, rMark
, nInsFlag
);
2255 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2256 BroadcastFromClip( nAllCol1
, nAllRow1
, nAllCol2
, nAllRow2
, rMark
, nInsFlag
);
2258 pClipDoc
->GetClipParam().mbCutMode
= false;
2259 SetAutoCalc( bOldAutoCalc
);
2264 void ScDocument::CopyMultiRangeFromClip(
2265 const ScAddress
& rDestPos
, const ScMarkData
& rMark
, sal_uInt16 nInsFlag
, ScDocument
* pClipDoc
,
2266 bool bResetCut
, bool bAsLink
, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty
)
2271 if (!pClipDoc
->bIsClip
|| !pClipDoc
->GetTableCount())
2272 // There is nothing in the clip doc to copy.
2275 BOOL bOldAutoCalc
= GetAutoCalc();
2276 SetAutoCalc( FALSE
); // avoid multiple recalculations
2278 NumFmtMergeHandler
aNumFmtMergeHdl(this, pClipDoc
);
2280 ScClipRangeNameData aClipRangeNames
;
2281 CopyRangeNamesFromClip(pClipDoc
, aClipRangeNames
);
2283 SCCOL nCol1
= rDestPos
.Col();
2284 SCROW nRow1
= rDestPos
.Row();
2285 ScClipParam
& rClipParam
= pClipDoc
->GetClipParam();
2287 ScCopyBlockFromClipParams aCBFCP
;
2288 aCBFCP
.pRefUndoDoc
= NULL
;
2289 aCBFCP
.pClipDoc
= pClipDoc
;
2290 aCBFCP
.nInsFlag
= nInsFlag
;
2291 aCBFCP
.bAsLink
= bAsLink
;
2292 aCBFCP
.bSkipAttrForEmpty
= bSkipAttrForEmpty
;
2293 aCBFCP
.nTabStart
= MAXTAB
;
2296 SCCOL nCols
= rClipParam
.getPasteColSize();
2297 SCROW nRows
= rClipParam
.getPasteRowSize();
2298 for (SCTAB j
= 0; j
<= MAXTAB
; ++j
)
2300 if (pTab
[j
] && rMark
.GetTableSelect(j
))
2302 if ( j
< aCBFCP
.nTabStart
)
2303 aCBFCP
.nTabStart
= j
;
2305 pTab
[j
]->IncRecalcLevel();
2309 bInsertingFromOtherDoc
= TRUE
; // kein Broadcast/Listener aufbauen bei Insert
2311 if (!bSkipAttrForEmpty
)
2313 sal_uInt16 nDelFlag
= IDF_CONTENTS
;
2314 DeleteArea(nCol1
, nRow1
, nCol1
+nCols
-1, nRow1
+nRows
-1, rMark
, nDelFlag
);
2317 for (ScRange
* p
= rClipParam
.maRanges
.First(); p
; p
= rClipParam
.maRanges
.Next())
2319 SCsCOL nDx
= static_cast<SCsCOL
>(nCol1
- p
->aStart
.Col());
2320 SCsROW nDy
= static_cast<SCsROW
>(nRow1
- p
->aStart
.Row());
2321 SCCOL nCol2
= nCol1
+ p
->aEnd
.Col() - p
->aStart
.Col();
2322 SCROW nRow2
= nRow1
+ p
->aEnd
.Row() - p
->aStart
.Row();
2324 CopyBlockFromClip(nCol1
, nRow1
, nCol2
, nRow2
, rMark
, nDx
, nDy
, &aCBFCP
);
2326 if (rClipParam
.meDirection
== ScClipParam::Column
)
2327 nCol1
+= p
->aEnd
.Col() - p
->aStart
.Col() + 1;
2328 if (rClipParam
.meDirection
== ScClipParam::Row
)
2329 nRow1
+= p
->aEnd
.Row() - p
->aStart
.Row() + 1;
2332 for (SCTAB i
= 0; i
<= MAXTAB
; i
++)
2333 if (pTab
[i
] && rMark
.GetTableSelect(i
))
2334 pTab
[i
]->DecRecalcLevel();
2336 bInsertingFromOtherDoc
= FALSE
;
2338 ScRange
aDestRange(rDestPos
.Col(), rDestPos
.Row(), rDestPos
.Tab(),
2339 rDestPos
.Col()+nCols
-1, rDestPos
.Row()+nRows
-1, rDestPos
.Tab());
2340 ScRangeList aRanges
;
2341 aRanges
.Append(aDestRange
);
2342 UpdateRangeNamesInFormulas(aClipRangeNames
, aRanges
, rMark
, nCols
-1, nRows
-1);
2344 // Listener aufbauen nachdem alles inserted wurde
2345 StartListeningFromClip(aDestRange
.aStart
.Col(), aDestRange
.aStart
.Row(),
2346 aDestRange
.aEnd
.Col(), aDestRange
.aEnd
.Row(), rMark
, nInsFlag
);
2347 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2348 BroadcastFromClip(aDestRange
.aStart
.Col(), aDestRange
.aStart
.Row(),
2349 aDestRange
.aEnd
.Col(), aDestRange
.aEnd
.Row(), rMark
, nInsFlag
);
2352 pClipDoc
->GetClipParam().mbCutMode
= false;
2353 SetAutoCalc( bOldAutoCalc
);
2356 void ScDocument::SetClipArea( const ScRange
& rArea
, BOOL bCut
)
2360 ScClipParam
& rClipParam
= GetClipParam();
2361 rClipParam
.maRanges
.RemoveAll();
2362 rClipParam
.maRanges
.Append(rArea
);
2363 rClipParam
.mbCutMode
= bCut
;
2367 DBG_ERROR("SetClipArea: kein Clip");
2372 void ScDocument::GetClipArea(SCCOL
& nClipX
, SCROW
& nClipY
, BOOL bIncludeFiltered
)
2376 DBG_ERROR("GetClipArea: kein Clip");
2380 ScRangeList
& rClipRanges
= GetClipParam().maRanges
;
2381 if (!rClipRanges
.Count())
2382 // No clip range. Bail out.
2385 ScRangePtr p
= rClipRanges
.First();
2386 SCCOL nStartCol
= p
->aStart
.Col();
2387 SCCOL nEndCol
= p
->aEnd
.Col();
2388 SCROW nStartRow
= p
->aStart
.Row();
2389 SCROW nEndRow
= p
->aEnd
.Row();
2390 for (p
= rClipRanges
.Next(); p
; p
= rClipRanges
.Next())
2392 if (p
->aStart
.Col() < nStartCol
)
2393 nStartCol
= p
->aStart
.Col();
2394 if (p
->aStart
.Row() < nStartRow
)
2395 nStartRow
= p
->aStart
.Row();
2396 if (p
->aEnd
.Col() > nEndCol
)
2397 nEndCol
= p
->aEnd
.Col();
2398 if (p
->aEnd
.Row() < nEndRow
)
2399 nEndRow
= p
->aEnd
.Row();
2402 nClipX
= nEndCol
- nStartCol
;
2404 if ( bIncludeFiltered
)
2405 nClipY
= nEndRow
- nStartRow
;
2408 // count non-filtered rows
2409 // count on first used table in clipboard
2410 SCTAB nCountTab
= 0;
2411 while ( nCountTab
< MAXTAB
&& !pTab
[nCountTab
] )
2414 SCROW nResult
= GetRowFlagsArray( nCountTab
).CountForCondition(
2415 nStartRow
, nEndRow
, CR_FILTERED
, 0);
2418 nClipY
= nResult
- 1;
2420 nClipY
= 0; // always return at least 1 row
2425 void ScDocument::GetClipStart(SCCOL
& nClipX
, SCROW
& nClipY
)
2429 ScRangeList
& rClipRanges
= GetClipParam().maRanges
;
2430 if (rClipRanges
.Count())
2432 nClipX
= rClipRanges
.First()->aStart
.Col();
2433 nClipY
= rClipRanges
.First()->aStart
.Row();
2438 DBG_ERROR("GetClipStart: kein Clip");
2443 BOOL
ScDocument::HasClipFilteredRows()
2445 // count on first used table in clipboard
2446 SCTAB nCountTab
= 0;
2447 while ( nCountTab
< MAXTAB
&& !pTab
[nCountTab
] )
2450 ScRangeList
& rClipRanges
= GetClipParam().maRanges
;
2451 if (!rClipRanges
.Count())
2454 return GetRowFlagsArray( nCountTab
).HasCondition( rClipRanges
.First()->aStart
.Row(),
2455 rClipRanges
.First()->aEnd
.Row(), CR_FILTERED
, CR_FILTERED
);
2459 void ScDocument::MixDocument( const ScRange
& rRange
, USHORT nFunction
, BOOL bSkipEmpty
,
2460 ScDocument
* pSrcDoc
)
2462 SCTAB nTab1
= rRange
.aStart
.Tab();
2463 SCTAB nTab2
= rRange
.aEnd
.Tab();
2464 for (SCTAB i
= nTab1
; i
<= nTab2
; i
++)
2465 if (pTab
[i
] && pSrcDoc
->pTab
[i
])
2466 pTab
[i
]->MixData( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
2467 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(),
2468 nFunction
, bSkipEmpty
, pSrcDoc
->pTab
[i
] );
2472 void ScDocument::FillTab( const ScRange
& rSrcArea
, const ScMarkData
& rMark
,
2473 USHORT nFlags
, USHORT nFunction
,
2474 BOOL bSkipEmpty
, BOOL bAsLink
)
2476 USHORT nDelFlags
= nFlags
;
2477 if (nDelFlags
& IDF_CONTENTS
)
2478 nDelFlags
|= IDF_CONTENTS
; // immer alle Inhalte oder keine loeschen!
2480 SCTAB nSrcTab
= rSrcArea
.aStart
.Tab();
2482 if (ValidTab(nSrcTab
) && pTab
[nSrcTab
])
2484 SCCOL nStartCol
= rSrcArea
.aStart
.Col();
2485 SCROW nStartRow
= rSrcArea
.aStart
.Row();
2486 SCCOL nEndCol
= rSrcArea
.aEnd
.Col();
2487 SCROW nEndRow
= rSrcArea
.aEnd
.Row();
2488 ScDocument
* pMixDoc
= NULL
;
2489 BOOL bDoMix
= ( bSkipEmpty
|| nFunction
) && ( nFlags
& IDF_CONTENTS
);
2491 BOOL bOldAutoCalc
= GetAutoCalc();
2492 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
2494 SCTAB nCount
= GetTableCount();
2495 for (SCTAB i
=0; i
<nCount
; i
++)
2496 if ( i
!=nSrcTab
&& pTab
[i
] && rMark
.GetTableSelect(i
) )
2502 pMixDoc
= new ScDocument( SCDOCMODE_UNDO
);
2503 pMixDoc
->InitUndo( this, i
, i
);
2506 pMixDoc
->AddUndoTab( i
, i
);
2507 pTab
[i
]->CopyToTable( nStartCol
,nStartRow
, nEndCol
,nEndRow
,
2508 IDF_CONTENTS
, FALSE
, pMixDoc
->pTab
[i
] );
2510 pTab
[i
]->DeleteArea( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nDelFlags
);
2511 pTab
[nSrcTab
]->CopyToTable( nStartCol
,nStartRow
, nEndCol
,nEndRow
,
2512 nFlags
, FALSE
, pTab
[i
], NULL
, bAsLink
);
2515 pTab
[i
]->MixData( nStartCol
,nStartRow
, nEndCol
,nEndRow
,
2516 nFunction
, bSkipEmpty
, pMixDoc
->pTab
[i
] );
2521 SetAutoCalc( bOldAutoCalc
);
2525 DBG_ERROR("falsche Tabelle");
2530 void ScDocument::FillTabMarked( SCTAB nSrcTab
, const ScMarkData
& rMark
,
2531 USHORT nFlags
, USHORT nFunction
,
2532 BOOL bSkipEmpty
, BOOL bAsLink
)
2534 USHORT nDelFlags
= nFlags
;
2535 if (nDelFlags
& IDF_CONTENTS
)
2536 nDelFlags
|= IDF_CONTENTS
; // immer alle Inhalte oder keine loeschen!
2538 if (ValidTab(nSrcTab
) && pTab
[nSrcTab
])
2540 ScDocument
* pMixDoc
= NULL
;
2541 BOOL bDoMix
= ( bSkipEmpty
|| nFunction
) && ( nFlags
& IDF_CONTENTS
);
2543 BOOL bOldAutoCalc
= GetAutoCalc();
2544 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
2547 rMark
.GetMultiMarkArea( aArea
);
2548 SCCOL nStartCol
= aArea
.aStart
.Col();
2549 SCROW nStartRow
= aArea
.aStart
.Row();
2550 SCCOL nEndCol
= aArea
.aEnd
.Col();
2551 SCROW nEndRow
= aArea
.aEnd
.Row();
2553 SCTAB nCount
= GetTableCount();
2554 for (SCTAB i
=0; i
<nCount
; i
++)
2555 if ( i
!=nSrcTab
&& pTab
[i
] && rMark
.GetTableSelect(i
) )
2561 pMixDoc
= new ScDocument( SCDOCMODE_UNDO
);
2562 pMixDoc
->InitUndo( this, i
, i
);
2565 pMixDoc
->AddUndoTab( i
, i
);
2566 pTab
[i
]->CopyToTable( nStartCol
,nStartRow
, nEndCol
,nEndRow
,
2567 IDF_CONTENTS
, TRUE
, pMixDoc
->pTab
[i
], &rMark
);
2570 pTab
[i
]->DeleteSelection( nDelFlags
, rMark
);
2571 pTab
[nSrcTab
]->CopyToTable( nStartCol
,nStartRow
, nEndCol
,nEndRow
,
2572 nFlags
, TRUE
, pTab
[i
], &rMark
, bAsLink
);
2575 pTab
[i
]->MixMarked( rMark
, nFunction
, bSkipEmpty
, pMixDoc
->pTab
[i
] );
2580 SetAutoCalc( bOldAutoCalc
);
2584 DBG_ERROR("falsche Tabelle");
2589 void ScDocument::PutCell( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, ScBaseCell
* pCell
, BOOL bForceTab
)
2593 if ( bForceTab
&& !pTab
[nTab
] )
2595 BOOL bExtras
= !bIsUndo
; // Spaltenbreiten, Zeilenhoehen, Flags
2597 pTab
[nTab
] = new ScTable(this, nTab
,
2598 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
2604 pTab
[nTab
]->PutCell( nCol
, nRow
, pCell
);
2609 void ScDocument::PutCell( const ScAddress
& rPos
, ScBaseCell
* pCell
, BOOL bForceTab
)
2611 SCTAB nTab
= rPos
.Tab();
2612 if ( bForceTab
&& !pTab
[nTab
] )
2614 BOOL bExtras
= !bIsUndo
; // Spaltenbreiten, Zeilenhoehen, Flags
2616 pTab
[nTab
] = new ScTable(this, nTab
,
2617 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
2623 pTab
[nTab
]->PutCell( rPos
, pCell
);
2627 BOOL
ScDocument::SetString( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const String
& rString
,
2628 SvNumberFormatter
* pFormatter
, bool bDetectNumberFormat
)
2630 if ( ValidTab(nTab
) && pTab
[nTab
] )
2631 return pTab
[nTab
]->SetString( nCol
, nRow
, nTab
, rString
, pFormatter
, bDetectNumberFormat
);
2637 void ScDocument::SetValue( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const double& rVal
)
2641 pTab
[nTab
]->SetValue( nCol
, nRow
, rVal
);
2645 void ScDocument::GetString( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, String
& rString
)
2647 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
2648 pTab
[nTab
]->GetString( nCol
, nRow
, rString
);
2654 void ScDocument::GetInputString( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, String
& rString
)
2656 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
2657 pTab
[nTab
]->GetInputString( nCol
, nRow
, rString
);
2663 void ScDocument::GetValue( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, double& rValue
)
2665 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
2666 rValue
= pTab
[nTab
]->GetValue( nCol
, nRow
);
2672 double ScDocument::GetValue( const ScAddress
& rPos
)
2674 SCTAB nTab
= rPos
.Tab();
2676 return pTab
[nTab
]->GetValue( rPos
);
2681 void ScDocument::GetNumberFormat( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
2682 sal_uInt32
& rFormat
)
2687 rFormat
= pTab
[nTab
]->GetNumberFormat( nCol
, nRow
);
2693 sal_uInt32
ScDocument::GetNumberFormat( const ScRange
& rRange
) const
2695 SCTAB nTab1
= rRange
.aStart
.Tab(), nTab2
= rRange
.aEnd
.Tab();
2696 SCCOL nCol1
= rRange
.aStart
.Col(), nCol2
= rRange
.aEnd
.Col();
2697 SCROW nRow1
= rRange
.aStart
.Row(), nRow2
= rRange
.aEnd
.Row();
2699 if (!ValidTab(nTab1
) || !ValidTab(nTab2
) || !pTab
[nTab1
] || !pTab
[nTab2
])
2702 sal_uInt32 nFormat
= 0;
2703 bool bFirstItem
= true;
2704 for (SCTAB nTab
= nTab1
; nTab
<= nTab2
; ++nTab
)
2705 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
2707 sal_uInt32 nThisFormat
= pTab
[nTab
]->GetNumberFormat(nCol
, nRow1
, nRow2
);
2710 nFormat
= nThisFormat
;
2713 else if (nThisFormat
!= nFormat
)
2720 sal_uInt32
ScDocument::GetNumberFormat( const ScAddress
& rPos
) const
2722 SCTAB nTab
= rPos
.Tab();
2724 return pTab
[nTab
]->GetNumberFormat( rPos
);
2729 void ScDocument::GetNumberFormatInfo( short& nType
, ULONG
& nIndex
,
2730 const ScAddress
& rPos
, const ScBaseCell
* pCell
) const
2732 SCTAB nTab
= rPos
.Tab();
2735 nIndex
= pTab
[nTab
]->GetNumberFormat( rPos
);
2736 if ( (nIndex
% SV_COUNTRY_LANGUAGE_OFFSET
) == 0 && pCell
&&
2737 pCell
->GetCellType() == CELLTYPE_FORMULA
)
2738 static_cast<const ScFormulaCell
*>(pCell
)->GetFormatInfo( nType
, nIndex
);
2740 nType
= GetFormatTable()->GetType( nIndex
);
2744 nType
= NUMBERFORMAT_UNDEFINED
;
2750 void ScDocument::GetFormula( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, String
& rFormula
,
2751 BOOL bAsciiExport
) const
2753 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
2754 pTab
[nTab
]->GetFormula( nCol
, nRow
, rFormula
, bAsciiExport
);
2760 CellType
ScDocument::GetCellType( const ScAddress
& rPos
) const
2762 SCTAB nTab
= rPos
.Tab();
2764 return pTab
[nTab
]->GetCellType( rPos
);
2765 return CELLTYPE_NONE
;
2769 void ScDocument::GetCellType( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
2770 CellType
& rCellType
) const
2772 if (ValidTab(nTab
) && pTab
[nTab
])
2773 rCellType
= pTab
[nTab
]->GetCellType( nCol
, nRow
);
2775 rCellType
= CELLTYPE_NONE
;
2779 void ScDocument::GetCell( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
2780 ScBaseCell
*& rpCell
) const
2782 if (ValidTab(nTab
) && pTab
[nTab
])
2783 rpCell
= pTab
[nTab
]->GetCell( nCol
, nRow
);
2786 DBG_ERROR("GetCell ohne Tabelle");
2792 ScBaseCell
* ScDocument::GetCell( const ScAddress
& rPos
) const
2794 SCTAB nTab
= rPos
.Tab();
2795 if (ValidTab(nTab
) && pTab
[nTab
])
2796 return pTab
[nTab
]->GetCell( rPos
);
2798 DBG_ERROR("GetCell ohne Tabelle");
2803 BOOL
ScDocument::HasStringData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
2805 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
2806 return pTab
[nTab
]->HasStringData( nCol
, nRow
);
2812 BOOL
ScDocument::HasValueData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
2814 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
2815 return pTab
[nTab
]->HasValueData( nCol
, nRow
);
2821 BOOL
ScDocument::HasStringCells( const ScRange
& rRange
) const
2823 // TRUE, wenn String- oder Editzellen im Bereich
2825 SCCOL nStartCol
= rRange
.aStart
.Col();
2826 SCROW nStartRow
= rRange
.aStart
.Row();
2827 SCTAB nStartTab
= rRange
.aStart
.Tab();
2828 SCCOL nEndCol
= rRange
.aEnd
.Col();
2829 SCROW nEndRow
= rRange
.aEnd
.Row();
2830 SCTAB nEndTab
= rRange
.aEnd
.Tab();
2832 for ( SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++ )
2833 if ( pTab
[nTab
] && pTab
[nTab
]->HasStringCells( nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
2840 BOOL
ScDocument::HasSelectionData( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
2842 sal_uInt32 nValidation
= static_cast< const SfxUInt32Item
* >( GetAttr( nCol
, nRow
, nTab
, ATTR_VALIDDATA
) )->GetValue();
2845 const ScValidationData
* pData
= GetValidationEntry( nValidation
);
2846 if( pData
&& pData
->HasSelectionList() )
2849 return HasStringCells( ScRange( nCol
, 0, nTab
, nCol
, MAXROW
, nTab
) );
2853 ScPostIt
* ScDocument::GetNote( const ScAddress
& rPos
)
2855 ScTable
* pTable
= ValidTab( rPos
.Tab() ) ? pTab
[ rPos
.Tab() ] : 0;
2856 return pTable
? pTable
->GetNote( rPos
.Col(), rPos
.Row() ) : 0;
2860 void ScDocument::TakeNote( const ScAddress
& rPos
, ScPostIt
*& rpNote
)
2862 if( ValidTab( rPos
.Tab() ) && pTab
[ rPos
.Tab() ] )
2863 pTab
[ rPos
.Tab() ]->TakeNote( rPos
.Col(), rPos
.Row(), rpNote
);
2869 ScPostIt
* ScDocument::ReleaseNote( const ScAddress
& rPos
)
2871 ScTable
* pTable
= ValidTab( rPos
.Tab() ) ? pTab
[ rPos
.Tab() ] : 0;
2872 return pTable
? pTable
->ReleaseNote( rPos
.Col(), rPos
.Row() ) : 0;
2876 ScPostIt
* ScDocument::GetOrCreateNote( const ScAddress
& rPos
)
2878 ScPostIt
* pNote
= GetNote( rPos
);
2881 pNote
= new ScPostIt( *this, rPos
, false );
2882 TakeNote( rPos
, pNote
);
2888 void ScDocument::DeleteNote( const ScAddress
& rPos
)
2890 if( ValidTab( rPos
.Tab() ) && pTab
[ rPos
.Tab() ] )
2891 pTab
[ rPos
.Tab() ]->DeleteNote( rPos
.Col(), rPos
.Row() );
2895 void ScDocument::InitializeNoteCaptions( SCTAB nTab
, bool bForced
)
2897 if( ValidTab( nTab
) && pTab
[ nTab
] )
2898 pTab
[ nTab
]->InitializeNoteCaptions( bForced
);
2901 void ScDocument::InitializeAllNoteCaptions( bool bForced
)
2903 for( SCTAB nTab
= 0; nTab
< GetTableCount(); ++nTab
)
2904 InitializeNoteCaptions( nTab
, bForced
);
2907 void ScDocument::SetDirty()
2909 BOOL bOldAutoCalc
= GetAutoCalc();
2910 bAutoCalc
= FALSE
; // keine Mehrfachberechnung
2911 { // scope for bulk broadcast
2912 ScBulkBroadcast
aBulkBroadcast( GetBASM());
2913 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
2914 if (pTab
[i
]) pTab
[i
]->SetDirty();
2917 // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt,
2918 // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt
2919 // (#45205#) - darum alle Charts nochmal explizit
2920 if (pChartListenerCollection
)
2921 pChartListenerCollection
->SetDirty();
2923 SetAutoCalc( bOldAutoCalc
);
2927 void ScDocument::SetDirty( const ScRange
& rRange
)
2929 BOOL bOldAutoCalc
= GetAutoCalc();
2930 bAutoCalc
= FALSE
; // keine Mehrfachberechnung
2931 { // scope for bulk broadcast
2932 ScBulkBroadcast
aBulkBroadcast( GetBASM());
2933 SCTAB nTab2
= rRange
.aEnd
.Tab();
2934 for (SCTAB i
=rRange
.aStart
.Tab(); i
<=nTab2
; i
++)
2935 if (pTab
[i
]) pTab
[i
]->SetDirty( rRange
);
2937 SetAutoCalc( bOldAutoCalc
);
2941 void ScDocument::SetTableOpDirty( const ScRange
& rRange
)
2943 BOOL bOldAutoCalc
= GetAutoCalc();
2944 bAutoCalc
= FALSE
; // no multiple recalculation
2945 SCTAB nTab2
= rRange
.aEnd
.Tab();
2946 for (SCTAB i
=rRange
.aStart
.Tab(); i
<=nTab2
; i
++)
2947 if (pTab
[i
]) pTab
[i
]->SetTableOpDirty( rRange
);
2948 SetAutoCalc( bOldAutoCalc
);
2952 void ScDocument::AddTableOpFormulaCell( ScFormulaCell
* pCell
)
2954 ScInterpreterTableOpParams
* p
= aTableOpList
.Last();
2955 if ( p
&& p
->bCollectNotifications
)
2958 { // refresh pointers only
2959 p
->aNotifiedFormulaCells
.push_back( pCell
);
2962 { // init both, address and pointer
2963 p
->aNotifiedFormulaCells
.push_back( pCell
);
2964 p
->aNotifiedFormulaPos
.push_back( pCell
->aPos
);
2970 void ScDocument::CalcAll()
2972 ClearLookupCaches(); // Ensure we don't deliver zombie data.
2973 BOOL bOldAutoCalc
= GetAutoCalc();
2974 SetAutoCalc( TRUE
);
2976 for (i
=0; i
<=MAXTAB
; i
++)
2977 if (pTab
[i
]) pTab
[i
]->SetDirtyVar();
2978 for (i
=0; i
<=MAXTAB
; i
++)
2979 if (pTab
[i
]) pTab
[i
]->CalcAll();
2981 SetAutoCalc( bOldAutoCalc
);
2985 void ScDocument::CompileAll()
2987 if ( pCondFormList
)
2988 pCondFormList
->CompileAll();
2990 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
2991 if (pTab
[i
]) pTab
[i
]->CompileAll();
2996 void ScDocument::CompileXML()
2998 BOOL bOldAutoCalc
= GetAutoCalc();
2999 SetAutoCalc( FALSE
);
3000 ScProgress
aProgress( GetDocumentShell(), ScGlobal::GetRscString(
3001 STR_PROGRESS_CALCULATING
), GetXMLImportedFormulaCount() );
3003 // #b6355215# set AutoNameCache to speed up automatic name lookup
3004 DBG_ASSERT( !pAutoNameCache
, "AutoNameCache already set" );
3005 pAutoNameCache
= new ScAutoNameCache( this );
3007 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
3008 if (pTab
[i
]) pTab
[i
]->CompileXML( aProgress
);
3010 DELETEZ( pAutoNameCache
); // valid only during CompileXML, where cell contents don't change
3012 if ( pCondFormList
)
3013 pCondFormList
->CompileXML();
3014 if ( pValidationList
)
3015 pValidationList
->CompileXML();
3018 SetAutoCalc( bOldAutoCalc
);
3022 void ScDocument::CalcAfterLoad()
3026 if (bIsClip
) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen
3027 return; // dann wird erst beim Einfuegen in das richtige Doc berechnet
3029 bCalcingAfterLoad
= TRUE
;
3030 for ( i
= 0; i
<= MAXTAB
; i
++)
3031 if (pTab
[i
]) pTab
[i
]->CalcAfterLoad();
3032 for (i
=0; i
<=MAXTAB
; i
++)
3033 if (pTab
[i
]) pTab
[i
]->SetDirtyAfterLoad();
3034 bCalcingAfterLoad
= FALSE
;
3036 SetDetectiveDirty(FALSE
); // noch keine wirklichen Aenderungen
3040 USHORT
ScDocument::GetErrCode( const ScAddress
& rPos
) const
3042 SCTAB nTab
= rPos
.Tab();
3044 return pTab
[nTab
]->GetErrCode( rPos
);
3049 void ScDocument::ResetChanged( const ScRange
& rRange
)
3051 SCTAB nStartTab
= rRange
.aStart
.Tab();
3052 SCTAB nEndTab
= rRange
.aEnd
.Tab();
3053 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
3055 pTab
[nTab
]->ResetChanged( rRange
);
3059 // Spaltenbreiten / Zeilenhoehen --------------------------------------
3063 void ScDocument::SetColWidth( SCCOL nCol
, SCTAB nTab
, USHORT nNewWidth
)
3065 if ( ValidTab(nTab
) && pTab
[nTab
] )
3066 pTab
[nTab
]->SetColWidth( nCol
, nNewWidth
);
3070 void ScDocument::SetRowHeight( SCROW nRow
, SCTAB nTab
, USHORT nNewHeight
)
3072 if ( ValidTab(nTab
) && pTab
[nTab
] )
3073 pTab
[nTab
]->SetRowHeight( nRow
, nNewHeight
);
3077 void ScDocument::SetRowHeightRange( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, USHORT nNewHeight
)
3079 if ( ValidTab(nTab
) && pTab
[nTab
] )
3080 pTab
[nTab
]->SetRowHeightRange
3081 ( nStartRow
, nEndRow
, nNewHeight
, 1.0, 1.0 );
3085 void ScDocument::SetManualHeight( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, BOOL bManual
)
3087 if ( ValidTab(nTab
) && pTab
[nTab
] )
3088 pTab
[nTab
]->SetManualHeight( nStartRow
, nEndRow
, bManual
);
3092 USHORT
ScDocument::GetColWidth( SCCOL nCol
, SCTAB nTab
) const
3094 if ( ValidTab(nTab
) && pTab
[nTab
] )
3095 return pTab
[nTab
]->GetColWidth( nCol
);
3096 DBG_ERROR("Falsche Tabellennummer");
3101 USHORT
ScDocument::GetOriginalWidth( SCCOL nCol
, SCTAB nTab
) const
3103 if ( ValidTab(nTab
) && pTab
[nTab
] )
3104 return pTab
[nTab
]->GetOriginalWidth( nCol
);
3105 DBG_ERROR("Falsche Tabellennummer");
3110 USHORT
ScDocument::GetCommonWidth( SCCOL nEndCol
, SCTAB nTab
) const
3112 if ( ValidTab(nTab
) && pTab
[nTab
] )
3113 return pTab
[nTab
]->GetCommonWidth( nEndCol
);
3114 DBG_ERROR("Wrong table number");
3119 USHORT
ScDocument::GetOriginalHeight( SCROW nRow
, SCTAB nTab
) const
3121 if ( ValidTab(nTab
) && pTab
[nTab
] )
3122 return pTab
[nTab
]->GetOriginalHeight( nRow
);
3123 DBG_ERROR("Wrong table number");
3128 USHORT
ScDocument::GetRowHeight( SCROW nRow
, SCTAB nTab
) const
3130 if ( ValidTab(nTab
) && pTab
[nTab
] )
3131 return pTab
[nTab
]->GetRowHeight( nRow
);
3132 DBG_ERROR("Falsche Tabellennummer");
3137 ULONG
ScDocument::GetRowHeight( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
3139 if (nStartRow
== nEndRow
)
3140 return GetRowHeight( nStartRow
, nTab
); // faster for a single row
3142 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3143 if (nStartRow
> nEndRow
)
3146 if ( ValidTab(nTab
) && pTab
[nTab
] )
3147 return pTab
[nTab
]->GetRowHeight( nStartRow
, nEndRow
);
3149 DBG_ERROR("wrong sheet number");
3153 ULONG
ScDocument::FastGetRowHeight( SCROW nStartRow
, SCROW nEndRow
,
3156 return pTab
[nTab
]->pRowFlags
->SumCoupledArrayForCondition( nStartRow
,
3157 nEndRow
, CR_HIDDEN
, 0, *(pTab
[nTab
]->pRowHeight
));
3160 ULONG
ScDocument::GetScaledRowHeight( SCROW nStartRow
, SCROW nEndRow
,
3161 SCTAB nTab
, double fScale
) const
3163 // faster for a single row
3164 if (nStartRow
== nEndRow
)
3165 return (ULONG
) (GetRowHeight( nStartRow
, nTab
) * fScale
);
3167 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3168 if (nStartRow
> nEndRow
)
3171 if ( ValidTab(nTab
) && pTab
[nTab
] )
3172 return pTab
[nTab
]->GetScaledRowHeight( nStartRow
, nEndRow
, fScale
);
3174 DBG_ERROR("wrong sheet number");
3179 const ScSummableCompressedArray
< SCROW
, USHORT
> & ScDocument::GetRowHeightArray(
3182 const ScSummableCompressedArray
< SCROW
, USHORT
> * pHeight
;
3183 if ( ValidTab(nTab
) && pTab
[nTab
] )
3184 pHeight
= pTab
[nTab
]->GetRowHeightArray();
3187 DBG_ERROR("wrong sheet number");
3192 DBG_ERROR("no row heights at sheet");
3193 static ScSummableCompressedArray
< SCROW
, USHORT
> aDummy( MAXROW
,
3194 ScGlobal::nStdRowHeight
);
3201 SCROW
ScDocument::GetHiddenRowCount( SCROW nRow
, SCTAB nTab
) const
3203 if ( ValidTab(nTab
) && pTab
[nTab
] )
3204 return pTab
[nTab
]->GetHiddenRowCount( nRow
);
3205 DBG_ERROR("Falsche Tabellennummer");
3210 ULONG
ScDocument::GetColOffset( SCCOL nCol
, SCTAB nTab
) const
3212 if ( ValidTab(nTab
) && pTab
[nTab
] )
3213 return pTab
[nTab
]->GetColOffset( nCol
);
3214 DBG_ERROR("Falsche Tabellennummer");
3219 ULONG
ScDocument::GetRowOffset( SCROW nRow
, SCTAB nTab
) const
3221 if ( ValidTab(nTab
) && pTab
[nTab
] )
3222 return pTab
[nTab
]->GetRowOffset( nRow
);
3223 DBG_ERROR("Falsche Tabellennummer");
3228 USHORT
ScDocument::GetOptimalColWidth( SCCOL nCol
, SCTAB nTab
, OutputDevice
* pDev
,
3229 double nPPTX
, double nPPTY
,
3230 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
3231 BOOL bFormula
, const ScMarkData
* pMarkData
,
3232 BOOL bSimpleTextImport
)
3234 if ( ValidTab(nTab
) && pTab
[nTab
] )
3235 return pTab
[nTab
]->GetOptimalColWidth( nCol
, pDev
, nPPTX
, nPPTY
,
3236 rZoomX
, rZoomY
, bFormula
, pMarkData
, bSimpleTextImport
);
3237 DBG_ERROR("Falsche Tabellennummer");
3242 long ScDocument::GetNeededSize( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
3244 double nPPTX
, double nPPTY
,
3245 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
3246 BOOL bWidth
, BOOL bTotalSize
)
3248 if ( ValidTab(nTab
) && pTab
[nTab
] )
3249 return pTab
[nTab
]->GetNeededSize
3250 ( nCol
, nRow
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bWidth
, bTotalSize
);
3251 DBG_ERROR("Falsche Tabellennummer");
3256 BOOL
ScDocument::SetOptimalHeight( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, USHORT nExtra
,
3258 double nPPTX
, double nPPTY
,
3259 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
3263 if ( ValidTab(nTab
) && pTab
[nTab
] )
3264 return pTab
[nTab
]->SetOptimalHeight( nStartRow
, nEndRow
, nExtra
,
3265 pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bShrink
);
3266 DBG_ERROR("Falsche Tabellennummer");
3271 void ScDocument::UpdateAllRowHeights( OutputDevice
* pDev
, double nPPTX
, double nPPTY
,
3272 const Fraction
& rZoomX
, const Fraction
& rZoomY
, const ScMarkData
* pTabMark
)
3274 // one progress across all (selected) sheets
3276 ULONG nCellCount
= 0;
3277 for ( SCTAB nTab
=0; nTab
<=MAXTAB
; nTab
++ )
3278 if ( pTab
[nTab
] && ( !pTabMark
|| pTabMark
->GetTableSelect(nTab
) ) )
3279 nCellCount
+= pTab
[nTab
]->GetWeightedCount();
3281 ScProgress
aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING
), nCellCount
);
3283 ULONG nProgressStart
= 0;
3284 for ( SCTAB nTab
=0; nTab
<=MAXTAB
; nTab
++ )
3285 if ( pTab
[nTab
] && ( !pTabMark
|| pTabMark
->GetTableSelect(nTab
) ) )
3287 pTab
[nTab
]->SetOptimalHeight( 0, MAXROW
, 0,
3288 pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, FALSE
, &aProgress
, nProgressStart
);
3289 nProgressStart
+= pTab
[nTab
]->GetWeightedCount();
3295 // Spalten-/Zeilen-Flags ----------------------------------------------
3298 void ScDocument::ShowCol(SCCOL nCol
, SCTAB nTab
, BOOL bShow
)
3300 if ( ValidTab(nTab
) && pTab
[nTab
] )
3301 pTab
[nTab
]->ShowCol( nCol
, bShow
);
3305 void ScDocument::ShowRow(SCROW nRow
, SCTAB nTab
, BOOL bShow
)
3307 if ( ValidTab(nTab
) && pTab
[nTab
] )
3308 pTab
[nTab
]->ShowRow( nRow
, bShow
);
3312 void ScDocument::ShowRows(SCROW nRow1
, SCROW nRow2
, SCTAB nTab
, BOOL bShow
)
3314 if ( ValidTab(nTab
) && pTab
[nTab
] )
3315 pTab
[nTab
]->ShowRows( nRow1
, nRow2
, bShow
);
3319 void ScDocument::SetColFlags( SCCOL nCol
, SCTAB nTab
, BYTE nNewFlags
)
3321 if ( ValidTab(nTab
) && pTab
[nTab
] )
3322 pTab
[nTab
]->SetColFlags( nCol
, nNewFlags
);
3326 void ScDocument::SetRowFlags( SCROW nRow
, SCTAB nTab
, BYTE nNewFlags
)
3328 if ( ValidTab(nTab
) && pTab
[nTab
] )
3329 pTab
[nTab
]->SetRowFlags( nRow
, nNewFlags
);
3333 void ScDocument::SetRowFlags( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, BYTE nNewFlags
)
3335 if ( ValidTab(nTab
) && pTab
[nTab
] )
3336 pTab
[nTab
]->SetRowFlags( nStartRow
, nEndRow
, nNewFlags
);
3340 BYTE
ScDocument::GetColFlags( SCCOL nCol
, SCTAB nTab
) const
3342 if ( ValidTab(nTab
) && pTab
[nTab
] )
3343 return pTab
[nTab
]->GetColFlags( nCol
);
3344 DBG_ERROR("Falsche Tabellennummer");
3348 BYTE
ScDocument::GetRowFlags( SCROW nRow
, SCTAB nTab
) const
3350 if ( ValidTab(nTab
) && pTab
[nTab
] )
3351 return pTab
[nTab
]->GetRowFlags( nRow
);
3352 DBG_ERROR("Falsche Tabellennummer");
3356 ScBitMaskCompressedArray
< SCROW
, BYTE
> & ScDocument::GetRowFlagsArrayModifiable(
3359 return const_cast< ScBitMaskCompressedArray
< SCROW
, BYTE
> & >(
3360 GetRowFlagsArray( nTab
));
3363 const ScBitMaskCompressedArray
< SCROW
, BYTE
> & ScDocument::GetRowFlagsArray(
3366 const ScBitMaskCompressedArray
< SCROW
, BYTE
> * pFlags
;
3367 if ( ValidTab(nTab
) && pTab
[nTab
] )
3368 pFlags
= pTab
[nTab
]->GetRowFlagsArray();
3371 DBG_ERROR("wrong sheet number");
3376 DBG_ERROR("no row flags at sheet");
3377 static ScBitMaskCompressedArray
< SCROW
, BYTE
> aDummy( MAXROW
, 0);
3384 SCROW
ScDocument::GetLastFlaggedRow( SCTAB nTab
) const
3386 if ( ValidTab(nTab
) && pTab
[nTab
] )
3387 return pTab
[nTab
]->GetLastFlaggedRow();
3392 SCCOL
ScDocument::GetLastChangedCol( SCTAB nTab
) const
3394 if ( ValidTab(nTab
) && pTab
[nTab
] )
3395 return pTab
[nTab
]->GetLastChangedCol();
3399 SCROW
ScDocument::GetLastChangedRow( SCTAB nTab
) const
3401 if ( ValidTab(nTab
) && pTab
[nTab
] )
3402 return pTab
[nTab
]->GetLastChangedRow();
3407 SCCOL
ScDocument::GetNextDifferentChangedCol( SCTAB nTab
, SCCOL nStart
) const
3409 if ( ValidTab(nTab
) && pTab
[nTab
] )
3411 BYTE nStartFlags
= pTab
[nTab
]->GetColFlags(nStart
);
3412 USHORT nStartWidth
= pTab
[nTab
]->GetOriginalWidth(nStart
);
3413 for (SCCOL nCol
= nStart
+ 1; nCol
<= MAXCOL
; nCol
++)
3415 if (((nStartFlags
& CR_MANUALBREAK
) != (pTab
[nTab
]->GetColFlags(nCol
) & CR_MANUALBREAK
)) ||
3416 (nStartWidth
!= pTab
[nTab
]->GetOriginalWidth(nCol
)) ||
3417 ((nStartFlags
& CR_HIDDEN
) != (pTab
[nTab
]->GetColFlags(nCol
) & CR_HIDDEN
)) )
3425 SCROW
ScDocument::GetNextDifferentChangedRow( SCTAB nTab
, SCROW nStart
, bool bCareManualSize
) const
3427 if ( ValidTab(nTab
) && pTab
[nTab
] && pTab
[nTab
]->GetRowFlagsArray() && pTab
[nTab
]->GetRowHeightArray() )
3429 BYTE nStartFlags
= pTab
[nTab
]->GetRowFlags(nStart
);
3430 USHORT nStartHeight
= pTab
[nTab
]->GetOriginalHeight(nStart
);
3431 for (SCROW nRow
= nStart
+ 1; nRow
<= MAXROW
; nRow
++)
3433 size_t nIndex
; // ignored
3435 SCROW nHeightEndRow
;
3436 BYTE nFlags
= pTab
[nTab
]->GetRowFlagsArray()->GetValue( nRow
, nIndex
, nFlagsEndRow
);
3437 USHORT nHeight
= pTab
[nTab
]->GetRowHeightArray()->GetValue( nRow
, nIndex
, nHeightEndRow
);
3438 if (((nStartFlags
& CR_MANUALBREAK
) != (nFlags
& CR_MANUALBREAK
)) ||
3439 ((nStartFlags
& CR_MANUALSIZE
) != (nFlags
& CR_MANUALSIZE
)) ||
3440 (bCareManualSize
&& (nStartFlags
& CR_MANUALSIZE
) && (nStartHeight
!= nHeight
)) ||
3441 (!bCareManualSize
&& ((nStartHeight
!= nHeight
))))
3444 nRow
= std::min( nFlagsEndRow
, nHeightEndRow
);
3451 BOOL
ScDocument::GetColDefault( SCTAB nTab
, SCCOL nCol
, SCROW nLastRow
, SCROW
& nDefault
)
3455 ScDocAttrIterator
aDocAttrItr(this, nTab
, nCol
, 0, nCol
, nLastRow
);
3459 const ScPatternAttr
* pAttr
= aDocAttrItr
.GetNext(nColumn
, nStartRow
, nEndRow
);
3460 if (nEndRow
< nLastRow
)
3462 ScDefaultAttrSet aSet
;
3463 ScDefaultAttrSet::iterator aItr
= aSet
.end();
3466 ScDefaultAttr
aAttr(pAttr
);
3467 aItr
= aSet
.find(aAttr
);
3468 if (aItr
== aSet
.end())
3470 aAttr
.nCount
= static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
3471 aAttr
.nFirst
= nStartRow
;
3476 aAttr
.nCount
= aItr
->nCount
+ static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
3477 aAttr
.nFirst
= aItr
->nFirst
;
3481 pAttr
= aDocAttrItr
.GetNext(nColumn
, nStartRow
, nEndRow
);
3483 ScDefaultAttrSet::iterator aDefaultItr
= aSet
.begin();
3486 while (aItr
!= aSet
.end())
3488 // for entries with equal count, use the one with the lowest start row,
3489 // don't use the random order of pointer comparisons
3490 if ( aItr
->nCount
> aDefaultItr
->nCount
||
3491 ( aItr
->nCount
== aDefaultItr
->nCount
&& aItr
->nFirst
< aDefaultItr
->nFirst
) )
3495 nDefault
= aDefaultItr
->nFirst
;
3503 BOOL
ScDocument::GetRowDefault( SCTAB
/* nTab */, SCROW
/* nRow */, SCCOL
/* nLastCol */, SCCOL
& /* nDefault */ )
3509 void ScDocument::StripHidden( SCCOL
& rX1
, SCROW
& rY1
, SCCOL
& rX2
, SCROW
& rY2
, SCTAB nTab
)
3511 if ( ValidTab(nTab
) && pTab
[nTab
] )
3512 pTab
[nTab
]->StripHidden( rX1
, rY1
, rX2
, rY2
);
3516 void ScDocument::ExtendHidden( SCCOL
& rX1
, SCROW
& rY1
, SCCOL
& rX2
, SCROW
& rY2
, SCTAB nTab
)
3518 if ( ValidTab(nTab
) && pTab
[nTab
] )
3519 pTab
[nTab
]->ExtendHidden( rX1
, rY1
, rX2
, rY2
);
3523 // Attribute ----------------------------------------------------------
3526 const SfxPoolItem
* ScDocument::GetAttr( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, USHORT nWhich
) const
3528 if ( ValidTab(nTab
) && pTab
[nTab
] )
3530 const SfxPoolItem
* pTemp
= pTab
[nTab
]->GetAttr( nCol
, nRow
, nWhich
);
3535 DBG_ERROR( "Attribut Null" );
3538 return &xPoolHelper
->GetDocPool()->GetDefaultItem( nWhich
);
3542 const ScPatternAttr
* ScDocument::GetPattern( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
3544 if ( ValidTab(nTab
) && pTab
[nTab
] )
3545 return pTab
[nTab
]->GetPattern( nCol
, nRow
);
3550 const ScPatternAttr
* ScDocument::GetMostUsedPattern( SCCOL nCol
, SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
) const
3552 if ( ValidTab(nTab
) && pTab
[nTab
] )
3553 return pTab
[nTab
]->GetMostUsedPattern( nCol
, nStartRow
, nEndRow
);
3558 void ScDocument::ApplyAttr( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const SfxPoolItem
& rAttr
)
3560 if ( ValidTab(nTab
) && pTab
[nTab
] )
3561 pTab
[nTab
]->ApplyAttr( nCol
, nRow
, rAttr
);
3565 void ScDocument::ApplyPattern( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const ScPatternAttr
& rAttr
)
3567 if ( ValidTab(nTab
) && pTab
[nTab
] )
3568 pTab
[nTab
]->ApplyPattern( nCol
, nRow
, rAttr
);
3572 void ScDocument::ApplyPatternArea( SCCOL nStartCol
, SCROW nStartRow
,
3573 SCCOL nEndCol
, SCROW nEndRow
,
3574 const ScMarkData
& rMark
,
3575 const ScPatternAttr
& rAttr
,
3576 ScEditDataArray
* pDataArray
)
3578 for (SCTAB i
=0; i
<= MAXTAB
; i
++)
3580 if (rMark
.GetTableSelect(i
))
3581 pTab
[i
]->ApplyPatternArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rAttr
, pDataArray
);
3585 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol
, SCROW nStartRow
,
3586 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, const ScPatternAttr
& rAttr
)
3590 pTab
[nTab
]->ApplyPatternArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rAttr
);
3593 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange
& rRange
,
3594 const ScMarkData
& rMark
, const ScPatternAttr
& rPattern
, short nNewType
)
3596 for (SCTAB i
=0; i
<= MAXTAB
; i
++)
3598 if (rMark
.GetTableSelect(i
))
3599 pTab
[i
]->ApplyPatternIfNumberformatIncompatible( rRange
, rPattern
, nNewType
);
3603 void ScDocument::ApplyStyle( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const ScStyleSheet
& rStyle
)
3607 pTab
[nTab
]->ApplyStyle( nCol
, nRow
, rStyle
);
3611 void ScDocument::ApplyStyleArea( SCCOL nStartCol
, SCROW nStartRow
,
3612 SCCOL nEndCol
, SCROW nEndRow
,
3613 const ScMarkData
& rMark
,
3614 const ScStyleSheet
& rStyle
)
3616 for (SCTAB i
=0; i
<= MAXTAB
; i
++)
3618 if (rMark
.GetTableSelect(i
))
3619 pTab
[i
]->ApplyStyleArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rStyle
);
3623 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol
, SCROW nStartRow
,
3624 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, const ScStyleSheet
& rStyle
)
3628 pTab
[nTab
]->ApplyStyleArea( nStartCol
, nStartRow
, nEndCol
, nEndRow
, rStyle
);
3632 void ScDocument::ApplySelectionStyle(const ScStyleSheet
& rStyle
, const ScMarkData
& rMark
)
3634 // ApplySelectionStyle needs multi mark
3635 if ( rMark
.IsMarked() && !rMark
.IsMultiMarked() )
3638 rMark
.GetMarkArea( aRange
);
3639 ApplyStyleArea( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
3640 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), rMark
, rStyle
);
3644 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
3645 if ( pTab
[i
] && rMark
.GetTableSelect(i
) )
3646 pTab
[i
]->ApplySelectionStyle( rStyle
, rMark
);
3651 void ScDocument::ApplySelectionLineStyle( const ScMarkData
& rMark
,
3652 const SvxBorderLine
* pLine
, BOOL bColorOnly
)
3654 if ( bColorOnly
&& !pLine
)
3657 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
3659 if (rMark
.GetTableSelect(i
))
3660 pTab
[i
]->ApplySelectionLineStyle( rMark
, pLine
, bColorOnly
);
3664 const ScStyleSheet
* ScDocument::GetStyle( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
3666 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
3667 return pTab
[nTab
]->GetStyle(nCol
, nRow
);
3673 const ScStyleSheet
* ScDocument::GetSelectionStyle( const ScMarkData
& rMark
) const
3678 const ScStyleSheet
* pStyle
= NULL
;
3679 const ScStyleSheet
* pNewStyle
;
3681 if ( rMark
.IsMultiMarked() )
3682 for (SCTAB i
=0; i
<=MAXTAB
&& bEqual
; i
++)
3683 if (pTab
[i
] && rMark
.GetTableSelect(i
))
3685 pNewStyle
= pTab
[i
]->GetSelectionStyle( rMark
, bFound
);
3688 if ( !pNewStyle
|| ( pStyle
&& pNewStyle
!= pStyle
) )
3689 bEqual
= FALSE
; // unterschiedliche
3693 if ( rMark
.IsMarked() )
3696 rMark
.GetMarkArea( aRange
);
3697 for (SCTAB i
=aRange
.aStart
.Tab(); i
<=aRange
.aEnd
.Tab() && bEqual
; i
++)
3698 if (pTab
[i
] && rMark
.GetTableSelect(i
))
3700 pNewStyle
= pTab
[i
]->GetAreaStyle( bFound
,
3701 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
3702 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
3705 if ( !pNewStyle
|| ( pStyle
&& pNewStyle
!= pStyle
) )
3706 bEqual
= FALSE
; // unterschiedliche
3712 return bEqual
? pStyle
: NULL
;
3716 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase
* pStyleSheet
, BOOL bRemoved
,
3718 double nPPTX
, double nPPTY
,
3719 const Fraction
& rZoomX
, const Fraction
& rZoomY
)
3721 for (SCTAB i
=0; i
<= MAXTAB
; i
++)
3723 pTab
[i
]->StyleSheetChanged
3724 ( pStyleSheet
, bRemoved
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
);
3726 if ( pStyleSheet
&& pStyleSheet
->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) )
3728 // update attributes for all note objects
3729 ScDetectiveFunc::UpdateAllComments( *this );
3734 BOOL
ScDocument::IsStyleSheetUsed( const ScStyleSheet
& rStyle
, BOOL bGatherAllStyles
) const
3736 if ( bStyleSheetUsageInvalid
|| rStyle
.GetUsage() == ScStyleSheet::UNKNOWN
)
3738 if ( bGatherAllStyles
)
3740 SfxStyleSheetIterator
aIter( xPoolHelper
->GetStylePool(),
3741 SFX_STYLE_FAMILY_PARA
);
3742 for ( const SfxStyleSheetBase
* pStyle
= aIter
.First(); pStyle
;
3743 pStyle
= aIter
.Next() )
3745 const ScStyleSheet
* pScStyle
= PTR_CAST( ScStyleSheet
, pStyle
);
3747 pScStyle
->SetUsage( ScStyleSheet::NOTUSED
);
3751 BOOL bIsUsed
= FALSE
;
3753 for ( SCTAB i
=0; i
<=MAXTAB
; i
++ )
3757 if ( pTab
[i
]->IsStyleSheetUsed( rStyle
, bGatherAllStyles
) )
3759 if ( !bGatherAllStyles
)
3766 if ( bGatherAllStyles
)
3767 bStyleSheetUsageInvalid
= FALSE
;
3772 return rStyle
.GetUsage() == ScStyleSheet::USED
;
3776 BOOL
ScDocument::ApplyFlagsTab( SCCOL nStartCol
, SCROW nStartRow
,
3777 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, INT16 nFlags
)
3781 return pTab
[nTab
]->ApplyFlags( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nFlags
);
3783 DBG_ERROR("ApplyFlags: falsche Tabelle");
3788 BOOL
ScDocument::RemoveFlagsTab( SCCOL nStartCol
, SCROW nStartRow
,
3789 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
, INT16 nFlags
)
3793 return pTab
[nTab
]->RemoveFlags( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nFlags
);
3795 DBG_ERROR("RemoveFlags: falsche Tabelle");
3800 void ScDocument::SetPattern( SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const ScPatternAttr
& rAttr
,
3805 pTab
[nTab
]->SetPattern( nCol
, nRow
, rAttr
, bPutToPool
);
3809 void ScDocument::SetPattern( const ScAddress
& rPos
, const ScPatternAttr
& rAttr
,
3812 SCTAB nTab
= rPos
.Tab();
3814 pTab
[nTab
]->SetPattern( rPos
, rAttr
, bPutToPool
);
3818 ScPatternAttr
* ScDocument::CreateSelectionPattern( const ScMarkData
& rMark
, BOOL bDeep
)
3820 ScMergePatternState aState
;
3822 if ( rMark
.IsMultiMarked() ) // multi selection
3824 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
3825 if (pTab
[i
] && rMark
.GetTableSelect(i
))
3826 pTab
[i
]->MergeSelectionPattern( aState
, rMark
, bDeep
);
3828 if ( rMark
.IsMarked() ) // simle selection
3831 rMark
.GetMarkArea(aRange
);
3832 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
3833 if (pTab
[i
] && rMark
.GetTableSelect(i
))
3834 pTab
[i
]->MergePatternArea( aState
,
3835 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
3836 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), bDeep
);
3839 DBG_ASSERT( aState
.pItemSet
, "SelectionPattern Null" );
3840 if (aState
.pItemSet
)
3841 return new ScPatternAttr( aState
.pItemSet
);
3843 return new ScPatternAttr( GetPool() ); // empty
3847 const ScPatternAttr
* ScDocument::GetSelectionPattern( const ScMarkData
& rMark
, BOOL bDeep
)
3849 delete pSelectionAttr
;
3850 pSelectionAttr
= CreateSelectionPattern( rMark
, bDeep
);
3851 return pSelectionAttr
;
3855 void ScDocument::GetSelectionFrame( const ScMarkData
& rMark
,
3856 SvxBoxItem
& rLineOuter
,
3857 SvxBoxInfoItem
& rLineInner
)
3859 rLineOuter
.SetLine(NULL
, BOX_LINE_TOP
);
3860 rLineOuter
.SetLine(NULL
, BOX_LINE_BOTTOM
);
3861 rLineOuter
.SetLine(NULL
, BOX_LINE_LEFT
);
3862 rLineOuter
.SetLine(NULL
, BOX_LINE_RIGHT
);
3863 rLineOuter
.SetDistance(0);
3865 rLineInner
.SetLine(NULL
, BOXINFO_LINE_HORI
);
3866 rLineInner
.SetLine(NULL
, BOXINFO_LINE_VERT
);
3867 rLineInner
.SetTable(TRUE
);
3868 rLineInner
.SetDist(TRUE
);
3869 rLineInner
.SetMinDist(FALSE
);
3873 if (rMark
.IsMarked())
3876 rMark
.GetMarkArea(aRange
);
3877 rLineInner
.EnableHor( aRange
.aStart
.Row() != aRange
.aEnd
.Row() );
3878 rLineInner
.EnableVer( aRange
.aStart
.Col() != aRange
.aEnd
.Col() );
3879 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
3880 if (pTab
[i
] && rMark
.GetTableSelect(i
))
3881 pTab
[i
]->MergeBlockFrame( &rLineOuter
, &rLineInner
, aFlags
,
3882 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
3883 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
3886 // Don't care Status auswerten
3888 rLineInner
.SetValid( VALID_LEFT
, ( aFlags
.nLeft
!= SC_LINE_DONTCARE
) );
3889 rLineInner
.SetValid( VALID_RIGHT
, ( aFlags
.nRight
!= SC_LINE_DONTCARE
) );
3890 rLineInner
.SetValid( VALID_TOP
, ( aFlags
.nTop
!= SC_LINE_DONTCARE
) );
3891 rLineInner
.SetValid( VALID_BOTTOM
, ( aFlags
.nBottom
!= SC_LINE_DONTCARE
) );
3892 rLineInner
.SetValid( VALID_HORI
, ( aFlags
.nHori
!= SC_LINE_DONTCARE
) );
3893 rLineInner
.SetValid( VALID_VERT
, ( aFlags
.nVert
!= SC_LINE_DONTCARE
) );
3897 BOOL
ScDocument::HasAttrib( SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
3898 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
, USHORT nMask
)
3900 if ( nMask
& HASATTR_ROTATE
)
3902 // Attribut im Dokument ueberhaupt verwendet?
3903 // (wie in fillinfo)
3905 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
3907 BOOL bAnyItem
= FALSE
;
3908 USHORT nRotCount
= pPool
->GetItemCount( ATTR_ROTATE_VALUE
);
3909 for (USHORT nItem
=0; nItem
<nRotCount
; nItem
++)
3911 const SfxPoolItem
* pItem
= pPool
->GetItem( ATTR_ROTATE_VALUE
, nItem
);
3914 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
3915 // (see ScPatternAttr::GetCellOrientation)
3916 INT32 nAngle
= static_cast<const SfxInt32Item
*>(pItem
)->GetValue();
3917 if ( nAngle
!= 0 && nAngle
!= 9000 && nAngle
!= 27000 )
3925 nMask
&= ~HASATTR_ROTATE
;
3928 if ( nMask
& HASATTR_RTL
)
3930 // first check if right-to left is in the pool at all
3931 // (the same item is used in cell and page format)
3933 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
3935 BOOL bHasRtl
= FALSE
;
3936 USHORT nDirCount
= pPool
->GetItemCount( ATTR_WRITINGDIR
);
3937 for (USHORT nItem
=0; nItem
<nDirCount
; nItem
++)
3939 const SfxPoolItem
* pItem
= pPool
->GetItem( ATTR_WRITINGDIR
, nItem
);
3940 if ( pItem
&& ((const SvxFrameDirectionItem
*)pItem
)->GetValue() == FRMDIR_HORI_RIGHT_TOP
)
3947 nMask
&= ~HASATTR_RTL
;
3953 BOOL bFound
= FALSE
;
3954 for (SCTAB i
=nTab1
; i
<=nTab2
&& !bFound
; i
++)
3957 if ( nMask
& HASATTR_RTL
)
3959 if ( GetEditTextDirection(i
) == EE_HTEXTDIR_R2L
) // sheet default
3962 if ( nMask
& HASATTR_RIGHTORCENTER
)
3964 // On a RTL sheet, don't start to look for the default left value
3965 // (which is then logically right), instead always assume TRUE.
3966 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets.
3968 if ( IsLayoutRTL(i
) )
3973 bFound
= pTab
[i
]->HasAttrib( nCol1
, nRow1
, nCol2
, nRow2
, nMask
);
3979 BOOL
ScDocument::HasAttrib( const ScRange
& rRange
, USHORT nMask
)
3981 return HasAttrib( rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
3982 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(),
3986 void ScDocument::FindMaxRotCol( SCTAB nTab
, RowInfo
* pRowInfo
, SCSIZE nArrCount
,
3987 SCCOL nX1
, SCCOL nX2
) const
3989 if ( ValidTab(nTab
) && pTab
[nTab
] )
3990 pTab
[nTab
]->FindMaxRotCol( pRowInfo
, nArrCount
, nX1
, nX2
);
3993 DBG_ERRORFILE("FindMaxRotCol: falsche Tabelle");
3997 void ScDocument::GetBorderLines( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
3998 const SvxBorderLine
** ppLeft
, const SvxBorderLine
** ppTop
,
3999 const SvxBorderLine
** ppRight
, const SvxBorderLine
** ppBottom
) const
4001 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
4003 const SvxBoxItem
* pThisAttr
= (const SvxBoxItem
*) GetEffItem( nCol
, nRow
, nTab
, ATTR_BORDER
);
4004 DBG_ASSERT(pThisAttr
,"wo ist das Attribut?");
4006 const SvxBorderLine
* pLeftLine
= pThisAttr
->GetLeft();
4007 const SvxBorderLine
* pTopLine
= pThisAttr
->GetTop();
4008 const SvxBorderLine
* pRightLine
= pThisAttr
->GetRight();
4009 const SvxBorderLine
* pBottomLine
= pThisAttr
->GetBottom();
4013 const SvxBorderLine
* pOther
= ((const SvxBoxItem
*)
4014 GetEffItem( nCol
-1, nRow
, nTab
, ATTR_BORDER
))->GetRight();
4015 if ( ScHasPriority( pOther
, pLeftLine
) )
4020 const SvxBorderLine
* pOther
= ((const SvxBoxItem
*)
4021 GetEffItem( nCol
, nRow
-1, nTab
, ATTR_BORDER
))->GetBottom();
4022 if ( ScHasPriority( pOther
, pTopLine
) )
4025 if ( nCol
< MAXCOL
)
4027 const SvxBorderLine
* pOther
= ((const SvxBoxItem
*)
4028 GetEffItem( nCol
+1, nRow
, nTab
, ATTR_BORDER
))->GetLeft();
4029 if ( ScHasPriority( pOther
, pRightLine
) )
4030 pRightLine
= pOther
;
4032 if ( nRow
< MAXROW
)
4034 const SvxBorderLine
* pOther
= ((const SvxBoxItem
*)
4035 GetEffItem( nCol
, nRow
+1, nTab
, ATTR_BORDER
))->GetTop();
4036 if ( ScHasPriority( pOther
, pBottomLine
) )
4037 pBottomLine
= pOther
;
4041 *ppLeft
= pLeftLine
;
4045 *ppRight
= pRightLine
;
4047 *ppBottom
= pBottomLine
;
4050 BOOL
ScDocument::IsBlockEmpty( SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
,
4051 SCCOL nEndCol
, SCROW nEndRow
, bool bIgnoreNotes
) const
4055 return pTab
[nTab
]->IsBlockEmpty( nStartCol
, nStartRow
, nEndCol
, nEndRow
, bIgnoreNotes
);
4057 DBG_ERROR("Falsche Tabellennummer");
4062 void ScDocument::LockTable(SCTAB nTab
)
4064 if ( ValidTab(nTab
) && pTab
[nTab
] )
4065 pTab
[nTab
]->LockTable();
4068 DBG_ERROR("Falsche Tabellennummer");
4073 void ScDocument::UnlockTable(SCTAB nTab
)
4075 if ( ValidTab(nTab
) && pTab
[nTab
] )
4076 pTab
[nTab
]->UnlockTable();
4079 DBG_ERROR("Falsche Tabellennummer");
4084 BOOL
ScDocument::IsBlockEditable( SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
,
4085 SCCOL nEndCol
, SCROW nEndRow
,
4086 BOOL
* pOnlyNotBecauseOfMatrix
/* = NULL */ ) const
4088 // import into read-only document is possible
4089 if ( !bImportingXML
&& !mbChangeReadOnlyEnabled
&& pShell
&& pShell
->IsReadOnly() )
4091 if ( pOnlyNotBecauseOfMatrix
)
4092 *pOnlyNotBecauseOfMatrix
= FALSE
;
4098 return pTab
[nTab
]->IsBlockEditable( nStartCol
, nStartRow
, nEndCol
,
4099 nEndRow
, pOnlyNotBecauseOfMatrix
);
4101 DBG_ERROR("Falsche Tabellennummer");
4102 if ( pOnlyNotBecauseOfMatrix
)
4103 *pOnlyNotBecauseOfMatrix
= FALSE
;
4108 BOOL
ScDocument::IsSelectionEditable( const ScMarkData
& rMark
,
4109 BOOL
* pOnlyNotBecauseOfMatrix
/* = NULL */ ) const
4111 // import into read-only document is possible
4112 if ( !bImportingXML
&& !mbChangeReadOnlyEnabled
&& pShell
&& pShell
->IsReadOnly() )
4114 if ( pOnlyNotBecauseOfMatrix
)
4115 *pOnlyNotBecauseOfMatrix
= FALSE
;
4120 rMark
.GetMarkArea(aRange
);
4123 BOOL bMatrix
= ( pOnlyNotBecauseOfMatrix
!= NULL
);
4124 for ( SCTAB i
=0; i
<=MAXTAB
&& (bOk
|| bMatrix
); i
++ )
4126 if ( pTab
[i
] && rMark
.GetTableSelect(i
) )
4128 if (rMark
.IsMarked())
4130 if ( !pTab
[i
]->IsBlockEditable( aRange
.aStart
.Col(),
4131 aRange
.aStart
.Row(), aRange
.aEnd
.Col(),
4132 aRange
.aEnd
.Row(), pOnlyNotBecauseOfMatrix
) )
4135 if ( pOnlyNotBecauseOfMatrix
)
4136 bMatrix
= *pOnlyNotBecauseOfMatrix
;
4139 if (rMark
.IsMultiMarked())
4141 if ( !pTab
[i
]->IsSelectionEditable( rMark
, pOnlyNotBecauseOfMatrix
) )
4144 if ( pOnlyNotBecauseOfMatrix
)
4145 bMatrix
= *pOnlyNotBecauseOfMatrix
;
4151 if ( pOnlyNotBecauseOfMatrix
)
4152 *pOnlyNotBecauseOfMatrix
= ( !bOk
&& bMatrix
);
4158 BOOL
ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol
, SCROW nStartRow
,
4159 SCCOL nEndCol
, SCROW nEndRow
,
4160 const ScMarkData
& rMark
) const
4163 for (SCTAB i
=0; i
<=MAXTAB
&& bOk
; i
++)
4165 if (rMark
.GetTableSelect(i
))
4166 if (pTab
[i
]->HasBlockMatrixFragment( nStartCol
, nStartRow
, nEndCol
, nEndRow
))
4173 BOOL
ScDocument::GetMatrixFormulaRange( const ScAddress
& rCellPos
, ScRange
& rMatrix
)
4175 // if rCell is part of a matrix formula, return its complete range
4178 ScBaseCell
* pCell
= GetCell( rCellPos
);
4179 if (pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
4181 ScAddress aOrigin
= rCellPos
;
4182 if ( ((ScFormulaCell
*)pCell
)->GetMatrixOrigin( aOrigin
) )
4184 if ( aOrigin
!= rCellPos
)
4185 pCell
= GetCell( aOrigin
);
4186 if (pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
4190 ((ScFormulaCell
*)pCell
)->GetMatColsRows(nSizeX
,nSizeY
);
4191 if ( !(nSizeX
> 0 && nSizeY
> 0) )
4193 // GetMatrixEdge computes also dimensions of the matrix
4194 // if not already done (may occur if document is loaded
4195 // from old file format).
4196 // Needs an "invalid" initialized address.
4197 aOrigin
.SetInvalid();
4198 ((ScFormulaCell
*)pCell
)->GetMatrixEdge(aOrigin
);
4199 ((ScFormulaCell
*)pCell
)->GetMatColsRows(nSizeX
,nSizeY
);
4201 if ( nSizeX
> 0 && nSizeY
> 0 )
4203 ScAddress
aEnd( aOrigin
.Col() + nSizeX
- 1,
4204 aOrigin
.Row() + nSizeY
- 1,
4207 rMatrix
.aStart
= aOrigin
;
4208 rMatrix
.aEnd
= aEnd
;
4218 BOOL
ScDocument::ExtendOverlapped( SCCOL
& rStartCol
, SCROW
& rStartRow
,
4219 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
)
4221 BOOL bFound
= FALSE
;
4222 if ( ValidColRow(rStartCol
,rStartRow
) && ValidColRow(nEndCol
,nEndRow
) && ValidTab(nTab
) )
4227 SCCOL nOldCol
= rStartCol
;
4228 SCROW nOldRow
= rStartRow
;
4229 for (nCol
=nOldCol
; nCol
<=nEndCol
; nCol
++)
4230 while (((ScMergeFlagAttr
*)GetAttr(nCol
,rStartRow
,nTab
,ATTR_MERGE_FLAG
))->
4236 ScAttrArray
* pAttrArray
= pTab
[nTab
]->aCol
[nOldCol
].pAttrArray
;
4238 pAttrArray
->Search( nOldRow
, nIndex
);
4239 SCROW nAttrPos
= nOldRow
;
4240 while (nAttrPos
<=nEndRow
)
4242 DBG_ASSERT( nIndex
< pAttrArray
->nCount
, "Falscher Index im AttrArray" );
4244 if (((ScMergeFlagAttr
&)pAttrArray
->pData
[nIndex
].pPattern
->
4245 GetItem(ATTR_MERGE_FLAG
)).IsHorOverlapped())
4247 SCROW nLoopEndRow
= Min( nEndRow
, pAttrArray
->pData
[nIndex
].nRow
);
4248 for (SCROW nAttrRow
= nAttrPos
; nAttrRow
<= nLoopEndRow
; nAttrRow
++)
4250 SCCOL nTempCol
= nOldCol
;
4253 while (((ScMergeFlagAttr
*)GetAttr(nTempCol
,nAttrRow
,nTab
,ATTR_MERGE_FLAG
))
4254 ->IsHorOverlapped());
4255 if (nTempCol
< rStartCol
)
4256 rStartCol
= nTempCol
;
4259 nAttrPos
= pAttrArray
->pData
[nIndex
].nRow
+ 1;
4266 DBG_ERROR("ExtendOverlapped: falscher Bereich");
4273 BOOL
ScDocument::ExtendMergeSel( SCCOL nStartCol
, SCROW nStartRow
,
4274 SCCOL
& rEndCol
, SCROW
& rEndRow
,
4275 const ScMarkData
& rMark
, BOOL bRefresh
, BOOL bAttrs
)
4277 // use all selected sheets from rMark
4279 BOOL bFound
= FALSE
;
4280 SCCOL nOldEndCol
= rEndCol
;
4281 SCROW nOldEndRow
= rEndRow
;
4283 for (SCTAB nTab
= 0; nTab
<= MAXTAB
; nTab
++)
4284 if ( pTab
[nTab
] && rMark
.GetTableSelect(nTab
) )
4286 SCCOL nThisEndCol
= nOldEndCol
;
4287 SCROW nThisEndRow
= nOldEndRow
;
4288 if ( ExtendMerge( nStartCol
, nStartRow
, nThisEndCol
, nThisEndRow
, nTab
, bRefresh
, bAttrs
) )
4290 if ( nThisEndCol
> rEndCol
)
4291 rEndCol
= nThisEndCol
;
4292 if ( nThisEndRow
> rEndRow
)
4293 rEndRow
= nThisEndRow
;
4300 BOOL
ScDocument::ExtendMerge( SCCOL nStartCol
, SCROW nStartRow
,
4301 SCCOL
& rEndCol
, SCROW
& rEndRow
,
4302 SCTAB nTab
, BOOL bRefresh
, BOOL bAttrs
)
4304 BOOL bFound
= FALSE
;
4305 if ( ValidColRow(nStartCol
,nStartRow
) && ValidColRow(rEndCol
,rEndRow
) && ValidTab(nTab
) )
4308 bFound
= pTab
[nTab
]->ExtendMerge( nStartCol
, nStartRow
, rEndCol
, rEndRow
, bRefresh
, bAttrs
);
4311 RefreshAutoFilter( nStartCol
, nStartRow
, rEndCol
, rEndRow
, nTab
);
4315 DBG_ERROR("ExtendMerge: falscher Bereich");
4322 BOOL
ScDocument::ExtendMerge( ScRange
& rRange
, BOOL bRefresh
, BOOL bAttrs
)
4324 BOOL bFound
= FALSE
;
4325 SCTAB nStartTab
= rRange
.aStart
.Tab();
4326 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4327 SCCOL nEndCol
= rRange
.aEnd
.Col();
4328 SCROW nEndRow
= rRange
.aEnd
.Row();
4330 PutInOrder( nStartTab
, nEndTab
);
4331 for (SCTAB nTab
= nStartTab
; nTab
<= nEndTab
; nTab
++ )
4333 SCCOL nExtendCol
= rRange
.aEnd
.Col();
4334 SCROW nExtendRow
= rRange
.aEnd
.Row();
4335 if (ExtendMerge( rRange
.aStart
.Col(), rRange
.aStart
.Row(),
4336 nExtendCol
, nExtendRow
,
4337 nTab
, bRefresh
, bAttrs
) )
4340 if (nExtendCol
> nEndCol
) nEndCol
= nExtendCol
;
4341 if (nExtendRow
> nEndRow
) nEndRow
= nExtendRow
;
4345 rRange
.aEnd
.SetCol(nEndCol
);
4346 rRange
.aEnd
.SetRow(nEndRow
);
4351 BOOL
ScDocument::ExtendTotalMerge( ScRange
& rRange
)
4353 // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn
4354 // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden
4357 ScRange aExt
= rRange
;
4358 if (ExtendMerge(aExt
))
4360 if ( aExt
.aEnd
.Row() > rRange
.aEnd
.Row() )
4362 ScRange aTest
= aExt
;
4363 aTest
.aStart
.SetRow( rRange
.aEnd
.Row() + 1 );
4364 if ( HasAttrib( aTest
, HASATTR_NOTOVERLAPPED
) )
4365 aExt
.aEnd
.SetRow(rRange
.aEnd
.Row());
4367 if ( aExt
.aEnd
.Col() > rRange
.aEnd
.Col() )
4369 ScRange aTest
= aExt
;
4370 aTest
.aStart
.SetCol( rRange
.aEnd
.Col() + 1 );
4371 if ( HasAttrib( aTest
, HASATTR_NOTOVERLAPPED
) )
4372 aExt
.aEnd
.SetCol(rRange
.aEnd
.Col());
4375 bRet
= ( aExt
.aEnd
!= rRange
.aEnd
);
4381 BOOL
ScDocument::ExtendOverlapped( ScRange
& rRange
)
4383 BOOL bFound
= FALSE
;
4384 SCTAB nStartTab
= rRange
.aStart
.Tab();
4385 SCTAB nEndTab
= rRange
.aEnd
.Tab();
4386 SCCOL nStartCol
= rRange
.aStart
.Col();
4387 SCROW nStartRow
= rRange
.aStart
.Row();
4389 PutInOrder( nStartTab
, nEndTab
);
4390 for (SCTAB nTab
= nStartTab
; nTab
<= nEndTab
; nTab
++ )
4392 SCCOL nExtendCol
= rRange
.aStart
.Col();
4393 SCROW nExtendRow
= rRange
.aStart
.Row();
4394 ExtendOverlapped( nExtendCol
, nExtendRow
,
4395 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), nTab
);
4396 if (nExtendCol
< nStartCol
)
4398 nStartCol
= nExtendCol
;
4401 if (nExtendRow
< nStartRow
)
4403 nStartRow
= nExtendRow
;
4408 rRange
.aStart
.SetCol(nStartCol
);
4409 rRange
.aStart
.SetRow(nStartRow
);
4414 BOOL
ScDocument::RefreshAutoFilter( SCCOL nStartCol
, SCROW nStartRow
,
4415 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
)
4417 USHORT nCount
= pDBCollection
->GetCount();
4426 // Autofilter loeschen
4428 BOOL bChange
= RemoveFlagsTab( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nTab
, SC_MF_AUTO
);
4430 // Autofilter setzen
4432 for (i
=0; i
<nCount
; i
++)
4434 pData
= (*pDBCollection
)[i
];
4435 if (pData
->HasAutoFilter())
4437 pData
->GetArea( nDBTab
, nDBStartCol
,nDBStartRow
, nDBEndCol
,nDBEndRow
);
4438 if ( nDBTab
==nTab
&& nDBStartRow
<=nEndRow
&& nDBEndRow
>=nStartRow
&&
4439 nDBStartCol
<=nEndCol
&& nDBEndCol
>=nStartCol
)
4441 if (ApplyFlagsTab( nDBStartCol
,nDBStartRow
, nDBEndCol
,nDBStartRow
,
4442 nDBTab
, SC_MF_AUTO
))
4450 void ScDocument::SkipOverlapped( SCCOL
& rCol
, SCROW
& rRow
, SCTAB nTab
) const
4452 while (IsHorOverlapped(rCol
, rRow
, nTab
))
4454 while (IsVerOverlapped(rCol
, rRow
, nTab
))
4458 BOOL
ScDocument::IsHorOverlapped( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
4460 const ScMergeFlagAttr
* pAttr
= (const ScMergeFlagAttr
*)
4461 GetAttr( nCol
, nRow
, nTab
, ATTR_MERGE_FLAG
);
4463 return pAttr
->IsHorOverlapped();
4466 DBG_ERROR("Overlapped: Attr==0");
4472 BOOL
ScDocument::IsVerOverlapped( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
4474 const ScMergeFlagAttr
* pAttr
= (const ScMergeFlagAttr
*)
4475 GetAttr( nCol
, nRow
, nTab
, ATTR_MERGE_FLAG
);
4477 return pAttr
->IsVerOverlapped();
4480 DBG_ERROR("Overlapped: Attr==0");
4486 void ScDocument::ApplySelectionFrame( const ScMarkData
& rMark
,
4487 const SvxBoxItem
* pLineOuter
,
4488 const SvxBoxInfoItem
* pLineInner
)
4490 ScRangeList aRangeList
;
4491 rMark
.FillRangeListWithMarks( &aRangeList
, FALSE
);
4492 ULONG nRangeCount
= aRangeList
.Count();
4493 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
4495 if (pTab
[i
] && rMark
.GetTableSelect(i
))
4497 for (ULONG j
=0; j
<nRangeCount
; j
++)
4499 ScRange aRange
= *aRangeList
.GetObject(j
);
4500 pTab
[i
]->ApplyBlockFrame( pLineOuter
, pLineInner
,
4501 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
4502 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
4509 void ScDocument::ApplyFrameAreaTab( const ScRange
& rRange
,
4510 const SvxBoxItem
* pLineOuter
,
4511 const SvxBoxInfoItem
* pLineInner
)
4513 SCTAB nStartTab
= rRange
.aStart
.Tab();
4514 SCTAB nEndTab
= rRange
.aStart
.Tab();
4515 for (SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++)
4517 pTab
[nTab
]->ApplyBlockFrame( pLineOuter
, pLineInner
,
4518 rRange
.aStart
.Col(), rRange
.aStart
.Row(),
4519 rRange
.aEnd
.Col(), rRange
.aEnd
.Row() );
4523 void ScDocument::ApplySelectionPattern( const ScPatternAttr
& rAttr
, const ScMarkData
& rMark
, ScEditDataArray
* pDataArray
)
4525 const SfxItemSet
* pSet
= &rAttr
.GetItemSet();
4528 for (i
=ATTR_PATTERN_START
; i
<=ATTR_PATTERN_END
&& !bSet
; i
++)
4529 if (pSet
->GetItemState(i
) == SFX_ITEM_SET
)
4534 // ApplySelectionCache needs multi mark
4535 if ( rMark
.IsMarked() && !rMark
.IsMultiMarked() )
4538 rMark
.GetMarkArea( aRange
);
4539 ApplyPatternArea( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
4540 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), rMark
, rAttr
, pDataArray
);
4544 SfxItemPoolCache
aCache( xPoolHelper
->GetDocPool(), pSet
);
4545 for (SCTAB nTab
=0; nTab
<=MAXTAB
; nTab
++)
4547 if (rMark
.GetTableSelect(nTab
))
4548 pTab
[nTab
]->ApplySelectionCache( &aCache
, rMark
, pDataArray
);
4554 void ScDocument::ChangeSelectionIndent( BOOL bIncrement
, const ScMarkData
& rMark
)
4556 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
4557 if (pTab
[i
] && rMark
.GetTableSelect(i
))
4558 pTab
[i
]->ChangeSelectionIndent( bIncrement
, rMark
);
4562 void ScDocument::ClearSelectionItems( const USHORT
* pWhich
, const ScMarkData
& rMark
)
4564 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
4565 if (pTab
[i
] && rMark
.GetTableSelect(i
))
4566 pTab
[i
]->ClearSelectionItems( pWhich
, rMark
);
4570 void ScDocument::DeleteSelection( USHORT nDelFlag
, const ScMarkData
& rMark
)
4572 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
4573 if (pTab
[i
] && rMark
.GetTableSelect(i
))
4574 pTab
[i
]->DeleteSelection( nDelFlag
, rMark
);
4578 void ScDocument::DeleteSelectionTab( SCTAB nTab
, USHORT nDelFlag
, const ScMarkData
& rMark
)
4580 if (ValidTab(nTab
) && pTab
[nTab
])
4581 pTab
[nTab
]->DeleteSelection( nDelFlag
, rMark
);
4584 DBG_ERROR("Falsche Tabelle");
4589 ScPatternAttr
* ScDocument::GetDefPattern() const
4591 return (ScPatternAttr
*) &xPoolHelper
->GetDocPool()->GetDefaultItem(ATTR_PATTERN
);
4595 ScDocumentPool
* ScDocument::GetPool()
4597 return xPoolHelper
->GetDocPool();
4602 ScStyleSheetPool
* ScDocument::GetStyleSheetPool() const
4604 return xPoolHelper
->GetStylePool();
4608 SCSIZE
ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol
, SCROW nStartRow
, SCTAB nStartTab
,
4609 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nEndTab
, ScDirection eDir
)
4611 PutInOrder(nStartCol
, nEndCol
);
4612 PutInOrder(nStartRow
, nEndRow
);
4613 PutInOrder(nStartTab
, nEndTab
);
4614 if (VALIDTAB(nStartTab
))
4616 if (pTab
[nStartTab
])
4617 return pTab
[nStartTab
]->GetEmptyLinesInBlock(nStartCol
, nStartRow
, nEndCol
, nEndRow
, eDir
);
4626 void ScDocument::FindAreaPos( SCCOL
& rCol
, SCROW
& rRow
, SCTAB nTab
, SCsCOL nMovX
, SCsROW nMovY
)
4628 if (ValidTab(nTab
) && pTab
[nTab
])
4629 pTab
[nTab
]->FindAreaPos( rCol
, rRow
, nMovX
, nMovY
);
4633 void ScDocument::GetNextPos( SCCOL
& rCol
, SCROW
& rRow
, SCTAB nTab
, SCsCOL nMovX
, SCsROW nMovY
,
4634 BOOL bMarked
, BOOL bUnprotected
, const ScMarkData
& rMark
)
4636 DBG_ASSERT( !nMovX
|| !nMovY
, "GetNextPos: nur X oder Y" );
4638 ScMarkData aCopyMark
= rMark
;
4639 aCopyMark
.SetMarking(FALSE
);
4640 aCopyMark
.MarkToMulti();
4642 if (ValidTab(nTab
) && pTab
[nTab
])
4643 pTab
[nTab
]->GetNextPos( rCol
, rRow
, nMovX
, nMovY
, bMarked
, bUnprotected
, aCopyMark
);
4647 // Datei-Operationen
4651 void ScDocument::UpdStlShtPtrsFrmNms()
4653 ScPatternAttr::pDoc
= this;
4655 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
4657 USHORT nCount
= pPool
->GetItemCount(ATTR_PATTERN
);
4658 ScPatternAttr
* pPattern
;
4659 for (USHORT i
=0; i
<nCount
; i
++)
4661 pPattern
= (ScPatternAttr
*)pPool
->GetItem(ATTR_PATTERN
, i
);
4663 pPattern
->UpdateStyleSheet();
4665 ((ScPatternAttr
&)pPool
->GetDefaultItem(ATTR_PATTERN
)).UpdateStyleSheet();
4669 void ScDocument::StylesToNames()
4671 ScPatternAttr::pDoc
= this;
4673 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
4675 USHORT nCount
= pPool
->GetItemCount(ATTR_PATTERN
);
4676 ScPatternAttr
* pPattern
;
4677 for (USHORT i
=0; i
<nCount
; i
++)
4679 pPattern
= (ScPatternAttr
*)pPool
->GetItem(ATTR_PATTERN
, i
);
4681 pPattern
->StyleToName();
4683 ((ScPatternAttr
&)pPool
->GetDefaultItem(ATTR_PATTERN
)).StyleToName();
4687 ULONG
ScDocument::GetCellCount() const
4689 ULONG nCellCount
= 0L;
4691 for ( SCTAB nTab
=0; nTab
<=MAXTAB
; nTab
++ )
4693 nCellCount
+= pTab
[nTab
]->GetCellCount();
4699 ULONG
ScDocument::GetCodeCount() const
4701 ULONG nCodeCount
= 0;
4703 for ( SCTAB nTab
=0; nTab
<=MAXTAB
; nTab
++ )
4705 nCodeCount
+= pTab
[nTab
]->GetCodeCount();
4711 ULONG
ScDocument::GetWeightedCount() const
4713 ULONG nCellCount
= 0L;
4715 for ( SCTAB nTab
=0; nTab
<=MAXTAB
; nTab
++ )
4717 nCellCount
+= pTab
[nTab
]->GetWeightedCount();
4723 void ScDocument::PageStyleModified( SCTAB nTab
, const String
& rNewName
)
4725 if ( ValidTab(nTab
) && pTab
[nTab
] )
4726 pTab
[nTab
]->PageStyleModified( rNewName
);
4730 void ScDocument::SetPageStyle( SCTAB nTab
, const String
& rName
)
4732 if ( ValidTab(nTab
) && pTab
[nTab
] )
4733 pTab
[nTab
]->SetPageStyle( rName
);
4737 const String
& ScDocument::GetPageStyle( SCTAB nTab
) const
4739 if ( ValidTab(nTab
) && pTab
[nTab
] )
4740 return pTab
[nTab
]->GetPageStyle();
4742 return EMPTY_STRING
;
4746 void ScDocument::SetPageSize( SCTAB nTab
, const Size
& rSize
)
4748 if ( ValidTab(nTab
) && pTab
[nTab
] )
4749 pTab
[nTab
]->SetPageSize( rSize
);
4752 Size
ScDocument::GetPageSize( SCTAB nTab
) const
4754 if ( ValidTab(nTab
) && pTab
[nTab
] )
4755 return pTab
[nTab
]->GetPageSize();
4757 DBG_ERROR("falsche Tab");
4762 void ScDocument::SetRepeatArea( SCTAB nTab
, SCCOL nStartCol
, SCCOL nEndCol
, SCROW nStartRow
, SCROW nEndRow
)
4764 if ( ValidTab(nTab
) && pTab
[nTab
] )
4765 pTab
[nTab
]->SetRepeatArea( nStartCol
, nEndCol
, nStartRow
, nEndRow
);
4769 void ScDocument::UpdatePageBreaks( SCTAB nTab
, const ScRange
* pUserArea
)
4771 if ( ValidTab(nTab
) && pTab
[nTab
] )
4772 pTab
[nTab
]->UpdatePageBreaks( pUserArea
);
4775 void ScDocument::RemoveManualBreaks( SCTAB nTab
)
4777 if ( ValidTab(nTab
) && pTab
[nTab
] )
4778 pTab
[nTab
]->RemoveManualBreaks();
4781 BOOL
ScDocument::HasManualBreaks( SCTAB nTab
) const
4783 if ( ValidTab(nTab
) && pTab
[nTab
] )
4784 return pTab
[nTab
]->HasManualBreaks();
4786 DBG_ERROR("falsche Tab");
4791 void ScDocument::GetDocStat( ScDocStat
& rDocStat
)
4793 rDocStat
.nTableCount
= GetTableCount();
4794 rDocStat
.aDocName
= aDocName
;
4795 rDocStat
.nCellCount
= GetCellCount();
4799 BOOL
ScDocument::HasPrintRange()
4801 BOOL bResult
= FALSE
;
4803 for ( SCTAB i
=0; !bResult
&& i
<nMaxTableNumber
; i
++ )
4805 bResult
= pTab
[i
]->IsPrintEntireSheet() || (pTab
[i
]->GetPrintRangeCount() > 0);
4811 BOOL
ScDocument::IsPrintEntireSheet( SCTAB nTab
) const
4813 return (ValidTab(nTab
) ) && pTab
[nTab
] && pTab
[nTab
]->IsPrintEntireSheet();
4817 USHORT
ScDocument::GetPrintRangeCount( SCTAB nTab
)
4819 if (ValidTab(nTab
) && pTab
[nTab
])
4820 return pTab
[nTab
]->GetPrintRangeCount();
4826 const ScRange
* ScDocument::GetPrintRange( SCTAB nTab
, USHORT nPos
)
4828 if (ValidTab(nTab
) && pTab
[nTab
])
4829 return pTab
[nTab
]->GetPrintRange(nPos
);
4835 const ScRange
* ScDocument::GetRepeatColRange( SCTAB nTab
)
4837 if (ValidTab(nTab
) && pTab
[nTab
])
4838 return pTab
[nTab
]->GetRepeatColRange();
4844 const ScRange
* ScDocument::GetRepeatRowRange( SCTAB nTab
)
4846 if (ValidTab(nTab
) && pTab
[nTab
])
4847 return pTab
[nTab
]->GetRepeatRowRange();
4853 void ScDocument::ClearPrintRanges( SCTAB nTab
)
4855 if (ValidTab(nTab
) && pTab
[nTab
])
4856 pTab
[nTab
]->ClearPrintRanges();
4860 void ScDocument::AddPrintRange( SCTAB nTab
, const ScRange
& rNew
)
4862 if (ValidTab(nTab
) && pTab
[nTab
])
4863 pTab
[nTab
]->AddPrintRange( rNew
);
4867 //UNUSED2009-05 void ScDocument::SetPrintRange( SCTAB nTab, const ScRange& rNew )
4869 //UNUSED2009-05 if (ValidTab(nTab) && pTab[nTab])
4870 //UNUSED2009-05 pTab[nTab]->SetPrintRange( rNew );
4874 void ScDocument::SetPrintEntireSheet( SCTAB nTab
)
4876 if (ValidTab(nTab
) && pTab
[nTab
])
4877 pTab
[nTab
]->SetPrintEntireSheet();
4881 void ScDocument::SetRepeatColRange( SCTAB nTab
, const ScRange
* pNew
)
4883 if (ValidTab(nTab
) && pTab
[nTab
])
4884 pTab
[nTab
]->SetRepeatColRange( pNew
);
4888 void ScDocument::SetRepeatRowRange( SCTAB nTab
, const ScRange
* pNew
)
4890 if (ValidTab(nTab
) && pTab
[nTab
])
4891 pTab
[nTab
]->SetRepeatRowRange( pNew
);
4895 ScPrintRangeSaver
* ScDocument::CreatePrintRangeSaver() const
4897 SCTAB nCount
= GetTableCount();
4898 ScPrintRangeSaver
* pNew
= new ScPrintRangeSaver( nCount
);
4899 for (SCTAB i
=0; i
<nCount
; i
++)
4901 pTab
[i
]->FillPrintSaver( pNew
->GetTabData(i
) );
4906 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver
& rSaver
)
4908 SCTAB nCount
= rSaver
.GetTabCount();
4909 for (SCTAB i
=0; i
<nCount
; i
++)
4911 pTab
[i
]->RestorePrintRanges( rSaver
.GetTabData(i
) );
4915 BOOL
ScDocument::NeedPageResetAfterTab( SCTAB nTab
) const
4917 // Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine
4918 // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen)
4919 // und eine Seitennummer angegeben ist (nicht 0)
4921 if ( nTab
< MAXTAB
&& pTab
[nTab
] && pTab
[nTab
+1] )
4923 String aNew
= pTab
[nTab
+1]->GetPageStyle();
4924 if ( aNew
!= pTab
[nTab
]->GetPageStyle() )
4926 SfxStyleSheetBase
* pStyle
= xPoolHelper
->GetStylePool()->Find( aNew
, SFX_STYLE_FAMILY_PAGE
);
4929 const SfxItemSet
& rSet
= pStyle
->GetItemSet();
4930 USHORT nFirst
= ((const SfxUInt16Item
&)rSet
.Get(ATTR_PAGE_FIRSTPAGENO
)).GetValue();
4932 return TRUE
; // Seitennummer in neuer Vorlage angegeben
4937 return FALSE
; // sonst nicht
4940 SfxUndoManager
* ScDocument::GetUndoManager()
4943 mpUndoManager
= new SfxUndoManager
;
4944 return mpUndoManager
;
4948 void ScDocument::EnableUndo( bool bVal
)
4950 GetUndoManager()->EnableUndo(bVal
);
4951 mbUndoEnabled
= bVal
;