Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / data / table2.cxx
blobf96d913b2cc5ed25e2c07e5016e854fa1617baa0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "table.hxx"
21 #include "patattr.hxx"
22 #include "docpool.hxx"
23 #include "formulacell.hxx"
24 #include "document.hxx"
25 #include "drwlayer.hxx"
26 #include "olinetab.hxx"
27 #include "rechead.hxx"
28 #include "stlpool.hxx"
29 #include "attarray.hxx"
30 #include "markdata.hxx"
31 #include "progress.hxx"
32 #include "dociter.hxx"
33 #include "conditio.hxx"
34 #include "chartlis.hxx"
35 #include "fillinfo.hxx"
36 #include "bcaslot.hxx"
37 #include "postit.hxx"
38 #include "sheetevents.hxx"
39 #include "globstr.hrc"
40 #include "segmenttree.hxx"
41 #include "queryparam.hxx"
42 #include "queryentry.hxx"
43 #include "dbdata.hxx"
44 #include "colorscale.hxx"
45 #include "tokenarray.hxx"
46 #include "clipcontext.hxx"
47 #include "types.hxx"
48 #include "editutil.hxx"
49 #include "mtvcellfunc.hxx"
50 #include "refupdatecontext.hxx"
51 #include "scopetools.hxx"
53 #include "scitems.hxx"
54 #include <editeng/boxitem.hxx>
55 #include "editeng/editobj.hxx"
56 #include <svl/poolcach.hxx>
57 #include <unotools/charclass.hxx>
58 #include <math.h>
59 #include <svl/PasswordHelper.hxx>
60 #include <unotools/transliterationwrapper.hxx>
62 namespace {
64 class ColumnRegroupFormulaCells
66 ScColumn* mpCols;
67 public:
68 ColumnRegroupFormulaCells(ScColumn* pCols) : mpCols(pCols) {}
70 void operator() (SCCOL nCol)
72 mpCols[nCol].RegroupFormulaCells();
78 sal_uInt16 ScTable::GetTextWidth(SCCOL nCol, SCROW nRow) const
80 return aCol[nCol].GetTextWidth(nRow);
83 bool ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
85 sal_uInt16 nOldSizeX = 0;
86 sal_uInt16 nOldSizeY = 0;
87 sal_uInt16 nNewSizeX = 0;
88 sal_uInt16 nNewSizeY = 0;
90 if (pOutlineTable)
92 nOldSizeX = pOutlineTable->GetColArray()->GetDepth();
93 nOldSizeY = pOutlineTable->GetRowArray()->GetDepth();
94 delete pOutlineTable;
97 if (pNewOutline)
99 pOutlineTable = new ScOutlineTable( *pNewOutline );
100 nNewSizeX = pOutlineTable->GetColArray()->GetDepth();
101 nNewSizeY = pOutlineTable->GetRowArray()->GetDepth();
103 else
104 pOutlineTable = NULL;
106 return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY ); // Groesse geaendert ?
110 void ScTable::StartOutlineTable()
112 if (!pOutlineTable)
113 pOutlineTable = new ScOutlineTable;
117 void ScTable::SetSheetEvents( const ScSheetEvents* pNew )
119 delete pSheetEvents;
120 if (pNew)
121 pSheetEvents = new ScSheetEvents(*pNew);
122 else
123 pSheetEvents = NULL;
125 SetCalcNotification( false ); // discard notifications before the events were set
127 if (IsStreamValid())
128 SetStreamValid(false);
132 void ScTable::SetCalcNotification( bool bSet )
134 bCalcNotification = bSet;
138 bool ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ) const
140 bool bTest = true;
142 if ( nStartCol==0 && nEndCol==MAXCOL && pOutlineTable )
143 bTest = pOutlineTable->TestInsertRow(nSize);
145 for (SCCOL i=nStartCol; (i<=nEndCol) && bTest; i++)
146 bTest = aCol[i].TestInsertRow(nStartRow, nSize);
148 return bTest;
152 void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize )
154 if (nStartCol==0 && nEndCol==MAXCOL)
156 if (mpRowHeights && pRowFlags)
158 mpRowHeights->insertSegment(nStartRow, nSize, false);
159 sal_uInt8 nNewFlags = pRowFlags->Insert( nStartRow, nSize);
160 // only copy manual size flag, clear all others
161 if (nNewFlags && (nNewFlags != CR_MANUALSIZE))
162 pRowFlags->SetValue( nStartRow, nStartRow + nSize - 1,
163 nNewFlags & CR_MANUALSIZE);
166 if (pOutlineTable)
167 pOutlineTable->InsertRow( nStartRow, nSize );
169 mpFilteredRows->insertSegment(nStartRow, nSize, true);
170 mpHiddenRows->insertSegment(nStartRow, nSize, true);
172 if (!maRowManualBreaks.empty())
174 // Copy all breaks up to nStartRow (non-inclusive).
175 ::std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
176 ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
178 // Copy all breaks from nStartRow (inclusive) to the last element,
179 // but add nSize to each value.
180 ::std::set<SCROW>::iterator itr2 = maRowManualBreaks.end();
181 for (; itr1 != itr2; ++itr1)
182 aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize));
184 maRowManualBreaks.swap(aNewBreaks);
188 for (SCCOL j=nStartCol; j<=nEndCol; j++)
189 aCol[j].InsertRow( nStartRow, nSize );
191 mpCondFormatList->InsertRow(nTab, nStartCol, nEndCol, nStartRow, nSize);
193 InvalidatePageBreaks();
195 if (IsStreamValid())
196 // TODO: In the future we may want to check if the table has been
197 // really modified before setting the stream invalid.
198 SetStreamValid(false);
202 void ScTable::DeleteRow(
203 const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
204 bool* pUndoOutline )
206 if (nStartCol==0 && nEndCol==MAXCOL)
208 if (pRowFlags)
209 pRowFlags->Remove( nStartRow, nSize);
211 if (mpRowHeights)
212 mpRowHeights->removeSegment(nStartRow, nStartRow+nSize);
214 if (pOutlineTable)
215 if (pOutlineTable->DeleteRow( nStartRow, nSize ))
216 if (pUndoOutline)
217 *pUndoOutline = true;
219 mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize);
220 mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize);
222 if (!maRowManualBreaks.empty())
224 // Erase all manual breaks between nStartRow and nStartRow + nSize - 1 (inclusive).
225 std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
226 std::set<SCROW>::iterator itr2 = maRowManualBreaks.upper_bound(static_cast<SCROW>(nStartRow + nSize - 1));
227 maRowManualBreaks.erase(itr1, itr2);
229 // Copy all breaks from the 1st element up to nStartRow to the new container.
230 itr1 = maRowManualBreaks.lower_bound(nStartRow);
231 ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
233 // Copy all breaks from nStartRow to the last element, but subtract each value by nSize.
234 itr2 = maRowManualBreaks.end();
235 for (; itr1 != itr2; ++itr1)
236 aNewBreaks.insert(static_cast<SCROW>(*itr1 - nSize));
238 maRowManualBreaks.swap(aNewBreaks);
242 { // scope for bulk broadcast
243 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
244 for (SCCOL j=nStartCol; j<=nEndCol; j++)
245 aCol[j].DeleteRow( nStartRow, nSize );
248 std::vector<SCCOL> aRegroupCols;
249 rRegroupCols.getColumns(nTab, aRegroupCols);
250 std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
252 InvalidatePageBreaks();
254 if (IsStreamValid())
255 // TODO: In the future we may want to check if the table has been
256 // really modified before setting the stream invalid.
257 SetStreamValid(false);
261 bool ScTable::TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) const
263 bool bTest = true;
265 if ( nStartRow==0 && nEndRow==MAXROW && pOutlineTable )
266 bTest = pOutlineTable->TestInsertCol(nSize);
268 if ( nSize > static_cast<SCSIZE>(MAXCOL) )
269 bTest = false;
271 for (SCCOL i=MAXCOL; (i+static_cast<SCCOL>(nSize)>MAXCOL) && bTest; i--)
272 bTest = aCol[i].TestInsertCol(nStartRow, nEndRow);
274 return bTest;
278 void ScTable::InsertCol(
279 const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize )
281 if (nStartRow==0 && nEndRow==MAXROW)
283 if (pColWidth && pColFlags)
285 memmove( &pColWidth[nStartCol+nSize], &pColWidth[nStartCol],
286 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
287 memmove( &pColFlags[nStartCol+nSize], &pColFlags[nStartCol],
288 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
290 if (pOutlineTable)
291 pOutlineTable->InsertCol( nStartCol, nSize );
293 mpHiddenCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
294 mpFilteredCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
296 if (!maColManualBreaks.empty())
298 std::set<SCCOL>::reverse_iterator rit = maColManualBreaks.rbegin();
299 while (rit != maColManualBreaks.rend())
301 SCCOL nCol = *rit;
302 if (nCol < nStartCol)
303 break; // while
304 else
306 maColManualBreaks.erase( (++rit).base());
307 maColManualBreaks.insert( static_cast<SCCOL>( nCol + nSize));
314 if ((nStartRow == 0) && (nEndRow == MAXROW))
316 for (SCSIZE i=0; i < nSize; i++)
317 for (SCCOL nCol = MAXCOL; nCol > nStartCol; nCol--)
318 aCol[nCol].SwapCol(aCol[nCol-1]);
320 else
322 for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
323 aCol[MAXCOL - nSize - i].MoveTo(nStartRow, nEndRow, aCol[MAXCOL - i]);
326 std::vector<SCCOL> aRegroupCols;
327 rRegroupCols.getColumns(nTab, aRegroupCols);
328 std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
330 if (nStartCol>0) // copy old attributes
332 sal_uInt16 nWhichArray[2];
333 nWhichArray[0] = ATTR_MERGE;
334 nWhichArray[1] = 0;
336 sc::CopyToDocContext aCxt(*pDocument);
337 for (SCSIZE i=0; i<nSize; i++)
339 aCol[nStartCol-1].CopyToColumn(aCxt, nStartRow, nEndRow, IDF_ATTRIB,
340 false, aCol[nStartCol+i] );
341 aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow,
342 SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
343 aCol[nStartCol+i].ClearItems( nStartRow, nEndRow, nWhichArray );
347 mpCondFormatList->InsertCol(nTab, nStartRow, nEndRow, nStartCol, nSize);
349 InvalidatePageBreaks();
351 if (IsStreamValid())
352 // TODO: In the future we may want to check if the table has been
353 // really modified before setting the stream invalid.
354 SetStreamValid(false);
357 void ScTable::DeleteCol(
358 const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize, bool* pUndoOutline )
360 if (nStartRow==0 && nEndRow==MAXROW)
362 if (pColWidth && pColFlags)
364 memmove( &pColWidth[nStartCol], &pColWidth[nStartCol+nSize],
365 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
366 memmove( &pColFlags[nStartCol], &pColFlags[nStartCol+nSize],
367 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
369 if (pOutlineTable)
370 if (pOutlineTable->DeleteCol( nStartCol, nSize ))
371 if (pUndoOutline)
372 *pUndoOutline = true;
374 SCCOL nRmSize = nStartCol + static_cast<SCCOL>(nSize);
375 mpHiddenCols->removeSegment(nStartCol, nRmSize);
376 mpFilteredCols->removeSegment(nStartCol, nRmSize);
378 if (!maColManualBreaks.empty())
380 std::set<SCCOL>::iterator it = maColManualBreaks.upper_bound( static_cast<SCCOL>( nStartCol + nSize - 1));
381 maColManualBreaks.erase( maColManualBreaks.lower_bound( nStartCol), it);
382 while (it != maColManualBreaks.end())
384 SCCOL nCol = *it;
385 maColManualBreaks.erase( it++);
386 maColManualBreaks.insert( static_cast<SCCOL>( nCol - nSize));
391 { // scope for bulk broadcast
392 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
393 for (SCSIZE i = 0; i < nSize; i++)
394 aCol[nStartCol + i].DeleteArea(nStartRow, nEndRow, IDF_ALL);
397 if ((nStartRow == 0) && (nEndRow == MAXROW))
399 for (SCSIZE i=0; i < nSize; i++)
400 for (SCCOL nCol = nStartCol; nCol < MAXCOL; nCol++)
401 aCol[nCol].SwapCol(aCol[nCol+1]);
403 else
405 for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
406 aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]);
409 std::vector<SCCOL> aRegroupCols;
410 rRegroupCols.getColumns(nTab, aRegroupCols);
411 std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
413 InvalidatePageBreaks();
415 if (IsStreamValid())
416 // TODO: In the future we may want to check if the table has been
417 // really modified before setting the stream invalid.
418 SetStreamValid(false);
422 void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nDelFlag)
424 if (nCol2 > MAXCOL) nCol2 = MAXCOL;
425 if (nRow2 > MAXROW) nRow2 = MAXROW;
426 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
428 { // scope for bulk broadcast
429 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
430 for (SCCOL i = nCol1; i <= nCol2; i++)
431 aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
435 // Zellschutz auf geschuetzter Tabelle nicht setzen
438 if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
440 ScPatternAttr aPattern(pDocument->GetPool());
441 aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
442 ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
445 if( nDelFlag & IDF_ATTRIB )
446 mpCondFormatList->DeleteArea( nCol1, nRow1, nCol2, nRow2 );
449 if (IsStreamValid())
450 // TODO: In the future we may want to check if the table has been
451 // really modified before setting the stream invalid.
452 SetStreamValid(false);
456 void ScTable::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
458 { // scope for bulk broadcast
459 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
460 for (SCCOL i=0; i<=MAXCOL; i++)
461 aCol[i].DeleteSelection( nDelFlag, rMark );
464 ScRangeList aRangeList;
465 rMark.FillRangeListWithMarks(&aRangeList, false);
467 for (size_t i = 0; i < aRangeList.size(); ++i)
469 ScRange* pRange = aRangeList[i];
471 if((nDelFlag & IDF_ATTRIB) && pRange && pRange->aStart.Tab() == nTab)
472 mpCondFormatList->DeleteArea( pRange->aStart.Col(), pRange->aStart.Row(), pRange->aEnd.Col(), pRange->aEnd.Row() );
476 // Zellschutz auf geschuetzter Tabelle nicht setzen
479 if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
481 ScDocumentPool* pPool = pDocument->GetPool();
482 SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END );
483 aSet.Put( ScProtectionAttr( false ) );
484 SfxItemPoolCache aCache( pPool, &aSet );
485 ApplySelectionCache( &aCache, rMark );
488 if (IsStreamValid())
489 // TODO: In the future we may want to check if the table has been
490 // really modified before setting the stream invalid.
491 SetStreamValid(false);
495 // pTable = Clipboard
496 void ScTable::CopyToClip(
497 sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
498 ScTable* pTable )
500 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
502 // copy content
503 //local range names need to be copied first for formula cells
504 if (!pTable->mpRangeName && mpRangeName)
505 pTable->mpRangeName = new ScRangeName(*mpRangeName);
507 SCCOL i;
509 for ( i = nCol1; i <= nCol2; i++)
510 aCol[i].CopyToClip(rCxt, nRow1, nRow2, pTable->aCol[i]); // notes are handled at column level
512 // copy widths/heights, and only "hidden", "filtered" and "manual" flags
513 // also for all preceding columns/rows, to have valid positions for drawing objects
515 if (pColWidth && pTable->pColWidth)
516 for (i=0; i<=nCol2; i++)
517 pTable->pColWidth[i] = pColWidth[i];
519 pTable->CopyColHidden(*this, 0, nCol2);
520 pTable->CopyColFiltered(*this, 0, nCol2);
521 if (pDBDataNoName)
522 pTable->SetAnonymousDBData(new ScDBData(*pDBDataNoName));
525 if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights)
527 pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CR_MANUALSIZE);
528 pTable->CopyRowHeight(*this, 0, nRow2, 0);
531 pTable->CopyRowHidden(*this, 0, nRow2);
532 pTable->CopyRowFiltered(*this, 0, nRow2);
534 // ggf. Formeln durch Werte ersetzen
536 if ( IsProtected() )
537 for (i = nCol1; i <= nCol2; i++)
538 pTable->aCol[i].RemoveProtected(nRow1, nRow2);
540 pTable->mpCondFormatList.reset(new ScConditionalFormatList(pTable->pDocument, *mpCondFormatList));
544 void ScTable::CopyToClip(
545 sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, ScTable* pTable )
547 ScRangeList aRanges(rRanges);
548 for ( size_t i = 0, nListSize = aRanges.size(); i < nListSize; ++i )
550 ScRange* p = aRanges[ i ];
551 CopyToClip(
552 rCxt, p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), pTable);
556 void ScTable::CopyStaticToDocument(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pDestTab)
558 if (nCol1 > nCol2)
559 return;
561 for (SCCOL i = nCol1; i <= nCol2; ++i)
563 ScColumn& rSrcCol = aCol[i];
564 ScColumn& rDestCol = pDestTab->aCol[i];
565 rSrcCol.CopyStaticToDocument(nRow1, nRow2, rDestCol);
569 void ScTable::CopyCellToDocument(SCCOL nSrcCol, SCROW nSrcRow, SCCOL nDestCol, SCROW nDestRow, ScTable& rDestTab )
571 if (!ValidColRow(nSrcCol, nSrcRow) || !ValidColRow(nDestCol, nDestRow))
572 return;
574 ScColumn& rSrcCol = aCol[nSrcCol];
575 ScColumn& rDestCol = rDestTab.aCol[nDestCol];
576 rSrcCol.CopyCellToDocument(nSrcRow, nDestRow, rDestCol);
579 void ScTable::CopyConditionalFormat( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
580 SCsCOL nDx, SCsROW nDy, ScTable* pTable)
582 ScRange aOldRange( nCol1 - nDx, nRow1 - nDy, pTable->nTab, nCol2 - nDx, nRow2 - nDy, pTable->nTab);
583 ScRange aNewRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
584 bool bSameDoc = pDocument == pTable->pDocument;
586 for(ScConditionalFormatList::const_iterator itr = pTable->mpCondFormatList->begin(),
587 itrEnd = pTable->mpCondFormatList->end(); itr != itrEnd; ++itr)
589 const ScRangeList& rCondFormatRange = itr->GetRange();
590 if(!rCondFormatRange.Intersects( aOldRange ))
591 continue;
593 ScRangeList aIntersectedRange = rCondFormatRange.GetIntersectedRange(aOldRange);
594 ScConditionalFormat* pNewFormat = itr->Clone(pDocument);
596 pNewFormat->AddRange(aIntersectedRange);
597 sc::RefUpdateContext aRefCxt(*pDocument);
598 aRefCxt.meMode = URM_COPY;
599 aRefCxt.maRange = aNewRange;
600 aRefCxt.mnColDelta = nDx;
601 aRefCxt.mnRowDelta = nDy;
602 aRefCxt.mnTabDelta = nTab - pTable->nTab;
603 pNewFormat->UpdateReference(aRefCxt, true);
605 sal_uLong nMax = 0;
606 for(ScConditionalFormatList::const_iterator itrCond = mpCondFormatList->begin();
607 itrCond != mpCondFormatList->end(); ++itrCond)
609 if(itrCond->GetKey() > nMax)
610 nMax = itrCond->GetKey();
612 pNewFormat->SetKey(nMax + 1);
613 mpCondFormatList->InsertNew(pNewFormat);
615 if(!bSameDoc)
617 for(size_t i = 0, n = pNewFormat->size();
618 i < n; ++i)
620 OUString aStyleName;
621 const ScFormatEntry* pEntry = pNewFormat->GetEntry(i);
622 if(pEntry->GetType() == condformat::CONDITION)
623 aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
624 else if(pEntry->GetType() == condformat::DATE)
625 aStyleName = static_cast<const ScCondDateFormatEntry*>(pEntry)->GetStyleName();
627 if(!aStyleName.isEmpty())
629 if(pDocument->GetStyleSheetPool()->Find(aStyleName, SFX_STYLE_FAMILY_PARA))
630 continue;
632 pDocument->GetStyleSheetPool()->CopyStyleFrom(
633 pTable->pDocument->GetStyleSheetPool(), aStyleName, SFX_STYLE_FAMILY_PARA );
638 pDocument->AddCondFormatData( pNewFormat->GetRange(), nTab, pNewFormat->GetKey() );
642 bool ScTable::InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol )
644 if (!ValidCol(nCol))
645 return false;
647 return aCol[nCol].InitBlockPosition(rBlockPos);
650 void ScTable::CopyFromClip(
651 sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
652 SCsCOL nDx, SCsROW nDy, ScTable* pTable )
655 if (nCol2 > MAXCOL)
656 nCol2 = MAXCOL;
657 if (nRow2 > MAXROW)
658 nRow2 = MAXROW;
660 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
662 for ( SCCOL i = nCol1; i <= nCol2; i++)
663 aCol[i].CopyFromClip(rCxt, nRow1, nRow2, nDy, pTable->aCol[i - nDx]); // notes are handles at column level
665 if (rCxt.getInsertFlag() & IDF_ATTRIB)
667 // make sure that there are no old references to the cond formats
668 sal_uInt16 nWhichArray[2];
669 nWhichArray[0] = ATTR_CONDITIONAL;
670 nWhichArray[1] = 0;
671 for ( SCCOL i = nCol1; i <= nCol2; ++i)
672 aCol[i].ClearItems(nRow1, nRow2, nWhichArray);
675 if ((rCxt.getInsertFlag() & IDF_ATTRIB) != 0)
677 if (nRow1==0 && nRow2==MAXROW && pColWidth && pTable->pColWidth)
678 for (SCCOL i=nCol1; i<=nCol2; i++)
679 pColWidth[i] = pTable->pColWidth[i-nDx];
681 if (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pTable->mpRowHeights &&
682 pRowFlags && pTable->pRowFlags)
684 CopyRowHeight(*pTable, nRow1, nRow2, -nDy);
685 // Must copy CR_MANUALSIZE bit too, otherwise pRowHeight doesn't make sense
686 for (SCROW j=nRow1; j<=nRow2; j++)
688 if ( pTable->pRowFlags->GetValue(j-nDy) & CR_MANUALSIZE )
689 pRowFlags->OrValue( j, CR_MANUALSIZE);
690 else
691 pRowFlags->AndValue( j, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
695 // Zellschutz auf geschuetzter Tabelle nicht setzen
696 if (IsProtected() && (rCxt.getInsertFlag() & IDF_ATTRIB))
698 ScPatternAttr aPattern(pDocument->GetPool());
699 aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
700 ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
703 // create deep copies for conditional formatting
704 CopyConditionalFormat( nCol1, nRow1, nCol2, nRow2, nDx, nDy, pTable);
710 void ScTable::MixData(
711 sc::MixDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
712 sal_uInt16 nFunction, bool bSkipEmpty, const ScTable* pSrcTab )
714 for (SCCOL i=nCol1; i<=nCol2; i++)
715 aCol[i].MixData(rCxt, nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
719 // Markierung von diesem Dokument
720 void ScTable::MixMarked(
721 sc::MixDocContext& rCxt, const ScMarkData& rMark, sal_uInt16 nFunction,
722 bool bSkipEmpty, const ScTable* pSrcTab )
724 for (SCCOL i=0; i<=MAXCOL; i++)
725 aCol[i].MixMarked(rCxt, rMark, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
728 namespace {
730 class TransClipHandler
732 ScTable& mrClipTab;
733 SCTAB mnSrcTab;
734 SCCOL mnSrcCol;
735 size_t mnTopRow;
736 SCROW mnTransRow;
737 bool mbAsLink;
738 bool mbWasCut;
740 ScAddress getDestPos(size_t nRow) const
742 return ScAddress(static_cast<SCCOL>(nRow-mnTopRow), mnTransRow, mrClipTab.GetTab());
745 ScFormulaCell* createRefCell(size_t nSrcRow, const ScAddress& rDestPos) const
747 ScAddress aSrcPos(mnSrcCol, nSrcRow, mnSrcTab);
748 ScSingleRefData aRef;
749 aRef.InitAddress(aSrcPos); // Absolute reference.
750 aRef.SetFlag3D(true);
752 ScTokenArray aArr;
753 aArr.AddSingleReference(aRef);
754 return new ScFormulaCell(&mrClipTab.GetDoc(), rDestPos, aArr);
757 void setLink(size_t nRow)
759 SCCOL nTransCol = nRow - mnTopRow;
760 mrClipTab.SetFormulaCell(
761 nTransCol, mnTransRow, createRefCell(nRow, getDestPos(nRow)));
764 public:
765 TransClipHandler(ScTable& rClipTab, SCTAB nSrcTab, SCCOL nSrcCol, size_t nTopRow, SCROW nTransRow, bool bAsLink, bool bWasCut) :
766 mrClipTab(rClipTab), mnSrcTab(nSrcTab), mnSrcCol(nSrcCol),
767 mnTopRow(nTopRow), mnTransRow(nTransRow), mbAsLink(bAsLink), mbWasCut(bWasCut) {}
769 void operator() (size_t nRow, double fVal)
771 if (mbAsLink)
773 setLink(nRow);
774 return;
777 SCCOL nTransCol = nRow - mnTopRow;
778 mrClipTab.SetValue(nTransCol, mnTransRow, fVal);
781 void operator() (size_t nRow, const svl::SharedString& rStr)
783 if (mbAsLink)
785 setLink(nRow);
786 return;
789 SCCOL nTransCol = nRow - mnTopRow;
790 mrClipTab.SetRawString(nTransCol, mnTransRow, rStr);
793 void operator() (size_t nRow, const EditTextObject* p)
795 if (mbAsLink)
797 setLink(nRow);
798 return;
801 SCCOL nTransCol = nRow - mnTopRow;
802 mrClipTab.SetEditText(nTransCol, mnTransRow, ScEditUtil::Clone(*p, mrClipTab.GetDoc()));
805 void operator() (size_t nRow, const ScFormulaCell* p)
807 if (mbAsLink)
809 setLink(nRow);
810 return;
813 ScFormulaCell* pNew = new ScFormulaCell(
814 *p, mrClipTab.GetDoc(), getDestPos(nRow), SC_CLONECELL_STARTLISTENING);
816 // Referenzen drehen
817 // bei Cut werden Referenzen spaeter per UpdateTranspose angepasst
819 if (!mbWasCut)
820 pNew->TransposeReference();
822 SCCOL nTransCol = nRow - mnTopRow;
823 mrClipTab.SetFormulaCell(nTransCol, mnTransRow, pNew);
829 void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
830 ScTable* pTransClip, sal_uInt16 nFlags, bool bAsLink )
832 bool bWasCut = pDocument->IsCutMode();
834 ScDocument* pDestDoc = pTransClip->pDocument;
836 for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
838 SCROW nRow;
839 if ( bAsLink && nFlags == IDF_ALL )
841 // with IDF_ALL, also create links (formulas) for empty cells
843 for ( nRow=nRow1; nRow<=nRow2; nRow++ )
845 // create simple formula, as in ScColumn::CreateRefCell
847 ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
848 ScSingleRefData aRef;
849 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
850 aRef.SetFlag3D(true);
851 ScTokenArray aArr;
852 aArr.AddSingleReference( aRef );
854 pTransClip->SetFormulaCell(
855 static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1),
856 new ScFormulaCell(pDestDoc, aDestPos, aArr));
859 else
861 TransClipHandler aFunc(*pTransClip, nTab, nCol, nRow1, static_cast<SCROW>(nCol-nCol1), bAsLink, bWasCut);
862 const sc::CellStoreType& rCells = aCol[nCol].maCells;
863 sc::ParseAllNonEmpty(rCells.begin(), rCells, nRow1, nRow2, aFunc);
866 // Attribute
868 SCROW nAttrRow1;
869 SCROW nAttrRow2;
870 const ScPatternAttr* pPattern;
871 boost::scoped_ptr<ScAttrIterator> pAttrIter(aCol[nCol].CreateAttrIterator( nRow1, nRow2 ));
872 while ( (pPattern = pAttrIter->Next( nAttrRow1, nAttrRow2 )) != 0 )
874 if ( !IsDefaultItem( pPattern ) )
876 const SfxItemSet& rSet = pPattern->GetItemSet();
877 if ( rSet.GetItemState( ATTR_MERGE, false ) == SFX_ITEM_DEFAULT &&
878 rSet.GetItemState( ATTR_MERGE_FLAG, false ) == SFX_ITEM_DEFAULT &&
879 rSet.GetItemState( ATTR_BORDER, false ) == SFX_ITEM_DEFAULT )
881 // no borders or merge items involved - use pattern as-is
882 for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
883 pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), *pPattern, true );
885 else
887 // transpose borders and merge values, remove merge flags (refreshed after pasting)
888 ScPatternAttr aNewPattern( *pPattern );
889 SfxItemSet& rNewSet = aNewPattern.GetItemSet();
891 const SvxBoxItem& rOldBox = (const SvxBoxItem&)rSet.Get(ATTR_BORDER);
892 if ( rOldBox.GetTop() || rOldBox.GetBottom() || rOldBox.GetLeft() || rOldBox.GetRight() )
894 SvxBoxItem aNew( ATTR_BORDER );
895 aNew.SetLine( rOldBox.GetLine( BOX_LINE_TOP ), BOX_LINE_LEFT );
896 aNew.SetLine( rOldBox.GetLine( BOX_LINE_LEFT ), BOX_LINE_TOP );
897 aNew.SetLine( rOldBox.GetLine( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
898 aNew.SetLine( rOldBox.GetLine( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
899 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_TOP ), BOX_LINE_LEFT );
900 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_LEFT ), BOX_LINE_TOP );
901 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
902 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
903 rNewSet.Put( aNew );
906 const ScMergeAttr& rOldMerge = (const ScMergeAttr&)rSet.Get(ATTR_MERGE);
907 if (rOldMerge.IsMerged())
908 rNewSet.Put( ScMergeAttr( std::min(
909 static_cast<SCsCOL>(rOldMerge.GetRowMerge()),
910 static_cast<SCsCOL>(MAXCOL+1 - (nAttrRow2-nRow1))),
911 std::min(
912 static_cast<SCsROW>(rOldMerge.GetColMerge()),
913 static_cast<SCsROW>(MAXROW+1 - (nCol-nCol1)))));
914 const ScMergeFlagAttr& rOldFlag = (const ScMergeFlagAttr&)rSet.Get(ATTR_MERGE_FLAG);
915 if (rOldFlag.IsOverlapped())
917 sal_Int16 nNewFlags = rOldFlag.GetValue() & ~( SC_MF_HOR | SC_MF_VER );
918 if ( nNewFlags )
919 rNewSet.Put( ScMergeFlagAttr( nNewFlags ) );
920 else
921 rNewSet.ClearItem( ATTR_MERGE_FLAG );
924 for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
925 pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1),
926 static_cast<SCROW>(nCol-nCol1), aNewPattern, true);
931 // Cell Notes - fdo#68381 paste cell notes on Transpose
932 if ( pDocument->HasColNotes(nCol, nTab) )
933 TransposeColNotes(pTransClip, nCol1, nCol, nRow1, nRow2);
937 void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, SCROW nRow2)
939 bool bCloneCaption = true;
941 sc::CellNoteStoreType::const_iterator itBlk = aCol[nCol].maCellNotes.begin(), itBlkEnd = aCol[nCol].maCellNotes.end();
943 // Locate the top row position.
944 size_t nOffsetInBlock = 0;
945 size_t nBlockStart = 0, nBlockEnd = 0, nRowPos = static_cast<size_t>(nRow1);
946 for (; itBlk != itBlkEnd; ++itBlk, nBlockStart = nBlockEnd)
948 nBlockEnd = nBlockStart + itBlk->size;
949 if (nBlockStart <= nRowPos && nRowPos < nBlockEnd)
951 // Found.
952 nOffsetInBlock = nRowPos - nBlockStart;
953 break;
957 if (itBlk != itBlkEnd)
958 // Specified range found
960 nRowPos = static_cast<size_t>(nRow2); // End row position.
962 // Keep processing until we hit the end row position.
963 sc::cellnote_block::const_iterator itData, itDataEnd;
964 for (; itBlk != itBlkEnd; ++itBlk, nBlockStart = nBlockEnd, nOffsetInBlock = 0)
966 nBlockEnd = nBlockStart + itBlk->size;
968 if (itBlk->data)
970 itData = sc::cellnote_block::begin(*itBlk->data);
971 std::advance(itData, nOffsetInBlock);
973 if (nBlockStart <= nRowPos && nRowPos < nBlockEnd)
975 // This block contains the end row. Only process partially.
976 size_t nOffsetEnd = nRowPos - nBlockStart + 1;
977 itDataEnd = sc::cellnote_block::begin(*itBlk->data);
978 std::advance(itDataEnd, nOffsetEnd);
979 size_t curRow = nBlockStart + nOffsetInBlock;
980 for (; itData != itDataEnd; ++itData, ++curRow)
982 ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
983 pTransClip->pDocument->ReleaseNote(aDestPos);
984 ScPostIt* pNote = *itData;
985 if (pNote)
987 ScPostIt* pClonedNote = pNote->Clone( ScAddress(nCol, curRow, nTab), *pTransClip->pDocument, aDestPos, bCloneCaption );
988 pTransClip->pDocument->SetNote(aDestPos, pClonedNote);
991 break; // we reached the last valid block
993 else
995 itDataEnd = sc::cellnote_block::end(*itBlk->data);
996 size_t curRow = nBlockStart + nOffsetInBlock;
997 for (; itData != itDataEnd; ++itData, ++curRow)
999 ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
1000 pTransClip->pDocument->ReleaseNote(aDestPos);
1001 ScPostIt* pNote = *itData;
1002 if (pNote)
1004 ScPostIt* pClonedNote = pNote->Clone( ScAddress(nCol, curRow, nTab), *pTransClip->pDocument, aDestPos, bCloneCaption );
1005 pTransClip->pDocument->SetNote(aDestPos, pClonedNote);
1010 else
1012 size_t curRow;
1013 for ( curRow = nBlockStart + nOffsetInBlock; curRow <= nBlockEnd && curRow <= nRowPos; ++curRow)
1015 ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
1016 pTransClip->pDocument->ReleaseNote(aDestPos);
1018 if (curRow == nRowPos)
1019 break;
1025 void ScTable::StartAllListeners()
1027 for (SCCOL i=0; i<=MAXCOL; i++)
1028 aCol[i].StartAllListeners();
1032 void ScTable::StartNeededListeners()
1034 for (SCCOL i=0; i<=MAXCOL; i++)
1035 aCol[i].StartNeededListeners();
1039 void ScTable::BroadcastInArea( SCCOL nCol1, SCROW nRow1,
1040 SCCOL nCol2, SCROW nRow2 )
1042 if (nCol2 > MAXCOL) nCol2 = MAXCOL;
1043 if (nRow2 > MAXROW) nRow2 = MAXROW;
1044 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1045 for (SCCOL i = nCol1; i <= nCol2; i++)
1046 aCol[i].SetDirty(nRow1, nRow2);
1050 void ScTable::StartListeningInArea(
1051 sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1053 if (nCol2 > MAXCOL) nCol2 = MAXCOL;
1054 if (nRow2 > MAXROW) nRow2 = MAXROW;
1055 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1056 for (SCCOL i = nCol1; i <= nCol2; i++)
1057 aCol[i].StartListeningInArea(rCxt, nRow1, nRow2);
1061 void ScTable::CopyToTable(
1062 sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1063 sal_uInt16 nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData,
1064 bool bAsLink, bool bColRowFlags )
1066 if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
1067 return;
1069 if (nFlags)
1070 for (SCCOL i = nCol1; i <= nCol2; i++)
1071 aCol[i].CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked,
1072 pDestTab->aCol[i], pMarkData, bAsLink);
1074 if (!bColRowFlags) // Spaltenbreiten/Zeilenhoehen/Flags
1075 return;
1077 if(pDestTab->pDocument->IsUndo() && (nFlags & IDF_ATTRIB))
1079 pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->pDocument, *mpCondFormatList));
1082 if (pDBDataNoName)
1084 ScDBData* pNewDBData = new ScDBData(*pDBDataNoName);
1085 SCCOL aCol1, aCol2;
1086 SCROW aRow1, aRow2;
1087 SCTAB aTab;
1088 pNewDBData->GetArea(aTab, aCol1, aRow1, aCol2, aRow2);
1089 pNewDBData->MoveTo(pDestTab->nTab, aCol1, aRow1, aCol2, aRow2);
1090 pDestTab->SetAnonymousDBData(pNewDBData);
1092 // Charts muessen beim Ein-/Ausblenden angepasst werden
1093 ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection();
1095 bool bFlagChange = false;
1097 bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
1098 bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
1100 if (bWidth || bHeight)
1102 if (bWidth)
1104 for (SCCOL i = nCol1; i <= nCol2; ++i)
1106 bool bThisHidden = ColHidden(i);
1107 bool bHiddenChange = (pDestTab->ColHidden(i) != bThisHidden);
1108 bool bChange = bHiddenChange || (pDestTab->pColWidth[i] != pColWidth[i]);
1109 pDestTab->pColWidth[i] = pColWidth[i];
1110 pDestTab->pColFlags[i] = pColFlags[i];
1111 pDestTab->SetColHidden(i, i, bThisHidden);
1112 //! Aenderungen zusammenfassen?
1113 if (bHiddenChange && pCharts)
1114 pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab ));
1116 if (bChange)
1117 bFlagChange = true;
1119 pDestTab->SetColManualBreaks( maColManualBreaks);
1122 if (bHeight)
1124 bool bChange = pDestTab->GetRowHeight(nRow1, nRow2) != GetRowHeight(nRow1, nRow2);
1126 if (bChange)
1127 bFlagChange = true;
1129 pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
1130 pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2);
1132 // Hidden flags.
1133 for (SCROW i = nRow1; i <= nRow2; ++i)
1135 SCROW nLastRow;
1136 bool bHidden = RowHidden(i, NULL, &nLastRow);
1137 if (nLastRow >= nRow2)
1138 // the last row shouldn't exceed the upper bound the caller specified.
1139 nLastRow = nRow2;
1141 bool bHiddenChanged = pDestTab->SetRowHidden(i, nLastRow, bHidden);
1142 if (bHiddenChanged && pCharts)
1143 // Hidden flags differ.
1144 pCharts->SetRangeDirty(ScRange(0, i, nTab, MAXCOL, nLastRow, nTab));
1146 if (bHiddenChanged)
1147 bFlagChange = true;
1149 // Jump to the last row of the identical flag segment.
1150 i = nLastRow;
1153 // Filtered flags.
1154 for (SCROW i = nRow1; i <= nRow2; ++i)
1156 SCROW nLastRow;
1157 bool bFiltered = RowFiltered(i, NULL, &nLastRow);
1158 if (nLastRow >= nRow2)
1159 // the last row shouldn't exceed the upper bound the caller specified.
1160 nLastRow = nRow2;
1161 pDestTab->SetRowFiltered(i, nLastRow, bFiltered);
1162 i = nLastRow;
1164 pDestTab->SetRowManualBreaks( maRowManualBreaks);
1168 if (bFlagChange)
1169 pDestTab->InvalidatePageBreaks();
1171 if(nFlags & IDF_ATTRIB)
1173 pDestTab->mpCondFormatList->DeleteArea(nCol1, nRow1, nCol2, nRow2);
1174 pDestTab->CopyConditionalFormat(nCol1, nRow1, nCol2, nRow2, 0, 0, this);
1177 if(nFlags & IDF_OUTLINE) // also only when bColRowFlags
1178 pDestTab->SetOutlineTable( pOutlineTable );
1182 void ScTable::UndoToTable(
1183 sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1184 sal_uInt16 nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData )
1186 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1188 bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
1189 bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
1191 for ( SCCOL i = 0; i <= MAXCOL; i++)
1193 if ( i >= nCol1 && i <= nCol2 )
1194 aCol[i].UndoToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, pDestTab->aCol[i], pMarkData);
1195 else
1196 aCol[i].CopyToColumn(rCxt, 0, MAXROW, IDF_FORMULA, false, pDestTab->aCol[i]);
1199 if (nFlags & IDF_ATTRIB)
1200 pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->pDocument, *mpCondFormatList));
1203 if (bWidth||bHeight)
1205 if (bWidth)
1207 for (SCCOL i=nCol1; i<=nCol2; i++)
1208 pDestTab->pColWidth[i] = pColWidth[i];
1209 pDestTab->SetColManualBreaks( maColManualBreaks);
1211 if (bHeight)
1213 pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
1214 pDestTab->SetRowManualBreaks( maRowManualBreaks);
1221 void ScTable::CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const
1223 for (SCCOL i=0; i<=MAXCOL; i++)
1224 aCol[i].CopyUpdated( pPosTab->aCol[i], pDestTab->aCol[i] );
1227 void ScTable::InvalidateTableArea()
1229 bTableAreaValid = false;
1232 void ScTable::InvalidatePageBreaks()
1234 mbPageBreaksValid = false;
1237 void ScTable::CopyScenarioTo( ScTable* pDestTab ) const
1239 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1241 for (SCCOL i=0; i<=MAXCOL; i++)
1242 aCol[i].CopyScenarioTo( pDestTab->aCol[i] );
1245 void ScTable::CopyScenarioFrom( const ScTable* pSrcTab )
1247 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1249 for (SCCOL i=0; i<=MAXCOL; i++)
1250 aCol[i].CopyScenarioFrom( pSrcTab->aCol[i] );
1253 void ScTable::MarkScenarioIn( ScMarkData& rDestMark, sal_uInt16 nNeededBits ) const
1255 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1257 if ( ( nScenarioFlags & nNeededBits ) != nNeededBits ) // alle Bits gesetzt?
1258 return;
1260 for (SCCOL i=0; i<=MAXCOL; i++)
1261 aCol[i].MarkScenarioIn( rDestMark );
1264 bool ScTable::HasScenarioRange( const ScRange& rRange ) const
1266 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1268 ScRange aTabRange = rRange;
1269 aTabRange.aStart.SetTab( nTab );
1270 aTabRange.aEnd.SetTab( nTab );
1272 const ScRangeList* pList = GetScenarioRanges();
1274 if (pList)
1276 for ( size_t j = 0, n = pList->size(); j < n; j++ )
1278 const ScRange* pR = (*pList)[j];
1279 if ( pR->Intersects( aTabRange ) )
1280 return true;
1284 return false;
1287 void ScTable::InvalidateScenarioRanges()
1289 delete pScenarioRanges;
1290 pScenarioRanges = NULL;
1293 const ScRangeList* ScTable::GetScenarioRanges() const
1295 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1297 if (!pScenarioRanges)
1299 ((ScTable*)this)->pScenarioRanges = new ScRangeList;
1300 ScMarkData aMark;
1301 MarkScenarioIn( aMark, 0 ); // immer
1302 aMark.FillRangeListWithMarks( pScenarioRanges, false );
1304 return pScenarioRanges;
1307 bool ScTable::TestCopyScenarioTo( const ScTable* pDestTab ) const
1309 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1311 if (!pDestTab->IsProtected())
1312 return true;
1314 bool bOk = true;
1315 for (SCCOL i=0; i<=MAXCOL && bOk; i++)
1316 bOk = aCol[i].TestCopyScenarioTo( pDestTab->aCol[i] );
1317 return bOk;
1320 bool ScTable::SetString( SCCOL nCol, SCROW nRow, SCTAB nTabP, const OUString& rString,
1321 ScSetStringParam* pParam )
1323 if (ValidColRow(nCol,nRow))
1324 return aCol[nCol].SetString(
1325 nRow, nTabP, rString, pDocument->GetAddressConvention(), pParam );
1326 else
1327 return false;
1330 void ScTable::SetEditText( SCCOL nCol, SCROW nRow, EditTextObject* pEditText )
1332 if (!ValidColRow(nCol, nRow))
1334 delete pEditText;
1335 return;
1338 aCol[nCol].SetEditText(nRow, pEditText);
1341 void ScTable::SetEditText( SCCOL nCol, SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
1343 if (!ValidColRow(nCol, nRow))
1344 return;
1346 aCol[nCol].SetEditText(nRow, rEditText, pEditPool);
1349 void ScTable::SetEmptyCell( SCCOL nCol, SCROW nRow )
1351 if (!ValidColRow(nCol, nRow))
1352 return;
1354 aCol[nCol].Delete(nRow);
1357 void ScTable::SetFormula(
1358 SCCOL nCol, SCROW nRow, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram )
1360 if (!ValidColRow(nCol, nRow))
1361 return;
1363 aCol[nCol].SetFormula(nRow, rArray, eGram);
1366 void ScTable::SetFormula(
1367 SCCOL nCol, SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram )
1369 if (!ValidColRow(nCol, nRow))
1370 return;
1372 aCol[nCol].SetFormula(nRow, rFormula, eGram);
1375 ScFormulaCell* ScTable::SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell )
1377 if (!ValidColRow(nCol, nRow))
1379 delete pCell;
1380 return NULL;
1383 return aCol[nCol].SetFormulaCell(nRow, pCell);
1386 svl::SharedString ScTable::GetSharedString( SCCOL nCol, SCROW nRow ) const
1388 if (!ValidColRow(nCol, nRow))
1389 return svl::SharedString();
1391 return aCol[nCol].GetSharedString(nRow);
1394 void ScTable::SetValue( SCCOL nCol, SCROW nRow, const double& rVal )
1396 if (ValidColRow(nCol, nRow))
1397 aCol[nCol].SetValue( nRow, rVal );
1400 void ScTable::SetRawString( SCCOL nCol, SCROW nRow, const OUString& rStr )
1402 if (ValidColRow(nCol, nRow))
1403 aCol[nCol].SetRawString(nRow, rStr);
1406 void ScTable::SetRawString( SCCOL nCol, SCROW nRow, const svl::SharedString& rStr )
1408 if (ValidColRow(nCol, nRow))
1409 aCol[nCol].SetRawString(nRow, rStr);
1412 void ScTable::GetString( SCCOL nCol, SCROW nRow, OUString& rString ) const
1414 if (ValidColRow(nCol,nRow))
1415 aCol[nCol].GetString( nRow, rString );
1416 else
1417 rString = OUString();
1420 double* ScTable::GetValueCell( SCCOL nCol, SCROW nRow )
1422 if (!ValidColRow(nCol,nRow))
1423 return NULL;
1425 return aCol[nCol].GetValueCell(nRow);
1428 void ScTable::GetInputString( SCCOL nCol, SCROW nRow, OUString& rString ) const
1430 if (ValidColRow(nCol,nRow))
1431 aCol[nCol].GetInputString( nRow, rString );
1432 else
1433 rString = OUString();
1437 double ScTable::GetValue( SCCOL nCol, SCROW nRow ) const
1439 if (ValidColRow( nCol, nRow ))
1440 return aCol[nCol].GetValue( nRow );
1441 return 0.0;
1444 const EditTextObject* ScTable::GetEditText( SCCOL nCol, SCROW nRow ) const
1446 if (!ValidColRow(nCol, nRow))
1447 return NULL;
1449 return aCol[nCol].GetEditText(nRow);
1452 void ScTable::RemoveEditTextCharAttribs( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
1454 if (!ValidColRow(nCol, nRow))
1455 return;
1457 return aCol[nCol].RemoveEditTextCharAttribs(nRow, rAttr);
1460 void ScTable::GetFormula( SCCOL nCol, SCROW nRow, OUString& rFormula ) const
1462 if (ValidColRow(nCol,nRow))
1463 aCol[nCol].GetFormula( nRow, rFormula );
1464 else
1465 rFormula = OUString();
1468 const ScTokenArray* ScTable::GetFormulaTokens( SCCOL nCol, SCROW nRow ) const
1470 if (!ValidColRow(nCol, nRow))
1471 return NULL;
1473 return aCol[nCol].GetFormulaTokens(nRow);
1476 const ScFormulaCell* ScTable::GetFormulaCell( SCCOL nCol, SCROW nRow ) const
1478 if (!ValidColRow(nCol, nRow))
1479 return NULL;
1481 return aCol[nCol].GetFormulaCell(nRow);
1484 ScFormulaCell* ScTable::GetFormulaCell( SCCOL nCol, SCROW nRow )
1486 if (!ValidColRow(nCol, nRow))
1487 return NULL;
1489 return aCol[nCol].GetFormulaCell(nRow);
1492 ScPostIt* ScTable::GetNote(const SCCOL nCol, const SCROW nRow)
1494 return pDocument->GetNote(nCol, nRow, nTab);
1497 size_t ScTable::GetNoteCount( SCCOL nCol ) const
1499 if (!ValidCol(nCol))
1500 return 0;
1502 return aCol[nCol].GetNoteCount();
1505 SCROW ScTable::GetNotePosition( SCCOL nCol, size_t nIndex ) const
1507 if (!ValidCol(nCol))
1508 return -1;
1510 return aCol[nCol].GetNotePosition(nIndex);
1513 void ScTable::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const
1515 for (SCCOL nCol = 0; nCol < MAXCOLCOUNT; ++nCol)
1516 aCol[nCol].GetAllNoteEntries(rNotes);
1519 void ScTable::GetNotesInRange( const ScRange& rRange, std::vector<sc::NoteEntry>& rNotes ) const
1521 SCROW nStartRow = rRange.aStart.Row();
1522 SCROW nEndRow = rRange.aEnd.Row();
1523 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1525 aCol[nCol].GetNotesInRange(nStartRow, nEndRow, rNotes);
1529 bool ScTable::ContainsNotesInRange( const ScRange& rRange ) const
1531 SCROW nStartRow = rRange.aStart.Row();
1532 SCROW nEndRow = rRange.aEnd.Row();
1533 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1535 bool bContainsNote = !aCol[nCol].IsNotesEmptyBlock(nStartRow, nEndRow);
1536 if(bContainsNote)
1537 return true;
1540 return false;
1543 CellType ScTable::GetCellType( SCCOL nCol, SCROW nRow ) const
1545 if (ValidColRow( nCol, nRow ))
1546 return aCol[nCol].GetCellType( nRow );
1547 return CELLTYPE_NONE;
1550 ScRefCellValue ScTable::GetCellValue( SCCOL nCol, SCROW nRow ) const
1552 if (!ValidColRow(nCol, nRow))
1553 return ScRefCellValue();
1555 return aCol[nCol].GetCellValue(nRow);
1558 void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const
1560 rCol = 0;
1561 rRow = MAXROW+1;
1562 while (aCol[rCol].IsEmptyData() && rCol < MAXCOL)
1563 ++rCol;
1564 SCCOL nCol = rCol;
1565 while (nCol <= MAXCOL && rRow > 0)
1567 if (!aCol[nCol].IsEmptyData())
1568 rRow = ::std::min( rRow, aCol[nCol].GetFirstDataPos());
1569 ++nCol;
1573 void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
1575 rCol = MAXCOL;
1576 rRow = 0;
1577 while (aCol[rCol].IsEmptyData() && (rCol > 0))
1578 rCol--;
1579 SCCOL nCol = rCol;
1580 while (nCol >= 0 && rRow < MAXROW)
1581 rRow = ::std::max( rRow, aCol[nCol--].GetLastDataPos());
1585 bool ScTable::HasData( SCCOL nCol, SCROW nRow ) const
1587 if (ValidColRow(nCol,nRow))
1588 return aCol[nCol].HasDataAt( nRow );
1589 else
1590 return false;
1594 bool ScTable::HasStringData( SCCOL nCol, SCROW nRow ) const
1596 if (ValidColRow(nCol,nRow))
1597 return aCol[nCol].HasStringData( nRow );
1598 else
1599 return false;
1603 bool ScTable::HasValueData( SCCOL nCol, SCROW nRow ) const
1605 if (ValidColRow(nCol,nRow))
1606 return aCol[nCol].HasValueData( nRow );
1607 else
1608 return false;
1612 bool ScTable::HasStringCells( SCCOL nStartCol, SCROW nStartRow,
1613 SCCOL nEndCol, SCROW nEndRow ) const
1615 if ( ValidCol(nEndCol) )
1616 for ( SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++ )
1617 if (aCol[nCol].HasStringCells(nStartRow, nEndRow))
1618 return true;
1620 return false;
1624 void ScTable::SetDirtyVar()
1626 for (SCCOL i=0; i<=MAXCOL; i++)
1627 aCol[i].SetDirtyVar();
1631 void ScTable::SetDirty()
1633 bool bOldAutoCalc = pDocument->GetAutoCalc();
1634 pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1635 for (SCCOL i=0; i<=MAXCOL; i++)
1636 aCol[i].SetDirty();
1637 pDocument->SetAutoCalc( bOldAutoCalc );
1641 void ScTable::SetDirty( const ScRange& rRange )
1643 bool bOldAutoCalc = pDocument->GetAutoCalc();
1644 pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1645 SCCOL nCol2 = rRange.aEnd.Col();
1646 for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
1647 aCol[i].SetDirty(rRange.aStart.Row(), rRange.aEnd.Row());
1648 pDocument->SetAutoCalc( bOldAutoCalc );
1652 void ScTable::SetTableOpDirty( const ScRange& rRange )
1654 bool bOldAutoCalc = pDocument->GetAutoCalc();
1655 pDocument->SetAutoCalc( false ); // no multiple recalculation
1656 SCCOL nCol2 = rRange.aEnd.Col();
1657 for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
1658 aCol[i].SetTableOpDirty( rRange );
1659 pDocument->SetAutoCalc( bOldAutoCalc );
1663 void ScTable::SetDirtyAfterLoad()
1665 bool bOldAutoCalc = pDocument->GetAutoCalc();
1666 pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1667 for (SCCOL i=0; i<=MAXCOL; i++)
1668 aCol[i].SetDirtyAfterLoad();
1669 pDocument->SetAutoCalc( bOldAutoCalc );
1673 void ScTable::SetDirtyIfPostponed()
1675 bool bOldAutoCalc = pDocument->GetAutoCalc();
1676 pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1677 for (SCCOL i=0; i<=MAXCOL; i++)
1678 aCol[i].SetDirtyIfPostponed();
1679 pDocument->SetAutoCalc( bOldAutoCalc );
1682 void ScTable::BroadcastRecalcOnRefMove()
1684 sc::AutoCalcSwitch aSwitch(*pDocument, false);
1685 for (SCCOL i = 0; i <= MAXCOL; ++i)
1686 aCol[i].BroadcastRecalcOnRefMove();
1689 void ScTable::SetLoadingMedium(bool bLoading)
1691 mpRowHeights->enableTreeSearch(!bLoading);
1695 void ScTable::CalcAll()
1697 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CalcAll();
1701 void ScTable::CompileAll()
1703 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CompileAll();
1705 if(mpCondFormatList)
1706 mpCondFormatList->CompileAll();
1710 void ScTable::CompileXML( ScProgress& rProgress )
1712 if (mpRangeName)
1713 mpRangeName->CompileUnresolvedXML();
1715 for (SCCOL i=0; i <= MAXCOL; i++)
1717 aCol[i].CompileXML( rProgress );
1720 if(mpCondFormatList)
1721 mpCondFormatList->CompileXML();
1724 bool ScTable::CompileErrorCells(sal_uInt16 nErrCode)
1726 bool bCompiled = false;
1727 for (SCCOL i = 0; i <= MAXCOL; ++i)
1729 if (aCol[i].CompileErrorCells(nErrCode))
1730 bCompiled = true;
1733 return bCompiled;
1736 void ScTable::CalcAfterLoad()
1738 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad();
1741 bool ScTable::IsEmptyData( SCCOL nCol ) const
1743 if (!ValidCol(nCol))
1744 return true;
1746 return aCol[nCol].IsEmptyData();
1749 void ScTable::ResetChanged( const ScRange& rRange )
1751 SCCOL nStartCol = rRange.aStart.Col();
1752 SCROW nStartRow = rRange.aStart.Row();
1753 SCCOL nEndCol = rRange.aEnd.Col();
1754 SCROW nEndRow = rRange.aEnd.Row();
1756 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
1757 aCol[nCol].ResetChanged(nStartRow, nEndRow);
1760 // Attribute
1762 const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) const
1764 if (ValidColRow(nCol,nRow))
1765 return aCol[nCol].GetAttr( nRow, nWhich );
1766 else
1767 return NULL;
1770 sal_uInt32 ScTable::GetNumberFormat( const ScAddress& rPos ) const
1772 return ValidColRow(rPos.Col(),rPos.Row()) ?
1773 aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) :
1777 sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nRow ) const
1779 if (ValidColRow(nCol,nRow))
1780 return aCol[nCol].GetNumberFormat( nRow );
1781 else
1782 return 0;
1785 sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
1787 if (!ValidCol(nCol) || !ValidRow(nStartRow) || !ValidRow(nEndRow))
1788 return 0;
1790 return aCol[nCol].GetNumberFormat(nStartRow, nEndRow);
1793 void ScTable::SetNumberFormat( SCCOL nCol, SCROW nRow, sal_uInt32 nNumberFormat )
1795 if (!ValidColRow(nCol, nRow))
1796 return;
1798 aCol[nCol].SetNumberFormat(nRow, nNumberFormat);
1801 const ScPatternAttr* ScTable::GetPattern( SCCOL nCol, SCROW nRow ) const
1803 if (ValidColRow(nCol,nRow))
1804 return aCol[nCol].GetPattern( nRow );
1805 else
1807 OSL_FAIL("wrong column or row");
1808 return pDocument->GetDefPattern(); // for safety
1813 const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
1815 if ( ValidColRow( nCol, nStartRow ) && ValidRow( nEndRow ) && (nStartRow <= nEndRow) )
1816 return aCol[nCol].GetMostUsedPattern( nStartRow, nEndRow );
1817 else
1818 return NULL;
1822 bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nMask ) const
1824 bool bFound = false;
1825 for (SCCOL i=nCol1; i<=nCol2 && !bFound; i++)
1826 bFound |= aCol[i].HasAttrib( nRow1, nRow2, nMask );
1827 return bFound;
1831 bool ScTable::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
1833 bool bFound = false;
1834 for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
1835 bFound |= aCol[i].HasAttribSelection( rMark, nMask );
1836 return bFound;
1840 bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
1841 SCCOL& rEndCol, SCROW& rEndRow,
1842 bool bRefresh )
1844 if (!(ValidCol(nStartCol) && ValidCol(rEndCol)))
1846 OSL_FAIL("ScTable::ExtendMerge: invalid column number");
1847 return false;
1849 bool bFound = false;
1850 SCCOL nOldEndX = rEndCol;
1851 SCROW nOldEndY = rEndRow;
1852 for (SCCOL i=nStartCol; i<=nOldEndX; i++)
1853 bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh );
1854 return bFound;
1858 bool ScTable::IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bIgnoreNotes ) const
1860 if (!(ValidCol(nCol1) && ValidCol(nCol2)))
1862 OSL_FAIL("ScTable::IsBlockEmpty: invalid column number");
1863 return false;
1865 bool bEmpty = true;
1866 for (SCCOL i=nCol1; i<=nCol2 && bEmpty; i++)
1868 bEmpty = aCol[i].IsEmptyBlock( nRow1, nRow2 );
1869 if (!bIgnoreNotes && bEmpty)
1871 bEmpty = aCol[i].IsNotesEmptyBlock(nRow1, nRow2);
1874 return bEmpty;
1877 SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2,
1878 SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY,
1879 const ScPatternAttr* pPattern, const SfxItemSet* pCondSet )
1881 // Rueckgabe = neues nArrY
1883 sal_uInt8 nRotDir = pPattern->GetRotateDir( pCondSet );
1884 if ( nRotDir != SC_ROTDIR_NONE )
1886 bool bHit = true;
1887 if ( nCol+1 < nX1 ) // column to the left
1888 bHit = ( nRotDir != SC_ROTDIR_LEFT );
1889 else if ( nCol > nX2+1 ) // column to the right
1890 bHit = ( nRotDir != SC_ROTDIR_RIGHT ); // SC_ROTDIR_STANDARD may now also be extended to the left
1892 if ( bHit )
1894 double nFactor = 0.0;
1895 if ( nCol > nX2+1 )
1897 long nRotVal = ((const SfxInt32Item&) pPattern->
1898 GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue();
1899 double nRealOrient = nRotVal * F_PI18000; // 1/100 Grad
1900 double nCos = cos( nRealOrient );
1901 double nSin = sin( nRealOrient );
1902 //! begrenzen !!!
1903 //! zusaetzlich Faktor fuer unterschiedliche PPT X/Y !!!
1905 // bei SC_ROTDIR_LEFT kommt immer ein negativer Wert heraus,
1906 // wenn der Modus beruecksichtigt wird
1907 nFactor = -fabs( nCos / nSin );
1910 for ( SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ )
1912 if (!RowHidden(nRow))
1914 bool bHitOne = true;
1915 if ( nCol > nX2+1 )
1917 // reicht die gedrehte Zelle bis in den sichtbaren Bereich?
1919 SCCOL nTouchedCol = nCol;
1920 long nWidth = static_cast<long>(mpRowHeights->getValue(nRow) * nFactor);
1921 OSL_ENSURE(nWidth <= 0, "Wrong direction");
1922 while ( nWidth < 0 && nTouchedCol > 0 )
1924 --nTouchedCol;
1925 nWidth += GetColWidth( nTouchedCol );
1927 if ( nTouchedCol > nX2 )
1928 bHitOne = false;
1931 if (bHitOne)
1933 while ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo < nRow )
1934 ++nArrY;
1935 if ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo == nRow )
1936 pRowInfo[nArrY].nRotMaxCol = nCol;
1943 return nArrY;
1946 void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 )
1948 if ( !pColWidth || !mpRowHeights || !pColFlags || !pRowFlags )
1950 OSL_FAIL( "Row/column info missing" );
1951 return;
1954 // nRotMaxCol ist auf SC_ROTMAX_NONE initialisiert, nRowNo ist schon gesetzt
1956 SCROW nY1 = pRowInfo[0].nRowNo;
1957 SCROW nY2 = pRowInfo[nArrCount-1].nRowNo;
1959 for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
1961 if (!ColHidden(nCol))
1963 SCSIZE nArrY = 0;
1964 ScDocAttrIterator aIter( pDocument, nTab, nCol, nY1, nCol, nY2 );
1965 SCCOL nAttrCol;
1966 SCROW nAttrRow1, nAttrRow2;
1967 const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
1968 while ( pPattern )
1970 const SfxPoolItem* pCondItem;
1971 if ( pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, true, &pCondItem )
1972 == SFX_ITEM_SET )
1974 // alle Formate durchgehen, damit die Zellen nicht einzeln
1975 // angeschaut werden muessen
1977 const std::vector<sal_uInt32>& rCondFormatData = static_cast<const ScCondFormatItem*>(pCondItem)->GetCondFormatData();
1978 ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool();
1979 if (mpCondFormatList && pStylePool && !rCondFormatData.empty())
1981 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatData.begin(), itrEnd = rCondFormatData.end();
1982 itr != itrEnd; ++itr)
1984 const ScConditionalFormat* pFormat = mpCondFormatList->GetFormat(*itr);
1985 if ( pFormat )
1987 size_t nEntryCount = pFormat->size();
1988 for (size_t nEntry=0; nEntry<nEntryCount; nEntry++)
1990 const ScFormatEntry* pEntry = pFormat->GetEntry(nEntry);
1991 if(pEntry->GetType() != condformat::CONDITION)
1992 continue;
1994 OUString aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
1995 if (!aStyleName.isEmpty())
1997 SfxStyleSheetBase* pStyleSheet =
1998 pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
1999 if ( pStyleSheet )
2001 FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2002 nCol, nAttrRow1, nAttrRow2,
2003 nArrY, pPattern, &pStyleSheet->GetItemSet() );
2004 // nArrY nicht veraendern
2013 nArrY = FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2014 nCol, nAttrRow1, nAttrRow2,
2015 nArrY, pPattern, NULL );
2017 pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
2023 bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
2025 using namespace sc;
2027 sal_uInt16 nEdges = 0;
2029 if ( nCol1 == nCol2 )
2030 { // linke und rechte Spalte
2031 const sal_uInt16 n = MatrixEdgeLeft | MatrixEdgeRight;
2032 nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n );
2033 // nicht (4 und 16) oder 1 oder 32
2034 if (nEdges && (((nEdges & n) != n) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
2035 return true; // linke oder rechte Kante fehlt oder offen
2037 else
2038 { // linke Spalte
2039 nEdges = aCol[nCol1].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdgeLeft);
2040 // nicht 4 oder 1 oder 32
2041 if (nEdges && (((nEdges & MatrixEdgeLeft) != MatrixEdgeLeft) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
2042 return true; // linke Kante fehlt oder offen
2043 // rechte Spalte
2044 nEdges = aCol[nCol2].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdgeRight);
2045 // nicht 16 oder 1 oder 32
2046 if (nEdges && (((nEdges & MatrixEdgeRight) != MatrixEdgeRight) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
2047 return true; // rechte Kante fehlt oder offen
2050 if ( nRow1 == nRow2 )
2051 { // obere und untere Zeile
2052 bool bOpen = false;
2053 const sal_uInt16 n = MatrixEdgeBottom | MatrixEdgeTop;
2054 for ( SCCOL i=nCol1; i<=nCol2; i++)
2056 nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n );
2057 if ( nEdges )
2059 if ( (nEdges & n) != n )
2060 return true; // obere oder untere Kante fehlt
2061 if (nEdges & MatrixEdgeLeft)
2062 bOpen = true; // linke Kante oeffnet, weitersehen
2063 else if ( !bOpen )
2064 return true; // es gibt was, was nicht geoeffnet wurde
2065 if (nEdges & MatrixEdgeRight)
2066 bOpen = false; // rechte Kante schliesst
2069 if ( bOpen )
2070 return true; // es geht noch weiter
2072 else
2074 sal_uInt16 j, n;
2075 SCROW nR;
2076 // erst obere Zeile, dann untere Zeile
2077 for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 )
2079 bool bOpen = false;
2080 for ( SCCOL i=nCol1; i<=nCol2; i++)
2082 nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n );
2083 if ( nEdges )
2085 // in oberere Zeile keine obere Kante bzw.
2086 // in unterer Zeile keine untere Kante
2087 if ( (nEdges & n) != n )
2088 return true;
2089 if (nEdges & MatrixEdgeLeft)
2090 bOpen = true; // linke Kante oeffnet, weitersehen
2091 else if ( !bOpen )
2092 return true; // es gibt was, was nicht geoeffnet wurde
2093 if (nEdges & MatrixEdgeRight)
2094 bOpen = false; // rechte Kante schliesst
2097 if ( bOpen )
2098 return true; // es geht noch weiter
2101 return false;
2105 bool ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const
2107 bool bFound = false;
2108 for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
2109 bFound |= aCol[i].HasSelectionMatrixFragment(rMark);
2110 return bFound;
2114 bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
2115 SCROW nRow2, bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
2117 if ( !ValidColRow( nCol2, nRow2 ) )
2119 OSL_FAIL("IsBlockEditable: invalid column or row");
2120 if (pOnlyNotBecauseOfMatrix)
2121 *pOnlyNotBecauseOfMatrix = false;
2122 return false;
2125 bool bIsEditable = true;
2126 if ( nLockCount )
2127 bIsEditable = false;
2128 else if ( IsProtected() && !pDocument->IsScenario(nTab) )
2130 bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED );
2131 if(bIsEditable)
2133 // If Sheet is protected and cells are not protected then
2134 // check the active scenario protect flag if this range is
2135 // on the active scenario range. Note the 'copy back' must also
2136 // be set to apply protection.
2137 sal_uInt16 nScenTab = nTab+1;
2138 while(pDocument->IsScenario(nScenTab))
2140 ScRange aEditRange(nCol1, nRow1, nScenTab, nCol2, nRow2, nScenTab);
2141 if(pDocument->IsActiveScenario(nScenTab) && pDocument->HasScenarioRange(nScenTab, aEditRange))
2143 sal_uInt16 nFlags;
2144 pDocument->GetScenarioFlags(nScenTab,nFlags);
2145 bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
2146 break;
2148 nScenTab++;
2152 else if (pDocument->IsScenario(nTab))
2154 // Determine if the preceding sheet is protected
2155 SCTAB nActualTab = nTab;
2158 nActualTab--;
2160 while(pDocument->IsScenario(nActualTab));
2162 if(pDocument->IsTabProtected(nActualTab))
2164 ScRange aEditRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
2165 if(pDocument->HasScenarioRange(nTab, aEditRange))
2167 sal_uInt16 nFlags;
2168 pDocument->GetScenarioFlags(nTab,nFlags);
2169 bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
2173 if ( bIsEditable )
2175 if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) )
2177 bIsEditable = false;
2178 if ( pOnlyNotBecauseOfMatrix )
2179 *pOnlyNotBecauseOfMatrix = true;
2181 else if ( pOnlyNotBecauseOfMatrix )
2182 *pOnlyNotBecauseOfMatrix = false;
2184 else if ( pOnlyNotBecauseOfMatrix )
2185 *pOnlyNotBecauseOfMatrix = false;
2186 return bIsEditable;
2190 bool ScTable::IsSelectionEditable( const ScMarkData& rMark,
2191 bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
2193 bool bIsEditable = true;
2194 if ( nLockCount )
2195 bIsEditable = false;
2196 else if ( IsProtected() && !pDocument->IsScenario(nTab) )
2198 if((bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED )) != false)
2200 // If Sheet is protected and cells are not protected then
2201 // check the active scenario protect flag if this area is
2202 // in the active scenario range.
2203 ScRangeList aRanges;
2204 rMark.FillRangeListWithMarks( &aRanges, false );
2205 SCTAB nScenTab = nTab+1;
2206 while(pDocument->IsScenario(nScenTab) && bIsEditable)
2208 if(pDocument->IsActiveScenario(nScenTab))
2210 for (size_t i=0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++ )
2212 ScRange aRange = *aRanges[ i ];
2213 if(pDocument->HasScenarioRange(nScenTab, aRange))
2215 sal_uInt16 nFlags;
2216 pDocument->GetScenarioFlags(nScenTab,nFlags);
2217 bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
2221 nScenTab++;
2225 else if (pDocument->IsScenario(nTab))
2227 // Determine if the preceding sheet is protected
2228 SCTAB nActualTab = nTab;
2231 nActualTab--;
2233 while(pDocument->IsScenario(nActualTab));
2235 if(pDocument->IsTabProtected(nActualTab))
2237 ScRangeList aRanges;
2238 rMark.FillRangeListWithMarks( &aRanges, false );
2239 for (size_t i = 0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++)
2241 ScRange aRange = *aRanges[ i ];
2242 if(pDocument->HasScenarioRange(nTab, aRange))
2244 sal_uInt16 nFlags;
2245 pDocument->GetScenarioFlags(nTab,nFlags);
2246 bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
2251 if ( bIsEditable )
2253 if ( HasSelectionMatrixFragment( rMark ) )
2255 bIsEditable = false;
2256 if ( pOnlyNotBecauseOfMatrix )
2257 *pOnlyNotBecauseOfMatrix = true;
2259 else if ( pOnlyNotBecauseOfMatrix )
2260 *pOnlyNotBecauseOfMatrix = false;
2262 else if ( pOnlyNotBecauseOfMatrix )
2263 *pOnlyNotBecauseOfMatrix = false;
2264 return bIsEditable;
2269 void ScTable::LockTable()
2271 ++nLockCount;
2275 void ScTable::UnlockTable()
2277 if (nLockCount)
2278 --nLockCount;
2279 else
2281 OSL_FAIL("UnlockTable without LockTable");
2286 void ScTable::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
2288 for (SCCOL i=0; i<=MAXCOL; i++)
2289 aCol[i].MergeSelectionPattern( rState, rMark, bDeep );
2293 void ScTable::MergePatternArea( ScMergePatternState& rState, SCCOL nCol1, SCROW nRow1,
2294 SCCOL nCol2, SCROW nRow2, bool bDeep ) const
2296 for (SCCOL i=nCol1; i<=nCol2; i++)
2297 aCol[i].MergePatternArea( rState, nRow1, nRow2, bDeep );
2301 void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags,
2302 SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const
2304 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2306 PutInOrder(nStartCol, nEndCol);
2307 PutInOrder(nStartRow, nEndRow);
2308 for (SCCOL i=nStartCol; i<=nEndCol; i++)
2309 aCol[i].MergeBlockFrame( pLineOuter, pLineInner, rFlags,
2310 nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
2315 void ScTable::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
2316 SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
2318 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2320 PutInOrder(nStartCol, nEndCol);
2321 PutInOrder(nStartRow, nEndRow);
2322 for (SCCOL i=nStartCol; i<=nEndCol; i++)
2323 aCol[i].ApplyBlockFrame( pLineOuter, pLineInner,
2324 nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
2329 void ScTable::ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
2331 if (ValidColRow(nCol,nRow))
2332 aCol[nCol].ApplyPattern( nRow, rAttr );
2336 void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2337 const ScPatternAttr& rAttr, ScEditDataArray* pDataArray )
2339 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2341 PutInOrder(nStartCol, nEndCol);
2342 PutInOrder(nStartRow, nEndRow);
2343 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2344 aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr, pDataArray);
2348 bool ScTable::SetAttrEntries(SCCOL nCol, ScAttrEntry* pData, SCSIZE nSize)
2350 if (!ValidCol(nCol))
2351 return false;
2353 return aCol[nCol].SetAttrEntries(pData, nSize);
2356 void ScTable::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
2357 const ScPatternAttr& rPattern, short nNewType )
2359 SCCOL nEndCol = rRange.aEnd.Col();
2360 for ( SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ )
2362 aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
2366 void ScTable::AddCondFormatData( const ScRangeList& rRange, sal_uInt32 nIndex )
2368 size_t n = rRange.size();
2369 for(size_t i = 0; i < n; ++i)
2371 const ScRange* pRange = rRange[i];
2372 SCCOL nColStart = pRange->aStart.Col();
2373 SCCOL nColEnd = pRange->aEnd.Col();
2374 SCROW nRowStart = pRange->aStart.Row();
2375 SCROW nRowEnd = pRange->aEnd.Row();
2376 for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2378 aCol[nCol].AddCondFormat(nRowStart, nRowEnd, nIndex);
2383 void ScTable::RemoveCondFormatData( const ScRangeList& rRange, sal_uInt32 nIndex )
2385 size_t n = rRange.size();
2386 for(size_t i = 0; i < n; ++i)
2388 const ScRange* pRange = rRange[i];
2389 SCCOL nColStart = pRange->aStart.Col();
2390 SCCOL nColEnd = pRange->aEnd.Col();
2391 SCROW nRowStart = pRange->aStart.Row();
2392 SCROW nRowEnd = pRange->aEnd.Row();
2393 for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2395 aCol[nCol].RemoveCondFormat(nRowStart, nRowEnd, nIndex);
2402 void ScTable::ApplyStyle( SCCOL nCol, SCROW nRow, const ScStyleSheet& rStyle )
2404 if (ValidColRow(nCol,nRow))
2405 aCol[nCol].ApplyStyle( nRow, rStyle );
2409 void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet& rStyle )
2411 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2413 PutInOrder(nStartCol, nEndCol);
2414 PutInOrder(nStartRow, nEndRow);
2415 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2416 aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
2421 void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
2423 for (SCCOL i=0; i<=MAXCOL; i++)
2424 aCol[i].ApplySelectionStyle( rStyle, rMark );
2428 void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark,
2429 const ::editeng::SvxBorderLine* pLine, bool bColorOnly )
2431 if ( bColorOnly && !pLine )
2432 return;
2434 for (SCCOL i=0; i<=MAXCOL; i++)
2435 aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly );
2439 const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW nRow ) const
2441 if (ValidColRow(nCol, nRow))
2442 return aCol[nCol].GetStyle(nRow);
2443 else
2444 return NULL;
2448 const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
2450 rFound = false;
2452 bool bEqual = true;
2453 bool bColFound;
2455 const ScStyleSheet* pStyle = NULL;
2456 const ScStyleSheet* pNewStyle;
2458 for (SCCOL i=0; i<=MAXCOL && bEqual; i++)
2459 if (rMark.HasMultiMarks(i))
2461 pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
2462 if (bColFound)
2464 rFound = true;
2465 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2466 bEqual = false; // unterschiedliche
2467 pStyle = pNewStyle;
2471 return bEqual ? pStyle : NULL;
2475 const ScStyleSheet* ScTable::GetAreaStyle( bool& rFound, SCCOL nCol1, SCROW nRow1,
2476 SCCOL nCol2, SCROW nRow2 ) const
2478 rFound = false;
2480 bool bEqual = true;
2481 bool bColFound;
2483 const ScStyleSheet* pStyle = NULL;
2484 const ScStyleSheet* pNewStyle;
2486 for (SCCOL i=nCol1; i<=nCol2 && bEqual; i++)
2488 pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
2489 if (bColFound)
2491 rFound = true;
2492 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2493 bEqual = false; // unterschiedliche
2494 pStyle = pNewStyle;
2498 return bEqual ? pStyle : NULL;
2502 bool ScTable::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
2504 bool bIsUsed = false;
2506 for ( SCCOL i=0; i<=MAXCOL; i++ )
2508 if ( aCol[i].IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
2510 if ( !bGatherAllStyles )
2511 return true;
2512 bIsUsed = true;
2516 return bIsUsed;
2520 void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved,
2521 OutputDevice* pDev,
2522 double nPPTX, double nPPTY,
2523 const Fraction& rZoomX, const Fraction& rZoomY )
2525 ScFlatBoolRowSegments aUsedRows;
2526 for (SCCOL i = 0; i <= MAXCOL; ++i)
2527 aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved);
2529 SCROW nRow = 0;
2530 while (nRow <= MAXROW)
2532 ScFlatBoolRowSegments::RangeData aData;
2533 if (!aUsedRows.getRangeData(nRow, aData))
2534 // search failed!
2535 return;
2537 SCROW nEndRow = aData.mnRow2;
2538 if (aData.mbValue)
2539 SetOptimalHeight(nRow, nEndRow, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, false);
2541 nRow = nEndRow + 1;
2546 bool ScTable::ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2547 sal_Int16 nFlags )
2549 bool bChanged = false;
2550 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2551 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2552 bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags);
2553 return bChanged;
2557 bool ScTable::RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2558 sal_Int16 nFlags )
2560 bool bChanged = false;
2561 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2562 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2563 bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags);
2564 return bChanged;
2568 void ScTable::SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, bool bPutToPool )
2570 if (ValidColRow(nCol,nRow))
2571 aCol[nCol].SetPattern( nRow, rAttr, bPutToPool );
2575 void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const SfxPoolItem& rAttr )
2577 if (ValidColRow(nCol,nRow))
2578 aCol[nCol].ApplyAttr( nRow, rAttr );
2582 void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark,
2583 ScEditDataArray* pDataArray )
2585 for (SCCOL i=0; i<=MAXCOL; i++)
2586 aCol[i].ApplySelectionCache( pCache, rMark, pDataArray );
2590 void ScTable::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
2592 for (SCCOL i=0; i<=MAXCOL; i++)
2593 aCol[i].ChangeSelectionIndent( bIncrement, rMark );
2597 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
2599 for (SCCOL i=0; i<=MAXCOL; i++)
2600 aCol[i].ClearSelectionItems( pWhich, rMark );
2604 // Spaltenbreiten / Zeilenhoehen
2606 void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth )
2608 if (ValidCol(nCol) && pColWidth)
2610 if (!nNewWidth)
2612 nNewWidth = STD_COL_WIDTH;
2615 if ( nNewWidth != pColWidth[nCol] )
2617 pColWidth[nCol] = nNewWidth;
2618 InvalidatePageBreaks();
2621 else
2623 OSL_FAIL("Invalid column number or no widths");
2627 void ScTable::SetColWidthOnly( SCCOL nCol, sal_uInt16 nNewWidth )
2629 if (!ValidCol(nCol) || !pColWidth)
2630 return;
2632 if (!nNewWidth)
2633 nNewWidth = STD_COL_WIDTH;
2635 if (nNewWidth != pColWidth[nCol])
2636 pColWidth[nCol] = nNewWidth;
2639 void ScTable::SetRowHeight( SCROW nRow, sal_uInt16 nNewHeight )
2641 if (ValidRow(nRow) && mpRowHeights)
2643 if (!nNewHeight)
2645 OSL_FAIL("SetRowHeight: Row height zero");
2646 nNewHeight = ScGlobal::nStdRowHeight;
2649 sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow);
2650 if ( nNewHeight != nOldHeight )
2652 mpRowHeights->setValue(nRow, nRow, nNewHeight);
2653 InvalidatePageBreaks();
2656 else
2658 OSL_FAIL("Invalid row number or no heights");
2662 namespace {
2665 * Check if the new pixel size is different from the old size between
2666 * specified ranges.
2668 bool lcl_pixelSizeChanged(
2669 ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow,
2670 sal_uInt16 nNewHeight, double nPPTY)
2672 long nNewPix = static_cast<long>(nNewHeight * nPPTY);
2674 ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights);
2675 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
2677 sal_uInt16 nHeight;
2678 if (!aFwdIter.getValue(nRow, nHeight))
2679 break;
2681 if (nHeight != nNewHeight)
2683 bool bChanged = (nNewPix != static_cast<long>(nHeight * nPPTY));
2684 if (bChanged)
2685 return true;
2688 // Skip ahead to the last position of the current range.
2689 nRow = aFwdIter.getLastPos();
2691 return false;
2696 bool ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight,
2697 double /* nPPTX */, double nPPTY )
2699 bool bChanged = false;
2700 if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2702 if (!nNewHeight)
2704 OSL_FAIL("SetRowHeight: Row height zero");
2705 nNewHeight = ScGlobal::nStdRowHeight;
2708 bool bSingle = false; // true = process every row for its own
2709 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2710 if (pDrawLayer)
2711 if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
2712 bSingle = true;
2714 if (bSingle)
2716 ScFlatUInt16RowSegments::RangeData aData;
2717 mpRowHeights->getRangeData(nStartRow, aData);
2718 if (nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2)
2719 bSingle = false; // no difference in this range
2721 if (bSingle)
2723 if (nEndRow-nStartRow < 20)
2725 if (!bChanged)
2726 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2728 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2730 else
2732 SCROW nMid = (nStartRow+nEndRow) / 2;
2733 if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 ))
2734 bChanged = true;
2735 if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 ))
2736 bChanged = true;
2739 else
2741 if (!bChanged)
2742 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2744 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2747 if (bChanged)
2748 InvalidatePageBreaks();
2750 else
2752 OSL_FAIL("Invalid row number or no heights");
2755 return bChanged;
2758 void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight )
2760 if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights)
2761 return;
2763 if (!nNewHeight)
2764 nNewHeight = ScGlobal::nStdRowHeight;
2766 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2769 void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, bool bManual )
2771 if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
2773 if (bManual)
2774 pRowFlags->OrValue( nStartRow, nEndRow, CR_MANUALSIZE);
2775 else
2776 pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
2778 else
2780 OSL_FAIL("Invalid row number or no column flags");
2785 sal_uInt16 ScTable::GetColWidth( SCCOL nCol, bool bHiddenAsZero ) const
2787 OSL_ENSURE(ValidCol(nCol),"wrong column number");
2789 if (ValidCol(nCol) && pColFlags && pColWidth)
2791 if (bHiddenAsZero && ColHidden(nCol))
2792 return 0;
2793 else
2794 return pColWidth[nCol];
2796 else
2797 return (sal_uInt16) STD_COL_WIDTH;
2801 sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const // immer die eingestellte
2803 OSL_ENSURE(ValidCol(nCol),"wrong column number");
2805 if (ValidCol(nCol) && pColWidth)
2806 return pColWidth[nCol];
2807 else
2808 return (sal_uInt16) STD_COL_WIDTH;
2812 sal_uInt16 ScTable::GetCommonWidth( SCCOL nEndCol ) const
2814 // get the width that is used in the largest continuous column range (up to nEndCol)
2816 if ( !ValidCol(nEndCol) )
2818 OSL_FAIL("wrong column");
2819 nEndCol = MAXCOL;
2822 sal_uInt16 nMaxWidth = 0;
2823 sal_uInt16 nMaxCount = 0;
2824 SCCOL nRangeStart = 0;
2825 while ( nRangeStart <= nEndCol )
2827 // skip hidden columns
2828 while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) )
2829 ++nRangeStart;
2830 if ( nRangeStart <= nEndCol )
2832 sal_uInt16 nThisCount = 0;
2833 sal_uInt16 nThisWidth = pColWidth[nRangeStart];
2834 SCCOL nRangeEnd = nRangeStart;
2835 while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth )
2837 ++nThisCount;
2838 ++nRangeEnd;
2840 // skip hidden columns
2841 while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) )
2842 ++nRangeEnd;
2845 if ( nThisCount > nMaxCount )
2847 nMaxCount = nThisCount;
2848 nMaxWidth = nThisWidth;
2851 nRangeStart = nRangeEnd; // next range
2855 return nMaxWidth;
2859 sal_uInt16 ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
2861 OSL_ENSURE(ValidRow(nRow),"Invalid row number");
2863 if (ValidRow(nRow) && mpRowHeights)
2865 if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow))
2866 return 0;
2867 else
2869 ScFlatUInt16RowSegments::RangeData aData;
2870 if (!mpRowHeights->getRangeData(nRow, aData))
2872 if (pStartRow)
2873 *pStartRow = nRow;
2874 if (pEndRow)
2875 *pEndRow = nRow;
2876 // TODO: What should we return in case the search fails?
2877 return 0;
2880 // If bHiddenAsZero, pStartRow and pEndRow were initialized to
2881 // boundaries of a non-hidden segment. Assume that the previous and
2882 // next segment are hidden then and limit the current height
2883 // segment.
2884 if (pStartRow)
2885 *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1);
2886 if (pEndRow)
2887 *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2);
2888 return aData.mnValue;
2891 else
2893 if (pStartRow)
2894 *pStartRow = nRow;
2895 if (pEndRow)
2896 *pEndRow = nRow;
2897 return (sal_uInt16) ScGlobal::nStdRowHeight;
2902 sal_uLong ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow, bool bHiddenAsZero ) const
2904 OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
2906 if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2908 sal_uLong nHeight = 0;
2909 SCROW nRow = nStartRow;
2910 while (nRow <= nEndRow)
2912 SCROW nLastRow = -1;
2913 if (!( ( RowHidden(nRow, NULL, &nLastRow) ) && bHiddenAsZero ) )
2915 if (nLastRow > nEndRow)
2916 nLastRow = nEndRow;
2917 nHeight += mpRowHeights->getSumValue(nRow, nLastRow);
2919 nRow = nLastRow + 1;
2921 return nHeight;
2923 else
2924 return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight);
2928 sal_uLong ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const
2930 OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
2932 if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2934 sal_uLong nHeight = 0;
2935 SCROW nRow = nStartRow;
2936 while (nRow <= nEndRow)
2938 SCROW nLastRow = -1;
2939 if (!RowHidden(nRow, NULL, &nLastRow))
2941 if (nLastRow > nEndRow)
2942 nLastRow = nEndRow;
2944 // #i117315# can't use getSumValue, because individual values must be rounded
2945 while (nRow <= nLastRow)
2947 ScFlatUInt16RowSegments::RangeData aData;
2948 if (!mpRowHeights->getRangeData(nRow, aData))
2949 return nHeight; // shouldn't happen
2951 SCROW nSegmentEnd = std::min( nLastRow, aData.mnRow2 );
2953 // round-down a single height value, multiply resulting (pixel) values
2954 sal_uLong nOneHeight = static_cast<sal_uLong>( aData.mnValue * fScale );
2955 nHeight += nOneHeight * ( nSegmentEnd + 1 - nRow );
2957 nRow = nSegmentEnd + 1;
2960 nRow = nLastRow + 1;
2962 return nHeight;
2964 else
2965 return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale);
2969 sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const // non-0 even if hidden
2971 OSL_ENSURE(ValidRow(nRow),"wrong row number");
2973 if (ValidRow(nRow) && mpRowHeights)
2974 return mpRowHeights->getValue(nRow);
2975 else
2976 return (sal_uInt16) ScGlobal::nStdRowHeight;
2980 // Spalten-/Zeilen-Flags
2983 SCROW ScTable::GetHiddenRowCount( SCROW nRow ) const
2985 if (!ValidRow(nRow))
2986 return 0;
2988 SCROW nLastRow = -1;
2989 if (!RowHidden(nRow, NULL, &nLastRow) || !ValidRow(nLastRow))
2990 return 0;
2992 return nLastRow - nRow + 1;
2996 //! ShowRows / DBShowRows zusammenfassen
2998 void ScTable::ShowCol(SCCOL nCol, bool bShow)
3000 if (ValidCol(nCol))
3002 bool bWasVis = !ColHidden(nCol);
3003 if (bWasVis != bShow)
3005 SetColHidden(nCol, nCol, !bShow);
3007 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3008 if ( pCharts )
3009 pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ));
3012 else
3014 OSL_FAIL("Invalid column number or no flags");
3019 void ScTable::ShowRow(SCROW nRow, bool bShow)
3021 if (ValidRow(nRow) && pRowFlags)
3023 bool bWasVis = !RowHidden(nRow);
3024 if (bWasVis != bShow)
3026 SetRowHidden(nRow, nRow, !bShow);
3027 if (bShow)
3028 SetRowFiltered(nRow, nRow, false);
3029 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3030 if ( pCharts )
3031 pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
3033 InvalidatePageBreaks();
3036 else
3038 OSL_FAIL("Invalid row number or no flags");
3043 void ScTable::DBShowRow(SCROW nRow, bool bShow)
3045 if (ValidRow(nRow) && pRowFlags)
3047 // Filter-Flag immer setzen, auch wenn Hidden unveraendert
3048 bool bChanged = SetRowHidden(nRow, nRow, !bShow);
3049 SetRowFiltered(nRow, nRow, !bShow);
3051 if (bChanged)
3053 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3054 if ( pCharts )
3055 pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
3057 if (pOutlineTable)
3058 UpdateOutlineRow( nRow, nRow, bShow );
3060 InvalidatePageBreaks();
3063 else
3065 OSL_FAIL("Invalid row number or no flags");
3070 void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3072 SCROW nStartRow = nRow1;
3073 while (nStartRow <= nRow2)
3075 SCROW nEndRow = -1;
3076 bool bWasVis = !RowHiddenLeaf(nStartRow, NULL, &nEndRow);
3077 if (nEndRow > nRow2)
3078 nEndRow = nRow2;
3080 bool bChanged = ( bWasVis != bShow );
3082 SetRowHidden(nStartRow, nEndRow, !bShow);
3083 SetRowFiltered(nStartRow, nEndRow, !bShow);
3085 if ( bChanged )
3087 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3088 if ( pCharts )
3089 pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
3092 nStartRow = nEndRow + 1;
3095 // #i12341# For Show/Hide rows, the outlines are updated separately from the outside.
3096 // For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has
3097 // to be done here.
3098 if (pOutlineTable)
3099 UpdateOutlineRow( nRow1, nRow2, bShow );
3103 void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3105 SCROW nStartRow = nRow1;
3107 // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
3108 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3109 bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2 );
3111 while (nStartRow <= nRow2)
3113 SCROW nEndRow = -1;
3114 bool bWasVis = !RowHiddenLeaf(nStartRow, NULL, &nEndRow);
3115 if (nEndRow > nRow2)
3116 nEndRow = nRow2;
3118 bool bChanged = ( bWasVis != bShow );
3120 SetRowHidden(nStartRow, nEndRow, !bShow);
3121 if (bShow)
3122 SetRowFiltered(nStartRow, nEndRow, false);
3124 if ( bChanged )
3126 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3127 if ( pCharts )
3128 pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
3130 InvalidatePageBreaks();
3133 nStartRow = nEndRow + 1;
3136 if ( !bHasObjects )
3138 // #i116164# set the flags for the whole range at once
3139 SetRowHidden(nRow1, nRow2, !bShow);
3140 if (bShow)
3141 SetRowFiltered(nRow1, nRow2, false);
3145 bool ScTable::IsDataFiltered(SCCOL nColStart, SCROW nRowStart, SCCOL nColEnd, SCROW nRowEnd) const
3147 for (SCROW i = nRowStart; i <= nRowEnd; ++i)
3149 if (RowHidden(i))
3150 return true;
3152 for (SCCOL i = nColStart; i <= nColEnd; ++i)
3154 if (ColHidden(i))
3155 return true;
3157 return false;
3160 bool ScTable::IsDataFiltered(const ScRange& rRange) const
3162 return IsDataFiltered(rRange.aStart.Col(), rRange.aStart.Row(),
3163 rRange.aEnd.Col(), rRange.aEnd.Row());
3166 void ScTable::SetRowFlags( SCROW nRow, sal_uInt8 nNewFlags )
3168 if (ValidRow(nRow) && pRowFlags)
3169 pRowFlags->SetValue( nRow, nNewFlags);
3170 else
3172 OSL_FAIL("Invalid row number or no flags");
3177 void ScTable::SetRowFlags( SCROW nStartRow, SCROW nEndRow, sal_uInt8 nNewFlags )
3179 if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
3180 pRowFlags->SetValue( nStartRow, nEndRow, nNewFlags);
3181 else
3183 OSL_FAIL("Invalid row number(s) or no flags");
3188 sal_uInt8 ScTable::GetColFlags( SCCOL nCol ) const
3190 if (ValidCol(nCol) && pColFlags)
3191 return pColFlags[nCol];
3192 else
3193 return 0;
3197 sal_uInt8 ScTable::GetRowFlags( SCROW nRow ) const
3199 if (ValidRow(nRow) && pRowFlags)
3200 return pRowFlags->GetValue(nRow);
3201 else
3202 return 0;
3206 SCROW ScTable::GetLastFlaggedRow() const
3208 SCROW nLastFound = 0;
3209 if (pRowFlags)
3211 SCROW nRow = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<sal_uInt8>(CR_ALL) );
3212 if (ValidRow(nRow))
3213 nLastFound = nRow;
3216 if (!maRowManualBreaks.empty())
3217 nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin());
3219 if (mpHiddenRows)
3221 SCROW nRow = mpHiddenRows->findLastNotOf(false);
3222 if (ValidRow(nRow))
3223 nLastFound = ::std::max(nLastFound, nRow);
3226 if (mpFilteredRows)
3228 SCROW nRow = mpFilteredRows->findLastNotOf(false);
3229 if (ValidRow(nRow))
3230 nLastFound = ::std::max(nLastFound, nRow);
3233 return nLastFound;
3237 SCCOL ScTable::GetLastChangedCol() const
3239 if ( !pColFlags )
3240 return 0;
3242 SCCOL nLastFound = 0;
3243 for (SCCOL nCol = 1; nCol <= MAXCOL; nCol++)
3244 if ((pColFlags[nCol] & CR_ALL) || (pColWidth[nCol] != STD_COL_WIDTH))
3245 nLastFound = nCol;
3247 return nLastFound;
3251 SCROW ScTable::GetLastChangedRow() const
3253 if ( !pRowFlags )
3254 return 0;
3256 SCROW nLastFlags = GetLastFlaggedRow();
3258 // Find the last row position where the height is NOT the standard row
3259 // height.
3260 // KOHEI: Test this to make sure it does what it's supposed to.
3261 SCROW nLastHeight = mpRowHeights->findLastNotOf(ScGlobal::nStdRowHeight);
3262 if (!ValidRow(nLastHeight))
3263 nLastHeight = 0;
3265 return std::max( nLastFlags, nLastHeight);
3269 bool ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, bool bShow )
3271 if (pOutlineTable && pColFlags)
3273 ScBitMaskCompressedArray< SCCOLROW, sal_uInt8> aArray( MAXCOL, pColFlags, MAXCOLCOUNT);
3274 return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, *this, true );
3276 else
3277 return false;
3281 bool ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, bool bShow )
3283 if (pOutlineTable && pRowFlags)
3284 return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *this, false );
3285 else
3286 return false;
3290 void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3292 // Column-wise expansion
3294 while (rX1 > 0 && ColHidden(rX1-1))
3295 --rX1;
3297 while (rX2 < MAXCOL && ColHidden(rX2+1))
3298 ++rX2;
3300 // Row-wise expansion
3302 if (rY1 > 0)
3304 ScFlatBoolRowSegments::RangeData aData;
3305 if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue)
3307 SCROW nStartRow = aData.mnRow1;
3308 if (ValidRow(nStartRow))
3309 rY1 = nStartRow;
3312 if (rY2 < MAXROW)
3314 SCROW nEndRow = -1;
3315 if (RowHidden(rY2+1, NULL, &nEndRow) && ValidRow(nEndRow))
3316 rY2 = nEndRow;
3321 void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3323 while ( rX2>rX1 && ColHidden(rX2) )
3324 --rX2;
3325 while ( rX2>rX1 && ColHidden(rX1) )
3326 ++rX1;
3328 if (rY1 < rY2)
3330 ScFlatBoolRowSegments::RangeData aData;
3331 if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue)
3333 SCROW nStartRow = aData.mnRow1;
3334 if (ValidRow(nStartRow) && nStartRow >= rY1)
3335 rY2 = nStartRow;
3339 if (rY1 < rY2)
3341 SCROW nEndRow = -1;
3342 if (RowHidden(rY1, NULL, &nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2)
3343 rY1 = nEndRow;
3348 // Auto-Outline
3350 template< typename T >
3351 short DiffSign( T a, T b )
3353 return (a<b) ? -1 :
3354 (a>b) ? 1 : 0;
3357 namespace {
3359 class OutlineArrayFinder
3361 ScRange maRef;
3362 SCCOL mnCol;
3363 SCTAB mnTab;
3364 ScOutlineArray* mpArray;
3365 bool mbSizeChanged;
3367 public:
3368 OutlineArrayFinder(const ScRange& rRef, SCCOL nCol, SCTAB nTab, ScOutlineArray* pArray, bool bSizeChanged) :
3369 maRef(rRef), mnCol(nCol), mnTab(nTab), mpArray(pArray),
3370 mbSizeChanged(bSizeChanged) {}
3372 bool operator() (size_t nRow, const ScFormulaCell* pCell)
3374 SCROW nRow2 = static_cast<SCROW>(nRow);
3376 if (!pCell->HasRefListExpressibleAsOneReference(maRef))
3377 return false;
3379 if (maRef.aStart.Row() != nRow2 || maRef.aEnd.Row() != nRow2 ||
3380 maRef.aStart.Tab() != mnTab || maRef.aEnd.Tab() != mnTab)
3381 return false;
3383 if (DiffSign(maRef.aStart.Col(), mnCol) != DiffSign(maRef.aEnd.Col(), mnCol))
3384 return false;
3386 return mpArray->Insert(maRef.aStart.Col(), maRef.aEnd.Col(), mbSizeChanged);
3392 void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
3394 typedef mdds::flat_segment_tree<SCROW, bool> UsedRowsType;
3396 bool bSizeChanged = false;
3398 SCCOL nCol;
3399 SCROW nRow;
3400 bool bFound;
3401 ScOutlineArray* pArray;
3402 ScRange aRef;
3404 StartOutlineTable();
3406 // Zeilen
3408 UsedRowsType aUsed(0, MAXROW+1, false);
3409 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3410 aCol[nCol].FindUsed(nStartRow, nEndRow, aUsed);
3411 aUsed.build_tree();
3413 pArray = pOutlineTable->GetRowArray();
3414 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
3416 bool bUsed = false;
3417 SCROW nLastRow = nRow;
3418 aUsed.search_tree(nRow, bUsed, NULL, &nLastRow);
3419 if (!bUsed)
3421 nRow = nLastRow;
3422 continue;
3425 bFound = false;
3426 for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++)
3428 ScRefCellValue aCell = aCol[nCol].GetCellValue(nRow);
3430 if (aCell.meType != CELLTYPE_FORMULA)
3431 continue;
3433 if (!aCell.mpFormula->HasRefListExpressibleAsOneReference(aRef))
3434 continue;
3436 if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
3437 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3438 DiffSign( aRef.aStart.Row(), nRow ) ==
3439 DiffSign( aRef.aEnd.Row(), nRow ) )
3441 if (pArray->Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged ))
3443 bFound = true;
3449 // Column
3450 pArray = pOutlineTable->GetColArray();
3451 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3453 if (aCol[nCol].IsEmptyData())
3454 continue;
3456 OutlineArrayFinder aFunc(aRef, nCol, nTab, pArray, bSizeChanged);
3457 sc::FindFormula(aCol[nCol].maCells, nStartRow, nEndRow, aFunc);
3461 // CopyData - fuer Query in anderen Bereich
3463 void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
3464 SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab )
3466 //! wenn fuer mehrere Zeilen benutzt, nach Spalten optimieren!
3468 ScAddress aSrc( nStartCol, nStartRow, nTab );
3469 ScAddress aDest( nDestCol, nDestRow, nDestTab );
3470 ScRange aRange( aSrc, aDest );
3471 bool bThisTab = ( nDestTab == nTab );
3472 SCROW nDestY = nDestRow;
3473 for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
3475 aSrc.SetRow( nRow );
3476 aDest.SetRow( nDestY );
3477 SCCOL nDestX = nDestCol;
3478 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
3480 aSrc.SetCol( nCol );
3481 aDest.SetCol( nDestX );
3482 ScCellValue aCell;
3483 aCell.assign(*pDocument, ScAddress(nCol, nRow, nTab));
3485 if (aCell.meType == CELLTYPE_FORMULA)
3487 sc::RefUpdateContext aCxt(*pDocument);
3488 aCxt.meMode = URM_COPY;
3489 aCxt.maRange = aRange;
3490 aCxt.mnColDelta = nDestCol - nStartCol;
3491 aCxt.mnRowDelta = nDestRow - nStartRow;
3492 aCxt.mnTabDelta = nDestTab - nTab;
3493 aCell.mpFormula->UpdateReference(aCxt);
3494 aCell.mpFormula->aPos = aDest;
3497 if (bThisTab)
3499 aCell.release(aCol[nDestX], nDestY);
3500 SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ), true );
3502 else
3504 aCell.release(*pDocument, aDest);
3505 pDocument->SetPattern( aDest, *GetPattern( nCol, nRow ), true );
3508 ++nDestX;
3510 ++nDestY;
3515 bool ScTable::RefVisible(ScFormulaCell* pCell)
3517 ScRange aRef;
3519 if (pCell->HasOneReference(aRef))
3521 if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab())
3523 SCROW nEndRow;
3524 if (!RowFiltered(aRef.aStart.Row(), NULL, &nEndRow))
3525 // row not filtered.
3526 nEndRow = ::std::numeric_limits<SCROW>::max();
3528 if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row())
3529 return true; // at least partly visible
3530 return false; // completely invisible
3534 return true; // irgendwie anders
3538 void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, OUString& rStr)
3540 GetInputString(nCol, nRow, rStr);
3541 rStr = ScGlobal::pCharClass->uppercase(rStr.trim());
3545 // Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage
3547 void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos)
3549 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3550 if( pDrawLayer )
3552 double fValX = GetColOffset( MAXCOL + 1 ) * HMM_PER_TWIPS;
3553 double fValY = GetRowOffset( MAXROW + 1 ) * HMM_PER_TWIPS;
3554 const long nMax = ::std::numeric_limits<long>::max();
3555 // #i113884# Avoid int32 overflow with possible negative results than can cause bad effects.
3556 // If the draw page size is smaller than all rows, only the bottom of the sheet is affected.
3557 long x = ( fValX > (double)nMax ) ? nMax : (long) fValX;
3558 long y = ( fValY > (double)nMax ) ? nMax : (long) fValY;
3560 if ( IsLayoutRTL() ) // IsNegativePage
3561 x = -x;
3563 pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( x, y ), bUpdateNoteCaptionPos );
3566 // #i102616# actions that modify the draw page size count as sheet modification
3567 // (exception: InitDrawLayer)
3568 if (bResetStreamValid && IsStreamValid())
3569 SetStreamValid(false);
3572 void ScTable::SetRangeName(ScRangeName* pNew)
3574 delete mpRangeName;
3575 mpRangeName = pNew;
3577 //fdo#39792: mark stream as invalid, otherwise new ScRangeName will not be written to file
3578 if (IsStreamValid())
3579 SetStreamValid(false);
3582 ScRangeName* ScTable::GetRangeName() const
3584 if (!mpRangeName)
3585 mpRangeName = new ScRangeName;
3586 return mpRangeName;
3590 sal_uLong ScTable::GetRowOffset( SCROW nRow, bool bHiddenAsZero ) const
3592 sal_uLong n = 0;
3593 if ( mpHiddenRows && mpRowHeights )
3595 if (nRow == 0)
3596 return 0;
3597 else if (nRow == 1)
3598 return GetRowHeight(0, NULL, NULL, bHiddenAsZero );
3600 n = GetTotalRowHeight(0, nRow-1, bHiddenAsZero);
3601 #if OSL_DEBUG_LEVEL > 0
3602 if (n == ::std::numeric_limits<unsigned long>::max())
3603 OSL_FAIL("ScTable::GetRowOffset: row heights overflow");
3604 #endif
3606 else
3608 OSL_FAIL("GetRowOffset: Data missing");
3610 return n;
3613 SCROW ScTable::GetRowForHeight(sal_uLong nHeight) const
3615 sal_uInt32 nSum = 0;
3617 ScFlatBoolRowSegments::RangeData aData;
3618 for (SCROW nRow = 0; nRow <= MAXROW; ++nRow)
3620 if (!mpHiddenRows->getRangeData(nRow, aData))
3621 break;
3623 if (aData.mbValue)
3625 nRow = aData.mnRow2;
3626 continue;
3629 sal_uInt32 nNew = mpRowHeights->getValue(nRow);
3630 nSum += nNew;
3631 if (nSum > nHeight)
3633 return nRow < MAXROW ? nRow + 1 : MAXROW;
3636 return -1;
3640 sal_uLong ScTable::GetColOffset( SCCOL nCol, bool bHiddenAsZero ) const
3642 sal_uLong n = 0;
3643 if ( pColWidth )
3645 SCCOL i;
3646 for( i = 0; i < nCol; i++ )
3647 if (!( bHiddenAsZero && ColHidden(i) ))
3648 n += pColWidth[i];
3650 else
3652 OSL_FAIL("GetColumnOffset: Data missing");
3654 return n;
3657 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */