1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <svx/algitem.hxx>
22 #include <editeng/justifyitem.hxx>
23 #include <unotools/textsearch.hxx>
24 #include <sfx2/objsh.hxx>
27 #include "patattr.hxx"
28 #include "formulacell.hxx"
30 #include "document.hxx"
31 #include "drwlayer.hxx"
32 #include "olinetab.hxx"
33 #include "stlsheet.hxx"
35 #include "globstr.hrc"
36 #include "refupdat.hxx"
37 #include "markdata.hxx"
38 #include "progress.hxx"
40 #include "prnsave.hxx"
41 #include "tabprotection.hxx"
42 #include "sheetevents.hxx"
43 #include "segmenttree.hxx"
45 #include "colorscale.hxx"
46 #include "conditio.hxx"
47 #include "globalnames.hxx"
48 #include "cellvalue.hxx"
49 #include "scmatrix.hxx"
50 #include "refupdatecontext.hxx"
52 #include "formula/vectortoken.hxx"
60 ScProgress
* GetProgressBar(
61 SCSIZE nCount
, SCSIZE nTotalCount
, ScProgress
* pOuterProgress
, ScDocument
* pDoc
)
63 if (nTotalCount
< 1000)
65 // if the total number of rows is less than 1000, don't even bother
66 // with the progress bar because drawing progress bar can be very
67 // expensive especially in GTK.
72 return pOuterProgress
;
75 return new ScProgress(
76 pDoc
->GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING
), nTotalCount
);
81 void GetOptimalHeightsInColumn(
82 ScColumn
* pCol
, SCROW nStartRow
, SCROW nEndRow
, vector
<sal_uInt16
>& aHeights
,
83 OutputDevice
* pDev
, double nPPTX
, double nPPTY
, const Fraction
& rZoomX
, const Fraction
& rZoomY
, bool bForce
,
84 ScProgress
* pProgress
, sal_uInt32 nProgressStart
)
86 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
88 // zuerst einmal ueber den ganzen Bereich
89 // (mit der letzten Spalte in der Hoffnung, dass die am ehesten noch auf
90 // Standard formatiert ist)
92 pCol
[MAXCOL
].GetOptimalHeight(
93 nStartRow
, nEndRow
, &aHeights
[0], pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
, 0, 0 );
95 // daraus Standardhoehe suchen, die im unteren Bereich gilt
97 sal_uInt16 nMinHeight
= aHeights
[nCount
-1];
98 SCSIZE nPos
= nCount
-1;
99 while ( nPos
&& aHeights
[nPos
-1] >= nMinHeight
)
101 SCROW nMinStart
= nStartRow
+ nPos
;
103 sal_uLong nWeightedCount
= 0;
104 for (SCCOL nCol
=0; nCol
<MAXCOL
; nCol
++) // MAXCOL schon oben
106 pCol
[nCol
].GetOptimalHeight(
107 nStartRow
, nEndRow
, &aHeights
[0], pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
,
108 nMinHeight
, nMinStart
);
112 sal_uLong nWeight
= pCol
[nCol
].GetWeightedCount();
113 if (nWeight
) // nochmal denselben Status muss auch nicht sein
115 nWeightedCount
+= nWeight
;
116 pProgress
->SetState( nWeightedCount
+ nProgressStart
);
122 struct OptimalHeightsFuncObjBase
124 virtual ~OptimalHeightsFuncObjBase() {}
125 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
) = 0;
128 struct SetRowHeightOnlyFunc
: public OptimalHeightsFuncObjBase
131 SetRowHeightOnlyFunc(ScTable
* pTab
) :
135 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
)
137 mpTab
->SetRowHeightOnly(nStartRow
, nEndRow
, nHeight
);
142 struct SetRowHeightRangeFunc
: public OptimalHeightsFuncObjBase
148 SetRowHeightRangeFunc(ScTable
* pTab
, double nPPTX
, double nPPTY
) :
154 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
)
156 return mpTab
->SetRowHeightRange(nStartRow
, nEndRow
, nHeight
, mnPPTX
, mnPPTY
);
160 bool SetOptimalHeightsToRows(OptimalHeightsFuncObjBase
& rFuncObj
,
161 ScBitMaskCompressedArray
<SCROW
, sal_uInt8
>* pRowFlags
, SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nExtra
,
162 const vector
<sal_uInt16
>& aHeights
, bool bForce
)
164 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
165 bool bChanged
= false;
168 sal_uInt16 nLast
= 0;
169 for (SCSIZE i
=0; i
<nCount
; i
++)
173 sal_uInt8 nRowFlag
= pRowFlags
->GetValue( nStartRow
+i
, nIndex
, nRegionEndRow
);
174 if ( nRegionEndRow
> nEndRow
)
175 nRegionEndRow
= nEndRow
;
176 SCSIZE nMoreRows
= nRegionEndRow
- ( nStartRow
+i
); // additional equal rows after first
178 bool bAutoSize
= ((nRowFlag
& CR_MANUALSIZE
) == 0);
179 if ( bAutoSize
|| bForce
)
184 pRowFlags
->SetValue( nStartRow
+i
, nRegionEndRow
, nRowFlag
| CR_MANUALSIZE
);
187 pRowFlags
->SetValue( nStartRow
+i
, nRegionEndRow
, nRowFlag
& ~CR_MANUALSIZE
);
189 for (SCSIZE nInner
= i
; nInner
<= i
+ nMoreRows
; ++nInner
)
193 if (aHeights
[nInner
]+nExtra
== nLast
)
194 nRngEnd
= nStartRow
+nInner
;
197 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
203 nLast
= aHeights
[nInner
]+nExtra
;
204 nRngStart
= nStartRow
+nInner
;
205 nRngEnd
= nStartRow
+nInner
;
212 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
215 i
+= nMoreRows
; // already handled - skip
218 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
225 // -----------------------------------------------------------------------
227 ScTable::ScTable( ScDocument
* pDoc
, SCTAB nNewTab
, const OUString
& rNewName
,
228 bool bColInfo
, bool bRowInfo
) :
230 aCodeName( rNewName
),
232 aPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) ),
233 nRepeatStartX( SCCOL_REPEAT_NONE
),
234 nRepeatEndX( SCCOL_REPEAT_NONE
),
235 nRepeatStartY( SCROW_REPEAT_NONE
),
236 nRepeatEndY( SCROW_REPEAT_NONE
),
237 pTabProtection( NULL
),
239 mpRowHeights( static_cast<ScFlatUInt16RowSegments
*>(NULL
) ),
242 mpHiddenCols(new ScFlatBoolColSegments
),
243 mpHiddenRows(new ScFlatBoolRowSegments
),
244 mpFilteredCols(new ScFlatBoolColSegments
),
245 mpFilteredRows(new ScFlatBoolRowSegments
),
246 pOutlineTable( NULL
),
247 pSheetEvents( NULL
),
250 pSearchText ( NULL
),
251 pSortCollator( NULL
),
252 pRepeatColRange( NULL
),
253 pRepeatRowRange( NULL
),
255 pScenarioRanges( NULL
),
256 aScenarioColor( COL_LIGHTGRAY
),
257 aTabBgColor( COL_AUTO
),
261 mpCondFormatList( new ScConditionalFormatList() ),
265 bPageSizeValid(false),
266 bTableAreaValid(false),
269 bPendingRowHeights(false),
270 bCalcNotification(false),
271 bGlobalKeepQuery(false),
272 bPrintEntireSheet(true),
273 bActiveScenario(false),
274 mbPageBreaksValid(false),
280 pColWidth
= new sal_uInt16
[ MAXCOL
+1 ];
281 pColFlags
= new sal_uInt8
[ MAXCOL
+1 ];
283 for (SCCOL i
=0; i
<=MAXCOL
; i
++)
285 pColWidth
[i
] = STD_COL_WIDTH
;
292 mpRowHeights
.reset(new ScFlatUInt16RowSegments(ScGlobal::nStdRowHeight
));
293 pRowFlags
= new ScBitMaskCompressedArray
< SCROW
, sal_uInt8
>( MAXROW
, 0);
296 if ( pDocument
->IsDocVisible() )
298 // when a sheet is added to a visible document,
299 // initialize its RTL flag from the system locale
300 bLayoutRTL
= ScGlobal::IsSystemRTL();
303 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
306 if ( pDrawLayer
->ScAddPage( nTab
) ) // sal_False (not inserted) during Undo
308 pDrawLayer
->ScRenamePage( nTab
, aName
);
309 sal_uLong nx
= (sal_uLong
) ((double) (MAXCOL
+1) * STD_COL_WIDTH
* HMM_PER_TWIPS
);
310 sal_uLong ny
= (sal_uLong
) ((double) (MAXROW
+1) * ScGlobal::nStdRowHeight
* HMM_PER_TWIPS
);
311 pDrawLayer
->SetPageSize( static_cast<sal_uInt16
>(nTab
), Size( nx
, ny
), false );
315 for (SCCOL k
=0; k
<=MAXCOL
; k
++)
316 aCol
[k
].Init( k
, nTab
, pDocument
);
321 if (!pDocument
->IsInDtorClear())
323 // nicht im dtor die Pages in der falschen Reihenfolge loeschen
324 // (nTab stimmt dann als Page-Number nicht!)
325 // In ScDocument::Clear wird hinterher per Clear am Draw Layer alles geloescht.
327 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
329 pDrawLayer
->ScRemovePage( nTab
);
336 delete pOutlineTable
;
338 delete pRepeatColRange
;
339 delete pRepeatRowRange
;
340 delete pScenarioRanges
;
342 delete pDBDataNoName
;
343 DestroySortCollator();
346 void ScTable::GetName( OUString
& rName
) const
351 void ScTable::SetName( const OUString
& rNewName
)
354 aUpperName
= OUString(); // invalidated if the name is changed
356 // SetStreamValid is handled in ScDocument::RenameTab
359 const OUString
& ScTable::GetUpperName() const
361 if (aUpperName
.isEmpty() && !aName
.isEmpty())
362 aUpperName
= ScGlobal::pCharClass
->uppercase(aName
);
366 void ScTable::SetVisible( bool bVis
)
368 if (bVisible
!= bVis
&& IsStreamValid())
369 SetStreamValid(false);
374 void ScTable::SetStreamValid( bool bSet
, bool bIgnoreLock
)
376 if ( bIgnoreLock
|| !pDocument
->IsStreamValidLocked() )
380 void ScTable::SetPendingRowHeights( bool bSet
)
382 bPendingRowHeights
= bSet
;
385 void ScTable::SetLayoutRTL( bool bSet
)
390 void ScTable::SetLoadingRTL( bool bSet
)
395 const Color
& ScTable::GetTabBgColor() const
400 void ScTable::SetTabBgColor(const Color
& rColor
)
402 if (aTabBgColor
!= rColor
)
404 // The tab color has changed. Set this table 'modified'.
405 aTabBgColor
= rColor
;
407 SetStreamValid(false);
411 void ScTable::SetScenario( bool bFlag
)
416 void ScTable::SetLink( sal_uInt8 nMode
,
417 const OUString
& rDoc
, const OUString
& rFlt
, const OUString
& rOpt
,
418 const OUString
& rTab
, sal_uLong nRefreshDelay
)
421 aLinkDoc
= rDoc
; // Datei
422 aLinkFlt
= rFlt
; // Filter
423 aLinkOpt
= rOpt
; // Filter-Optionen
424 aLinkTab
= rTab
; // Tabellenname in Quelldatei
425 nLinkRefreshDelay
= nRefreshDelay
; // refresh delay in seconds, 0==off
428 SetStreamValid(false);
431 sal_uInt16
ScTable::GetOptimalColWidth( SCCOL nCol
, OutputDevice
* pDev
,
432 double nPPTX
, double nPPTY
,
433 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
434 bool bFormula
, const ScMarkData
* pMarkData
,
435 const ScColWidthParam
* pParam
)
437 return aCol
[nCol
].GetOptimalColWidth( pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
,
438 bFormula
, STD_COL_WIDTH
- STD_EXTRA_WIDTH
, pMarkData
, pParam
);
441 long ScTable::GetNeededSize( SCCOL nCol
, SCROW nRow
,
443 double nPPTX
, double nPPTY
,
444 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
445 bool bWidth
, bool bTotalSize
)
447 ScNeededSizeOptions aOptions
;
448 aOptions
.bSkipMerged
= false; // zusammengefasste mitzaehlen
449 aOptions
.bTotalSize
= bTotalSize
;
451 return aCol
[nCol
].GetNeededSize
452 ( nRow
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bWidth
, aOptions
);
455 bool ScTable::SetOptimalHeight( SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nExtra
,
457 double nPPTX
, double nPPTY
,
458 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
459 bool bForce
, ScProgress
* pOuterProgress
, sal_uLong nProgressStart
)
461 OSL_ENSURE( nExtra
==0 || bForce
, "automatic OptimalHeight with Extra" );
463 if ( !pDocument
->IsAdjustHeightEnabled() )
468 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
470 ScProgress
* pProgress
= GetProgressBar(nCount
, GetWeightedCount(), pOuterProgress
, pDocument
);
472 vector
<sal_uInt16
> aHeights(nCount
, 0);
474 GetOptimalHeightsInColumn(
475 aCol
, nStartRow
, nEndRow
, aHeights
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
,
476 pProgress
, nProgressStart
);
478 SetRowHeightRangeFunc
aFunc(this, nPPTX
, nPPTY
);
479 bool bChanged
= SetOptimalHeightsToRows(
480 aFunc
, pRowFlags
, nStartRow
, nEndRow
, nExtra
, aHeights
, bForce
);
482 if ( pProgress
!= pOuterProgress
)
488 void ScTable::SetOptimalHeightOnly( SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nExtra
,
490 double nPPTX
, double nPPTY
,
491 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
492 bool bForce
, ScProgress
* pOuterProgress
, sal_uLong nProgressStart
)
494 OSL_ENSURE( nExtra
==0 || bForce
, "automatic OptimalHeight with Extra" );
496 if ( !pDocument
->IsAdjustHeightEnabled() )
499 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
501 ScProgress
* pProgress
= GetProgressBar(nCount
, GetWeightedCount(), pOuterProgress
, pDocument
);
503 vector
<sal_uInt16
> aHeights(nCount
, 0);
505 GetOptimalHeightsInColumn(
506 aCol
, nStartRow
, nEndRow
, aHeights
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
,
507 pProgress
, nProgressStart
);
509 SetRowHeightOnlyFunc
aFunc(this);
510 SetOptimalHeightsToRows(
511 aFunc
, pRowFlags
, nStartRow
, nEndRow
, nExtra
, aHeights
, bForce
);
513 if ( pProgress
!= pOuterProgress
)
517 bool ScTable::GetCellArea( SCCOL
& rEndCol
, SCROW
& rEndRow
) const
522 for (SCCOL i
=0; i
<=MAXCOL
; i
++)
524 if (!aCol
[i
].IsEmptyData())
528 SCROW nRow
= aCol
[i
].GetLastDataPos();
532 if ( aCol
[i
].HasCellNotes() )
534 SCROW maxNoteRow
= aCol
[i
].GetCellNotesMaxRow();
535 if (maxNoteRow
>= nMaxY
)
553 bool ScTable::GetTableArea( SCCOL
& rEndCol
, SCROW
& rEndRow
) const
555 bool bRet
= true; //! merken?
556 if (!bTableAreaValid
)
558 bRet
= GetPrintArea(nTableAreaX
, nTableAreaY
, true);
559 bTableAreaValid
= true;
561 rEndCol
= nTableAreaX
;
562 rEndRow
= nTableAreaY
;
566 const SCCOL SC_COLUMNS_STOP
= 30;
568 bool ScTable::GetPrintArea( SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bNotes
, bool bFullFormattedArea
) const
575 for (i
=0; i
<=MAXCOL
; i
++) // Daten testen
577 if (!aCol
[i
].IsEmptyData())
582 SCROW nColY
= aCol
[i
].GetLastDataPos();
588 if ( aCol
[i
].HasCellNotes() )
590 SCROW maxNoteRow
= aCol
[i
].GetCellNotesMaxRow();
591 if (maxNoteRow
>= nMaxY
)
605 SCCOL nMaxDataX
= nMaxX
;
607 for (i
=0; i
<=MAXCOL
; i
++) // Attribute testen
610 if (aCol
[i
].GetLastVisibleAttr( nLastRow
, bFullFormattedArea
))
614 if (nLastRow
> nMaxY
)
619 if (nMaxX
== MAXCOL
) // Attribute rechts weglassen
622 while ( nMaxX
>0 && aCol
[nMaxX
].IsVisibleAttrEqual(aCol
[nMaxX
+1]) )
626 if ( nMaxX
< nMaxDataX
)
630 else if ( nMaxX
> nMaxDataX
)
632 SCCOL nAttrStartX
= nMaxDataX
+ 1;
633 while ( nAttrStartX
< MAXCOL
)
635 SCCOL nAttrEndX
= nAttrStartX
;
636 while ( nAttrEndX
< MAXCOL
&& aCol
[nAttrStartX
].IsVisibleAttrEqual(aCol
[nAttrEndX
+1]) )
638 if ( nAttrEndX
+ 1 - nAttrStartX
>= SC_COLUMNS_STOP
)
640 // found equally-formatted columns behind data -> stop before these columns
641 nMaxX
= nAttrStartX
- 1;
643 // also don't include default-formatted columns before that
645 while ( nMaxX
> nMaxDataX
&& !aCol
[nMaxX
].GetLastVisibleAttr( nDummyRow
) )
649 nAttrStartX
= nAttrEndX
+ 1;
658 bool ScTable::GetPrintAreaHor( SCROW nStartRow
, SCROW nEndRow
,
659 SCCOL
& rEndCol
, bool /* bNotes */ ) const
665 for (i
=0; i
<=MAXCOL
; i
++) // Attribute testen
667 if (aCol
[i
].HasVisibleAttrIn( nStartRow
, nEndRow
))
674 if (nMaxX
== MAXCOL
) // Attribute rechts weglassen
677 while ( nMaxX
>0 && aCol
[nMaxX
].IsVisibleAttrEqual(aCol
[nMaxX
+1], nStartRow
, nEndRow
) )
681 for (i
=0; i
<=MAXCOL
; i
++) // Daten testen
683 if (!aCol
[i
].IsEmptyBlock( nStartRow
, nEndRow
)) //! bNotes ??????
695 bool ScTable::GetPrintAreaVer( SCCOL nStartCol
, SCCOL nEndCol
,
696 SCROW
& rEndRow
, bool bNotes
) const
702 for (i
=nStartCol
; i
<=nEndCol
; i
++) // Attribute testen
705 if (aCol
[i
].GetLastVisibleAttr( nLastRow
))
708 if (nLastRow
> nMaxY
)
713 for (i
=nStartCol
; i
<=nEndCol
; i
++) // Daten testen
715 if (!aCol
[i
].IsEmptyData())
718 SCROW nColY
= aCol
[i
].GetLastDataPos();
724 if ( aCol
[i
].HasCellNotes() )
726 SCROW maxNoteRow
=aCol
[i
].GetCellNotesMaxRow();
727 if (maxNoteRow
> nMaxY
)
740 bool ScTable::GetDataStart( SCCOL
& rStartCol
, SCROW
& rStartRow
) const
743 SCCOL nMinX
= MAXCOL
;
744 SCROW nMinY
= MAXROW
;
747 for (i
=0; i
<=MAXCOL
; i
++) // Attribute testen
750 if (aCol
[i
].GetFirstVisibleAttr( nFirstRow
))
755 if (nFirstRow
< nMinY
)
760 if (nMinX
== 0) // Attribute links weglassen
762 if ( aCol
[0].IsVisibleAttrEqual(aCol
[1]) ) // keine einzelnen
765 while ( nMinX
<MAXCOL
&& aCol
[nMinX
].IsVisibleAttrEqual(aCol
[nMinX
-1]) )
770 bool bDatFound
= false;
771 for (i
=0; i
<=MAXCOL
; i
++) // Daten testen
773 if (!aCol
[i
].IsEmptyData())
775 if (!bDatFound
&& i
<nMinX
)
777 bFound
= bDatFound
= true;
778 SCROW nRow
= aCol
[i
].GetFirstDataPos();
782 if ( aCol
[i
].HasCellNotes() )
784 SCROW minNoteRow
= aCol
[i
].GetCellNotesMinRow();
785 if (minNoteRow
<= nMinY
)
802 void ScTable::GetDataArea( SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
,
803 bool bIncludeOld
, bool bOnlyDown
) const
805 // return the smallest area containing at least all contiguous cells having data. This area
806 // is a square containing also empty cells. It may shrink or extend the area given as input
807 // Flags as modifiers:
809 // bIncludeOld = true ensure that the returned area contains at least the initial area,
810 // independently of the emptniess of rows / columns (i.e. does not allow shrinking)
811 // bOnlyDown = true means extend / shrink the inputed area only down, i.e modifiy only rEndRow
816 bool bBottom
= false;
817 bool bChanged
= false;
825 SCROW nStart
= rStartRow
;
826 SCROW nEnd
= rEndRow
;
827 if (nStart
>0) --nStart
;
828 if (nEnd
<MAXROW
) ++nEnd
;
830 if (rEndCol
< MAXCOL
)
831 if (!aCol
[rEndCol
+1].IsEmptyBlock(nStart
,nEnd
))
839 if (!aCol
[rStartCol
-1].IsEmptyBlock(nStart
,nEnd
))
848 SCROW nTest
= rStartRow
-1;
849 bool needExtend
= false;
850 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& !needExtend
; i
++)
851 if (aCol
[i
].HasDataAt(nTest
))
862 if (rEndRow
< MAXROW
)
864 SCROW nTest
= rEndRow
+1;
865 bool needExtend
= false;
866 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& !needExtend
; i
++)
867 if (aCol
[i
].HasDataAt(nTest
))
879 if ( !bIncludeOld
&& !bOnlyDown
)
882 while ( aCol
[rStartCol
].IsEmptyBlock(rStartRow
,rEndRow
) && rStartCol
< MAXCOL
&& rStartCol
< rEndCol
)
886 while ( aCol
[rEndCol
].IsEmptyBlock(rStartRow
,rEndRow
) && rEndCol
> 0 && rStartCol
< rEndCol
)
889 if ( !bTop
&& rStartRow
< MAXROW
&& rStartRow
< rEndRow
)
894 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& shrink
; i
++)
895 if (aCol
[i
].HasDataAt(rStartRow
))
899 }while( shrink
&& rStartRow
< MAXROW
&& rStartRow
< rEndRow
);
905 if ( !bBottom
&& rEndRow
> 0 && rStartRow
< rEndRow
)
910 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& shrink
; i
++)
911 if (aCol
[i
].HasDataAt(rEndRow
))
915 }while( shrink
&& rEndRow
> 0 && rStartRow
< rEndRow
);
921 bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk
, SCCOL
& rStartCol
, SCROW
& rStartRow
,
922 SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bColumnsOnly
) const
926 PutInOrder( rStartCol
, rEndCol
);
927 PutInOrder( rStartRow
, rEndRow
);
929 rStartCol
= 0, o_bShrunk
= true;
931 rStartRow
= 0, o_bShrunk
= true;
932 if (rEndCol
> MAXCOL
)
933 rEndCol
= MAXCOL
, o_bShrunk
= true;
934 if (rEndRow
> MAXROW
)
935 rEndRow
= MAXROW
, o_bShrunk
= true;
942 while (rStartCol
< rEndCol
)
944 if (aCol
[rEndCol
].IsEmptyBlock( rStartRow
, rEndRow
))
953 while (rStartCol
< rEndCol
)
955 if (aCol
[rStartCol
].IsEmptyBlock( rStartRow
, rEndRow
))
966 if (rStartRow
< rEndRow
)
969 for (SCCOL i
=rStartCol
; i
<=rEndCol
&& !bFound
; i
++)
970 if (aCol
[i
].HasDataAt( rStartRow
))
979 if (rStartRow
< rEndRow
)
982 for (SCCOL i
=rStartCol
; i
<=rEndCol
&& !bFound
; i
++)
983 if (aCol
[i
].HasDataAt( rEndRow
))
997 return rStartCol
!= rEndCol
|| (bColumnsOnly
?
998 !aCol
[rStartCol
].IsEmptyBlock( rStartRow
, rEndRow
) :
999 (rStartRow
!= rEndRow
|| aCol
[rStartCol
].HasDataAt( rStartRow
)));
1002 SCROW
ScTable::GetLastDataRow( SCCOL nCol1
, SCCOL nCol2
, SCROW nLastRow
) const
1004 if (!ValidCol(nCol1
) || !ValidCol(nCol2
))
1007 SCROW nNewLastRow
= 0;
1008 for (SCCOL i
= nCol1
; i
<= nCol2
; ++i
)
1010 SCROW nThis
= aCol
[i
].GetLastDataPos(nLastRow
);
1011 if (nNewLastRow
< nThis
)
1012 nNewLastRow
= nThis
;
1018 SCSIZE
ScTable::GetEmptyLinesInBlock( SCCOL nStartCol
, SCROW nStartRow
,
1019 SCCOL nEndCol
, SCROW nEndRow
, ScDirection eDir
) const
1023 if ((eDir
== DIR_BOTTOM
) || (eDir
== DIR_TOP
))
1025 nCount
= static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
1026 for (nCol
= nStartCol
; nCol
<= nEndCol
; nCol
++)
1027 nCount
= std::min(nCount
, aCol
[nCol
].GetEmptyLinesInBlock(nStartRow
, nEndRow
, eDir
));
1029 else if (eDir
== DIR_RIGHT
)
1032 while (((SCsCOL
)nCol
>= (SCsCOL
)nStartCol
) &&
1033 aCol
[nCol
].IsEmptyBlock(nStartRow
, nEndRow
))
1042 while ((nCol
<= nEndCol
) && aCol
[nCol
].IsEmptyBlock(nStartRow
, nEndRow
))
1051 bool ScTable::IsEmptyLine( SCROW nRow
, SCCOL nStartCol
, SCCOL nEndCol
) const
1053 bool bFound
= false;
1054 for (SCCOL i
=nStartCol
; i
<=nEndCol
&& !bFound
; i
++)
1055 if (aCol
[i
].HasDataAt(nRow
))
1060 void ScTable::LimitChartArea( SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
1062 while ( rStartCol
<rEndCol
&& aCol
[rStartCol
].IsEmptyBlock(rStartRow
,rEndRow
) )
1065 while ( rStartCol
<rEndCol
&& aCol
[rEndCol
].IsEmptyBlock(rStartRow
,rEndRow
) )
1068 while ( rStartRow
<rEndRow
&& IsEmptyLine(rStartRow
, rStartCol
, rEndCol
) )
1071 while ( rStartRow
<rEndRow
&& IsEmptyLine(rEndRow
, rStartCol
, rEndCol
) )
1075 SCCOL
ScTable::FindNextVisibleCol( SCCOL nCol
, bool bRight
) const
1081 bool bHidden
= pDocument
->ColHidden(nCol
, nTab
, NULL
, &nEnd
);
1085 return std::min
<SCCOL
>(MAXCOL
, nCol
);
1090 SCCOL nStart
= MAXCOL
;
1091 bool bHidden
= pDocument
->ColHidden(nCol
, nTab
, &nStart
, NULL
);
1095 return std::max
<SCCOL
>(0, nCol
);
1099 SCCOL
ScTable::FindNextVisibleColWithContent( SCCOL nCol
, bool bRight
, SCROW nRow
) const
1110 bool bHidden
= pDocument
->ColHidden( nCol
, nTab
, NULL
, &nEndCol
);
1114 if(nEndCol
>= MAXCOL
)
1118 if(aCol
[nCol
].HasVisibleDataAt(nRow
))
1121 while(nCol
< MAXCOL
);
1133 SCCOL nStartCol
= MAXCOL
;
1134 bool bHidden
= pDocument
->ColHidden( nCol
, nTab
, &nStartCol
, NULL
);
1137 nCol
= nStartCol
-1;
1142 if(aCol
[nCol
].HasVisibleDataAt(nRow
))
1151 void ScTable::FindAreaPos( SCCOL
& rCol
, SCROW
& rRow
, ScMoveDirection eDirection
) const
1153 if (eDirection
== SC_MOVE_LEFT
|| eDirection
== SC_MOVE_RIGHT
)
1155 SCCOL nNewCol
= rCol
;
1156 bool bThere
= aCol
[nNewCol
].HasVisibleDataAt(rRow
);
1157 bool bRight
= (eDirection
== SC_MOVE_RIGHT
);
1160 if(nNewCol
>= MAXCOL
&& eDirection
== SC_MOVE_RIGHT
)
1162 else if(nNewCol
== 0 && eDirection
== SC_MOVE_LEFT
)
1165 SCCOL nNextCol
= FindNextVisibleCol( nNewCol
, bRight
);
1167 if(aCol
[nNextCol
].HasVisibleDataAt(rRow
))
1169 bool bFound
= false;
1173 nNextCol
= FindNextVisibleCol( nNewCol
, bRight
);
1174 if(aCol
[nNextCol
].HasVisibleDataAt(rRow
))
1179 while(!bFound
&& nNextCol
> 0 && nNextCol
< MAXCOL
);
1183 nNewCol
= FindNextVisibleColWithContent(nNewCol
, bRight
, rRow
);
1188 nNewCol
= FindNextVisibleColWithContent(nNewCol
, bRight
, rRow
);
1199 aCol
[rCol
].FindDataAreaPos(rRow
,eDirection
== SC_MOVE_DOWN
);
1203 bool ScTable::ValidNextPos( SCCOL nCol
, SCROW nRow
, const ScMarkData
& rMark
,
1204 bool bMarked
, bool bUnprotected
) const
1206 if (!ValidCol(nCol
) || !ValidRow(nRow
))
1209 if (pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
))
1210 // Skip an overlapped cell.
1213 if (bMarked
&& !rMark
.IsCellMarked(nCol
,nRow
))
1216 if (bUnprotected
&& ((const ScProtectionAttr
*)
1217 GetAttr(nCol
,nRow
,ATTR_PROTECTION
))->GetProtection())
1220 if (bMarked
|| bUnprotected
) //! auch sonst ???
1222 // ausgeblendete muessen uebersprungen werden, weil der Cursor sonst
1223 // auf der naechsten Zelle landet, auch wenn die geschuetzt/nicht markiert ist.
1224 //! per Extra-Parameter steuern, nur fuer Cursor-Bewegung ???
1226 if (RowHidden(nRow
))
1229 if (ColHidden(nCol
))
1236 void ScTable::GetNextPos( SCCOL
& rCol
, SCROW
& rRow
, SCsCOL nMovX
, SCsROW nMovY
,
1237 bool bMarked
, bool bUnprotected
, const ScMarkData
& rMark
) const
1239 if (bUnprotected
&& !IsProtected()) // Tabelle ueberhaupt geschuetzt?
1240 bUnprotected
= false;
1242 sal_uInt16 nWrap
= 0;
1246 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ nMovX
);
1247 nRow
= sal::static_int_cast
<SCsROW
>( nRow
+ nMovY
);
1249 OSL_ENSURE( !nMovY
|| !bUnprotected
,
1250 "GetNextPos mit bUnprotected horizontal nicht implementiert" );
1252 if ( nMovY
&& bMarked
)
1254 bool bUp
= ( nMovY
< 0 );
1255 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1256 while ( ValidRow(nRow
) &&
1257 (RowHidden(nRow
) || pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
)) )
1259 // ausgeblendete ueberspringen (s.o.)
1261 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1264 while ( nRow
< 0 || nRow
> MAXROW
)
1266 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ static_cast<SCsCOL
>(nMovY
) );
1267 while ( ValidCol(nCol
) && ColHidden(nCol
) )
1268 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ static_cast<SCsCOL
>(nMovY
) ); // skip hidden rows (see above)
1275 else if (nCol
> MAXCOL
)
1283 else if (nRow
> MAXROW
)
1285 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1286 while ( ValidRow(nRow
) &&
1287 (RowHidden(nRow
) || pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
)) )
1289 // ausgeblendete ueberspringen (s.o.)
1291 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1296 if ( nMovX
&& ( bMarked
|| bUnprotected
) )
1298 // initiales Weiterzaehlen wrappen:
1314 if ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) )
1316 SCsROW
* pNextRows
= new SCsROW
[MAXCOL
+1];
1319 if ( nMovX
> 0 ) // vorwaerts
1321 for (i
=0; i
<=MAXCOL
; i
++)
1322 pNextRows
[i
] = (i
<nCol
) ? (nRow
+1) : nRow
;
1325 SCsROW nNextRow
= pNextRows
[nCol
] + 1;
1327 nNextRow
= rMark
.GetNextMarked( nCol
, nNextRow
, false );
1329 nNextRow
= aCol
[nCol
].GetNextUnprotected( nNextRow
, false );
1330 pNextRows
[nCol
] = nNextRow
;
1332 SCsROW nMinRow
= MAXROW
+1;
1333 for (i
=0; i
<=MAXCOL
; i
++)
1334 if (pNextRows
[i
] < nMinRow
) // bei gleichen den linken
1336 nMinRow
= pNextRows
[i
];
1341 if ( nRow
> MAXROW
)
1343 if (++nWrap
>= 2) break; // ungueltigen Wert behalten
1346 for (i
=0; i
<=MAXCOL
; i
++)
1347 pNextRows
[i
] = 0; // alles ganz von vorne
1350 while ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) );
1354 for (i
=0; i
<=MAXCOL
; i
++)
1355 pNextRows
[i
] = (i
>nCol
) ? (nRow
-1) : nRow
;
1358 SCsROW nNextRow
= pNextRows
[nCol
] - 1;
1360 nNextRow
= rMark
.GetNextMarked( nCol
, nNextRow
, true );
1362 nNextRow
= aCol
[nCol
].GetNextUnprotected( nNextRow
, true );
1363 pNextRows
[nCol
] = nNextRow
;
1365 SCsROW nMaxRow
= -1;
1366 for (i
=0; i
<=MAXCOL
; i
++)
1367 if (pNextRows
[i
] >= nMaxRow
) // bei gleichen den rechten
1369 nMaxRow
= pNextRows
[i
];
1376 if (++nWrap
>= 2) break; // ungueltigen Wert behalten
1379 for (i
=0; i
<=MAXCOL
; i
++)
1380 pNextRows
[i
] = MAXROW
; // alles ganz von vorne
1383 while ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) );
1390 // ungueltige Werte kommen z.b. bei Tab heraus,
1391 // wenn nicht markiert und nicht geschuetzt ist (linker / rechter Rand),
1392 // dann Werte unveraendert lassen
1394 if (ValidColRow(nCol
,nRow
))
1401 bool ScTable::GetNextMarkedCell( SCCOL
& rCol
, SCROW
& rRow
, const ScMarkData
& rMark
) const
1403 const ScMarkArray
* pMarkArray
= rMark
.GetArray();
1404 OSL_ENSURE(pMarkArray
,"GetNextMarkedCell without MarkArray");
1408 ++rRow
; // naechste Zelle ist gesucht
1410 while ( rCol
<= MAXCOL
)
1412 const ScMarkArray
& rArray
= pMarkArray
[rCol
];
1413 while ( rRow
<= MAXROW
)
1415 SCROW nStart
= (SCROW
) rArray
.GetNextMarked( (SCsROW
) rRow
, false );
1416 if ( nStart
<= MAXROW
)
1418 SCROW nEnd
= rArray
.GetMarkEnd( nStart
, false );
1420 const sc::CellStoreType
& rCells
= aCol
[rCol
].maCells
;
1421 std::pair
<sc::CellStoreType::const_iterator
,size_t> aPos
= rCells
.position(nStart
);
1422 sc::CellStoreType::const_iterator it
= aPos
.first
;
1423 SCROW nTestRow
= nStart
;
1424 if (it
->type
== sc::element_type_empty
)
1426 // Skip the empty block.
1427 nTestRow
+= it
->size
- aPos
.second
;
1429 if (it
== rCells
.end())
1437 if (nTestRow
< nEnd
)
1444 rRow
= nEnd
+ 1; // naechsten markierten Bereich suchen
1447 rRow
= MAXROW
+ 1; // Ende der Spalte
1450 ++rCol
; // naechste Spalte testen
1453 return false; // alle Spalten durch
1456 void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode
, SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1457 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
1458 SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
, bool bUpdateNoteCaptionPos
)
1460 if ( nTab
>= nTab1
&& nTab
<= nTab2
&& nDz
== 0 ) // only within the table
1462 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
1463 if ( eUpdateRefMode
!= URM_COPY
&& pDrawLayer
)
1465 if ( eUpdateRefMode
== URM_MOVE
)
1467 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
- nDx
);
1468 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
- nDy
);
1469 nCol2
= sal::static_int_cast
<SCCOL
>( nCol2
- nDx
);
1470 nRow2
= sal::static_int_cast
<SCROW
>( nRow2
- nDy
);
1472 pDrawLayer
->MoveArea( nTab
, nCol1
,nRow1
, nCol2
,nRow2
, nDx
,nDy
,
1473 (eUpdateRefMode
== URM_INSDEL
), bUpdateNoteCaptionPos
);
1478 void ScTable::UpdateReference(
1479 sc::RefUpdateContext
& rCxt
, ScDocument
* pUndoDoc
, bool bIncludeDraw
, bool bUpdateNoteCaptionPos
)
1481 bool bUpdated
= false;
1484 if (rCxt
.meMode
== URM_COPY
)
1486 i
= rCxt
.maRange
.aStart
.Col();
1487 iMax
= rCxt
.maRange
.aEnd
.Col();
1495 UpdateRefMode eUpdateRefMode
= rCxt
.meMode
;
1496 SCCOL nDx
= rCxt
.mnColDelta
;
1497 SCROW nDy
= rCxt
.mnRowDelta
;
1498 SCTAB nDz
= rCxt
.mnTabDelta
;
1499 SCCOL nCol1
= rCxt
.maRange
.aStart
.Col(), nCol2
= rCxt
.maRange
.aEnd
.Col();
1500 SCROW nRow1
= rCxt
.maRange
.aStart
.Row(), nRow2
= rCxt
.maRange
.aEnd
.Row();
1501 SCTAB nTab1
= rCxt
.maRange
.aStart
.Tab(), nTab2
= rCxt
.maRange
.aEnd
.Tab();
1503 // Named expressions need to be updated before formulas acessing them.
1505 mpRangeName
->UpdateReference(rCxt
, nTab
);
1507 for ( ; i
<=iMax
; i
++)
1508 bUpdated
|= aCol
[i
].UpdateReference(rCxt
, pUndoDoc
);
1511 UpdateDrawRef( eUpdateRefMode
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, nDx
, nDy
, nDz
, bUpdateNoteCaptionPos
);
1513 if ( nTab
>= nTab1
&& nTab
<= nTab2
&& nDz
== 0 ) // print ranges: only within the table
1521 bool bRecalcPages
= false;
1523 for ( ScRangeVec::iterator aIt
= aPrintRanges
.begin(), aEnd
= aPrintRanges
.end(); aIt
!= aEnd
; ++aIt
)
1525 nSCol
= aIt
->aStart
.Col();
1526 nSRow
= aIt
->aStart
.Row();
1527 nECol
= aIt
->aEnd
.Col();
1528 nERow
= aIt
->aEnd
.Row();
1530 // do not try to modify sheet index of print range
1531 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1532 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1534 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1536 *aIt
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1537 bRecalcPages
= true;
1541 if ( pRepeatColRange
)
1543 nSCol
= pRepeatColRange
->aStart
.Col();
1544 nSRow
= pRepeatColRange
->aStart
.Row();
1545 nECol
= pRepeatColRange
->aEnd
.Col();
1546 nERow
= pRepeatColRange
->aEnd
.Row();
1548 // do not try to modify sheet index of repeat range
1549 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1550 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1552 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1554 *pRepeatColRange
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1555 bRecalcPages
= true;
1556 nRepeatStartX
= nSCol
; // fuer UpdatePageBreaks
1557 nRepeatEndX
= nECol
;
1561 if ( pRepeatRowRange
)
1563 nSCol
= pRepeatRowRange
->aStart
.Col();
1564 nSRow
= pRepeatRowRange
->aStart
.Row();
1565 nECol
= pRepeatRowRange
->aEnd
.Col();
1566 nERow
= pRepeatRowRange
->aEnd
.Row();
1568 // do not try to modify sheet index of repeat range
1569 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1570 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1572 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1574 *pRepeatRowRange
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1575 bRecalcPages
= true;
1576 nRepeatStartY
= nSRow
; // fuer UpdatePageBreaks
1577 nRepeatEndY
= nERow
;
1581 // updating print ranges is not necessary with multiple print ranges
1582 if ( bRecalcPages
&& GetPrintRangeCount() <= 1 )
1584 UpdatePageBreaks(NULL
);
1586 pDocument
->RepaintRange( ScRange(0,0,nTab
,MAXCOL
,MAXROW
,nTab
) );
1590 if (bUpdated
&& IsStreamValid())
1591 SetStreamValid(false);
1593 if(mpCondFormatList
)
1594 mpCondFormatList
->UpdateReference(rCxt
);
1597 void ScTable::UpdateTranspose( const ScRange
& rSource
, const ScAddress
& rDest
,
1598 ScDocument
* pUndoDoc
)
1600 for ( SCCOL i
=0; i
<=MAXCOL
; i
++ )
1601 aCol
[i
].UpdateTranspose( rSource
, rDest
, pUndoDoc
);
1604 void ScTable::UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
1606 for ( SCCOL i
=0; i
<=MAXCOL
; i
++ )
1607 aCol
[i
].UpdateGrow( rArea
, nGrowX
, nGrowY
);
1610 void ScTable::UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
)
1612 if (nTab
>= rCxt
.mnInsertPos
)
1614 nTab
+= rCxt
.mnSheets
;
1616 pDBDataNoName
->UpdateMoveTab(nTab
- 1 ,nTab
);
1620 mpRangeName
->UpdateInsertTab(rCxt
, nTab
);
1622 if (mpCondFormatList
)
1623 mpCondFormatList
->UpdateInsertTab(rCxt
);
1625 for (SCCOL i
=0; i
<= MAXCOL
; i
++) aCol
[i
].UpdateInsertTab(rCxt
);
1627 if (IsStreamValid())
1628 SetStreamValid(false);
1631 void ScTable::UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
)
1633 if (nTab
> rCxt
.mnDeletePos
)
1635 nTab
-= rCxt
.mnSheets
;
1637 pDBDataNoName
->UpdateMoveTab(nTab
+ 1,nTab
);
1641 mpRangeName
->UpdateDeleteTab(rCxt
, nTab
);
1643 if (mpCondFormatList
)
1644 mpCondFormatList
->UpdateDeleteTab(rCxt
);
1646 for (SCCOL i
= 0; i
<= MAXCOL
; ++i
)
1647 aCol
[i
].UpdateDeleteTab(rCxt
);
1649 if (IsStreamValid())
1650 SetStreamValid(false);
1653 void ScTable::UpdateMoveTab(
1654 sc::RefUpdateMoveTabContext
& rCxt
, SCTAB nTabNo
, ScProgress
* pProgress
)
1658 mpRangeName
->UpdateMoveTab(rCxt
, nTab
);
1661 pDBDataNoName
->UpdateMoveTab(rCxt
.mnOldPos
, rCxt
.mnNewPos
);
1663 if(mpCondFormatList
)
1664 mpCondFormatList
->UpdateMoveTab(rCxt
);
1666 for ( SCCOL i
=0; i
<= MAXCOL
; i
++ )
1668 aCol
[i
].UpdateMoveTab(rCxt
, nTabNo
);
1670 pProgress
->SetState(pProgress
->GetState() + aCol
[i
].GetCodeCount());
1673 if (IsStreamValid())
1674 SetStreamValid(false);
1677 void ScTable::UpdateCompile( bool bForceIfNameInUse
)
1679 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1681 aCol
[i
].UpdateCompile( bForceIfNameInUse
);
1685 void ScTable::SetTabNo(SCTAB nNewTab
)
1688 for (SCCOL i
=0; i
<= MAXCOL
; i
++) aCol
[i
].SetTabNo(nNewTab
);
1691 void ScTable::FindRangeNamesInUse(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1692 std::set
<sal_uInt16
>& rIndexes
) const
1694 for (SCCOL i
= nCol1
; i
<= nCol2
&& ValidCol(i
); i
++)
1695 aCol
[i
].FindRangeNamesInUse(nRow1
, nRow2
, rIndexes
);
1698 void ScTable::ExtendPrintArea( OutputDevice
* pDev
,
1699 SCCOL
/* nStartCol */, SCROW nStartRow
, SCCOL
& rEndCol
, SCROW nEndRow
)
1701 if ( !pColFlags
|| !pRowFlags
)
1703 OSL_FAIL("ExtendPrintArea: No ColInfo or RowInfo");
1707 Point aPix1000
= pDev
->LogicToPixel( Point(1000,1000), MAP_TWIP
);
1708 double nPPTX
= aPix1000
.X() / 1000.0;
1709 double nPPTY
= aPix1000
.Y() / 1000.0;
1711 // First, mark those columns that we need to skip i.e. hidden and empty columns.
1713 ScFlatBoolColSegments aSkipCols
;
1714 aSkipCols
.setFalse(0, MAXCOL
);
1715 for (SCCOL i
= 0; i
<= MAXCOL
; ++i
)
1718 if (ColHidden(i
, NULL
, &nLastCol
))
1720 // Columns are hidden in this range.
1721 aSkipCols
.setTrue(i
, nLastCol
);
1725 // These columns are visible. Check for empty columns.
1726 for (SCCOL j
= i
; j
<= nLastCol
; ++j
)
1728 if (aCol
[j
].GetCellCount() == 0)
1730 aSkipCols
.setTrue(j
,j
);
1736 ScFlatBoolColSegments::RangeData aColData
;
1737 for (SCCOL nCol
= rEndCol
; nCol
>= 0; --nCol
)
1739 if (!aSkipCols
.getRangeData(nCol
, aColData
))
1740 // Failed to get the data. This should never happen!
1743 if (aColData
.mbValue
)
1745 // Skip these columns.
1746 nCol
= aColData
.mnCol1
; // move toward 0.
1750 // These are visible and non-empty columns.
1751 for (SCCOL nDataCol
= nCol
; 0 <= nDataCol
&& nDataCol
>= aColData
.mnCol1
; --nDataCol
)
1753 SCCOL nPrintCol
= nDataCol
;
1754 VisibleDataCellIterator
aIter(*mpHiddenRows
, aCol
[nDataCol
]);
1755 ScRefCellValue aCell
= aIter
.reset(nStartRow
);
1756 if (aCell
.isEmpty())
1757 // No visible cells found in this column. Skip it.
1760 while (!aCell
.isEmpty())
1762 SCCOL nNewCol
= nDataCol
;
1763 SCROW nRow
= aIter
.getRow();
1765 // Went past the last row position. Bail out.
1768 MaybeAddExtraColumn(nNewCol
, nRow
, pDev
, nPPTX
, nPPTY
);
1769 if (nNewCol
> nPrintCol
)
1770 nPrintCol
= nNewCol
;
1771 aCell
= aIter
.next();
1774 if (nPrintCol
> rEndCol
)
1775 // Make sure we don't shrink the print area.
1776 rEndCol
= nPrintCol
;
1778 nCol
= aColData
.mnCol1
; // move toward 0.
1782 void ScTable::MaybeAddExtraColumn(SCCOL
& rCol
, SCROW nRow
, OutputDevice
* pDev
, double nPPTX
, double nPPTY
)
1784 ScRefCellValue aCell
= aCol
[rCol
].GetCellValue(nRow
);
1785 if (!aCell
.hasString())
1788 bool bFormula
= false; //! ueberge
1789 long nPixel
= aCol
[rCol
].GetTextWidth(nRow
);
1791 // Breite bereits im Idle-Handler berechnet?
1792 if ( TEXTWIDTH_DIRTY
== nPixel
)
1794 ScNeededSizeOptions aOptions
;
1795 aOptions
.bTotalSize
= true;
1796 aOptions
.bFormula
= bFormula
;
1797 aOptions
.bSkipMerged
= false;
1799 Fraction
aZoom(1,1);
1800 nPixel
= aCol
[rCol
].GetNeededSize(
1801 nRow
, pDev
, nPPTX
, nPPTY
, aZoom
, aZoom
, true, aOptions
);
1803 aCol
[rCol
].SetTextWidth(nRow
, static_cast<sal_uInt16
>(nPixel
));
1806 long nTwips
= (long) (nPixel
/ nPPTX
);
1807 long nDocW
= GetColWidth( rCol
);
1809 long nMissing
= nTwips
- nDocW
;
1812 // look at alignment
1814 const ScPatternAttr
* pPattern
= GetPattern( rCol
, nRow
);
1815 const SfxItemSet
* pCondSet
= pDocument
->GetCondResult( rCol
, nRow
, nTab
);
1817 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)
1818 pPattern
->GetItem( ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
1819 if ( eHorJust
== SVX_HOR_JUSTIFY_CENTER
)
1820 nMissing
/= 2; // distributed into both directions
1823 // STANDARD is LEFT (only text is handled here)
1824 bool bRight
= ( eHorJust
== SVX_HOR_JUSTIFY_RIGHT
);
1825 if ( IsLayoutRTL() )
1828 nMissing
= 0; // extended only to the left (logical)
1832 SCCOL nNewCol
= rCol
;
1833 while (nMissing
> 0 && nNewCol
< MAXCOL
)
1835 ScRefCellValue aNextCell
= aCol
[nNewCol
+1].GetCellValue(nRow
);
1836 if (!aNextCell
.isEmpty())
1837 // Cell content in a next column ends display of this string.
1840 nMissing
-= GetColWidth(++nNewCol
);
1847 class SetTableIndex
: public ::std::unary_function
<ScRange
, void>
1851 SetTableIndex(SCTAB nTab
) : mnTab(nTab
) {}
1853 void operator() (ScRange
& rRange
) const
1855 rRange
.aStart
.SetTab(mnTab
);
1856 rRange
.aEnd
.SetTab(mnTab
);
1860 void setPrintRange(ScRange
*& pRange1
, const ScRange
* pRange2
)
1865 *pRange1
= *pRange2
;
1867 pRange1
= new ScRange(*pRange2
);
1875 void ScTable::CopyPrintRange(const ScTable
& rTable
)
1877 // The table index shouldn't be used when the print range is used, but
1878 // just in case set the correct table index.
1880 aPrintRanges
= rTable
.aPrintRanges
;
1881 ::std::for_each(aPrintRanges
.begin(), aPrintRanges
.end(), SetTableIndex(nTab
));
1883 bPrintEntireSheet
= rTable
.bPrintEntireSheet
;
1885 delete pRepeatColRange
;
1886 pRepeatColRange
= NULL
;
1887 if (rTable
.pRepeatColRange
)
1889 pRepeatColRange
= new ScRange(*rTable
.pRepeatColRange
);
1890 pRepeatColRange
->aStart
.SetTab(nTab
);
1891 pRepeatColRange
->aEnd
.SetTab(nTab
);
1894 delete pRepeatRowRange
;
1895 pRepeatRowRange
= NULL
;
1896 if (rTable
.pRepeatRowRange
)
1898 pRepeatRowRange
= new ScRange(*rTable
.pRepeatRowRange
);
1899 pRepeatRowRange
->aStart
.SetTab(nTab
);
1900 pRepeatRowRange
->aEnd
.SetTab(nTab
);
1904 void ScTable::SetRepeatColRange( const ScRange
* pNew
)
1906 setPrintRange( pRepeatColRange
, pNew
);
1908 if (IsStreamValid())
1909 SetStreamValid(false);
1911 InvalidatePageBreaks();
1914 void ScTable::SetRepeatRowRange( const ScRange
* pNew
)
1916 setPrintRange( pRepeatRowRange
, pNew
);
1918 if (IsStreamValid())
1919 SetStreamValid(false);
1921 InvalidatePageBreaks();
1924 void ScTable::ClearPrintRanges()
1926 aPrintRanges
.clear();
1927 bPrintEntireSheet
= false;
1929 if (IsStreamValid())
1930 SetStreamValid(false);
1932 InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1935 void ScTable::AddPrintRange( const ScRange
& rNew
)
1937 bPrintEntireSheet
= false;
1938 if( aPrintRanges
.size() < 0xFFFF )
1939 aPrintRanges
.push_back( rNew
);
1941 if (IsStreamValid())
1942 SetStreamValid(false);
1944 InvalidatePageBreaks();
1948 void ScTable::SetPrintEntireSheet()
1950 if( !IsPrintEntireSheet() )
1953 bPrintEntireSheet
= true;
1957 const ScRange
* ScTable::GetPrintRange(sal_uInt16 nPos
) const
1959 return (nPos
< GetPrintRangeCount()) ? &aPrintRanges
[ nPos
] : NULL
;
1962 void ScTable::FillPrintSaver( ScPrintSaverTab
& rSaveTab
) const
1964 rSaveTab
.SetAreas( aPrintRanges
, bPrintEntireSheet
);
1965 rSaveTab
.SetRepeat( pRepeatColRange
, pRepeatRowRange
);
1968 void ScTable::RestorePrintRanges( const ScPrintSaverTab
& rSaveTab
)
1970 aPrintRanges
= rSaveTab
.GetPrintRanges();
1971 bPrintEntireSheet
= rSaveTab
.IsEntireSheet();
1972 SetRepeatColRange( rSaveTab
.GetRepeatCol() );
1973 SetRepeatRowRange( rSaveTab
.GetRepeatRow() );
1975 InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1976 UpdatePageBreaks(NULL
);
1979 SCROW
ScTable::VisibleDataCellIterator::ROW_NOT_FOUND
= -1;
1981 ScTable::VisibleDataCellIterator::VisibleDataCellIterator(ScFlatBoolRowSegments
& rRowSegs
, ScColumn
& rColumn
) :
1982 mrRowSegs(rRowSegs
),
1984 mnCurRow(ROW_NOT_FOUND
),
1985 mnUBound(ROW_NOT_FOUND
)
1989 ScTable::VisibleDataCellIterator::~VisibleDataCellIterator()
1993 ScRefCellValue
ScTable::VisibleDataCellIterator::reset(SCROW nRow
)
1997 mnCurRow
= ROW_NOT_FOUND
;
1998 return ScRefCellValue();
2001 ScFlatBoolRowSegments::RangeData aData
;
2002 if (!mrRowSegs
.getRangeData(nRow
, aData
))
2004 mnCurRow
= ROW_NOT_FOUND
;
2005 return ScRefCellValue();
2010 // specified row is visible. Take it.
2012 mnUBound
= aData
.mnRow2
;
2016 // specified row is not-visible. The first visible row is the start of
2017 // the next segment.
2018 mnCurRow
= aData
.mnRow2
+ 1;
2019 mnUBound
= mnCurRow
; // get range data on the next iteration.
2020 if (mnCurRow
> MAXROW
)
2022 // Make sure the row doesn't exceed our current limit.
2023 mnCurRow
= ROW_NOT_FOUND
;
2024 return ScRefCellValue();
2028 maCell
= mrColumn
.GetCellValue(mnCurRow
);
2029 if (!maCell
.isEmpty())
2030 // First visible cell found.
2033 // Find a first visible cell below this row (if any).
2037 ScRefCellValue
ScTable::VisibleDataCellIterator::next()
2039 if (mnCurRow
== ROW_NOT_FOUND
)
2040 return ScRefCellValue();
2042 while (mrColumn
.GetNextDataPos(mnCurRow
))
2044 if (mnCurRow
> mnUBound
)
2046 // We don't know the visibility of this row range. Query it.
2047 ScFlatBoolRowSegments::RangeData aData
;
2048 if (!mrRowSegs
.getRangeData(mnCurRow
, aData
))
2050 mnCurRow
= ROW_NOT_FOUND
;
2051 return ScRefCellValue();
2056 // This row is invisible. Skip to the last invisible row and
2058 mnCurRow
= mnUBound
= aData
.mnRow2
;
2062 // This row is visible.
2063 mnUBound
= aData
.mnRow2
;
2066 maCell
= mrColumn
.GetCellValue(mnCurRow
);
2067 if (!maCell
.isEmpty())
2071 mnCurRow
= ROW_NOT_FOUND
;
2072 return ScRefCellValue();
2075 SCROW
ScTable::VisibleDataCellIterator::getRow() const
2080 void ScTable::SetAnonymousDBData(ScDBData
* pDBData
)
2082 delete pDBDataNoName
;
2083 pDBDataNoName
= pDBData
;
2086 ScDBData
* ScTable::GetAnonymousDBData()
2088 return pDBDataNoName
;
2091 sal_uLong
ScTable::AddCondFormat( ScConditionalFormat
* pNew
)
2093 if(!mpCondFormatList
)
2094 mpCondFormatList
.reset(new ScConditionalFormatList());
2097 for(ScConditionalFormatList::const_iterator itr
= mpCondFormatList
->begin();
2098 itr
!= mpCondFormatList
->end(); ++itr
)
2100 sal_uLong nKey
= itr
->GetKey();
2105 pNew
->SetKey(nMax
+1);
2106 mpCondFormatList
->InsertNew(pNew
);
2111 sal_uInt8
ScTable::GetScriptType( SCCOL nCol
, SCROW nRow
) const
2113 if (!ValidCol(nCol
))
2116 return aCol
[nCol
].GetScriptType(nRow
);
2119 void ScTable::SetScriptType( SCCOL nCol
, SCROW nRow
, sal_uInt8 nType
)
2121 if (!ValidCol(nCol
))
2124 aCol
[nCol
].SetScriptType(nRow
, nType
);
2127 sal_uInt8
ScTable::GetRangeScriptType(
2128 sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2130 if (!ValidCol(nCol
))
2133 sc::CellStoreType::iterator itr
= aCol
[nCol
].maCells
.begin();
2134 return aCol
[nCol
].GetRangeScriptType(rBlockPos
.miCellTextAttrPos
, nRow1
, nRow2
, itr
);
2137 size_t ScTable::GetFormulaHash( SCCOL nCol
, SCROW nRow
) const
2139 if (!ValidCol(nCol
))
2142 return aCol
[nCol
].GetFormulaHash(nRow
);
2145 ScFormulaVectorState
ScTable::GetFormulaVectorState( SCCOL nCol
, SCROW nRow
) const
2147 if (!ValidCol(nCol
))
2148 return FormulaVectorUnknown
;
2150 return aCol
[nCol
].GetFormulaVectorState(nRow
);
2153 formula::FormulaTokenRef
ScTable::ResolveStaticReference( SCCOL nCol
, SCROW nRow
)
2155 if (!ValidCol(nCol
) || !ValidRow(nRow
))
2156 return formula::FormulaTokenRef();
2158 return aCol
[nCol
].ResolveStaticReference(nRow
);
2161 formula::FormulaTokenRef
ScTable::ResolveStaticReference( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
2163 if (nCol2
< nCol1
|| nRow2
< nRow1
)
2164 return formula::FormulaTokenRef();
2166 if (!ValidCol(nCol1
) || !ValidCol(nCol2
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
2167 return formula::FormulaTokenRef();
2169 ScMatrixRef
pMat(new ScMatrix(nCol2
-nCol1
+1, nRow2
-nRow1
+1, 0.0));
2170 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
2172 if (!aCol
[nCol
].ResolveStaticReference(*pMat
, nCol2
-nCol1
, nRow1
, nRow2
))
2173 // Column contains non-static cell. Failed.
2174 return formula::FormulaTokenRef();
2177 return formula::FormulaTokenRef(new ScMatrixToken(pMat
));
2180 formula::VectorRefArray
ScTable::FetchVectorRefArray( SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2183 return formula::VectorRefArray();
2185 if (!ValidCol(nCol
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
2186 return formula::VectorRefArray();
2188 return aCol
[nCol
].FetchVectorRefArray(nRow1
, nRow2
);
2191 ScRefCellValue
ScTable::GetRefCellValue( SCCOL nCol
, SCROW nRow
)
2193 if (!ValidColRow(nCol
, nRow
))
2194 return ScRefCellValue();
2196 return aCol
[nCol
].GetCellValue(nRow
);
2199 SvtBroadcaster
* ScTable::GetBroadcaster( SCCOL nCol
, SCROW nRow
)
2201 if (!ValidColRow(nCol
, nRow
))
2204 return aCol
[nCol
].GetBroadcaster(nRow
);
2207 void ScTable::DeleteBroadcasters(
2208 sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2210 if (!ValidCol(nCol
))
2213 aCol
[nCol
].DeleteBroadcasters(rBlockPos
, nRow1
, nRow2
);
2216 bool ScTable::HasBroadcaster( SCCOL nCol
) const
2218 if (!ValidCol(nCol
))
2221 return aCol
[nCol
].HasBroadcaster();
2224 void ScTable::FillMatrix( ScMatrix
& rMat
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
) const
2227 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
, ++nMatCol
)
2228 aCol
[nCol
].FillMatrix(rMat
, nMatCol
, nRow1
, nRow2
);
2231 void ScTable::InterpretDirtyCells( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
2233 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
2234 aCol
[nCol
].InterpretDirtyCells(nRow1
, nRow2
);
2237 void ScTable::SetFormulaResults( SCCOL nCol
, SCROW nRow
, const double* pResults
, size_t nLen
)
2239 if (!ValidCol(nCol
))
2242 aCol
[nCol
].SetFormulaResults(nRow
, pResults
, nLen
);
2245 void ScTable::SetFormulaResults(
2246 SCCOL nCol
, SCROW nRow
, const formula::FormulaTokenRef
* pResults
, size_t nLen
)
2248 if (!ValidCol(nCol
))
2251 aCol
[nCol
].SetFormulaResults(nRow
, pResults
, nLen
);
2254 #if DEBUG_COLUMN_STORAGE
2255 void ScTable::DumpFormulaGroups( SCCOL nCol
) const
2257 if (!ValidCol(nCol
))
2260 aCol
[nCol
].DumpFormulaGroups();
2264 const SvtBroadcaster
* ScTable::GetBroadcaster( SCCOL nCol
, SCROW nRow
) const
2266 if (!ValidColRow(nCol
, nRow
))
2269 return aCol
[nCol
].GetBroadcaster(nRow
);
2272 void ScTable::DeleteConditionalFormat( sal_uLong nIndex
)
2274 mpCondFormatList
->erase(nIndex
);
2277 void ScTable::SetCondFormList( ScConditionalFormatList
* pNew
)
2279 mpCondFormatList
.reset( pNew
);
2282 ScConditionalFormatList
* ScTable::GetCondFormList()
2284 if(!mpCondFormatList
)
2285 mpCondFormatList
.reset( new ScConditionalFormatList() );
2287 return mpCondFormatList
.get();
2290 const ScConditionalFormatList
* ScTable::GetCondFormList() const
2292 return mpCondFormatList
.get();
2295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */