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"
39 #include "hints.hxx" // fuer Paint-Broadcast
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"
56 ScProgress
* GetProgressBar(
57 SCSIZE nCount
, SCSIZE nTotalCount
, ScProgress
* pOuterProgress
, ScDocument
* pDoc
)
59 if (nTotalCount
< 1000)
61 // if the total number of rows is less than 1000, don't even bother
62 // with the progress bar because drawing progress bar can be very
63 // expensive especially in GTK.
68 return pOuterProgress
;
71 return new ScProgress(
72 pDoc
->GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING
), nTotalCount
);
77 void GetOptimalHeightsInColumn(
78 ScColumn
* pCol
, SCROW nStartRow
, SCROW nEndRow
, vector
<sal_uInt16
>& aHeights
,
79 OutputDevice
* pDev
, double nPPTX
, double nPPTY
, const Fraction
& rZoomX
, const Fraction
& rZoomY
, bool bForce
,
80 ScProgress
* pProgress
, sal_uInt32 nProgressStart
)
82 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
84 // zuerst einmal ueber den ganzen Bereich
85 // (mit der letzten Spalte in der Hoffnung, dass die am ehesten noch auf
86 // Standard formatiert ist)
88 pCol
[MAXCOL
].GetOptimalHeight(
89 nStartRow
, nEndRow
, &aHeights
[0], pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
, 0, 0 );
91 // daraus Standardhoehe suchen, die im unteren Bereich gilt
93 sal_uInt16 nMinHeight
= aHeights
[nCount
-1];
94 SCSIZE nPos
= nCount
-1;
95 while ( nPos
&& aHeights
[nPos
-1] >= nMinHeight
)
97 SCROW nMinStart
= nStartRow
+ nPos
;
99 sal_uLong nWeightedCount
= 0;
100 for (SCCOL nCol
=0; nCol
<MAXCOL
; nCol
++) // MAXCOL schon oben
102 pCol
[nCol
].GetOptimalHeight(
103 nStartRow
, nEndRow
, &aHeights
[0], pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
,
104 nMinHeight
, nMinStart
);
108 sal_uLong nWeight
= pCol
[nCol
].GetWeightedCount();
109 if (nWeight
) // nochmal denselben Status muss auch nicht sein
111 nWeightedCount
+= nWeight
;
112 pProgress
->SetState( nWeightedCount
+ nProgressStart
);
118 struct OptimalHeightsFuncObjBase
120 virtual ~OptimalHeightsFuncObjBase() {}
121 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
) = 0;
124 struct SetRowHeightOnlyFunc
: public OptimalHeightsFuncObjBase
127 SetRowHeightOnlyFunc(ScTable
* pTab
) :
131 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
)
133 mpTab
->SetRowHeightOnly(nStartRow
, nEndRow
, nHeight
);
138 struct SetRowHeightRangeFunc
: public OptimalHeightsFuncObjBase
144 SetRowHeightRangeFunc(ScTable
* pTab
, double nPPTX
, double nPPTY
) :
150 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
)
152 return mpTab
->SetRowHeightRange(nStartRow
, nEndRow
, nHeight
, mnPPTX
, mnPPTY
);
156 bool SetOptimalHeightsToRows(OptimalHeightsFuncObjBase
& rFuncObj
,
157 ScBitMaskCompressedArray
<SCROW
, sal_uInt8
>* pRowFlags
, SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nExtra
,
158 const vector
<sal_uInt16
>& aHeights
, bool bForce
)
160 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
161 bool bChanged
= false;
164 sal_uInt16 nLast
= 0;
165 for (SCSIZE i
=0; i
<nCount
; i
++)
169 sal_uInt8 nRowFlag
= pRowFlags
->GetValue( nStartRow
+i
, nIndex
, nRegionEndRow
);
170 if ( nRegionEndRow
> nEndRow
)
171 nRegionEndRow
= nEndRow
;
172 SCSIZE nMoreRows
= nRegionEndRow
- ( nStartRow
+i
); // additional equal rows after first
174 bool bAutoSize
= ((nRowFlag
& CR_MANUALSIZE
) == 0);
175 if ( bAutoSize
|| bForce
)
180 pRowFlags
->SetValue( nStartRow
+i
, nRegionEndRow
, nRowFlag
| CR_MANUALSIZE
);
183 pRowFlags
->SetValue( nStartRow
+i
, nRegionEndRow
, nRowFlag
& ~CR_MANUALSIZE
);
185 for (SCSIZE nInner
= i
; nInner
<= i
+ nMoreRows
; ++nInner
)
189 if (aHeights
[nInner
]+nExtra
== nLast
)
190 nRngEnd
= nStartRow
+nInner
;
193 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
199 nLast
= aHeights
[nInner
]+nExtra
;
200 nRngStart
= nStartRow
+nInner
;
201 nRngEnd
= nStartRow
+nInner
;
208 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
211 i
+= nMoreRows
; // already handled - skip
214 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
221 // -----------------------------------------------------------------------
223 ScTable::ScTable( ScDocument
* pDoc
, SCTAB nNewTab
, const OUString
& rNewName
,
224 bool bColInfo
, bool bRowInfo
) :
226 aCodeName( rNewName
),
228 aPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) ),
229 nRepeatStartX( SCCOL_REPEAT_NONE
),
230 nRepeatEndX( SCCOL_REPEAT_NONE
),
231 nRepeatStartY( SCROW_REPEAT_NONE
),
232 nRepeatEndY( SCROW_REPEAT_NONE
),
233 pTabProtection( NULL
),
235 mpRowHeights( static_cast<ScFlatUInt16RowSegments
*>(NULL
) ),
238 mpHiddenCols(new ScFlatBoolColSegments
),
239 mpHiddenRows(new ScFlatBoolRowSegments
),
240 mpFilteredCols(new ScFlatBoolColSegments
),
241 mpFilteredRows(new ScFlatBoolRowSegments
),
242 pOutlineTable( NULL
),
243 pSheetEvents( NULL
),
246 pSearchText ( NULL
),
247 pSortCollator( NULL
),
248 pRepeatColRange( NULL
),
249 pRepeatRowRange( NULL
),
251 pScenarioRanges( NULL
),
252 aScenarioColor( COL_LIGHTGRAY
),
253 aTabBgColor( COL_AUTO
),
257 mpCondFormatList( new ScConditionalFormatList() ),
262 bPageSizeValid(false),
263 bTableAreaValid(false),
266 bPendingRowHeights(false),
267 bCalcNotification(false),
268 bGlobalKeepQuery(false),
269 bPrintEntireSheet(true),
270 bActiveScenario(false),
271 mbPageBreaksValid(false)
276 pColWidth
= new sal_uInt16
[ MAXCOL
+1 ];
277 pColFlags
= new sal_uInt8
[ MAXCOL
+1 ];
279 for (SCCOL i
=0; i
<=MAXCOL
; i
++)
281 pColWidth
[i
] = STD_COL_WIDTH
;
288 mpRowHeights
.reset(new ScFlatUInt16RowSegments(ScGlobal::nStdRowHeight
));
289 pRowFlags
= new ScBitMaskCompressedArray
< SCROW
, sal_uInt8
>( MAXROW
, 0);
292 if ( pDocument
->IsDocVisible() )
294 // when a sheet is added to a visible document,
295 // initialize its RTL flag from the system locale
296 bLayoutRTL
= ScGlobal::IsSystemRTL();
299 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
302 if ( pDrawLayer
->ScAddPage( nTab
) ) // sal_False (not inserted) during Undo
304 pDrawLayer
->ScRenamePage( nTab
, aName
);
305 sal_uLong nx
= (sal_uLong
) ((double) (MAXCOL
+1) * STD_COL_WIDTH
* HMM_PER_TWIPS
);
306 sal_uLong ny
= (sal_uLong
) ((double) (MAXROW
+1) * ScGlobal::nStdRowHeight
* HMM_PER_TWIPS
);
307 pDrawLayer
->SetPageSize( static_cast<sal_uInt16
>(nTab
), Size( nx
, ny
), false );
311 for (SCCOL k
=0; k
<=MAXCOL
; k
++)
312 aCol
[k
].Init( k
, nTab
, pDocument
);
317 if (!pDocument
->IsInDtorClear())
319 // nicht im dtor die Pages in der falschen Reihenfolge loeschen
320 // (nTab stimmt dann als Page-Number nicht!)
321 // In ScDocument::Clear wird hinterher per Clear am Draw Layer alles geloescht.
323 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
325 pDrawLayer
->ScRemovePage( nTab
);
332 delete pOutlineTable
;
334 delete pRepeatColRange
;
335 delete pRepeatRowRange
;
336 delete pScenarioRanges
;
338 delete pDBDataNoName
;
339 DestroySortCollator();
342 void ScTable::GetName( OUString
& rName
) const
347 void ScTable::SetName( const OUString
& rNewName
)
350 aUpperName
= OUString(); // invalidated if the name is changed
352 // SetStreamValid is handled in ScDocument::RenameTab
355 const OUString
& ScTable::GetUpperName() const
357 if (aUpperName
.isEmpty() && !aName
.isEmpty())
358 aUpperName
= ScGlobal::pCharClass
->uppercase(aName
);
362 void ScTable::SetVisible( bool bVis
)
364 if (bVisible
!= bVis
&& IsStreamValid())
365 SetStreamValid(false);
370 void ScTable::SetStreamValid( bool bSet
, bool bIgnoreLock
)
372 if ( bIgnoreLock
|| !pDocument
->IsStreamValidLocked() )
376 void ScTable::SetPendingRowHeights( bool bSet
)
378 bPendingRowHeights
= bSet
;
381 void ScTable::SetLayoutRTL( bool bSet
)
386 void ScTable::SetLoadingRTL( bool bSet
)
391 const Color
& ScTable::GetTabBgColor() const
396 void ScTable::SetTabBgColor(const Color
& rColor
)
398 if (aTabBgColor
!= rColor
)
400 // The tab color has changed. Set this table 'modified'.
401 aTabBgColor
= rColor
;
403 SetStreamValid(false);
407 void ScTable::SetScenario( bool bFlag
)
412 void ScTable::SetLink( sal_uInt8 nMode
,
413 const String
& rDoc
, const String
& rFlt
, const String
& rOpt
,
414 const String
& rTab
, sal_uLong nRefreshDelay
)
417 aLinkDoc
= rDoc
; // Datei
418 aLinkFlt
= rFlt
; // Filter
419 aLinkOpt
= rOpt
; // Filter-Optionen
420 aLinkTab
= rTab
; // Tabellenname in Quelldatei
421 nLinkRefreshDelay
= nRefreshDelay
; // refresh delay in seconds, 0==off
424 SetStreamValid(false);
427 sal_uInt16
ScTable::GetOptimalColWidth( SCCOL nCol
, OutputDevice
* pDev
,
428 double nPPTX
, double nPPTY
,
429 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
430 bool bFormula
, const ScMarkData
* pMarkData
,
431 const ScColWidthParam
* pParam
)
433 return aCol
[nCol
].GetOptimalColWidth( pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
,
434 bFormula
, STD_COL_WIDTH
- STD_EXTRA_WIDTH
, pMarkData
, pParam
);
437 long ScTable::GetNeededSize( SCCOL nCol
, SCROW nRow
,
439 double nPPTX
, double nPPTY
,
440 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
441 bool bWidth
, bool bTotalSize
)
443 ScNeededSizeOptions aOptions
;
444 aOptions
.bSkipMerged
= false; // zusammengefasste mitzaehlen
445 aOptions
.bTotalSize
= bTotalSize
;
447 return aCol
[nCol
].GetNeededSize
448 ( nRow
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bWidth
, aOptions
);
451 bool ScTable::SetOptimalHeight( SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nExtra
,
453 double nPPTX
, double nPPTY
,
454 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
455 bool bForce
, ScProgress
* pOuterProgress
, sal_uLong nProgressStart
)
457 OSL_ENSURE( nExtra
==0 || bForce
, "automatic OptimalHeight with Extra" );
459 if ( !pDocument
->IsAdjustHeightEnabled() )
464 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
466 ScProgress
* pProgress
= GetProgressBar(nCount
, GetWeightedCount(), pOuterProgress
, pDocument
);
468 vector
<sal_uInt16
> aHeights(nCount
, 0);
470 GetOptimalHeightsInColumn(
471 aCol
, nStartRow
, nEndRow
, aHeights
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
,
472 pProgress
, nProgressStart
);
474 SetRowHeightRangeFunc
aFunc(this, nPPTX
, nPPTY
);
475 bool bChanged
= SetOptimalHeightsToRows(
476 aFunc
, pRowFlags
, nStartRow
, nEndRow
, nExtra
, aHeights
, bForce
);
478 if ( pProgress
!= pOuterProgress
)
484 void ScTable::SetOptimalHeightOnly( SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nExtra
,
486 double nPPTX
, double nPPTY
,
487 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
488 bool bForce
, ScProgress
* pOuterProgress
, sal_uLong nProgressStart
)
490 OSL_ENSURE( nExtra
==0 || bForce
, "automatic OptimalHeight with Extra" );
492 if ( !pDocument
->IsAdjustHeightEnabled() )
495 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
497 ScProgress
* pProgress
= GetProgressBar(nCount
, GetWeightedCount(), pOuterProgress
, pDocument
);
499 vector
<sal_uInt16
> aHeights(nCount
, 0);
501 GetOptimalHeightsInColumn(
502 aCol
, nStartRow
, nEndRow
, aHeights
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bForce
,
503 pProgress
, nProgressStart
);
505 SetRowHeightOnlyFunc
aFunc(this);
506 SetOptimalHeightsToRows(
507 aFunc
, pRowFlags
, nStartRow
, nEndRow
, nExtra
, aHeights
, bForce
);
509 if ( pProgress
!= pOuterProgress
)
513 bool ScTable::GetCellArea( SCCOL
& rEndCol
, SCROW
& rEndRow
) const
518 for (SCCOL i
=0; i
<=MAXCOL
; i
++)
519 if (!aCol
[i
].IsEmptyVisData())
523 SCROW nColY
= aCol
[i
].GetLastVisDataPos();
528 for (ScNotes::const_iterator itr
= maNotes
.begin(); itr
!= maNotes
.end(); ++itr
)
530 SCCOL nCol
= itr
->first
.first
;
531 SCROW nRow
= itr
->first
.second
;
544 bool ScTable::GetTableArea( SCCOL
& rEndCol
, SCROW
& rEndRow
) const
546 bool bRet
= true; //! merken?
547 if (!bTableAreaValid
)
549 bRet
= GetPrintArea(nTableAreaX
, nTableAreaY
, true);
550 bTableAreaValid
= true;
552 rEndCol
= nTableAreaX
;
553 rEndRow
= nTableAreaY
;
557 const SCCOL SC_COLUMNS_STOP
= 30;
559 bool ScTable::GetPrintArea( SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bNotes
, bool bFullFormattedArea
) const
566 for (i
=0; i
<=MAXCOL
; i
++) // Daten testen
567 if (!aCol
[i
].IsEmptyVisData())
572 SCROW nColY
= aCol
[i
].GetLastVisDataPos();
579 for (ScNotes::const_iterator itr
= maNotes
.begin(); itr
!= maNotes
.end(); ++itr
)
581 SCCOL nCol
= itr
->first
.first
;
582 SCROW nRow
= itr
->first
.second
;
591 SCCOL nMaxDataX
= nMaxX
;
593 for (i
=0; i
<=MAXCOL
; i
++) // Attribute testen
596 if (aCol
[i
].GetLastVisibleAttr( nLastRow
, bFullFormattedArea
))
600 if (nLastRow
> nMaxY
)
605 if (nMaxX
== MAXCOL
) // Attribute rechts weglassen
608 while ( nMaxX
>0 && aCol
[nMaxX
].IsVisibleAttrEqual(aCol
[nMaxX
+1]) )
612 if ( nMaxX
< nMaxDataX
)
616 else if ( nMaxX
> nMaxDataX
)
618 SCCOL nAttrStartX
= nMaxDataX
+ 1;
619 while ( nAttrStartX
< MAXCOL
)
621 SCCOL nAttrEndX
= nAttrStartX
;
622 while ( nAttrEndX
< MAXCOL
&& aCol
[nAttrStartX
].IsVisibleAttrEqual(aCol
[nAttrEndX
+1]) )
624 if ( nAttrEndX
+ 1 - nAttrStartX
>= SC_COLUMNS_STOP
)
626 // found equally-formatted columns behind data -> stop before these columns
627 nMaxX
= nAttrStartX
- 1;
629 // also don't include default-formatted columns before that
631 while ( nMaxX
> nMaxDataX
&& !aCol
[nMaxX
].GetLastVisibleAttr( nDummyRow
) )
635 nAttrStartX
= nAttrEndX
+ 1;
644 bool ScTable::GetPrintAreaHor( SCROW nStartRow
, SCROW nEndRow
,
645 SCCOL
& rEndCol
, bool /* bNotes */ ) const
651 for (i
=0; i
<=MAXCOL
; i
++) // Attribute testen
653 if (aCol
[i
].HasVisibleAttrIn( nStartRow
, nEndRow
))
660 if (nMaxX
== MAXCOL
) // Attribute rechts weglassen
663 while ( nMaxX
>0 && aCol
[nMaxX
].IsVisibleAttrEqual(aCol
[nMaxX
+1], nStartRow
, nEndRow
) )
667 for (i
=0; i
<=MAXCOL
; i
++) // Daten testen
669 if (!aCol
[i
].IsEmptyBlock( nStartRow
, nEndRow
)) //! bNotes ??????
681 bool ScTable::GetPrintAreaVer( SCCOL nStartCol
, SCCOL nEndCol
,
682 SCROW
& rEndRow
, bool bNotes
) const
688 for (i
=nStartCol
; i
<=nEndCol
; i
++) // Attribute testen
691 if (aCol
[i
].GetLastVisibleAttr( nLastRow
))
694 if (nLastRow
> nMaxY
)
699 for (i
=nStartCol
; i
<=nEndCol
; i
++) // Daten testen
700 if (!aCol
[i
].IsEmptyVisData())
703 SCROW nColY
= aCol
[i
].GetLastVisDataPos();
710 for (ScNotes::const_iterator itr
= maNotes
.begin(); itr
!= maNotes
.end(); ++itr
)
712 SCCOL nCol
= itr
->first
.first
;
713 SCROW nRow
= itr
->first
.second
;
715 if (nStartCol
> nCol
|| nEndCol
< nCol
)
727 bool ScTable::GetDataStart( SCCOL
& rStartCol
, SCROW
& rStartRow
) const
730 SCCOL nMinX
= MAXCOL
;
731 SCROW nMinY
= MAXROW
;
734 for (i
=0; i
<=MAXCOL
; i
++) // Attribute testen
737 if (aCol
[i
].GetFirstVisibleAttr( nFirstRow
))
742 if (nFirstRow
< nMinY
)
747 if (nMinX
== 0) // Attribute links weglassen
749 if ( aCol
[0].IsVisibleAttrEqual(aCol
[1]) ) // keine einzelnen
752 while ( nMinX
<MAXCOL
&& aCol
[nMinX
].IsVisibleAttrEqual(aCol
[nMinX
-1]) )
757 bool bDatFound
= false;
758 for (i
=0; i
<=MAXCOL
; i
++) // Daten testen
759 if (!aCol
[i
].IsEmptyVisData())
761 if (!bDatFound
&& i
<nMinX
)
763 bFound
= bDatFound
= true;
764 SCROW nColY
= aCol
[i
].GetFirstVisDataPos();
769 for (ScNotes::const_iterator itr
= maNotes
.begin(); itr
!= maNotes
.end(); ++itr
)
771 bFound
= bDatFound
= true;
772 SCCOL nCol
= itr
->first
.first
;
773 SCROW nRow
= itr
->first
.second
;
786 void ScTable::GetDataArea( SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
,
787 bool bIncludeOld
, bool bOnlyDown
) const
789 // return the smallest area containing at least all contiguous cells having data. This area
790 // is a square containing also empty cells. It may shrink or extend the area given as input
791 // Flags as modifiers:
793 // bIncludeOld = true ensure that the returned area contains at least the initial area,
794 // independently of the emptniess of rows / columns (i.e. does not allow shrinking)
795 // bOnlyDown = true means extend / shrink the inputed area only down, i.e modifiy only rEndRow
800 bool bBottom
= false;
801 bool bChanged
= false;
809 SCROW nStart
= rStartRow
;
810 SCROW nEnd
= rEndRow
;
811 if (nStart
>0) --nStart
;
812 if (nEnd
<MAXROW
) ++nEnd
;
814 if (rEndCol
< MAXCOL
)
815 if (!aCol
[rEndCol
+1].IsEmptyBlock(nStart
,nEnd
))
823 if (!aCol
[rStartCol
-1].IsEmptyBlock(nStart
,nEnd
))
832 SCROW nTest
= rStartRow
-1;
833 bool needExtend
= false;
834 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& !needExtend
; i
++)
835 if (aCol
[i
].HasDataAt(nTest
))
846 if (rEndRow
< MAXROW
)
848 SCROW nTest
= rEndRow
+1;
849 bool needExtend
= false;
850 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& !needExtend
; i
++)
851 if (aCol
[i
].HasDataAt(nTest
))
863 if ( !bIncludeOld
&& !bOnlyDown
)
866 while ( aCol
[rStartCol
].IsEmptyBlock(rStartRow
,rEndRow
) && rStartCol
< MAXCOL
&& rStartCol
< rEndCol
)
870 while ( aCol
[rEndCol
].IsEmptyBlock(rStartRow
,rEndRow
) && rEndCol
> 0 && rStartCol
< rEndCol
)
873 if ( !bTop
&& rStartRow
< MAXROW
&& rStartRow
< rEndRow
)
878 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& shrink
; i
++)
879 if (aCol
[i
].HasDataAt(rStartRow
))
883 }while( shrink
&& rStartRow
< MAXROW
&& rStartRow
< rEndRow
);
889 if ( !bBottom
&& rEndRow
> 0 && rStartRow
< rEndRow
)
894 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& shrink
; i
++)
895 if (aCol
[i
].HasDataAt(rEndRow
))
899 }while( shrink
&& rEndRow
> 0 && rStartRow
< rEndRow
);
905 bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk
, SCCOL
& rStartCol
, SCROW
& rStartRow
,
906 SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bColumnsOnly
) const
910 PutInOrder( rStartCol
, rEndCol
);
911 PutInOrder( rStartRow
, rEndRow
);
913 rStartCol
= 0, o_bShrunk
= true;
915 rStartRow
= 0, o_bShrunk
= true;
916 if (rEndCol
> MAXCOL
)
917 rEndCol
= MAXCOL
, o_bShrunk
= true;
918 if (rEndRow
> MAXROW
)
919 rEndRow
= MAXROW
, o_bShrunk
= true;
926 while (rStartCol
< rEndCol
)
928 if (aCol
[rEndCol
].IsEmptyBlock( rStartRow
, rEndRow
))
937 while (rStartCol
< rEndCol
)
939 if (aCol
[rStartCol
].IsEmptyBlock( rStartRow
, rEndRow
))
950 if (rStartRow
< rEndRow
)
953 for (SCCOL i
=rStartCol
; i
<=rEndCol
&& !bFound
; i
++)
954 if (aCol
[i
].HasDataAt( rStartRow
))
963 if (rStartRow
< rEndRow
)
966 for (SCCOL i
=rStartCol
; i
<=rEndCol
&& !bFound
; i
++)
967 if (aCol
[i
].HasDataAt( rEndRow
))
981 return rStartCol
!= rEndCol
|| (bColumnsOnly
?
982 !aCol
[rStartCol
].IsEmptyBlock( rStartRow
, rEndRow
) :
983 (rStartRow
!= rEndRow
|| aCol
[rStartCol
].HasDataAt( rStartRow
)));
987 SCSIZE
ScTable::GetEmptyLinesInBlock( SCCOL nStartCol
, SCROW nStartRow
,
988 SCCOL nEndCol
, SCROW nEndRow
, ScDirection eDir
) const
992 if ((eDir
== DIR_BOTTOM
) || (eDir
== DIR_TOP
))
994 nCount
= static_cast<SCSIZE
>(nEndRow
- nStartRow
);
995 for (nCol
= nStartCol
; nCol
<= nEndCol
; nCol
++)
996 nCount
= std::min(nCount
, aCol
[nCol
].GetEmptyLinesInBlock(nStartRow
, nEndRow
, eDir
));
998 else if (eDir
== DIR_RIGHT
)
1001 while (((SCsCOL
)nCol
>= (SCsCOL
)nStartCol
) &&
1002 aCol
[nCol
].IsEmptyBlock(nStartRow
, nEndRow
))
1011 while ((nCol
<= nEndCol
) && aCol
[nCol
].IsEmptyBlock(nStartRow
, nEndRow
))
1020 bool ScTable::IsEmptyLine( SCROW nRow
, SCCOL nStartCol
, SCCOL nEndCol
) const
1022 bool bFound
= false;
1023 for (SCCOL i
=nStartCol
; i
<=nEndCol
&& !bFound
; i
++)
1024 if (aCol
[i
].HasDataAt(nRow
))
1029 void ScTable::LimitChartArea( SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
1031 while ( rStartCol
<rEndCol
&& aCol
[rStartCol
].IsEmptyBlock(rStartRow
,rEndRow
) )
1034 while ( rStartCol
<rEndCol
&& aCol
[rEndCol
].IsEmptyBlock(rStartRow
,rEndRow
) )
1037 while ( rStartRow
<rEndRow
&& IsEmptyLine(rStartRow
, rStartCol
, rEndCol
) )
1040 while ( rStartRow
<rEndRow
&& IsEmptyLine(rEndRow
, rStartCol
, rEndCol
) )
1044 SCCOL
ScTable::FindNextVisibleCol( SCCOL nCol
, bool bRight
) const
1050 bool bHidden
= pDocument
->ColHidden(nCol
, nTab
, NULL
, &nEnd
);
1054 return std::min
<SCCOL
>(MAXCOL
, nCol
);
1059 SCCOL nStart
= MAXCOL
;
1060 bool bHidden
= pDocument
->ColHidden(nCol
, nTab
, &nStart
, NULL
);
1064 return std::max
<SCCOL
>(0, nCol
);
1068 SCCOL
ScTable::FindNextVisibleColWithContent( SCCOL nCol
, bool bRight
, SCROW nRow
) const
1079 bool bHidden
= pDocument
->ColHidden( nCol
, nTab
, NULL
, &nEndCol
);
1083 if(nEndCol
>= MAXCOL
)
1087 if(aCol
[nCol
].HasVisibleDataAt(nRow
))
1090 while(nCol
< MAXCOL
);
1102 SCCOL nStartCol
= MAXCOL
;
1103 bool bHidden
= pDocument
->ColHidden( nCol
, nTab
, &nStartCol
, NULL
);
1106 nCol
= nStartCol
-1;
1111 if(aCol
[nCol
].HasVisibleDataAt(nRow
))
1120 void ScTable::FindAreaPos( SCCOL
& rCol
, SCROW
& rRow
, ScMoveDirection eDirection
) const
1122 if (eDirection
== SC_MOVE_LEFT
|| eDirection
== SC_MOVE_RIGHT
)
1124 SCCOL nNewCol
= rCol
;
1125 bool bThere
= aCol
[nNewCol
].HasVisibleDataAt(rRow
);
1126 bool bRight
= (eDirection
== SC_MOVE_RIGHT
);
1129 if(nNewCol
>= MAXCOL
&& eDirection
== SC_MOVE_RIGHT
)
1131 else if(nNewCol
== 0 && eDirection
== SC_MOVE_LEFT
)
1134 SCCOL nNextCol
= FindNextVisibleCol( nNewCol
, bRight
);
1136 if(aCol
[nNextCol
].HasVisibleDataAt(rRow
))
1138 bool bFound
= false;
1142 nNextCol
= FindNextVisibleCol( nNewCol
, bRight
);
1143 if(aCol
[nNextCol
].HasVisibleDataAt(rRow
))
1148 while(!bFound
&& nNextCol
> 0 && nNextCol
< MAXCOL
);
1152 nNewCol
= FindNextVisibleColWithContent(nNewCol
, bRight
, rRow
);
1157 nNewCol
= FindNextVisibleColWithContent(nNewCol
, bRight
, rRow
);
1168 aCol
[rCol
].FindDataAreaPos(rRow
,eDirection
== SC_MOVE_DOWN
);
1172 bool ScTable::ValidNextPos( SCCOL nCol
, SCROW nRow
, const ScMarkData
& rMark
,
1173 bool bMarked
, bool bUnprotected
) const
1175 if (!ValidCol(nCol
) || !ValidRow(nRow
))
1178 if (pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
))
1179 // Skip an overlapped cell.
1182 if (bMarked
&& !rMark
.IsCellMarked(nCol
,nRow
))
1185 if (bUnprotected
&& ((const ScProtectionAttr
*)
1186 GetAttr(nCol
,nRow
,ATTR_PROTECTION
))->GetProtection())
1189 if (bMarked
|| bUnprotected
) //! auch sonst ???
1191 // ausgeblendete muessen uebersprungen werden, weil der Cursor sonst
1192 // auf der naechsten Zelle landet, auch wenn die geschuetzt/nicht markiert ist.
1193 //! per Extra-Parameter steuern, nur fuer Cursor-Bewegung ???
1195 if (RowHidden(nRow
))
1198 if (ColHidden(nCol
))
1205 void ScTable::GetNextPos( SCCOL
& rCol
, SCROW
& rRow
, SCsCOL nMovX
, SCsROW nMovY
,
1206 bool bMarked
, bool bUnprotected
, const ScMarkData
& rMark
) const
1208 if (bUnprotected
&& !IsProtected()) // Tabelle ueberhaupt geschuetzt?
1209 bUnprotected
= false;
1211 sal_uInt16 nWrap
= 0;
1215 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ nMovX
);
1216 nRow
= sal::static_int_cast
<SCsROW
>( nRow
+ nMovY
);
1218 OSL_ENSURE( !nMovY
|| !bUnprotected
,
1219 "GetNextPos mit bUnprotected horizontal nicht implementiert" );
1221 if ( nMovY
&& bMarked
)
1223 bool bUp
= ( nMovY
< 0 );
1224 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1225 while ( ValidRow(nRow
) &&
1226 (RowHidden(nRow
) || pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
)) )
1228 // ausgeblendete ueberspringen (s.o.)
1230 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1233 while ( nRow
< 0 || nRow
> MAXROW
)
1235 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ static_cast<SCsCOL
>(nMovY
) );
1236 while ( ValidCol(nCol
) && ColHidden(nCol
) )
1237 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ static_cast<SCsCOL
>(nMovY
) ); // skip hidden rows (see above)
1244 else if (nCol
> MAXCOL
)
1252 else if (nRow
> MAXROW
)
1254 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1255 while ( ValidRow(nRow
) &&
1256 (RowHidden(nRow
) || pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
)) )
1258 // ausgeblendete ueberspringen (s.o.)
1260 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1265 if ( nMovX
&& ( bMarked
|| bUnprotected
) )
1267 // initiales Weiterzaehlen wrappen:
1283 if ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) )
1285 SCsROW
* pNextRows
= new SCsROW
[MAXCOL
+1];
1288 if ( nMovX
> 0 ) // vorwaerts
1290 for (i
=0; i
<=MAXCOL
; i
++)
1291 pNextRows
[i
] = (i
<nCol
) ? (nRow
+1) : nRow
;
1294 SCsROW nNextRow
= pNextRows
[nCol
] + 1;
1296 nNextRow
= rMark
.GetNextMarked( nCol
, nNextRow
, false );
1298 nNextRow
= aCol
[nCol
].GetNextUnprotected( nNextRow
, false );
1299 pNextRows
[nCol
] = nNextRow
;
1301 SCsROW nMinRow
= MAXROW
+1;
1302 for (i
=0; i
<=MAXCOL
; i
++)
1303 if (pNextRows
[i
] < nMinRow
) // bei gleichen den linken
1305 nMinRow
= pNextRows
[i
];
1310 if ( nRow
> MAXROW
)
1312 if (++nWrap
>= 2) break; // ungueltigen Wert behalten
1315 for (i
=0; i
<=MAXCOL
; i
++)
1316 pNextRows
[i
] = 0; // alles ganz von vorne
1319 while ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) );
1323 for (i
=0; i
<=MAXCOL
; i
++)
1324 pNextRows
[i
] = (i
>nCol
) ? (nRow
-1) : nRow
;
1327 SCsROW nNextRow
= pNextRows
[nCol
] - 1;
1329 nNextRow
= rMark
.GetNextMarked( nCol
, nNextRow
, true );
1331 nNextRow
= aCol
[nCol
].GetNextUnprotected( nNextRow
, true );
1332 pNextRows
[nCol
] = nNextRow
;
1334 SCsROW nMaxRow
= -1;
1335 for (i
=0; i
<=MAXCOL
; i
++)
1336 if (pNextRows
[i
] >= nMaxRow
) // bei gleichen den rechten
1338 nMaxRow
= pNextRows
[i
];
1345 if (++nWrap
>= 2) break; // ungueltigen Wert behalten
1348 for (i
=0; i
<=MAXCOL
; i
++)
1349 pNextRows
[i
] = MAXROW
; // alles ganz von vorne
1352 while ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) );
1359 // ungueltige Werte kommen z.b. bei Tab heraus,
1360 // wenn nicht markiert und nicht geschuetzt ist (linker / rechter Rand),
1361 // dann Werte unveraendert lassen
1363 if (ValidColRow(nCol
,nRow
))
1370 bool ScTable::GetNextMarkedCell( SCCOL
& rCol
, SCROW
& rRow
, const ScMarkData
& rMark
) const
1372 const ScMarkArray
* pMarkArray
= rMark
.GetArray();
1373 OSL_ENSURE(pMarkArray
,"GetNextMarkedCell without MarkArray");
1377 ++rRow
; // naechste Zelle ist gesucht
1379 while ( rCol
<= MAXCOL
)
1381 const ScMarkArray
& rArray
= pMarkArray
[rCol
];
1382 while ( rRow
<= MAXROW
)
1384 SCROW nStart
= (SCROW
) rArray
.GetNextMarked( (SCsROW
) rRow
, false );
1385 if ( nStart
<= MAXROW
)
1387 SCROW nEnd
= rArray
.GetMarkEnd( nStart
, false );
1388 ScColumnIterator
aColIter( &aCol
[rCol
], nStart
, nEnd
);
1390 ScBaseCell
* pCell
= NULL
;
1391 while ( aColIter
.Next( nCellRow
, pCell
) )
1396 return true; // Zelle gefunden
1399 rRow
= nEnd
+ 1; // naechsten markierten Bereich suchen
1402 rRow
= MAXROW
+ 1; // Ende der Spalte
1405 ++rCol
; // naechste Spalte testen
1408 return false; // alle Spalten durch
1411 void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode
, SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1412 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
1413 SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
, bool bUpdateNoteCaptionPos
)
1415 if ( nTab
>= nTab1
&& nTab
<= nTab2
&& nDz
== 0 ) // only within the table
1417 InitializeNoteCaptions();
1418 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
1419 if ( eUpdateRefMode
!= URM_COPY
&& pDrawLayer
)
1421 if ( eUpdateRefMode
== URM_MOVE
)
1423 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
- nDx
);
1424 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
- nDy
);
1425 nCol2
= sal::static_int_cast
<SCCOL
>( nCol2
- nDx
);
1426 nRow2
= sal::static_int_cast
<SCROW
>( nRow2
- nDy
);
1428 pDrawLayer
->MoveArea( nTab
, nCol1
,nRow1
, nCol2
,nRow2
, nDx
,nDy
,
1429 (eUpdateRefMode
== URM_INSDEL
), bUpdateNoteCaptionPos
);
1434 void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode
, SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1435 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
,
1436 ScDocument
* pUndoDoc
, bool bIncludeDraw
, bool bUpdateNoteCaptionPos
)
1438 bool bUpdated
= false;
1441 if ( eUpdateRefMode
== URM_COPY
)
1452 // Named expressions need to be updated before formulas acessing them.
1455 ScRange
aRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);;
1456 mpRangeName
->UpdateReference( eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
, true );
1459 for ( ; i
<=iMax
; i
++)
1460 bUpdated
|= aCol
[i
].UpdateReference(
1461 eUpdateRefMode
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, nDx
, nDy
, nDz
, pUndoDoc
);
1464 UpdateDrawRef( eUpdateRefMode
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, nDx
, nDy
, nDz
, bUpdateNoteCaptionPos
);
1466 if ( nTab
>= nTab1
&& nTab
<= nTab2
&& nDz
== 0 ) // print ranges: only within the table
1474 bool bRecalcPages
= false;
1476 for ( ScRangeVec::iterator aIt
= aPrintRanges
.begin(), aEnd
= aPrintRanges
.end(); aIt
!= aEnd
; ++aIt
)
1478 nSCol
= aIt
->aStart
.Col();
1479 nSRow
= aIt
->aStart
.Row();
1480 nECol
= aIt
->aEnd
.Col();
1481 nERow
= aIt
->aEnd
.Row();
1483 // do not try to modify sheet index of print range
1484 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1485 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1487 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1489 *aIt
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1490 bRecalcPages
= true;
1494 if ( pRepeatColRange
)
1496 nSCol
= pRepeatColRange
->aStart
.Col();
1497 nSRow
= pRepeatColRange
->aStart
.Row();
1498 nECol
= pRepeatColRange
->aEnd
.Col();
1499 nERow
= pRepeatColRange
->aEnd
.Row();
1501 // do not try to modify sheet index of repeat range
1502 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1503 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1505 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1507 *pRepeatColRange
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1508 bRecalcPages
= true;
1509 nRepeatStartX
= nSCol
; // fuer UpdatePageBreaks
1510 nRepeatEndX
= nECol
;
1514 if ( pRepeatRowRange
)
1516 nSCol
= pRepeatRowRange
->aStart
.Col();
1517 nSRow
= pRepeatRowRange
->aStart
.Row();
1518 nECol
= pRepeatRowRange
->aEnd
.Col();
1519 nERow
= pRepeatRowRange
->aEnd
.Row();
1521 // do not try to modify sheet index of repeat range
1522 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1523 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1525 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1527 *pRepeatRowRange
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1528 bRecalcPages
= true;
1529 nRepeatStartY
= nSRow
; // fuer UpdatePageBreaks
1530 nRepeatEndY
= nERow
;
1534 // updating print ranges is not necessary with multiple print ranges
1535 if ( bRecalcPages
&& GetPrintRangeCount() <= 1 )
1537 UpdatePageBreaks(NULL
);
1539 pDocument
->RepaintRange( ScRange(0,0,nTab
,MAXCOL
,MAXROW
,nTab
) );
1543 if (bUpdated
&& IsStreamValid())
1544 SetStreamValid(false);
1546 if(mpCondFormatList
)
1547 mpCondFormatList
->UpdateReference( eUpdateRefMode
, ScRange(nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
), nDx
, nDy
, nDz
);
1550 void ScTable::UpdateTranspose( const ScRange
& rSource
, const ScAddress
& rDest
,
1551 ScDocument
* pUndoDoc
)
1553 for ( SCCOL i
=0; i
<=MAXCOL
; i
++ )
1554 aCol
[i
].UpdateTranspose( rSource
, rDest
, pUndoDoc
);
1557 void ScTable::UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
1559 for ( SCCOL i
=0; i
<=MAXCOL
; i
++ )
1560 aCol
[i
].UpdateGrow( rArea
, nGrowX
, nGrowY
);
1563 void ScTable::UpdateInsertTab(SCTAB nTable
, SCTAB nNewSheets
)
1569 pDBDataNoName
->UpdateMoveTab(nTab
- 1 ,nTab
);
1571 for (SCCOL i
=0; i
<= MAXCOL
; i
++) aCol
[i
].UpdateInsertTab(nTable
, nNewSheets
);
1574 mpRangeName
->UpdateTabRef( nTable
, 1, 0, nNewSheets
);
1577 mpRangeName
->UpdateTabRef( nTable
, 1);
1579 if (IsStreamValid())
1580 SetStreamValid(false);
1582 if(mpCondFormatList
)
1583 mpCondFormatList
->UpdateReference( URM_INSDEL
, ScRange(0,0, nTable
, MAXCOL
, MAXROW
, nTable
+nNewSheets
-1),0,0, nNewSheets
);
1586 void ScTable::UpdateDeleteTab( SCTAB nTable
, bool bIsMove
, ScTable
* pRefUndo
, SCTAB nSheets
)
1592 pDBDataNoName
->UpdateMoveTab(nTab
+ 1,nTab
);
1597 for (i
=0; i
<= MAXCOL
; i
++) aCol
[i
].UpdateDeleteTab(nTable
, bIsMove
, &pRefUndo
->aCol
[i
], nSheets
);
1599 for (i
=0; i
<= MAXCOL
; i
++) aCol
[i
].UpdateDeleteTab(nTable
, bIsMove
, NULL
, nSheets
);
1603 for (SCTAB aTab
= 0; aTab
< nSheets
; ++aTab
)
1605 mpRangeName
->UpdateTabRef( nTable
+ aTab
, 2 );
1611 mpRangeName
->UpdateTabRef( nTable
, 2 );
1614 if (IsStreamValid())
1615 SetStreamValid(false);
1617 if(mpCondFormatList
)
1618 mpCondFormatList
->UpdateReference( URM_INSDEL
, ScRange(0,0, nTable
, MAXCOL
, MAXROW
, nTable
+nSheets
-1),0,0, -1*nSheets
);
1621 void ScTable::UpdateMoveTab( SCTAB nOldPos
, SCTAB nNewPos
, SCTAB nTabNo
,
1622 ScProgress
* pProgress
)
1625 for ( SCCOL i
=0; i
<= MAXCOL
; i
++ )
1627 aCol
[i
].UpdateMoveTab( nOldPos
, nNewPos
, nTabNo
);
1629 pProgress
->SetState(pProgress
->GetState() + aCol
[i
].GetCodeCount());
1633 mpRangeName
->UpdateTabRef(nOldPos
, 3, nNewPos
);
1635 if (IsStreamValid())
1636 SetStreamValid(false);
1638 pDBDataNoName
->UpdateMoveTab(nOldPos
, nNewPos
);
1640 if(mpCondFormatList
)
1641 mpCondFormatList
->UpdateMoveTab(nOldPos
, nNewPos
);
1644 void ScTable::UpdateCompile( bool bForceIfNameInUse
)
1646 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1648 aCol
[i
].UpdateCompile( bForceIfNameInUse
);
1652 void ScTable::SetTabNo(SCTAB nNewTab
)
1655 for (SCCOL i
=0; i
<= MAXCOL
; i
++) aCol
[i
].SetTabNo(nNewTab
);
1658 void ScTable::FindRangeNamesInUse(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1659 std::set
<sal_uInt16
>& rIndexes
) const
1661 for (SCCOL i
= nCol1
; i
<= nCol2
&& ValidCol(i
); i
++)
1662 aCol
[i
].FindRangeNamesInUse(nRow1
, nRow2
, rIndexes
);
1665 void ScTable::ExtendPrintArea( OutputDevice
* pDev
,
1666 SCCOL
/* nStartCol */, SCROW nStartRow
, SCCOL
& rEndCol
, SCROW nEndRow
)
1668 if ( !pColFlags
|| !pRowFlags
)
1670 OSL_FAIL("ExtendPrintArea: No ColInfo or RowInfo");
1674 Point aPix1000
= pDev
->LogicToPixel( Point(1000,1000), MAP_TWIP
);
1675 double nPPTX
= aPix1000
.X() / 1000.0;
1676 double nPPTY
= aPix1000
.Y() / 1000.0;
1678 // First, mark those columns that we need to skip i.e. hidden and empty columns.
1680 ScFlatBoolColSegments aSkipCols
;
1681 aSkipCols
.setFalse(0, MAXCOL
);
1682 for (SCCOL i
= 0; i
<= MAXCOL
; ++i
)
1685 if (ColHidden(i
, NULL
, &nLastCol
))
1687 // Columns are hidden in this range.
1688 aSkipCols
.setTrue(i
, nLastCol
);
1692 // These columns are visible. Check for empty columns.
1693 for (SCCOL j
= i
; j
<= nLastCol
; ++j
)
1695 if (aCol
[j
].GetCellCount() == 0)
1697 aSkipCols
.setTrue(j
,j
);
1703 ScFlatBoolColSegments::RangeData aColData
;
1704 for (SCCOL nCol
= rEndCol
; nCol
>= 0; --nCol
)
1706 if (!aSkipCols
.getRangeData(nCol
, aColData
))
1707 // Failed to get the data. This should never happen!
1710 if (aColData
.mbValue
)
1712 // Skip these columns.
1713 nCol
= aColData
.mnCol1
; // move toward 0.
1717 // These are visible and non-empty columns.
1718 for (SCCOL nDataCol
= nCol
; 0 <= nDataCol
&& nDataCol
>= aColData
.mnCol1
; --nDataCol
)
1720 SCCOL nPrintCol
= nDataCol
;
1721 VisibleDataCellIterator
aIter(*mpHiddenRows
, aCol
[nDataCol
]);
1722 ScBaseCell
* pCell
= aIter
.reset(nStartRow
);
1724 // No visible cells found in this column. Skip it.
1729 SCCOL nNewCol
= nDataCol
;
1730 SCROW nRow
= aIter
.getRow();
1732 // Went past the last row position. Bail out.
1735 MaybeAddExtraColumn(nNewCol
, nRow
, pDev
, nPPTX
, nPPTY
);
1736 if (nNewCol
> nPrintCol
)
1737 nPrintCol
= nNewCol
;
1738 pCell
= aIter
.next();
1741 if (nPrintCol
> rEndCol
)
1742 // Make sure we don't shrink the print area.
1743 rEndCol
= nPrintCol
;
1745 nCol
= aColData
.mnCol1
; // move toward 0.
1749 void ScTable::MaybeAddExtraColumn(SCCOL
& rCol
, SCROW nRow
, OutputDevice
* pDev
, double nPPTX
, double nPPTY
)
1751 ScBaseCell
* pCell
= aCol
[rCol
].GetCell(nRow
);
1752 if (!pCell
|| !pCell
->HasStringData())
1755 bool bFormula
= false; //! ueberge
1756 long nPixel
= aCol
[rCol
].GetTextWidth(nRow
);
1758 // Breite bereits im Idle-Handler berechnet?
1759 if ( TEXTWIDTH_DIRTY
== nPixel
)
1761 ScNeededSizeOptions aOptions
;
1762 aOptions
.bTotalSize
= true;
1763 aOptions
.bFormula
= bFormula
;
1764 aOptions
.bSkipMerged
= false;
1766 Fraction
aZoom(1,1);
1767 nPixel
= aCol
[rCol
].GetNeededSize(
1768 nRow
, pDev
, nPPTX
, nPPTY
, aZoom
, aZoom
, true, aOptions
);
1770 aCol
[rCol
].SetTextWidth(nRow
, static_cast<sal_uInt16
>(nPixel
));
1773 long nTwips
= (long) (nPixel
/ nPPTX
);
1774 long nDocW
= GetColWidth( rCol
);
1776 long nMissing
= nTwips
- nDocW
;
1779 // look at alignment
1781 const ScPatternAttr
* pPattern
= GetPattern( rCol
, nRow
);
1782 const SfxItemSet
* pCondSet
= pDocument
->GetCondResult( rCol
, nRow
, nTab
);
1784 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)
1785 pPattern
->GetItem( ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
1786 if ( eHorJust
== SVX_HOR_JUSTIFY_CENTER
)
1787 nMissing
/= 2; // distributed into both directions
1790 // STANDARD is LEFT (only text is handled here)
1791 bool bRight
= ( eHorJust
== SVX_HOR_JUSTIFY_RIGHT
);
1792 if ( IsLayoutRTL() )
1795 nMissing
= 0; // extended only to the left (logical)
1799 SCCOL nNewCol
= rCol
;
1800 while (nMissing
> 0 && nNewCol
< MAXCOL
)
1802 ScBaseCell
* pNextCell
= aCol
[nNewCol
+1].GetCell(nRow
);
1804 // Cell content in a next column ends display of this string.
1807 nMissing
-= GetColWidth(++nNewCol
);
1814 class SetTableIndex
: public ::std::unary_function
<ScRange
, void>
1818 SetTableIndex(SCTAB nTab
) : mnTab(nTab
) {}
1820 void operator() (ScRange
& rRange
) const
1822 rRange
.aStart
.SetTab(mnTab
);
1823 rRange
.aEnd
.SetTab(mnTab
);
1827 void setPrintRange(ScRange
*& pRange1
, const ScRange
* pRange2
)
1832 *pRange1
= *pRange2
;
1834 pRange1
= new ScRange(*pRange2
);
1842 void ScTable::CopyPrintRange(const ScTable
& rTable
)
1844 // The table index shouldn't be used when the print range is used, but
1845 // just in case set the correct table index.
1847 aPrintRanges
= rTable
.aPrintRanges
;
1848 ::std::for_each(aPrintRanges
.begin(), aPrintRanges
.end(), SetTableIndex(nTab
));
1850 bPrintEntireSheet
= rTable
.bPrintEntireSheet
;
1852 delete pRepeatColRange
;
1853 pRepeatColRange
= NULL
;
1854 if (rTable
.pRepeatColRange
)
1856 pRepeatColRange
= new ScRange(*rTable
.pRepeatColRange
);
1857 pRepeatColRange
->aStart
.SetTab(nTab
);
1858 pRepeatColRange
->aEnd
.SetTab(nTab
);
1861 delete pRepeatRowRange
;
1862 pRepeatRowRange
= NULL
;
1863 if (rTable
.pRepeatRowRange
)
1865 pRepeatRowRange
= new ScRange(*rTable
.pRepeatRowRange
);
1866 pRepeatRowRange
->aStart
.SetTab(nTab
);
1867 pRepeatRowRange
->aEnd
.SetTab(nTab
);
1871 void ScTable::DoColResize( SCCOL nCol1
, SCCOL nCol2
, SCSIZE nAdd
)
1873 for (SCCOL nCol
=nCol1
; nCol
<=nCol2
; nCol
++)
1874 aCol
[nCol
].ReserveSize(aCol
[nCol
].GetCellCount() + nAdd
);
1877 void ScTable::SetRepeatColRange( const ScRange
* pNew
)
1879 setPrintRange( pRepeatColRange
, pNew
);
1881 if (IsStreamValid())
1882 SetStreamValid(false);
1884 InvalidatePageBreaks();
1887 void ScTable::SetRepeatRowRange( const ScRange
* pNew
)
1889 setPrintRange( pRepeatRowRange
, pNew
);
1891 if (IsStreamValid())
1892 SetStreamValid(false);
1894 InvalidatePageBreaks();
1897 void ScTable::ClearPrintRanges()
1899 aPrintRanges
.clear();
1900 bPrintEntireSheet
= false;
1902 if (IsStreamValid())
1903 SetStreamValid(false);
1905 InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1908 void ScTable::AddPrintRange( const ScRange
& rNew
)
1910 bPrintEntireSheet
= false;
1911 if( aPrintRanges
.size() < 0xFFFF )
1912 aPrintRanges
.push_back( rNew
);
1914 if (IsStreamValid())
1915 SetStreamValid(false);
1917 InvalidatePageBreaks();
1921 void ScTable::SetPrintEntireSheet()
1923 if( !IsPrintEntireSheet() )
1926 bPrintEntireSheet
= true;
1930 const ScRange
* ScTable::GetPrintRange(sal_uInt16 nPos
) const
1932 return (nPos
< GetPrintRangeCount()) ? &aPrintRanges
[ nPos
] : NULL
;
1935 void ScTable::FillPrintSaver( ScPrintSaverTab
& rSaveTab
) const
1937 rSaveTab
.SetAreas( aPrintRanges
, bPrintEntireSheet
);
1938 rSaveTab
.SetRepeat( pRepeatColRange
, pRepeatRowRange
);
1941 void ScTable::RestorePrintRanges( const ScPrintSaverTab
& rSaveTab
)
1943 aPrintRanges
= rSaveTab
.GetPrintRanges();
1944 bPrintEntireSheet
= rSaveTab
.IsEntireSheet();
1945 SetRepeatColRange( rSaveTab
.GetRepeatCol() );
1946 SetRepeatRowRange( rSaveTab
.GetRepeatRow() );
1948 InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1949 UpdatePageBreaks(NULL
);
1952 SCROW
ScTable::VisibleDataCellIterator::ROW_NOT_FOUND
= -1;
1954 ScTable::VisibleDataCellIterator::VisibleDataCellIterator(ScFlatBoolRowSegments
& rRowSegs
, ScColumn
& rColumn
) :
1955 mrRowSegs(rRowSegs
),
1958 mnCurRow(ROW_NOT_FOUND
),
1959 mnUBound(ROW_NOT_FOUND
)
1963 ScTable::VisibleDataCellIterator::~VisibleDataCellIterator()
1967 ScBaseCell
* ScTable::VisibleDataCellIterator::reset(SCROW nRow
)
1971 mnCurRow
= ROW_NOT_FOUND
;
1975 ScFlatBoolRowSegments::RangeData aData
;
1976 if (!mrRowSegs
.getRangeData(nRow
, aData
))
1978 mnCurRow
= ROW_NOT_FOUND
;
1984 // specified row is visible. Take it.
1986 mnUBound
= aData
.mnRow2
;
1990 // specified row is not-visible. The first visible row is the start of
1991 // the next segment.
1992 mnCurRow
= aData
.mnRow2
+ 1;
1993 mnUBound
= mnCurRow
; // get range data on the next iteration.
1994 if (mnCurRow
> MAXROW
)
1996 // Make sure the row doesn't exceed our current limit.
1997 mnCurRow
= ROW_NOT_FOUND
;
2002 mpCell
= mrColumn
.GetCell(mnCurRow
);
2004 // First visible cell found.
2007 // Find a first visible cell below this row (if any).
2011 ScBaseCell
* ScTable::VisibleDataCellIterator::next()
2013 if (mnCurRow
== ROW_NOT_FOUND
)
2016 while (mrColumn
.GetNextDataPos(mnCurRow
))
2018 if (mnCurRow
> mnUBound
)
2020 // We don't know the visibility of this row range. Query it.
2021 ScFlatBoolRowSegments::RangeData aData
;
2022 if (!mrRowSegs
.getRangeData(mnCurRow
, aData
))
2024 mnCurRow
= ROW_NOT_FOUND
;
2030 // This row is invisible. Skip to the last invisible row and
2032 mnCurRow
= mnUBound
= aData
.mnRow2
;
2036 // This row is visible.
2037 mnUBound
= aData
.mnRow2
;
2040 mpCell
= mrColumn
.GetCell(mnCurRow
);
2044 mnCurRow
= ROW_NOT_FOUND
;
2048 SCROW
ScTable::VisibleDataCellIterator::getRow() const
2053 void ScTable::SetAnonymousDBData(ScDBData
* pDBData
)
2055 delete pDBDataNoName
;
2056 pDBDataNoName
= pDBData
;
2059 ScDBData
* ScTable::GetAnonymousDBData()
2061 return pDBDataNoName
;
2064 sal_uLong
ScTable::AddCondFormat( ScConditionalFormat
* pNew
)
2066 if(!mpCondFormatList
)
2067 mpCondFormatList
.reset(new ScConditionalFormatList());
2070 for(ScConditionalFormatList::const_iterator itr
= mpCondFormatList
->begin();
2071 itr
!= mpCondFormatList
->end(); ++itr
)
2073 sal_uLong nKey
= itr
->GetKey();
2078 pNew
->SetKey(nMax
+1);
2079 mpCondFormatList
->InsertNew(pNew
);
2084 sal_uInt8
ScTable::GetScriptType( SCCOL nCol
, SCROW nRow
) const
2086 if (!ValidCol(nCol
))
2089 return aCol
[nCol
].GetScriptType(nRow
);
2092 void ScTable::SetScriptType( SCCOL nCol
, SCROW nRow
, sal_uInt8 nType
)
2094 if (!ValidCol(nCol
))
2097 aCol
[nCol
].SetScriptType(nRow
, nType
);
2100 sal_uInt8
ScTable::GetRangeScriptType(
2101 sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2103 if (!ValidCol(nCol
))
2106 return aCol
[nCol
].GetRangeScriptType(rBlockPos
.miCellTextAttrPos
, nRow1
, nRow2
);
2109 size_t ScTable::GetFormulaHash( SCCOL nCol
, SCROW nRow
) const
2111 if (!ValidCol(nCol
))
2114 return aCol
[nCol
].GetFormulaHash(nRow
);
2117 ScFormulaVectorState
ScTable::GetFormulaVectorState( SCCOL nCol
, SCROW nRow
) const
2119 if (!ValidCol(nCol
))
2120 return FormulaVectorUnknown
;
2122 return aCol
[nCol
].GetFormulaVectorState(nRow
);
2125 formula::FormulaTokenRef
ScTable::ResolveStaticReference( SCCOL nCol
, SCROW nRow
)
2127 if (!ValidCol(nCol
) || !ValidRow(nRow
))
2128 return formula::FormulaTokenRef();
2130 return aCol
[nCol
].ResolveStaticReference(nRow
);
2133 formula::FormulaTokenRef
ScTable::ResolveStaticReference( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
2135 if (nCol2
< nCol1
|| nRow2
< nRow1
)
2136 return formula::FormulaTokenRef();
2138 if (!ValidCol(nCol1
) || !ValidCol(nCol2
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
2139 return formula::FormulaTokenRef();
2141 ScMatrixRef
pMat(new ScMatrix(nCol2
-nCol1
+1, nRow2
-nRow1
+1, 0.0));
2142 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
2144 if (!aCol
[nCol
].ResolveStaticReference(*pMat
, nCol2
-nCol1
, nRow1
, nRow2
))
2145 // Column contains non-static cell. Failed.
2146 return formula::FormulaTokenRef();
2149 return formula::FormulaTokenRef(new ScMatrixToken(pMat
));
2152 const double* ScTable::FetchDoubleArray(
2153 sc::FormulaGroupContext
& rCxt
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
) const
2158 if (!ValidCol(nCol
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
2161 return aCol
[nCol
].FetchDoubleArray(rCxt
, nRow1
, nRow2
);
2164 ScRefCellValue
ScTable::GetRefCellValue( SCCOL nCol
, SCROW nRow
)
2166 if (!ValidColRow(nCol
, nRow
))
2167 return ScRefCellValue();
2169 return aCol
[nCol
].GetRefCellValue(nRow
);
2172 SvtBroadcaster
* ScTable::GetBroadcaster( SCCOL nCol
, SCROW nRow
)
2174 if (!ValidColRow(nCol
, nRow
))
2177 return aCol
[nCol
].GetBroadcaster(nRow
);
2180 void ScTable::DeleteBroadcasters(
2181 sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2183 if (!ValidCol(nCol
))
2186 aCol
[nCol
].DeleteBroadcasters(rBlockPos
, nRow1
, nRow2
);
2189 bool ScTable::HasBroadcaster( SCCOL nCol
) const
2191 if (!ValidCol(nCol
))
2194 return aCol
[nCol
].HasBroadcaster();
2197 const SvtBroadcaster
* ScTable::GetBroadcaster( SCCOL nCol
, SCROW nRow
) const
2199 if (!ValidColRow(nCol
, nRow
))
2202 return aCol
[nCol
].GetBroadcaster(nRow
);
2205 void ScTable::DeleteConditionalFormat( sal_uLong nIndex
)
2207 mpCondFormatList
->erase(nIndex
);
2210 void ScTable::SetCondFormList( ScConditionalFormatList
* pNew
)
2212 mpCondFormatList
.reset( pNew
);
2215 ScConditionalFormatList
* ScTable::GetCondFormList()
2217 if(!mpCondFormatList
)
2218 mpCondFormatList
.reset( new ScConditionalFormatList() );
2220 return mpCondFormatList
.get();
2223 const ScConditionalFormatList
* ScTable::GetCondFormList() const
2225 return mpCondFormatList
.get();
2228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */