re-enabled user-defined numeric fields for dBase export
[LibreOffice.git] / sc / source / core / data / table2.cxx
blob821ab9261c764b63e22494b8740a0bf151ca3d51
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" // Iterator
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"
48 #include "scitems.hxx"
49 #include <editeng/boxitem.hxx>
50 #include "editeng/editobj.hxx"
51 #include <svl/poolcach.hxx>
52 #include <unotools/charclass.hxx>
53 #include <math.h>
54 #include <svl/PasswordHelper.hxx>
55 #include <unotools/transliterationwrapper.hxx>
57 // STATIC DATA -----------------------------------------------------------
59 sal_uInt16 ScTable::GetTextWidth(SCCOL nCol, SCROW nRow) const
61 return aCol[nCol].GetTextWidth(nRow);
64 void ScTable::SetTextWidth(SCCOL nCol, SCROW nRow, sal_uInt16 nWidth)
66 aCol[nCol].SetTextWidth(nRow, nWidth);
69 bool ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
71 sal_uInt16 nOldSizeX = 0;
72 sal_uInt16 nOldSizeY = 0;
73 sal_uInt16 nNewSizeX = 0;
74 sal_uInt16 nNewSizeY = 0;
76 if (pOutlineTable)
78 nOldSizeX = pOutlineTable->GetColArray()->GetDepth();
79 nOldSizeY = pOutlineTable->GetRowArray()->GetDepth();
80 delete pOutlineTable;
83 if (pNewOutline)
85 pOutlineTable = new ScOutlineTable( *pNewOutline );
86 nNewSizeX = pOutlineTable->GetColArray()->GetDepth();
87 nNewSizeY = pOutlineTable->GetRowArray()->GetDepth();
89 else
90 pOutlineTable = NULL;
92 return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY ); // Groesse geaendert ?
96 void ScTable::StartOutlineTable()
98 if (!pOutlineTable)
99 pOutlineTable = new ScOutlineTable;
103 void ScTable::SetSheetEvents( const ScSheetEvents* pNew )
105 delete pSheetEvents;
106 if (pNew)
107 pSheetEvents = new ScSheetEvents(*pNew);
108 else
109 pSheetEvents = NULL;
111 SetCalcNotification( false ); // discard notifications before the events were set
113 if (IsStreamValid())
114 SetStreamValid(false);
118 void ScTable::SetCalcNotification( bool bSet )
120 bCalcNotification = bSet;
124 bool ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize ) const
126 bool bTest = true;
128 if ( nStartCol==0 && nEndCol==MAXCOL && pOutlineTable )
129 bTest = pOutlineTable->TestInsertRow(nSize);
131 for (SCCOL i=nStartCol; (i<=nEndCol) && bTest; i++)
132 bTest = aCol[i].TestInsertRow( nSize );
134 return bTest;
138 void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize )
140 if (nStartCol==0 && nEndCol==MAXCOL)
142 if (mpRowHeights && pRowFlags)
144 mpRowHeights->insertSegment(nStartRow, nSize, false);
145 sal_uInt8 nNewFlags = pRowFlags->Insert( nStartRow, nSize);
146 // only copy manual size flag, clear all others
147 if (nNewFlags && (nNewFlags != CR_MANUALSIZE))
148 pRowFlags->SetValue( nStartRow, nStartRow + nSize - 1,
149 nNewFlags & CR_MANUALSIZE);
152 if (pOutlineTable)
153 pOutlineTable->InsertRow( nStartRow, nSize );
155 mpFilteredRows->insertSegment(nStartRow, nSize, true);
156 mpHiddenRows->insertSegment(nStartRow, nSize, true);
158 if (!maRowManualBreaks.empty())
160 // Copy all breaks up to nStartRow (non-inclusive).
161 ::std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
162 ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
164 // Copy all breaks from nStartRow (inclusive) to the last element,
165 // but add nSize to each value.
166 ::std::set<SCROW>::iterator itr2 = maRowManualBreaks.end();
167 for (; itr1 != itr2; ++itr1)
168 aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize));
170 maRowManualBreaks.swap(aNewBreaks);
174 for (SCCOL j=nStartCol; j<=nEndCol; j++)
175 aCol[j].InsertRow( nStartRow, nSize );
177 // Transfer those notes that will get shifted into another container.
178 ScNotes aNotes(pDocument);
179 ScNotes::iterator itr = maNotes.begin();
180 while( itr != maNotes.end() )
182 SCCOL nCol = itr->first.first;
183 SCROW nRow = itr->first.second;
184 ScPostIt* pPostIt = itr->second;
185 ++itr;
187 if (nStartRow <= nRow && nStartCol <= nCol && nCol <= nEndCol)
189 aNotes.insert(nCol, nRow + nSize, pPostIt);
190 maNotes.ReleaseNote(nCol, nRow);
194 // Re-insert the shifted notes.
195 itr = aNotes.begin();
196 while( itr != aNotes.end() )
198 SCCOL nCol = itr->first.first;
199 SCROW nRow = itr->first.second;
200 ScPostIt* pPostIt = itr->second;
201 ++itr;
203 maNotes.insert( nCol, nRow, pPostIt);
204 aNotes.ReleaseNote( nCol, nRow);
207 InvalidatePageBreaks();
209 if (IsStreamValid())
210 // TODO: In the future we may want to check if the table has been
211 // really modified before setting the stream invalid.
212 SetStreamValid(false);
216 void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
217 bool* pUndoOutline )
219 if (nStartCol==0 && nEndCol==MAXCOL)
221 if (pRowFlags)
222 pRowFlags->Remove( nStartRow, nSize);
224 if (mpRowHeights)
225 mpRowHeights->removeSegment(nStartRow, nStartRow+nSize);
227 if (pOutlineTable)
228 if (pOutlineTable->DeleteRow( nStartRow, nSize ))
229 if (pUndoOutline)
230 *pUndoOutline = true;
232 mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize);
233 mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize);
235 if (!maRowManualBreaks.empty())
237 // Erase all manual breaks between nStartRow and nStartRow + nSize - 1 (inclusive).
238 std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
239 std::set<SCROW>::iterator itr2 = maRowManualBreaks.upper_bound(static_cast<SCROW>(nStartRow + nSize - 1));
240 maRowManualBreaks.erase(itr1, itr2);
242 // Copy all breaks from the 1st element up to nStartRow to the new container.
243 itr1 = maRowManualBreaks.lower_bound(nStartRow);
244 ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
246 // Copy all breaks from nStartRow to the last element, but subtract each value by nSize.
247 itr2 = maRowManualBreaks.end();
248 for (; itr1 != itr2; ++itr1)
249 aNewBreaks.insert(static_cast<SCROW>(*itr1 - nSize));
251 maRowManualBreaks.swap(aNewBreaks);
255 // Transfer those notes that will get shifted into another container.
256 ScNotes aNotes(pDocument);
257 ScNotes::iterator itr = maNotes.begin();
258 while( itr != maNotes.end() )
260 SCCOL nCol = itr->first.first;
261 SCROW nRow = itr->first.second;
262 ScPostIt* pPostIt = itr->second;
263 ++itr;
265 if (nStartRow <= nRow && nStartCol <= nCol && nCol <= nEndCol)
267 SCROW nEndRow = nStartRow + nSize - 1; // last row of deleted region
268 if (nEndRow < nRow)
270 // This note will get shifted.
271 aNotes.insert(nCol, nRow - nSize, pPostIt);
272 maNotes.ReleaseNote(nCol, nRow);
274 else
275 // Note is in the deleted area. Remove it.
276 maNotes.erase(nCol, nRow);
280 // Re-insert the shifted notes.
281 itr = aNotes.begin();
282 while( itr != aNotes.end() )
284 SCCOL nCol = itr->first.first;
285 SCROW nRow = itr->first.second;
286 ScPostIt* pPostIt = itr->second;
287 ++itr;
289 maNotes.insert( nCol, nRow, pPostIt);
290 aNotes.ReleaseNote( nCol, nRow);
293 { // scope for bulk broadcast
294 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
295 for (SCCOL j=nStartCol; j<=nEndCol; j++)
296 aCol[j].DeleteRow( nStartRow, nSize );
299 InvalidatePageBreaks();
301 if (IsStreamValid())
302 // TODO: In the future we may want to check if the table has been
303 // really modified before setting the stream invalid.
304 SetStreamValid(false);
308 bool ScTable::TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) const
310 bool bTest = true;
312 if ( nStartRow==0 && nEndRow==MAXROW && pOutlineTable )
313 bTest = pOutlineTable->TestInsertCol(nSize);
315 if ( nSize > static_cast<SCSIZE>(MAXCOL) )
316 bTest = false;
318 for (SCCOL i=MAXCOL; (i+static_cast<SCCOL>(nSize)>MAXCOL) && bTest; i--)
319 bTest = aCol[i].TestInsertCol(nStartRow, nEndRow);
321 return bTest;
325 void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize )
327 if (nStartRow==0 && nEndRow==MAXROW)
329 if (pColWidth && pColFlags)
331 memmove( &pColWidth[nStartCol+nSize], &pColWidth[nStartCol],
332 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
333 memmove( &pColFlags[nStartCol+nSize], &pColFlags[nStartCol],
334 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
336 if (pOutlineTable)
337 pOutlineTable->InsertCol( nStartCol, nSize );
339 mpHiddenCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
340 mpFilteredCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
342 if (!maColManualBreaks.empty())
344 std::set<SCCOL>::reverse_iterator rit = maColManualBreaks.rbegin();
345 while (rit != maColManualBreaks.rend())
347 SCCOL nCol = *rit;
348 if (nCol < nStartCol)
349 break; // while
350 else
352 maColManualBreaks.erase( (++rit).base());
353 maColManualBreaks.insert( static_cast<SCCOL>( nCol + nSize));
360 if ((nStartRow == 0) && (nEndRow == MAXROW))
362 for (SCSIZE i=0; i < nSize; i++)
363 for (SCCOL nCol = MAXCOL; nCol > nStartCol; nCol--)
364 aCol[nCol].SwapCol(aCol[nCol-1]);
366 else
368 for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
369 aCol[MAXCOL - nSize - i].MoveTo(nStartRow, nEndRow, aCol[MAXCOL - i]);
372 // Transfer those notes that will get shifted into another container.
373 ScNotes aNotes(pDocument);
374 ScNotes::iterator itr = maNotes.begin();
375 while( itr != maNotes.end() )
377 SCCOL nCol = itr->first.first;
378 SCROW nRow = itr->first.second;
379 ScPostIt* pPostIt = itr->second;
380 ++itr;
382 if (nStartCol <= nCol && nStartRow <= nRow && nRow <= nEndRow)
384 aNotes.insert(nCol + nSize, nRow, pPostIt);
385 maNotes.ReleaseNote(nCol, nRow);
389 // Re-insert the shifted notes.
390 itr = aNotes.begin();
391 while( itr != aNotes.end() )
393 SCCOL nCol = itr->first.first;
394 SCROW nRow = itr->first.second;
395 ScPostIt* pPostIt = itr->second;
396 ++itr;
398 maNotes.insert( nCol, nRow, pPostIt);
399 aNotes.ReleaseNote( nCol, nRow);
402 if (nStartCol>0) // copy old attributes
404 sal_uInt16 nWhichArray[3];
405 nWhichArray[0] = ATTR_MERGE;
406 nWhichArray[1] = ATTR_CONDITIONAL;
407 nWhichArray[2] = 0;
409 sc::CopyToDocContext aCxt(*pDocument);
410 for (SCSIZE i=0; i<nSize; i++)
412 aCol[nStartCol-1].CopyToColumn(aCxt, nStartRow, nEndRow, IDF_ATTRIB,
413 false, aCol[nStartCol+i] );
414 aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow,
415 SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
416 aCol[nStartCol+i].ClearItems( nStartRow, nEndRow, nWhichArray );
420 InvalidatePageBreaks();
422 if (IsStreamValid())
423 // TODO: In the future we may want to check if the table has been
424 // really modified before setting the stream invalid.
425 SetStreamValid(false);
429 void ScTable::DeleteCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize,
430 bool* pUndoOutline )
432 if (nStartRow==0 && nEndRow==MAXROW)
434 if (pColWidth && pColFlags)
436 memmove( &pColWidth[nStartCol], &pColWidth[nStartCol+nSize],
437 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
438 memmove( &pColFlags[nStartCol], &pColFlags[nStartCol+nSize],
439 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
441 if (pOutlineTable)
442 if (pOutlineTable->DeleteCol( nStartCol, nSize ))
443 if (pUndoOutline)
444 *pUndoOutline = true;
446 SCCOL nRmSize = nStartCol + static_cast<SCCOL>(nSize);
447 mpHiddenCols->removeSegment(nStartCol, nRmSize);
448 mpFilteredCols->removeSegment(nStartCol, nRmSize);
450 if (!maColManualBreaks.empty())
452 std::set<SCCOL>::iterator it = maColManualBreaks.upper_bound( static_cast<SCCOL>( nStartCol + nSize - 1));
453 maColManualBreaks.erase( maColManualBreaks.lower_bound( nStartCol), it);
454 while (it != maColManualBreaks.end())
456 SCCOL nCol = *it;
457 maColManualBreaks.erase( it++);
458 maColManualBreaks.insert( static_cast<SCCOL>( nCol - nSize));
464 { // scope for bulk broadcast
465 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
466 for (SCSIZE i = 0; i < nSize; i++)
467 aCol[nStartCol + i].DeleteArea(nStartRow, nEndRow, IDF_ALL);
470 if ((nStartRow == 0) && (nEndRow == MAXROW))
472 for (SCSIZE i=0; i < nSize; i++)
473 for (SCCOL nCol = nStartCol; nCol < MAXCOL; nCol++)
474 aCol[nCol].SwapCol(aCol[nCol+1]);
476 else
478 for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
479 aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]);
482 // Transfer those notes that will get shifted into another container.
483 ScNotes aNotes(pDocument);
484 ScNotes::iterator itr = maNotes.begin();
485 while( itr != maNotes.end() )
487 SCCOL nCol = itr->first.first;
488 SCROW nRow = itr->first.second;
489 ScPostIt* pPostIt = itr->second;
490 ++itr;
492 if (nStartCol <= nCol && nStartRow <= nRow && nRow <= nEndRow)
494 SCCOL nEndCol = nStartCol + nSize - 1;
495 if (nEndCol < nCol)
497 // This note will get shifted.
498 aNotes.insert(nCol - nSize, nRow, pPostIt);
499 maNotes.ReleaseNote(nCol, nRow);
501 else
502 // The note is in the deleted region. Remove it.
503 maNotes.erase(nCol, nRow);
507 // Re-insert the shifted notes.
508 itr = aNotes.begin();
509 while( itr != aNotes.end() )
511 SCCOL nCol = itr->first.first;
512 SCROW nRow = itr->first.second;
513 ScPostIt* pPostIt = itr->second;
514 ++itr;
516 maNotes.insert( nCol, nRow, pPostIt);
517 aNotes.ReleaseNote( nCol, nRow);
520 InvalidatePageBreaks();
522 if (IsStreamValid())
523 // TODO: In the future we may want to check if the table has been
524 // really modified before setting the stream invalid.
525 SetStreamValid(false);
529 void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nDelFlag)
531 if (nCol2 > MAXCOL) nCol2 = MAXCOL;
532 if (nRow2 > MAXROW) nRow2 = MAXROW;
533 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
535 { // scope for bulk broadcast
536 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
537 for (SCCOL i = nCol1; i <= nCol2; i++)
538 aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
542 // Zellschutz auf geschuetzter Tabelle nicht setzen
545 if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
547 ScPatternAttr aPattern(pDocument->GetPool());
548 aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
549 ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
552 if( nDelFlag & IDF_ATTRIB )
553 mpCondFormatList->DeleteArea( nCol1, nRow1, nCol2, nRow2 );
556 if (nDelFlag & IDF_NOTE)
557 maNotes.erase( nCol1, nRow1, nCol2, nRow2 );
559 if (IsStreamValid())
560 // TODO: In the future we may want to check if the table has been
561 // really modified before setting the stream invalid.
562 SetStreamValid(false);
566 void ScTable::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
568 { // scope for bulk broadcast
569 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
570 for (SCCOL i=0; i<=MAXCOL; i++)
571 aCol[i].DeleteSelection( nDelFlag, rMark );
574 ScRangeList aRangeList;
575 rMark.FillRangeListWithMarks(&aRangeList, false);
577 for (size_t i = 0; i < aRangeList.size(); ++i)
579 ScRange* pRange = aRangeList[i];
580 if (nDelFlag & IDF_NOTE && pRange)
582 maNotes.erase(pRange->aStart.Col(), pRange->aStart.Row(), pRange->aEnd.Col(), pRange->aEnd.Row(), nDelFlag & IDF_NOCAPTIONS);
585 if((nDelFlag & IDF_ATTRIB) && pRange && pRange->aStart.Tab() == nTab)
586 mpCondFormatList->DeleteArea( pRange->aStart.Col(), pRange->aStart.Row(), pRange->aEnd.Col(), pRange->aEnd.Row() );
590 // Zellschutz auf geschuetzter Tabelle nicht setzen
593 if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
595 ScDocumentPool* pPool = pDocument->GetPool();
596 SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END );
597 aSet.Put( ScProtectionAttr( false ) );
598 SfxItemPoolCache aCache( pPool, &aSet );
599 ApplySelectionCache( &aCache, rMark );
602 if (IsStreamValid())
603 // TODO: In the future we may want to check if the table has been
604 // really modified before setting the stream invalid.
605 SetStreamValid(false);
609 // pTable = Clipboard
610 void ScTable::CopyToClip(
611 sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
612 ScTable* pTable )
614 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
616 // copy content
617 //local range names need to be copied first for formula cells
618 if (!pTable->mpRangeName && mpRangeName)
619 pTable->mpRangeName = new ScRangeName(*mpRangeName);
621 // notes
622 maNotes.clone(
623 pTable->pDocument, nCol1, nRow1, nCol2, nRow2, rCxt.isCloneNotes(), nTab, pTable->maNotes);
625 SCCOL i;
627 for ( i = nCol1; i <= nCol2; i++)
628 aCol[i].CopyToClip(rCxt, nRow1, nRow2, pTable->aCol[i]);
630 // copy widths/heights, and only "hidden", "filtered" and "manual" flags
631 // also for all preceding columns/rows, to have valid positions for drawing objects
633 if (pColWidth && pTable->pColWidth)
634 for (i=0; i<=nCol2; i++)
635 pTable->pColWidth[i] = pColWidth[i];
637 pTable->CopyColHidden(*this, 0, nCol2);
638 pTable->CopyColFiltered(*this, 0, nCol2);
639 if (pDBDataNoName)
640 pTable->SetAnonymousDBData(new ScDBData(*pDBDataNoName));
643 if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights)
645 pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CR_MANUALSIZE);
646 pTable->CopyRowHeight(*this, 0, nRow2, 0);
649 pTable->CopyRowHidden(*this, 0, nRow2);
650 pTable->CopyRowFiltered(*this, 0, nRow2);
652 // ggf. Formeln durch Werte ersetzen
654 if ( IsProtected() )
655 for (i = nCol1; i <= nCol2; i++)
656 pTable->aCol[i].RemoveProtected(nRow1, nRow2);
658 pTable->mpCondFormatList.reset(new ScConditionalFormatList(pTable->pDocument, *mpCondFormatList));
662 void ScTable::CopyToClip(
663 sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, ScTable* pTable )
665 ScRangeList aRanges(rRanges);
666 for ( size_t i = 0, nListSize = aRanges.size(); i < nListSize; ++i )
668 ScRange* p = aRanges[ i ];
669 CopyToClip(
670 rCxt, p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), pTable);
674 void ScTable::CopyStaticToDocument(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pDestTab)
676 if (nCol1 > nCol2)
677 return;
679 for (SCCOL i = nCol1; i <= nCol2; ++i)
681 ScColumn& rSrcCol = aCol[i];
682 ScColumn& rDestCol = pDestTab->aCol[i];
683 rSrcCol.CopyStaticToDocument(nRow1, nRow2, rDestCol);
687 void ScTable::CopyCellToDocument(SCCOL nSrcCol, SCROW nSrcRow, SCCOL nDestCol, SCROW nDestRow, ScTable& rDestTab )
689 if (!ValidColRow(nSrcCol, nSrcRow) || !ValidColRow(nDestCol, nDestRow))
690 return;
692 ScColumn& rSrcCol = aCol[nSrcCol];
693 ScColumn& rDestCol = rDestTab.aCol[nDestCol];
694 rSrcCol.CopyCellToDocument(nSrcRow, nDestRow, rDestCol);
697 void ScTable::CopyConditionalFormat( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
698 SCsCOL nDx, SCsROW nDy, ScTable* pTable)
700 ScRange aOldRange( nCol1 - nDx, nRow1 - nDy, pTable->nTab, nCol2 - nDx, nRow2 - nDy, pTable->nTab);
701 ScRange aNewRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
702 bool bSameDoc = pDocument == pTable->pDocument;
704 for(ScConditionalFormatList::const_iterator itr = pTable->mpCondFormatList->begin(),
705 itrEnd = pTable->mpCondFormatList->end(); itr != itrEnd; ++itr)
707 const ScRangeList& rCondFormatRange = itr->GetRange();
708 if(!rCondFormatRange.Intersects( aOldRange ))
709 continue;
711 ScRangeList aIntersectedRange = rCondFormatRange.GetIntersectedRange(aOldRange);
712 ScConditionalFormat* pNewFormat = itr->Clone(pDocument);
714 pNewFormat->AddRange(aIntersectedRange);
715 pNewFormat->UpdateReference(URM_COPY, aNewRange, nDx, nDy, nTab - pTable->nTab, true);
717 sal_uLong nMax = 0;
718 for(ScConditionalFormatList::const_iterator itrCond = mpCondFormatList->begin();
719 itrCond != mpCondFormatList->end(); ++itrCond)
721 if(itrCond->GetKey() > nMax)
722 nMax = itrCond->GetKey();
724 pNewFormat->SetKey(nMax + 1);
725 mpCondFormatList->InsertNew(pNewFormat);
727 if(!bSameDoc)
729 for(size_t i = 0, n = pNewFormat->size();
730 i < n; ++i)
732 OUString aStyleName;
733 const ScFormatEntry* pEntry = pNewFormat->GetEntry(i);
734 if(pEntry->GetType() == condformat::CONDITION)
735 aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
736 else if(pEntry->GetType() == condformat::DATE)
737 aStyleName = static_cast<const ScCondDateFormatEntry*>(pEntry)->GetStyleName();
739 if(!aStyleName.isEmpty())
741 if(pDocument->GetStyleSheetPool()->Find(aStyleName, SFX_STYLE_FAMILY_PARA))
742 continue;
744 pDocument->GetStyleSheetPool()->CopyStyleFrom(
745 pTable->pDocument->GetStyleSheetPool(), aStyleName, SFX_STYLE_FAMILY_PARA );
750 pDocument->AddCondFormatData( pNewFormat->GetRange(), nTab, pNewFormat->GetKey() );
754 bool ScTable::InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol )
756 if (!ValidCol(nCol))
757 return false;
759 return aCol[nCol].InitBlockPosition(rBlockPos);
762 void ScTable::CopyFromClip(
763 sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
764 SCsCOL nDx, SCsROW nDy, ScTable* pTable )
767 if (nCol2 > MAXCOL)
768 nCol2 = MAXCOL;
769 if (nRow2 > MAXROW)
770 nRow2 = MAXROW;
772 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
774 for ( SCCOL i = nCol1; i <= nCol2; i++)
775 aCol[i].CopyFromClip(rCxt, nRow1, nRow2, nDy, pTable->aCol[i - nDx]);
778 if (rCxt.getInsertFlag() == IDF_ATTRIB)
780 // make sure that there are no old references to the cond formats
781 sal_uInt16 nWhichArray[2];
782 nWhichArray[0] = ATTR_CONDITIONAL;
783 nWhichArray[1] = 0;
784 for ( SCCOL i = nCol1; i <= nCol2; ++i)
785 aCol[i].ClearItems(nRow1, nRow2, nWhichArray);
788 //remove old notes
789 if (rCxt.getInsertFlag() & (IDF_NOTE|IDF_ADDNOTES))
790 maNotes.erase(nCol1, nRow1, nCol2, nRow2);
792 bool bAddNotes = rCxt.getInsertFlag() & (IDF_NOTE | IDF_ADDNOTES);
793 if (bAddNotes)
795 bool bCloneCaption = (rCxt.getInsertFlag() & IDF_NOCAPTIONS) == 0;
796 maNotes.CopyFromClip(pTable->maNotes, pDocument, nCol1, nRow1, nCol2, nRow2, nDx, nDy, nTab, bCloneCaption);
800 if ((rCxt.getInsertFlag() & IDF_ATTRIB) != 0)
802 if (nRow1==0 && nRow2==MAXROW && pColWidth && pTable->pColWidth)
803 for (SCCOL i=nCol1; i<=nCol2; i++)
804 pColWidth[i] = pTable->pColWidth[i-nDx];
806 if (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pTable->mpRowHeights &&
807 pRowFlags && pTable->pRowFlags)
809 CopyRowHeight(*pTable, nRow1, nRow2, -nDy);
810 // Must copy CR_MANUALSIZE bit too, otherwise pRowHeight doesn't make sense
811 for (SCROW j=nRow1; j<=nRow2; j++)
813 if ( pTable->pRowFlags->GetValue(j-nDy) & CR_MANUALSIZE )
814 pRowFlags->OrValue( j, CR_MANUALSIZE);
815 else
816 pRowFlags->AndValue( j, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
820 // Zellschutz auf geschuetzter Tabelle nicht setzen
821 if (IsProtected() && (rCxt.getInsertFlag() & IDF_ATTRIB))
823 ScPatternAttr aPattern(pDocument->GetPool());
824 aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
825 ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
828 // create deep copies for conditional formatting
829 CopyConditionalFormat( nCol1, nRow1, nCol2, nRow2, nDx, nDy, pTable);
835 void ScTable::MixData(
836 sc::MixDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
837 sal_uInt16 nFunction, bool bSkipEmpty, const ScTable* pSrcTab )
839 for (SCCOL i=nCol1; i<=nCol2; i++)
840 aCol[i].MixData(rCxt, nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
844 // Markierung von diesem Dokument
845 void ScTable::MixMarked(
846 sc::MixDocContext& rCxt, const ScMarkData& rMark, sal_uInt16 nFunction,
847 bool bSkipEmpty, const ScTable* pSrcTab )
849 for (SCCOL i=0; i<=MAXCOL; i++)
850 aCol[i].MixMarked(rCxt, rMark, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
854 void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
855 ScTable* pTransClip, sal_uInt16 nFlags, bool bAsLink )
857 bool bWasCut = pDocument->IsCutMode();
859 ScDocument* pDestDoc = pTransClip->pDocument;
861 for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
863 SCROW nRow;
864 ScBaseCell* pCell;
866 if ( bAsLink && nFlags == IDF_ALL )
868 // with IDF_ALL, also create links (formulas) for empty cells
870 for ( nRow=nRow1; nRow<=nRow2; nRow++ )
872 // create simple formula, as in ScColumn::CreateRefCell
874 ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
875 ScSingleRefData aRef;
876 aRef.nCol = nCol;
877 aRef.nRow = nRow;
878 aRef.nTab = nTab;
879 aRef.InitFlags(); // -> all absolute
880 aRef.SetFlag3D(true);
881 aRef.CalcRelFromAbs( aDestPos );
882 ScTokenArray aArr;
883 aArr.AddSingleReference( aRef );
885 ScBaseCell* pNew = new ScFormulaCell( pDestDoc, aDestPos, &aArr );
886 pTransClip->PutCell( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pNew );
889 else
891 ScColumnIterator aIter( &aCol[nCol], nRow1, nRow2 );
892 while (aIter.Next( nRow, pCell ))
894 ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
895 ScBaseCell* pNew;
896 if ( bAsLink ) // Referenz erzeugen ?
898 pNew = aCol[nCol].CreateRefCell( pDestDoc, aDestPos, aIter.GetIndex(), nFlags );
900 else // kopieren
902 ScAddress aOwnPos( nCol, nRow, nTab );
903 if (pCell->GetCellType() == CELLTYPE_FORMULA)
905 pNew = pCell->Clone( *pDestDoc, aDestPos, SC_CLONECELL_STARTLISTENING );
907 // Referenzen drehen
908 // bei Cut werden Referenzen spaeter per UpdateTranspose angepasst
910 if (!bWasCut)
911 ((ScFormulaCell*)pNew)->TransposeReference();
913 else
915 pNew = pCell->Clone( *pDestDoc, aDestPos );
918 pTransClip->PutCell( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pNew );
922 // Attribute
924 SCROW nAttrRow1;
925 SCROW nAttrRow2;
926 const ScPatternAttr* pPattern;
927 boost::scoped_ptr<ScAttrIterator> pAttrIter(aCol[nCol].CreateAttrIterator( nRow1, nRow2 ));
928 while ( (pPattern = pAttrIter->Next( nAttrRow1, nAttrRow2 )) != 0 )
930 if ( !IsDefaultItem( pPattern ) )
932 const SfxItemSet& rSet = pPattern->GetItemSet();
933 if ( rSet.GetItemState( ATTR_MERGE, false ) == SFX_ITEM_DEFAULT &&
934 rSet.GetItemState( ATTR_MERGE_FLAG, false ) == SFX_ITEM_DEFAULT &&
935 rSet.GetItemState( ATTR_BORDER, false ) == SFX_ITEM_DEFAULT )
937 // no borders or merge items involved - use pattern as-is
938 for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
939 pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), *pPattern, true );
941 else
943 // transpose borders and merge values, remove merge flags (refreshed after pasting)
944 ScPatternAttr aNewPattern( *pPattern );
945 SfxItemSet& rNewSet = aNewPattern.GetItemSet();
947 const SvxBoxItem& rOldBox = (const SvxBoxItem&)rSet.Get(ATTR_BORDER);
948 if ( rOldBox.GetTop() || rOldBox.GetBottom() || rOldBox.GetLeft() || rOldBox.GetRight() )
950 SvxBoxItem aNew( ATTR_BORDER );
951 aNew.SetLine( rOldBox.GetLine( BOX_LINE_TOP ), BOX_LINE_LEFT );
952 aNew.SetLine( rOldBox.GetLine( BOX_LINE_LEFT ), BOX_LINE_TOP );
953 aNew.SetLine( rOldBox.GetLine( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
954 aNew.SetLine( rOldBox.GetLine( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
955 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_TOP ), BOX_LINE_LEFT );
956 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_LEFT ), BOX_LINE_TOP );
957 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
958 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
959 rNewSet.Put( aNew );
962 const ScMergeAttr& rOldMerge = (const ScMergeAttr&)rSet.Get(ATTR_MERGE);
963 if (rOldMerge.IsMerged())
964 rNewSet.Put( ScMergeAttr( std::min(
965 static_cast<SCsCOL>(rOldMerge.GetRowMerge()),
966 static_cast<SCsCOL>(MAXCOL+1 - (nAttrRow2-nRow1))),
967 std::min(
968 static_cast<SCsROW>(rOldMerge.GetColMerge()),
969 static_cast<SCsROW>(MAXROW+1 - (nCol-nCol1)))));
970 const ScMergeFlagAttr& rOldFlag = (const ScMergeFlagAttr&)rSet.Get(ATTR_MERGE_FLAG);
971 if (rOldFlag.IsOverlapped())
973 sal_Int16 nNewFlags = rOldFlag.GetValue() & ~( SC_MF_HOR | SC_MF_VER );
974 if ( nNewFlags )
975 rNewSet.Put( ScMergeFlagAttr( nNewFlags ) );
976 else
977 rNewSet.ClearItem( ATTR_MERGE_FLAG );
980 for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
981 pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1),
982 static_cast<SCROW>(nCol-nCol1), aNewPattern, true);
988 // fdo#68381 paste cell notes on Transpose
989 bool bCloneCaption = true;
990 for (ScNotes::const_iterator itr = maNotes.begin(); itr != maNotes.end(); ++itr)
992 SCCOL nCol = itr->first.first;
993 SCROW nRow = itr->first.second;
994 if (nCol >= nCol1 && nCol <= nCol2 && nRow >= nRow1 && nRow <= nRow2)
996 ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
997 pTransClip->maNotes.erase(aDestPos);
998 pTransClip->maNotes.insert(aDestPos, itr->second->Clone( ScAddress(nCol, nRow, nTab), *pTransClip->pDocument, aDestPos, bCloneCaption ));
1004 void ScTable::StartAllListeners()
1006 for (SCCOL i=0; i<=MAXCOL; i++)
1007 aCol[i].StartAllListeners();
1011 void ScTable::StartNeededListeners()
1013 for (SCCOL i=0; i<=MAXCOL; i++)
1014 aCol[i].StartNeededListeners();
1018 void ScTable::BroadcastInArea( SCCOL nCol1, SCROW nRow1,
1019 SCCOL nCol2, SCROW nRow2 )
1021 if (nCol2 > MAXCOL) nCol2 = MAXCOL;
1022 if (nRow2 > MAXROW) nRow2 = MAXROW;
1023 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1024 for (SCCOL i = nCol1; i <= nCol2; i++)
1025 aCol[i].BroadcastInArea( nRow1, nRow2 );
1029 void ScTable::StartListeningInArea(
1030 sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1032 if (nCol2 > MAXCOL) nCol2 = MAXCOL;
1033 if (nRow2 > MAXROW) nRow2 = MAXROW;
1034 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1035 for (SCCOL i = nCol1; i <= nCol2; i++)
1036 aCol[i].StartListeningInArea(rCxt, nRow1, nRow2);
1040 void ScTable::CopyToTable(
1041 sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1042 sal_uInt16 nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData,
1043 bool bAsLink, bool bColRowFlags )
1045 if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
1046 return;
1048 if (nFlags)
1049 for (SCCOL i = nCol1; i <= nCol2; i++)
1050 aCol[i].CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked,
1051 pDestTab->aCol[i], pMarkData, bAsLink);
1053 if (!bColRowFlags) // Spaltenbreiten/Zeilenhoehen/Flags
1054 return;
1056 //remove old notes
1057 if (nFlags & IDF_NOTE)
1058 pDestTab->maNotes.erase(nCol1, nRow1, nCol2, nRow2);
1060 bool bAddNotes = nFlags & (IDF_NOTE | IDF_ADDNOTES);
1061 if (bAddNotes)
1063 bool bCloneCaption = (nFlags & IDF_NOCAPTIONS) == 0;
1064 pDestTab->maNotes.CopyFromClip(maNotes, pDestTab->pDocument, nCol1, nRow1, nCol2, nRow2, 0, 0, pDestTab->nTab, bCloneCaption);
1067 if(pDestTab->pDocument->IsUndo() && (nFlags & IDF_ATTRIB))
1069 pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->pDocument, *mpCondFormatList));
1072 if (pDBDataNoName)
1074 ScDBData* pNewDBData = new ScDBData(*pDBDataNoName);
1075 SCCOL aCol1, aCol2;
1076 SCROW aRow1, aRow2;
1077 SCTAB aTab;
1078 pNewDBData->GetArea(aTab, aCol1, aRow1, aCol2, aRow2);
1079 pNewDBData->MoveTo(pDestTab->nTab, aCol1, aRow1, aCol2, aRow2);
1080 pDestTab->SetAnonymousDBData(pNewDBData);
1082 // Charts muessen beim Ein-/Ausblenden angepasst werden
1083 ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection();
1085 bool bFlagChange = false;
1087 bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
1088 bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
1090 if (bWidth || bHeight)
1092 if (bWidth)
1094 for (SCCOL i = nCol1; i <= nCol2; ++i)
1096 bool bThisHidden = ColHidden(i);
1097 bool bHiddenChange = (pDestTab->ColHidden(i) != bThisHidden);
1098 bool bChange = bHiddenChange || (pDestTab->pColWidth[i] != pColWidth[i]);
1099 pDestTab->pColWidth[i] = pColWidth[i];
1100 pDestTab->pColFlags[i] = pColFlags[i];
1101 pDestTab->SetColHidden(i, i, bThisHidden);
1102 //! Aenderungen zusammenfassen?
1103 if (bHiddenChange && pCharts)
1104 pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab ));
1106 if (bChange)
1107 bFlagChange = true;
1109 pDestTab->SetColManualBreaks( maColManualBreaks);
1112 if (bHeight)
1114 bool bChange = pDestTab->GetRowHeight(nRow1, nRow2) != GetRowHeight(nRow1, nRow2);
1116 if (bChange)
1117 bFlagChange = true;
1119 pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
1120 pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2);
1122 // Hidden flags.
1123 for (SCROW i = nRow1; i <= nRow2; ++i)
1125 SCROW nLastRow;
1126 bool bHidden = RowHidden(i, NULL, &nLastRow);
1127 if (nLastRow >= nRow2)
1128 // the last row shouldn't exceed the upper bound the caller specified.
1129 nLastRow = nRow2;
1131 bool bHiddenChanged = pDestTab->SetRowHidden(i, nLastRow, bHidden);
1132 if (bHiddenChanged && pCharts)
1133 // Hidden flags differ.
1134 pCharts->SetRangeDirty(ScRange(0, i, nTab, MAXCOL, nLastRow, nTab));
1136 if (bHiddenChanged)
1137 bFlagChange = true;
1139 // Jump to the last row of the identical flag segment.
1140 i = nLastRow;
1143 // Filtered flags.
1144 for (SCROW i = nRow1; i <= nRow2; ++i)
1146 SCROW nLastRow;
1147 bool bFiltered = RowFiltered(i, NULL, &nLastRow);
1148 if (nLastRow >= nRow2)
1149 // the last row shouldn't exceed the upper bound the caller specified.
1150 nLastRow = nRow2;
1151 pDestTab->SetRowFiltered(i, nLastRow, bFiltered);
1152 i = nLastRow;
1154 pDestTab->SetRowManualBreaks( maRowManualBreaks);
1158 if (bFlagChange)
1159 pDestTab->InvalidatePageBreaks();
1161 if(nFlags & IDF_ATTRIB)
1163 pDestTab->mpCondFormatList->DeleteArea(nCol1, nRow1, nCol2, nRow2);
1164 pDestTab->CopyConditionalFormat(nCol1, nRow1, nCol2, nRow2, 0, 0, this);
1167 if(nFlags & IDF_OUTLINE) // also only when bColRowFlags
1168 pDestTab->SetOutlineTable( pOutlineTable );
1172 void ScTable::UndoToTable(
1173 sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1174 sal_uInt16 nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData )
1176 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1178 bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
1179 bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
1181 for ( SCCOL i = 0; i <= MAXCOL; i++)
1183 if ( i >= nCol1 && i <= nCol2 )
1184 aCol[i].UndoToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, pDestTab->aCol[i], pMarkData);
1185 else
1186 aCol[i].CopyToColumn(rCxt, 0, MAXROW, IDF_FORMULA, false, pDestTab->aCol[i]);
1189 //remove old notes
1190 if (nFlags & IDF_CONTENTS)
1191 pDestTab->maNotes.erase(nCol1, nRow1, nCol2, nRow2);
1193 if (nFlags & IDF_ATTRIB)
1194 pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->pDocument, *mpCondFormatList));
1196 bool bAddNotes = nFlags & (IDF_NOTE | IDF_ADDNOTES);
1197 if (bAddNotes)
1199 bool bCloneCaption = (nFlags & IDF_NOCAPTIONS) == 0;
1200 pDestTab->maNotes.CopyFromClip(maNotes, pDocument, nCol1, nRow1, nCol2, nRow2, 0, 0, pDestTab->nTab, bCloneCaption);
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] );
1226 // insert notes with captions
1227 for(ScNotes::iterator itr = pDestTab->maNotes.begin(); itr != pDestTab->maNotes.end(); ++itr)
1229 SCCOL nCol = itr->first.first;
1230 SCROW nRow = itr->first.second;
1231 ScPostIt* pPostIt = itr->second;
1233 pDestTab->maNotes.insert(nCol, nRow, pPostIt->Clone( ScAddress(nCol, nRow, nTab),*pDestTab->pDocument, ScAddress(nCol, nRow, pDestTab->nTab), true ));
1237 void ScTable::InvalidateTableArea()
1239 bTableAreaValid = false;
1242 void ScTable::InvalidatePageBreaks()
1244 mbPageBreaksValid = false;
1247 void ScTable::CopyScenarioTo( ScTable* pDestTab ) const
1249 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1251 for (SCCOL i=0; i<=MAXCOL; i++)
1252 aCol[i].CopyScenarioTo( pDestTab->aCol[i] );
1255 void ScTable::CopyScenarioFrom( const ScTable* pSrcTab )
1257 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1259 for (SCCOL i=0; i<=MAXCOL; i++)
1260 aCol[i].CopyScenarioFrom( pSrcTab->aCol[i] );
1263 void ScTable::MarkScenarioIn( ScMarkData& rDestMark, sal_uInt16 nNeededBits ) const
1265 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1267 if ( ( nScenarioFlags & nNeededBits ) != nNeededBits ) // alle Bits gesetzt?
1268 return;
1270 for (SCCOL i=0; i<=MAXCOL; i++)
1271 aCol[i].MarkScenarioIn( rDestMark );
1274 bool ScTable::HasScenarioRange( const ScRange& rRange ) const
1276 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1278 ScRange aTabRange = rRange;
1279 aTabRange.aStart.SetTab( nTab );
1280 aTabRange.aEnd.SetTab( nTab );
1282 const ScRangeList* pList = GetScenarioRanges();
1284 if (pList)
1286 for ( size_t j = 0, n = pList->size(); j < n; j++ )
1288 const ScRange* pR = (*pList)[j];
1289 if ( pR->Intersects( aTabRange ) )
1290 return true;
1294 return false;
1297 void ScTable::InvalidateScenarioRanges()
1299 delete pScenarioRanges;
1300 pScenarioRanges = NULL;
1303 const ScRangeList* ScTable::GetScenarioRanges() const
1305 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1307 if (!pScenarioRanges)
1309 ((ScTable*)this)->pScenarioRanges = new ScRangeList;
1310 ScMarkData aMark;
1311 MarkScenarioIn( aMark, 0 ); // immer
1312 aMark.FillRangeListWithMarks( pScenarioRanges, false );
1314 return pScenarioRanges;
1317 bool ScTable::TestCopyScenarioTo( const ScTable* pDestTab ) const
1319 OSL_ENSURE( bScenario, "bScenario == FALSE" );
1321 if (!pDestTab->IsProtected())
1322 return true;
1324 bool bOk = true;
1325 for (SCCOL i=0; i<=MAXCOL && bOk; i++)
1326 bOk = aCol[i].TestCopyScenarioTo( pDestTab->aCol[i] );
1327 return bOk;
1330 void ScTable::PutCell( SCCOL nCol, SCROW nRow, ScBaseCell* pCell )
1332 if (ValidColRow(nCol,nRow))
1334 if (pCell)
1335 aCol[nCol].Insert( nRow, pCell );
1336 else
1337 aCol[nCol].Delete( nRow );
1342 void ScTable::PutCell( SCCOL nCol, SCROW nRow, sal_uLong nFormatIndex, ScBaseCell* pCell )
1344 if (ValidColRow(nCol,nRow))
1346 if (pCell)
1347 aCol[nCol].Insert( nRow, nFormatIndex, pCell );
1348 else
1349 aCol[nCol].Delete( nRow );
1354 void ScTable::PutCell( const ScAddress& rPos, ScBaseCell* pCell )
1356 if (pCell)
1357 aCol[rPos.Col()].Insert( rPos.Row(), pCell );
1358 else
1359 aCol[rPos.Col()].Delete( rPos.Row() );
1363 bool ScTable::SetString( SCCOL nCol, SCROW nRow, SCTAB nTabP, const String& rString,
1364 ScSetStringParam* pParam )
1366 if (ValidColRow(nCol,nRow))
1367 return aCol[nCol].SetString(
1368 nRow, nTabP, rString, pDocument->GetAddressConvention(), pParam );
1369 else
1370 return false;
1373 void ScTable::SetEditText( SCCOL nCol, SCROW nRow, EditTextObject* pEditText )
1375 if (!ValidColRow(nCol, nRow))
1377 delete pEditText;
1378 return;
1381 aCol[nCol].SetEditText(nRow, pEditText);
1384 void ScTable::SetEditText( SCCOL nCol, SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
1386 if (!ValidColRow(nCol, nRow))
1387 return;
1389 aCol[nCol].SetEditText(nRow, rEditText, pEditPool);
1392 void ScTable::SetEmptyCell( SCCOL nCol, SCROW nRow )
1394 if (!ValidColRow(nCol, nRow))
1395 return;
1397 aCol[nCol].Delete(nRow);
1400 void ScTable::SetFormula(
1401 SCCOL nCol, SCROW nRow, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram )
1403 if (!ValidColRow(nCol, nRow))
1404 return;
1406 aCol[nCol].SetFormula(nRow, rArray, eGram);
1409 void ScTable::SetFormula(
1410 SCCOL nCol, SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram )
1412 if (!ValidColRow(nCol, nRow))
1413 return;
1415 aCol[nCol].SetFormula(nRow, rFormula, eGram);
1418 void ScTable::SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell )
1420 if (!ValidColRow(nCol, nRow))
1422 pCell->Delete();
1423 return;
1426 aCol[nCol].SetFormulaCell(nRow, pCell);
1429 void ScTable::SetValue( SCCOL nCol, SCROW nRow, const double& rVal )
1431 if (ValidColRow(nCol, nRow))
1432 aCol[nCol].SetValue( nRow, rVal );
1436 void ScTable::GetString( SCCOL nCol, SCROW nRow, OUString& rString ) const
1438 if (ValidColRow(nCol,nRow))
1439 aCol[nCol].GetString( nRow, rString );
1440 else
1441 rString = OUString();
1444 const OUString* ScTable::GetStringCell( SCCOL nCol, SCROW nRow ) const
1446 if (!ValidColRow(nCol,nRow))
1447 return NULL;
1449 return aCol[nCol].GetStringCell(nRow);
1452 double* ScTable::GetValueCell( SCCOL nCol, SCROW nRow )
1454 if (!ValidColRow(nCol,nRow))
1455 return NULL;
1457 return aCol[nCol].GetValueCell(nRow);
1460 void ScTable::GetInputString( SCCOL nCol, SCROW nRow, OUString& rString ) const
1462 if (ValidColRow(nCol,nRow))
1463 aCol[nCol].GetInputString( nRow, rString );
1464 else
1465 rString = OUString();
1469 double ScTable::GetValue( SCCOL nCol, SCROW nRow ) const
1471 if (ValidColRow( nCol, nRow ))
1472 return aCol[nCol].GetValue( nRow );
1473 return 0.0;
1476 const EditTextObject* ScTable::GetEditText( SCCOL nCol, SCROW nRow ) const
1478 if (!ValidColRow(nCol, nRow))
1479 return NULL;
1481 return aCol[nCol].GetEditText(nRow);
1484 void ScTable::RemoveEditTextCharAttribs( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
1486 if (!ValidColRow(nCol, nRow))
1487 return;
1489 return aCol[nCol].RemoveEditTextCharAttribs(nRow, rAttr);
1492 void ScTable::GetFormula( SCCOL nCol, SCROW nRow, OUString& rFormula ) const
1494 if (ValidColRow(nCol,nRow))
1495 aCol[nCol].GetFormula( nRow, rFormula );
1496 else
1497 rFormula = OUString();
1500 const ScTokenArray* ScTable::GetFormulaTokens( SCCOL nCol, SCROW nRow ) const
1502 if (!ValidColRow(nCol, nRow))
1503 return NULL;
1505 return aCol[nCol].GetFormulaTokens(nRow);
1508 const ScFormulaCell* ScTable::GetFormulaCell( SCCOL nCol, SCROW nRow ) const
1510 if (!ValidColRow(nCol, nRow))
1511 return NULL;
1513 return aCol[nCol].GetFormulaCell(nRow);
1516 ScFormulaCell* ScTable::GetFormulaCell( SCCOL nCol, SCROW nRow )
1518 if (!ValidColRow(nCol, nRow))
1519 return NULL;
1521 return aCol[nCol].GetFormulaCell(nRow);
1524 ScNotes* ScTable::GetNotes()
1526 return &maNotes;
1530 void ScTable::InitializeNoteCaptions( bool bForced )
1532 if( mxUninitNotes.get() && (bForced || pDocument->IsUndoEnabled()) )
1534 for( ScAddress2DVec::iterator aIt = mxUninitNotes->begin(), aEnd = mxUninitNotes->end(); aIt != aEnd; ++aIt )
1535 if( ScPostIt* pNote = maNotes.findByAddress( aIt->first, aIt->second ) )
1536 pNote->GetOrCreateCaption( ScAddress( aIt->first, aIt->second, nTab ) );
1537 mxUninitNotes.reset();
1541 CellType ScTable::GetCellType( SCCOL nCol, SCROW nRow ) const
1543 if (ValidColRow( nCol, nRow ))
1544 return aCol[nCol].GetCellType( nRow );
1545 return CELLTYPE_NONE;
1549 ScBaseCell* ScTable::GetCell( SCCOL nCol, SCROW nRow ) const
1551 if (ValidColRow( nCol, nRow ))
1552 return aCol[nCol].GetCell( nRow );
1554 OSL_FAIL("GetCell: out of range");
1555 return NULL;
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 );
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 bool bOldAutoCalc = pDocument->GetAutoCalc();
1685 pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1686 for (SCCOL i = 0; i <= MAXCOL; ++i)
1687 aCol[i].BroadcastRecalcOnRefMove();
1688 pDocument->SetAutoCalc( bOldAutoCalc );
1691 void ScTable::SetLoadingMedium(bool bLoading)
1693 mpRowHeights->enableTreeSearch(!bLoading);
1697 void ScTable::CalcAll()
1699 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CalcAll();
1703 void ScTable::CompileAll()
1705 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CompileAll();
1707 if(mpCondFormatList)
1708 mpCondFormatList->CompileAll();
1712 void ScTable::CompileXML( ScProgress& rProgress )
1714 if (mpRangeName)
1715 mpRangeName->CompileUnresolvedXML();
1717 for (SCCOL i=0; i <= MAXCOL; i++)
1719 aCol[i].CompileXML( rProgress );
1722 if(mpCondFormatList)
1723 mpCondFormatList->CompileXML();
1726 bool ScTable::CompileErrorCells(sal_uInt16 nErrCode)
1728 bool bCompiled = false;
1729 for (SCCOL i = 0; i <= MAXCOL; ++i)
1731 if (aCol[i].CompileErrorCells(nErrCode))
1732 bCompiled = true;
1735 return bCompiled;
1738 void ScTable::CalcAfterLoad()
1740 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad();
1744 void ScTable::ResetChanged( const ScRange& rRange )
1746 SCCOL nStartCol = rRange.aStart.Col();
1747 SCROW nStartRow = rRange.aStart.Row();
1748 SCCOL nEndCol = rRange.aEnd.Col();
1749 SCROW nEndRow = rRange.aEnd.Row();
1751 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
1752 aCol[nCol].ResetChanged(nStartRow, nEndRow);
1755 // Attribute
1757 const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) const
1759 if (ValidColRow(nCol,nRow))
1760 return aCol[nCol].GetAttr( nRow, nWhich );
1761 else
1762 return NULL;
1765 sal_uInt32 ScTable::GetNumberFormat( const ScAddress& rPos ) const
1767 return ValidColRow(rPos.Col(),rPos.Row()) ?
1768 aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) :
1772 sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nRow ) const
1774 if (ValidColRow(nCol,nRow))
1775 return aCol[nCol].GetNumberFormat( nRow );
1776 else
1777 return 0;
1780 sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
1782 if (!ValidCol(nCol) || !ValidRow(nStartRow) || !ValidRow(nEndRow))
1783 return 0;
1785 return aCol[nCol].GetNumberFormat(nStartRow, nEndRow);
1788 void ScTable::SetNumberFormat( SCCOL nCol, SCROW nRow, sal_uInt32 nNumberFormat )
1790 if (!ValidColRow(nCol, nRow))
1791 return;
1793 aCol[nCol].SetNumberFormat(nRow, nNumberFormat);
1796 const ScPatternAttr* ScTable::GetPattern( SCCOL nCol, SCROW nRow ) const
1798 if (ValidColRow(nCol,nRow))
1799 return aCol[nCol].GetPattern( nRow );
1800 else
1802 OSL_FAIL("wrong column or row");
1803 return pDocument->GetDefPattern(); // for safety
1808 const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
1810 if ( ValidColRow( nCol, nStartRow ) && ValidRow( nEndRow ) && (nStartRow <= nEndRow) )
1811 return aCol[nCol].GetMostUsedPattern( nStartRow, nEndRow );
1812 else
1813 return NULL;
1817 bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nMask ) const
1819 bool bFound = false;
1820 for (SCCOL i=nCol1; i<=nCol2 && !bFound; i++)
1821 bFound |= aCol[i].HasAttrib( nRow1, nRow2, nMask );
1822 return bFound;
1826 bool ScTable::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
1828 bool bFound = false;
1829 for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
1830 bFound |= aCol[i].HasAttribSelection( rMark, nMask );
1831 return bFound;
1835 bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
1836 SCCOL& rEndCol, SCROW& rEndRow,
1837 bool bRefresh )
1839 if (!(ValidCol(nStartCol) && ValidCol(rEndCol)))
1841 OSL_FAIL("ScTable::ExtendMerge: invalid column number");
1842 return false;
1844 bool bFound = false;
1845 SCCOL nOldEndX = rEndCol;
1846 SCROW nOldEndY = rEndRow;
1847 for (SCCOL i=nStartCol; i<=nOldEndX; i++)
1848 bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh );
1849 return bFound;
1853 bool ScTable::IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bIgnoreNotes ) const
1855 if (!(ValidCol(nCol1) && ValidCol(nCol2)))
1857 OSL_FAIL("ScTable::IsBlockEmpty: invalid column number");
1858 return false;
1860 bool bEmpty = true;
1861 for (SCCOL i=nCol1; i<=nCol2 && bEmpty; i++)
1863 bEmpty = aCol[i].IsEmptyBlock( nRow1, nRow2 );
1864 if (!bIgnoreNotes)
1866 for (ScNotes::const_iterator itr = maNotes.begin(); itr != maNotes.end() && bEmpty; ++itr)
1868 SCCOL nCol = itr->first.first;
1869 SCROW nRow = itr->first.second;
1871 if (nCol >= nCol1 && nCol <= nCol2 && nRow >= nRow1 && nRow <= nRow2)
1872 bEmpty = false;
1876 return bEmpty;
1879 SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2,
1880 SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY,
1881 const ScPatternAttr* pPattern, const SfxItemSet* pCondSet )
1883 // Rueckgabe = neues nArrY
1885 sal_uInt8 nRotDir = pPattern->GetRotateDir( pCondSet );
1886 if ( nRotDir != SC_ROTDIR_NONE )
1888 bool bHit = true;
1889 if ( nCol+1 < nX1 ) // column to the left
1890 bHit = ( nRotDir != SC_ROTDIR_LEFT );
1891 else if ( nCol > nX2+1 ) // column to the right
1892 bHit = ( nRotDir != SC_ROTDIR_RIGHT ); // SC_ROTDIR_STANDARD may now also be extended to the left
1894 if ( bHit )
1896 double nFactor = 0.0;
1897 if ( nCol > nX2+1 )
1899 long nRotVal = ((const SfxInt32Item&) pPattern->
1900 GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue();
1901 double nRealOrient = nRotVal * F_PI18000; // 1/100 Grad
1902 double nCos = cos( nRealOrient );
1903 double nSin = sin( nRealOrient );
1904 //! begrenzen !!!
1905 //! zusaetzlich Faktor fuer unterschiedliche PPT X/Y !!!
1907 // bei SC_ROTDIR_LEFT kommt immer ein negativer Wert heraus,
1908 // wenn der Modus beruecksichtigt wird
1909 nFactor = -fabs( nCos / nSin );
1912 for ( SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ )
1914 if (!RowHidden(nRow))
1916 bool bHitOne = true;
1917 if ( nCol > nX2+1 )
1919 // reicht die gedrehte Zelle bis in den sichtbaren Bereich?
1921 SCCOL nTouchedCol = nCol;
1922 long nWidth = static_cast<long>(mpRowHeights->getValue(nRow) * nFactor);
1923 OSL_ENSURE(nWidth <= 0, "Wrong direction");
1924 while ( nWidth < 0 && nTouchedCol > 0 )
1926 --nTouchedCol;
1927 nWidth += GetColWidth( nTouchedCol );
1929 if ( nTouchedCol > nX2 )
1930 bHitOne = false;
1933 if (bHitOne)
1935 while ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo < nRow )
1936 ++nArrY;
1937 if ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo == nRow )
1938 pRowInfo[nArrY].nRotMaxCol = nCol;
1945 return nArrY;
1948 void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 )
1950 if ( !pColWidth || !mpRowHeights || !pColFlags || !pRowFlags )
1952 OSL_FAIL( "Row/column info missing" );
1953 return;
1956 // nRotMaxCol ist auf SC_ROTMAX_NONE initialisiert, nRowNo ist schon gesetzt
1958 SCROW nY1 = pRowInfo[0].nRowNo;
1959 SCROW nY2 = pRowInfo[nArrCount-1].nRowNo;
1961 for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
1963 if (!ColHidden(nCol))
1965 SCSIZE nArrY = 0;
1966 ScDocAttrIterator aIter( pDocument, nTab, nCol, nY1, nCol, nY2 );
1967 SCCOL nAttrCol;
1968 SCROW nAttrRow1, nAttrRow2;
1969 const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
1970 while ( pPattern )
1972 const SfxPoolItem* pCondItem;
1973 if ( pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, true, &pCondItem )
1974 == SFX_ITEM_SET )
1976 // alle Formate durchgehen, damit die Zellen nicht einzeln
1977 // angeschaut werden muessen
1979 const std::vector<sal_uInt32>& rCondFormatData = static_cast<const ScCondFormatItem*>(pCondItem)->GetCondFormatData();
1980 ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool();
1981 if (mpCondFormatList && pStylePool && !rCondFormatData.empty())
1983 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatData.begin(), itrEnd = rCondFormatData.end();
1984 itr != itrEnd; ++itr)
1986 const ScConditionalFormat* pFormat = mpCondFormatList->GetFormat(*itr);
1987 if ( pFormat )
1989 size_t nEntryCount = pFormat->size();
1990 for (size_t nEntry=0; nEntry<nEntryCount; nEntry++)
1992 const ScFormatEntry* pEntry = pFormat->GetEntry(nEntry);
1993 if(pEntry->GetType() != condformat::CONDITION)
1994 continue;
1996 String aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
1997 if (aStyleName.Len())
1999 SfxStyleSheetBase* pStyleSheet =
2000 pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
2001 if ( pStyleSheet )
2003 FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2004 nCol, nAttrRow1, nAttrRow2,
2005 nArrY, pPattern, &pStyleSheet->GetItemSet() );
2006 // nArrY nicht veraendern
2015 nArrY = FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2016 nCol, nAttrRow1, nAttrRow2,
2017 nArrY, pPattern, NULL );
2019 pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
2025 bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
2027 // nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32
2028 sal_uInt16 nEdges;
2030 if ( nCol1 == nCol2 )
2031 { // linke und rechte Spalte
2032 const sal_uInt16 n = 4 | 16;
2033 nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n );
2034 // nicht (4 und 16) oder 1 oder 32
2035 if ( nEdges && (((nEdges & n) != n) || (nEdges & 33)) )
2036 return true; // linke oder rechte Kante fehlt oder offen
2038 else
2039 { // linke Spalte
2040 nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, 4 );
2041 // nicht 4 oder 1 oder 32
2042 if ( nEdges && (((nEdges & 4) != 4) || (nEdges & 33)) )
2043 return true; // linke Kante fehlt oder offen
2044 // rechte Spalte
2045 nEdges = aCol[nCol2].GetBlockMatrixEdges( nRow1, nRow2, 16 );
2046 // nicht 16 oder 1 oder 32
2047 if ( nEdges && (((nEdges & 16) != 16) || (nEdges & 33)) )
2048 return true; // rechte Kante fehlt oder offen
2051 if ( nRow1 == nRow2 )
2052 { // obere und untere Zeile
2053 bool bOpen = false;
2054 const sal_uInt16 n = 2 | 8;
2055 for ( SCCOL i=nCol1; i<=nCol2; i++)
2057 nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n );
2058 if ( nEdges )
2060 if ( (nEdges & n) != n )
2061 return true; // obere oder untere Kante fehlt
2062 if ( nEdges & 4 )
2063 bOpen = true; // linke Kante oeffnet, weitersehen
2064 else if ( !bOpen )
2065 return true; // es gibt was, was nicht geoeffnet wurde
2066 if ( nEdges & 16 )
2067 bOpen = false; // rechte Kante schliesst
2070 if ( bOpen )
2071 return true; // es geht noch weiter
2073 else
2075 sal_uInt16 j, n;
2076 SCROW nR;
2077 // erst obere Zeile, dann untere Zeile
2078 for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 )
2080 bool bOpen = false;
2081 for ( SCCOL i=nCol1; i<=nCol2; i++)
2083 nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n );
2084 if ( nEdges )
2086 // in oberere Zeile keine obere Kante bzw.
2087 // in unterer Zeile keine untere Kante
2088 if ( (nEdges & n) != n )
2089 return true;
2090 if ( nEdges & 4 )
2091 bOpen = true; // linke Kante oeffnet, weitersehen
2092 else if ( !bOpen )
2093 return true; // es gibt was, was nicht geoeffnet wurde
2094 if ( nEdges & 16 )
2095 bOpen = false; // rechte Kante schliesst
2098 if ( bOpen )
2099 return true; // es geht noch weiter
2102 return false;
2106 bool ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const
2108 bool bFound = false;
2109 for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
2110 bFound |= aCol[i].HasSelectionMatrixFragment(rMark);
2111 return bFound;
2115 bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
2116 SCROW nRow2, bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
2118 if ( !ValidColRow( nCol2, nRow2 ) )
2120 OSL_FAIL("IsBlockEditable: invalid column or row");
2121 if (pOnlyNotBecauseOfMatrix)
2122 *pOnlyNotBecauseOfMatrix = false;
2123 return false;
2126 bool bIsEditable = true;
2127 if ( nLockCount )
2128 bIsEditable = false;
2129 else if ( IsProtected() && !pDocument->IsScenario(nTab) )
2131 bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED );
2132 if(bIsEditable)
2134 // If Sheet is protected and cells are not protected then
2135 // check the active scenario protect flag if this range is
2136 // on the active scenario range. Note the 'copy back' must also
2137 // be set to apply protection.
2138 sal_uInt16 nScenTab = nTab+1;
2139 while(pDocument->IsScenario(nScenTab))
2141 ScRange aEditRange(nCol1, nRow1, nScenTab, nCol2, nRow2, nScenTab);
2142 if(pDocument->IsActiveScenario(nScenTab) && pDocument->HasScenarioRange(nScenTab, aEditRange))
2144 sal_uInt16 nFlags;
2145 pDocument->GetScenarioFlags(nScenTab,nFlags);
2146 bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
2147 break;
2149 nScenTab++;
2153 else if (pDocument->IsScenario(nTab))
2155 // Determine if the preceding sheet is protected
2156 SCTAB nActualTab = nTab;
2159 nActualTab--;
2161 while(pDocument->IsScenario(nActualTab));
2163 if(pDocument->IsTabProtected(nActualTab))
2165 ScRange aEditRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
2166 if(pDocument->HasScenarioRange(nTab, aEditRange))
2168 sal_uInt16 nFlags;
2169 pDocument->GetScenarioFlags(nTab,nFlags);
2170 bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
2174 if ( bIsEditable )
2176 if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) )
2178 bIsEditable = false;
2179 if ( pOnlyNotBecauseOfMatrix )
2180 *pOnlyNotBecauseOfMatrix = true;
2182 else if ( pOnlyNotBecauseOfMatrix )
2183 *pOnlyNotBecauseOfMatrix = false;
2185 else if ( pOnlyNotBecauseOfMatrix )
2186 *pOnlyNotBecauseOfMatrix = false;
2187 return bIsEditable;
2191 bool ScTable::IsSelectionEditable( const ScMarkData& rMark,
2192 bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
2194 bool bIsEditable = true;
2195 if ( nLockCount )
2196 bIsEditable = false;
2197 else if ( IsProtected() && !pDocument->IsScenario(nTab) )
2199 if((bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED )) != false)
2201 // If Sheet is protected and cells are not protected then
2202 // check the active scenario protect flag if this area is
2203 // in the active scenario range.
2204 ScRangeList aRanges;
2205 rMark.FillRangeListWithMarks( &aRanges, false );
2206 SCTAB nScenTab = nTab+1;
2207 while(pDocument->IsScenario(nScenTab) && bIsEditable)
2209 if(pDocument->IsActiveScenario(nScenTab))
2211 for (size_t i=0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++ )
2213 ScRange aRange = *aRanges[ i ];
2214 if(pDocument->HasScenarioRange(nScenTab, aRange))
2216 sal_uInt16 nFlags;
2217 pDocument->GetScenarioFlags(nScenTab,nFlags);
2218 bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
2222 nScenTab++;
2226 else if (pDocument->IsScenario(nTab))
2228 // Determine if the preceding sheet is protected
2229 SCTAB nActualTab = nTab;
2232 nActualTab--;
2234 while(pDocument->IsScenario(nActualTab));
2236 if(pDocument->IsTabProtected(nActualTab))
2238 ScRangeList aRanges;
2239 rMark.FillRangeListWithMarks( &aRanges, false );
2240 for (size_t i = 0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++)
2242 ScRange aRange = *aRanges[ i ];
2243 if(pDocument->HasScenarioRange(nTab, aRange))
2245 sal_uInt16 nFlags;
2246 pDocument->GetScenarioFlags(nTab,nFlags);
2247 bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
2252 if ( bIsEditable )
2254 if ( HasSelectionMatrixFragment( rMark ) )
2256 bIsEditable = false;
2257 if ( pOnlyNotBecauseOfMatrix )
2258 *pOnlyNotBecauseOfMatrix = true;
2260 else if ( pOnlyNotBecauseOfMatrix )
2261 *pOnlyNotBecauseOfMatrix = false;
2263 else if ( pOnlyNotBecauseOfMatrix )
2264 *pOnlyNotBecauseOfMatrix = false;
2265 return bIsEditable;
2270 void ScTable::LockTable()
2272 ++nLockCount;
2276 void ScTable::UnlockTable()
2278 if (nLockCount)
2279 --nLockCount;
2280 else
2282 OSL_FAIL("UnlockTable without LockTable");
2287 void ScTable::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
2289 for (SCCOL i=0; i<=MAXCOL; i++)
2290 aCol[i].MergeSelectionPattern( rState, rMark, bDeep );
2294 void ScTable::MergePatternArea( ScMergePatternState& rState, SCCOL nCol1, SCROW nRow1,
2295 SCCOL nCol2, SCROW nRow2, bool bDeep ) const
2297 for (SCCOL i=nCol1; i<=nCol2; i++)
2298 aCol[i].MergePatternArea( rState, nRow1, nRow2, bDeep );
2302 void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags,
2303 SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const
2305 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2307 PutInOrder(nStartCol, nEndCol);
2308 PutInOrder(nStartRow, nEndRow);
2309 for (SCCOL i=nStartCol; i<=nEndCol; i++)
2310 aCol[i].MergeBlockFrame( pLineOuter, pLineInner, rFlags,
2311 nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
2316 void ScTable::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
2317 SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
2319 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2321 PutInOrder(nStartCol, nEndCol);
2322 PutInOrder(nStartRow, nEndRow);
2323 for (SCCOL i=nStartCol; i<=nEndCol; i++)
2324 aCol[i].ApplyBlockFrame( pLineOuter, pLineInner,
2325 nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
2330 void ScTable::ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
2332 if (ValidColRow(nCol,nRow))
2333 aCol[nCol].ApplyPattern( nRow, rAttr );
2337 void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2338 const ScPatternAttr& rAttr, ScEditDataArray* pDataArray )
2340 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2342 PutInOrder(nStartCol, nEndCol);
2343 PutInOrder(nStartRow, nEndRow);
2344 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2345 aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr, pDataArray);
2349 bool ScTable::SetAttrEntries(SCCOL nCol, ScAttrEntry* pData, SCSIZE nSize)
2351 if (!ValidCol(nCol))
2352 return false;
2354 return aCol[nCol].SetAttrEntries(pData, nSize);
2357 void ScTable::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
2358 const ScPatternAttr& rPattern, short nNewType )
2360 SCCOL nEndCol = rRange.aEnd.Col();
2361 for ( SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ )
2363 aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
2367 void ScTable::AddCondFormatData( const ScRangeList& rRange, sal_uInt32 nIndex )
2369 size_t n = rRange.size();
2370 for(size_t i = 0; i < n; ++i)
2372 const ScRange* pRange = rRange[i];
2373 SCCOL nColStart = pRange->aStart.Col();
2374 SCCOL nColEnd = pRange->aEnd.Col();
2375 SCROW nRowStart = pRange->aStart.Row();
2376 SCROW nRowEnd = pRange->aEnd.Row();
2377 for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2379 aCol[nCol].AddCondFormat(nRowStart, nRowEnd, nIndex);
2384 void ScTable::RemoveCondFormatData( const ScRangeList& rRange, sal_uInt32 nIndex )
2386 size_t n = rRange.size();
2387 for(size_t i = 0; i < n; ++i)
2389 const ScRange* pRange = rRange[i];
2390 SCCOL nColStart = pRange->aStart.Col();
2391 SCCOL nColEnd = pRange->aEnd.Col();
2392 SCROW nRowStart = pRange->aStart.Row();
2393 SCROW nRowEnd = pRange->aEnd.Row();
2394 for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2396 aCol[nCol].RemoveCondFormat(nRowStart, nRowEnd, nIndex);
2403 void ScTable::ApplyStyle( SCCOL nCol, SCROW nRow, const ScStyleSheet& rStyle )
2405 if (ValidColRow(nCol,nRow))
2406 aCol[nCol].ApplyStyle( nRow, rStyle );
2410 void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet& rStyle )
2412 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2414 PutInOrder(nStartCol, nEndCol);
2415 PutInOrder(nStartRow, nEndRow);
2416 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2417 aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
2422 void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
2424 for (SCCOL i=0; i<=MAXCOL; i++)
2425 aCol[i].ApplySelectionStyle( rStyle, rMark );
2429 void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark,
2430 const ::editeng::SvxBorderLine* pLine, bool bColorOnly )
2432 if ( bColorOnly && !pLine )
2433 return;
2435 for (SCCOL i=0; i<=MAXCOL; i++)
2436 aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly );
2440 const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW nRow ) const
2442 if (ValidColRow(nCol, nRow))
2443 return aCol[nCol].GetStyle(nRow);
2444 else
2445 return NULL;
2449 const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
2451 rFound = false;
2453 bool bEqual = true;
2454 bool bColFound;
2456 const ScStyleSheet* pStyle = NULL;
2457 const ScStyleSheet* pNewStyle;
2459 for (SCCOL i=0; i<=MAXCOL && bEqual; i++)
2460 if (rMark.HasMultiMarks(i))
2462 pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
2463 if (bColFound)
2465 rFound = true;
2466 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2467 bEqual = false; // unterschiedliche
2468 pStyle = pNewStyle;
2472 return bEqual ? pStyle : NULL;
2476 const ScStyleSheet* ScTable::GetAreaStyle( bool& rFound, SCCOL nCol1, SCROW nRow1,
2477 SCCOL nCol2, SCROW nRow2 ) const
2479 rFound = false;
2481 bool bEqual = true;
2482 bool bColFound;
2484 const ScStyleSheet* pStyle = NULL;
2485 const ScStyleSheet* pNewStyle;
2487 for (SCCOL i=nCol1; i<=nCol2 && bEqual; i++)
2489 pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
2490 if (bColFound)
2492 rFound = true;
2493 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2494 bEqual = false; // unterschiedliche
2495 pStyle = pNewStyle;
2499 return bEqual ? pStyle : NULL;
2503 bool ScTable::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
2505 bool bIsUsed = false;
2507 for ( SCCOL i=0; i<=MAXCOL; i++ )
2509 if ( aCol[i].IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
2511 if ( !bGatherAllStyles )
2512 return true;
2513 bIsUsed = true;
2517 return bIsUsed;
2521 void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved,
2522 OutputDevice* pDev,
2523 double nPPTX, double nPPTY,
2524 const Fraction& rZoomX, const Fraction& rZoomY )
2526 ScFlatBoolRowSegments aUsedRows;
2527 for (SCCOL i = 0; i <= MAXCOL; ++i)
2528 aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved);
2530 SCROW nRow = 0;
2531 while (nRow <= MAXROW)
2533 ScFlatBoolRowSegments::RangeData aData;
2534 if (!aUsedRows.getRangeData(nRow, aData))
2535 // search failed!
2536 return;
2538 SCROW nEndRow = aData.mnRow2;
2539 if (aData.mbValue)
2540 SetOptimalHeight(nRow, nEndRow, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, false);
2542 nRow = nEndRow + 1;
2547 bool ScTable::ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2548 sal_Int16 nFlags )
2550 bool bChanged = false;
2551 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2552 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2553 bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags);
2554 return bChanged;
2558 bool ScTable::RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2559 sal_Int16 nFlags )
2561 bool bChanged = false;
2562 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2563 for (SCCOL i = nStartCol; i <= nEndCol; i++)
2564 bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags);
2565 return bChanged;
2569 void ScTable::SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, bool bPutToPool )
2571 if (ValidColRow(nCol,nRow))
2572 aCol[nCol].SetPattern( nRow, rAttr, bPutToPool );
2576 void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const SfxPoolItem& rAttr )
2578 if (ValidColRow(nCol,nRow))
2579 aCol[nCol].ApplyAttr( nRow, rAttr );
2583 void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark,
2584 ScEditDataArray* pDataArray )
2586 for (SCCOL i=0; i<=MAXCOL; i++)
2587 aCol[i].ApplySelectionCache( pCache, rMark, pDataArray );
2591 void ScTable::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
2593 for (SCCOL i=0; i<=MAXCOL; i++)
2594 aCol[i].ChangeSelectionIndent( bIncrement, rMark );
2598 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
2600 for (SCCOL i=0; i<=MAXCOL; i++)
2601 aCol[i].ClearSelectionItems( pWhich, rMark );
2605 // Spaltenbreiten / Zeilenhoehen
2607 void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth )
2609 if (ValidCol(nCol) && pColWidth)
2611 if (!nNewWidth)
2613 nNewWidth = STD_COL_WIDTH;
2616 if ( nNewWidth != pColWidth[nCol] )
2618 pColWidth[nCol] = nNewWidth;
2619 InvalidatePageBreaks();
2622 else
2624 OSL_FAIL("Invalid column number or no widths");
2628 void ScTable::SetColWidthOnly( SCCOL nCol, sal_uInt16 nNewWidth )
2630 if (!ValidCol(nCol) || !pColWidth)
2631 return;
2633 if (!nNewWidth)
2634 nNewWidth = STD_COL_WIDTH;
2636 if (nNewWidth != pColWidth[nCol])
2637 pColWidth[nCol] = nNewWidth;
2640 void ScTable::SetRowHeight( SCROW nRow, sal_uInt16 nNewHeight )
2642 if (ValidRow(nRow) && mpRowHeights)
2644 if (!nNewHeight)
2646 OSL_FAIL("SetRowHeight: Row height zero");
2647 nNewHeight = ScGlobal::nStdRowHeight;
2650 sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow);
2651 if ( nNewHeight != nOldHeight )
2653 mpRowHeights->setValue(nRow, nRow, nNewHeight);
2654 InvalidatePageBreaks();
2657 else
2659 OSL_FAIL("Invalid row number or no heights");
2663 namespace {
2666 * Check if the new pixel size is different from the old size between
2667 * specified ranges.
2669 bool lcl_pixelSizeChanged(
2670 ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow,
2671 sal_uInt16 nNewHeight, double nPPTY)
2673 long nNewPix = static_cast<long>(nNewHeight * nPPTY);
2675 ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights);
2676 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
2678 sal_uInt16 nHeight;
2679 if (!aFwdIter.getValue(nRow, nHeight))
2680 break;
2682 if (nHeight != nNewHeight)
2684 bool bChanged = (nNewPix != static_cast<long>(nHeight * nPPTY));
2685 if (bChanged)
2686 return true;
2689 // Skip ahead to the last position of the current range.
2690 nRow = aFwdIter.getLastPos();
2692 return false;
2697 bool ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight,
2698 double /* nPPTX */, double nPPTY )
2700 bool bChanged = false;
2701 if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2703 if (!nNewHeight)
2705 OSL_FAIL("SetRowHeight: Row height zero");
2706 nNewHeight = ScGlobal::nStdRowHeight;
2709 bool bSingle = false; // true = process every row for its own
2710 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2711 if (pDrawLayer)
2712 if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
2713 bSingle = true;
2715 if (bSingle)
2717 ScFlatUInt16RowSegments::RangeData aData;
2718 mpRowHeights->getRangeData(nStartRow, aData);
2719 if (nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2)
2720 bSingle = false; // no difference in this range
2722 if (bSingle)
2724 if (nEndRow-nStartRow < 20)
2726 if (!bChanged)
2727 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2729 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2731 else
2733 SCROW nMid = (nStartRow+nEndRow) / 2;
2734 if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 ))
2735 bChanged = true;
2736 if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 ))
2737 bChanged = true;
2740 else
2742 if (!bChanged)
2743 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2745 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2748 if (bChanged)
2749 InvalidatePageBreaks();
2751 else
2753 OSL_FAIL("Invalid row number or no heights");
2756 return bChanged;
2759 void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight )
2761 if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights)
2762 return;
2764 if (!nNewHeight)
2765 nNewHeight = ScGlobal::nStdRowHeight;
2767 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2770 void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, bool bManual )
2772 if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
2774 if (bManual)
2775 pRowFlags->OrValue( nStartRow, nEndRow, CR_MANUALSIZE);
2776 else
2777 pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
2779 else
2781 OSL_FAIL("Invalid row number or no column flags");
2786 sal_uInt16 ScTable::GetColWidth( SCCOL nCol, bool bHiddenAsZero ) const
2788 OSL_ENSURE(ValidCol(nCol),"wrong column number");
2790 if (ValidCol(nCol) && pColFlags && pColWidth)
2792 if (bHiddenAsZero && ColHidden(nCol))
2793 return 0;
2794 else
2795 return pColWidth[nCol];
2797 else
2798 return (sal_uInt16) STD_COL_WIDTH;
2802 sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const // immer die eingestellte
2804 OSL_ENSURE(ValidCol(nCol),"wrong column number");
2806 if (ValidCol(nCol) && pColWidth)
2807 return pColWidth[nCol];
2808 else
2809 return (sal_uInt16) STD_COL_WIDTH;
2813 sal_uInt16 ScTable::GetCommonWidth( SCCOL nEndCol ) const
2815 // get the width that is used in the largest continuous column range (up to nEndCol)
2817 if ( !ValidCol(nEndCol) )
2819 OSL_FAIL("wrong column");
2820 nEndCol = MAXCOL;
2823 sal_uInt16 nMaxWidth = 0;
2824 sal_uInt16 nMaxCount = 0;
2825 SCCOL nRangeStart = 0;
2826 while ( nRangeStart <= nEndCol )
2828 // skip hidden columns
2829 while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) )
2830 ++nRangeStart;
2831 if ( nRangeStart <= nEndCol )
2833 sal_uInt16 nThisCount = 0;
2834 sal_uInt16 nThisWidth = pColWidth[nRangeStart];
2835 SCCOL nRangeEnd = nRangeStart;
2836 while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth )
2838 ++nThisCount;
2839 ++nRangeEnd;
2841 // skip hidden columns
2842 while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) )
2843 ++nRangeEnd;
2846 if ( nThisCount > nMaxCount )
2848 nMaxCount = nThisCount;
2849 nMaxWidth = nThisWidth;
2852 nRangeStart = nRangeEnd; // next range
2856 return nMaxWidth;
2860 sal_uInt16 ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
2862 OSL_ENSURE(ValidRow(nRow),"Invalid row number");
2864 if (ValidRow(nRow) && mpRowHeights)
2866 if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow))
2867 return 0;
2868 else
2870 ScFlatUInt16RowSegments::RangeData aData;
2871 if (!mpRowHeights->getRangeData(nRow, aData))
2873 if (pStartRow)
2874 *pStartRow = nRow;
2875 if (pEndRow)
2876 *pEndRow = nRow;
2877 // TODO: What should we return in case the search fails?
2878 return 0;
2881 // If bHiddenAsZero, pStartRow and pEndRow were initialized to
2882 // boundaries of a non-hidden segment. Assume that the previous and
2883 // next segment are hidden then and limit the current height
2884 // segment.
2885 if (pStartRow)
2886 *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1);
2887 if (pEndRow)
2888 *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2);
2889 return aData.mnValue;
2892 else
2894 if (pStartRow)
2895 *pStartRow = nRow;
2896 if (pEndRow)
2897 *pEndRow = nRow;
2898 return (sal_uInt16) ScGlobal::nStdRowHeight;
2903 sal_uLong ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow, bool bHiddenAsZero ) const
2905 OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
2907 if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2909 sal_uLong nHeight = 0;
2910 SCROW nRow = nStartRow;
2911 while (nRow <= nEndRow)
2913 SCROW nLastRow = -1;
2914 if (!( ( RowHidden(nRow, NULL, &nLastRow) ) && bHiddenAsZero ) )
2916 if (nLastRow > nEndRow)
2917 nLastRow = nEndRow;
2918 nHeight += mpRowHeights->getSumValue(nRow, nLastRow);
2920 nRow = nLastRow + 1;
2922 return nHeight;
2924 else
2925 return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight);
2929 sal_uLong ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const
2931 OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
2933 if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2935 sal_uLong nHeight = 0;
2936 SCROW nRow = nStartRow;
2937 while (nRow <= nEndRow)
2939 SCROW nLastRow = -1;
2940 if (!RowHidden(nRow, NULL, &nLastRow))
2942 if (nLastRow > nEndRow)
2943 nLastRow = nEndRow;
2945 // #i117315# can't use getSumValue, because individual values must be rounded
2946 while (nRow <= nLastRow)
2948 ScFlatUInt16RowSegments::RangeData aData;
2949 if (!mpRowHeights->getRangeData(nRow, aData))
2950 return nHeight; // shouldn't happen
2952 SCROW nSegmentEnd = std::min( nLastRow, aData.mnRow2 );
2954 // round-down a single height value, multiply resulting (pixel) values
2955 sal_uLong nOneHeight = static_cast<sal_uLong>( aData.mnValue * fScale );
2956 nHeight += nOneHeight * ( nSegmentEnd + 1 - nRow );
2958 nRow = nSegmentEnd + 1;
2961 nRow = nLastRow + 1;
2963 return nHeight;
2965 else
2966 return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale);
2970 sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const // non-0 even if hidden
2972 OSL_ENSURE(ValidRow(nRow),"wrong row number");
2974 if (ValidRow(nRow) && mpRowHeights)
2975 return mpRowHeights->getValue(nRow);
2976 else
2977 return (sal_uInt16) ScGlobal::nStdRowHeight;
2981 // Spalten-/Zeilen-Flags
2984 SCROW ScTable::GetHiddenRowCount( SCROW nRow ) const
2986 if (!ValidRow(nRow))
2987 return 0;
2989 SCROW nLastRow = -1;
2990 if (!RowHidden(nRow, NULL, &nLastRow) || !ValidRow(nLastRow))
2991 return 0;
2993 return nLastRow - nRow + 1;
2997 //! ShowRows / DBShowRows zusammenfassen
2999 void ScTable::ShowCol(SCCOL nCol, bool bShow)
3001 if (ValidCol(nCol))
3003 bool bWasVis = !ColHidden(nCol);
3004 if (bWasVis != bShow)
3006 SetColHidden(nCol, nCol, !bShow);
3008 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3009 if ( pCharts )
3010 pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ));
3013 else
3015 OSL_FAIL("Invalid column number or no flags");
3020 void ScTable::ShowRow(SCROW nRow, bool bShow)
3022 if (ValidRow(nRow) && pRowFlags)
3024 bool bWasVis = !RowHidden(nRow);
3025 if (bWasVis != bShow)
3027 SetRowHidden(nRow, nRow, !bShow);
3028 if (bShow)
3029 SetRowFiltered(nRow, nRow, false);
3030 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3031 if ( pCharts )
3032 pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
3034 InvalidatePageBreaks();
3037 else
3039 OSL_FAIL("Invalid row number or no flags");
3044 void ScTable::DBShowRow(SCROW nRow, bool bShow)
3046 if (ValidRow(nRow) && pRowFlags)
3048 // Filter-Flag immer setzen, auch wenn Hidden unveraendert
3049 bool bChanged = SetRowHidden(nRow, nRow, !bShow);
3050 SetRowFiltered(nRow, nRow, !bShow);
3052 if (bChanged)
3054 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3055 if ( pCharts )
3056 pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
3058 if (pOutlineTable)
3059 UpdateOutlineRow( nRow, nRow, bShow );
3061 InvalidatePageBreaks();
3064 else
3066 OSL_FAIL("Invalid row number or no flags");
3071 void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3073 SCROW nStartRow = nRow1;
3074 while (nStartRow <= nRow2)
3076 SCROW nEndRow = -1;
3077 bool bWasVis = !RowHiddenLeaf(nStartRow, NULL, &nEndRow);
3078 if (nEndRow > nRow2)
3079 nEndRow = nRow2;
3081 bool bChanged = ( bWasVis != bShow );
3083 SetRowHidden(nStartRow, nEndRow, !bShow);
3084 SetRowFiltered(nStartRow, nEndRow, !bShow);
3086 if ( bChanged )
3088 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3089 if ( pCharts )
3090 pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
3093 nStartRow = nEndRow + 1;
3096 // #i12341# For Show/Hide rows, the outlines are updated separately from the outside.
3097 // For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has
3098 // to be done here.
3099 if (pOutlineTable)
3100 UpdateOutlineRow( nRow1, nRow2, bShow );
3104 void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3106 SCROW nStartRow = nRow1;
3108 // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
3109 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3110 bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2 );
3112 while (nStartRow <= nRow2)
3114 SCROW nEndRow = -1;
3115 bool bWasVis = !RowHiddenLeaf(nStartRow, NULL, &nEndRow);
3116 if (nEndRow > nRow2)
3117 nEndRow = nRow2;
3119 bool bChanged = ( bWasVis != bShow );
3121 SetRowHidden(nStartRow, nEndRow, !bShow);
3122 if (bShow)
3123 SetRowFiltered(nStartRow, nEndRow, false);
3125 if ( bChanged )
3127 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3128 if ( pCharts )
3129 pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
3131 InvalidatePageBreaks();
3134 nStartRow = nEndRow + 1;
3137 if ( !bHasObjects )
3139 // #i116164# set the flags for the whole range at once
3140 SetRowHidden(nRow1, nRow2, !bShow);
3141 if (bShow)
3142 SetRowFiltered(nRow1, nRow2, false);
3146 bool ScTable::IsDataFiltered(SCCOL nColStart, SCROW nRowStart, SCCOL nColEnd, SCROW nRowEnd) const
3148 for (SCROW i = nRowStart; i <= nRowEnd; ++i)
3150 if (RowHidden(i))
3151 return true;
3153 for (SCCOL i = nColStart; i <= nColEnd; ++i)
3155 if (ColHidden(i))
3156 return true;
3158 return false;
3161 bool ScTable::IsDataFiltered(const ScRange& rRange) const
3163 return IsDataFiltered(rRange.aStart.Col(), rRange.aStart.Row(),
3164 rRange.aEnd.Col(), rRange.aEnd.Row());
3167 void ScTable::SetRowFlags( SCROW nRow, sal_uInt8 nNewFlags )
3169 if (ValidRow(nRow) && pRowFlags)
3170 pRowFlags->SetValue( nRow, nNewFlags);
3171 else
3173 OSL_FAIL("Invalid row number or no flags");
3178 void ScTable::SetRowFlags( SCROW nStartRow, SCROW nEndRow, sal_uInt8 nNewFlags )
3180 if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
3181 pRowFlags->SetValue( nStartRow, nEndRow, nNewFlags);
3182 else
3184 OSL_FAIL("Invalid row number(s) or no flags");
3189 sal_uInt8 ScTable::GetColFlags( SCCOL nCol ) const
3191 if (ValidCol(nCol) && pColFlags)
3192 return pColFlags[nCol];
3193 else
3194 return 0;
3198 sal_uInt8 ScTable::GetRowFlags( SCROW nRow ) const
3200 if (ValidRow(nRow) && pRowFlags)
3201 return pRowFlags->GetValue(nRow);
3202 else
3203 return 0;
3207 SCROW ScTable::GetLastFlaggedRow() const
3209 SCROW nLastFound = 0;
3210 if (pRowFlags)
3212 SCROW nRow = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<sal_uInt8>(CR_ALL) );
3213 if (ValidRow(nRow))
3214 nLastFound = nRow;
3217 if (!maRowManualBreaks.empty())
3218 nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin());
3220 if (mpHiddenRows)
3222 SCROW nRow = mpHiddenRows->findLastNotOf(false);
3223 if (ValidRow(nRow))
3224 nLastFound = ::std::max(nLastFound, nRow);
3227 if (mpFilteredRows)
3229 SCROW nRow = mpFilteredRows->findLastNotOf(false);
3230 if (ValidRow(nRow))
3231 nLastFound = ::std::max(nLastFound, nRow);
3234 return nLastFound;
3238 SCCOL ScTable::GetLastChangedCol() const
3240 if ( !pColFlags )
3241 return 0;
3243 SCCOL nLastFound = 0;
3244 for (SCCOL nCol = 1; nCol <= MAXCOL; nCol++)
3245 if ((pColFlags[nCol] & CR_ALL) || (pColWidth[nCol] != STD_COL_WIDTH))
3246 nLastFound = nCol;
3248 return nLastFound;
3252 SCROW ScTable::GetLastChangedRow() const
3254 if ( !pRowFlags )
3255 return 0;
3257 SCROW nLastFlags = GetLastFlaggedRow();
3259 // Find the last row position where the height is NOT the standard row
3260 // height.
3261 // KOHEI: Test this to make sure it does what it's supposed to.
3262 SCROW nLastHeight = mpRowHeights->findLastNotOf(ScGlobal::nStdRowHeight);
3263 if (!ValidRow(nLastHeight))
3264 nLastHeight = 0;
3266 return std::max( nLastFlags, nLastHeight);
3270 bool ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, bool bShow )
3272 if (pOutlineTable && pColFlags)
3274 ScBitMaskCompressedArray< SCCOLROW, sal_uInt8> aArray( MAXCOL, pColFlags, MAXCOLCOUNT);
3275 return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, *this, true );
3277 else
3278 return false;
3282 bool ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, bool bShow )
3284 if (pOutlineTable && pRowFlags)
3285 return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *this, false );
3286 else
3287 return false;
3291 void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3293 // Column-wise expansion
3295 while (rX1 > 0 && ColHidden(rX1-1))
3296 --rX1;
3298 while (rX2 < MAXCOL && ColHidden(rX2+1))
3299 ++rX2;
3301 // Row-wise expansion
3303 if (rY1 > 0)
3305 ScFlatBoolRowSegments::RangeData aData;
3306 if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue)
3308 SCROW nStartRow = aData.mnRow1;
3309 if (ValidRow(nStartRow))
3310 rY1 = nStartRow;
3313 if (rY2 < MAXROW)
3315 SCROW nEndRow = -1;
3316 if (RowHidden(rY2+1, NULL, &nEndRow) && ValidRow(nEndRow))
3317 rY2 = nEndRow;
3322 void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3324 while ( rX2>rX1 && ColHidden(rX2) )
3325 --rX2;
3326 while ( rX2>rX1 && ColHidden(rX1) )
3327 ++rX1;
3329 if (rY1 < rY2)
3331 ScFlatBoolRowSegments::RangeData aData;
3332 if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue)
3334 SCROW nStartRow = aData.mnRow1;
3335 if (ValidRow(nStartRow) && nStartRow >= rY1)
3336 rY2 = nStartRow;
3340 if (rY1 < rY2)
3342 SCROW nEndRow = -1;
3343 if (RowHidden(rY1, NULL, &nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2)
3344 rY1 = nEndRow;
3349 // Auto-Outline
3351 template< typename T >
3352 short DiffSign( T a, T b )
3354 return (a<b) ? -1 :
3355 (a>b) ? 1 : 0;
3359 void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
3361 bool bSizeChanged = false;
3363 SCCOL nCol;
3364 SCROW nRow;
3365 SCROW i;
3366 bool bFound;
3367 ScOutlineArray* pArray;
3368 ScBaseCell* pCell;
3369 ScRange aRef;
3371 StartOutlineTable();
3373 // Zeilen
3375 SCROW nCount = nEndRow-nStartRow+1;
3376 bool* pUsed = new bool[nCount];
3377 for (i=0; i<nCount; i++)
3378 pUsed[i] = false;
3379 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3380 if (!aCol[nCol].IsEmptyData())
3381 aCol[nCol].FindUsed( nStartRow, nEndRow, pUsed );
3383 pArray = pOutlineTable->GetRowArray();
3384 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
3385 if (pUsed[nRow-nStartRow])
3387 bFound = false;
3388 for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++)
3389 if (!aCol[nCol].IsEmptyData())
3391 pCell = aCol[nCol].GetCell( nRow );
3392 if (pCell)
3393 if ( pCell->GetCellType() == CELLTYPE_FORMULA )
3394 if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
3395 if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
3396 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3397 DiffSign( aRef.aStart.Row(), nRow ) ==
3398 DiffSign( aRef.aEnd.Row(), nRow ) )
3400 if (pArray->Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged ))
3402 bFound = true;
3408 delete[] pUsed;
3410 // Spalten
3412 pArray = pOutlineTable->GetColArray();
3413 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3415 if (!aCol[nCol].IsEmptyData())
3417 bFound = false;
3418 ScColumnIterator aIter( &aCol[nCol], nStartRow, nEndRow );
3419 while ( aIter.Next( nRow, pCell ) && !bFound )
3421 if ( pCell->GetCellType() == CELLTYPE_FORMULA )
3422 if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
3423 if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow &&
3424 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3425 DiffSign( aRef.aStart.Col(), nCol ) ==
3426 DiffSign( aRef.aEnd.Col(), nCol ) )
3428 if (pArray->Insert( aRef.aStart.Col(), aRef.aEnd.Col(), bSizeChanged ))
3430 bFound = true;
3438 // CopyData - fuer Query in anderen Bereich
3440 void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
3441 SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab )
3443 //! wenn fuer mehrere Zeilen benutzt, nach Spalten optimieren!
3445 ScAddress aSrc( nStartCol, nStartRow, nTab );
3446 ScAddress aDest( nDestCol, nDestRow, nDestTab );
3447 ScRange aRange( aSrc, aDest );
3448 bool bThisTab = ( nDestTab == nTab );
3449 SCROW nDestY = nDestRow;
3450 for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
3452 aSrc.SetRow( nRow );
3453 aDest.SetRow( nDestY );
3454 SCCOL nDestX = nDestCol;
3455 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
3457 aSrc.SetCol( nCol );
3458 aDest.SetCol( nDestX );
3459 ScBaseCell* pCell = GetCell( nCol, nRow );
3460 if (pCell)
3462 pCell = pCell->Clone( *pDocument );
3463 if (pCell->GetCellType() == CELLTYPE_FORMULA)
3465 ((ScFormulaCell*)pCell)->UpdateReference( URM_COPY, aRange,
3466 ((SCsCOL) nDestCol) - ((SCsCOL) nStartCol),
3467 ((SCsROW) nDestRow) - ((SCsROW) nStartRow),
3468 ((SCsTAB) nDestTab) - ((SCsTAB) nTab) );
3469 ((ScFormulaCell*)pCell)->aPos = aDest;
3472 if (bThisTab)
3474 PutCell( nDestX, nDestY, pCell );
3475 SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ), true );
3477 else
3479 pDocument->PutCell( aDest, pCell );
3480 pDocument->SetPattern( aDest, *GetPattern( nCol, nRow ), true );
3483 ++nDestX;
3485 ++nDestY;
3490 bool ScTable::RefVisible(ScFormulaCell* pCell)
3492 ScRange aRef;
3494 if (pCell->HasOneReference(aRef))
3496 if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab())
3498 SCROW nEndRow;
3499 if (!RowFiltered(aRef.aStart.Row(), NULL, &nEndRow))
3500 // row not filtered.
3501 nEndRow = ::std::numeric_limits<SCROW>::max();
3503 if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row())
3504 return true; // at least partly visible
3505 return false; // completely invisible
3509 return true; // irgendwie anders
3513 void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, OUString& rStr)
3515 GetInputString(nCol, nRow, rStr);
3516 rStr = ScGlobal::pCharClass->uppercase(rStr.trim());
3520 // Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage
3522 void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos)
3524 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3525 if( pDrawLayer )
3527 double fValX = GetColOffset( MAXCOL + 1 ) * HMM_PER_TWIPS;
3528 double fValY = GetRowOffset( MAXROW + 1 ) * HMM_PER_TWIPS;
3529 const long nMax = ::std::numeric_limits<long>::max();
3530 // #i113884# Avoid int32 overflow with possible negative results than can cause bad effects.
3531 // If the draw page size is smaller than all rows, only the bottom of the sheet is affected.
3532 long x = ( fValX > (double)nMax ) ? nMax : (long) fValX;
3533 long y = ( fValY > (double)nMax ) ? nMax : (long) fValY;
3535 if ( IsLayoutRTL() ) // IsNegativePage
3536 x = -x;
3538 pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( x, y ), bUpdateNoteCaptionPos );
3541 // #i102616# actions that modify the draw page size count as sheet modification
3542 // (exception: InitDrawLayer)
3543 if (bResetStreamValid && IsStreamValid())
3544 SetStreamValid(false);
3547 void ScTable::SetRangeName(ScRangeName* pNew)
3549 delete mpRangeName;
3550 mpRangeName = pNew;
3552 //fdo#39792: mark stream as invalid, otherwise new ScRangeName will not be written to file
3553 if (IsStreamValid())
3554 SetStreamValid(false);
3557 ScRangeName* ScTable::GetRangeName() const
3559 if (!mpRangeName)
3560 mpRangeName = new ScRangeName;
3561 return mpRangeName;
3565 sal_uLong ScTable::GetRowOffset( SCROW nRow, bool bHiddenAsZero ) const
3567 sal_uLong n = 0;
3568 if ( mpHiddenRows && mpRowHeights )
3570 if (nRow == 0)
3571 return 0;
3572 else if (nRow == 1)
3573 return GetRowHeight(0, NULL, NULL, bHiddenAsZero );
3575 n = GetTotalRowHeight(0, nRow-1, bHiddenAsZero);
3576 #if OSL_DEBUG_LEVEL > 0
3577 if (n == ::std::numeric_limits<unsigned long>::max())
3578 OSL_FAIL("ScTable::GetRowOffset: row heights overflow");
3579 #endif
3581 else
3583 OSL_FAIL("GetRowOffset: Data missing");
3585 return n;
3588 SCROW ScTable::GetRowForHeight(sal_uLong nHeight) const
3590 sal_uInt32 nSum = 0;
3592 ScFlatBoolRowSegments::RangeData aData;
3593 for (SCROW nRow = 0; nRow <= MAXROW; ++nRow)
3595 if (!mpHiddenRows->getRangeData(nRow, aData))
3596 break;
3598 if (aData.mbValue)
3600 nRow = aData.mnRow2;
3601 continue;
3604 sal_uInt32 nNew = mpRowHeights->getValue(nRow);
3605 nSum += nNew;
3606 if (nSum > nHeight)
3608 return nRow < MAXROW ? nRow + 1 : MAXROW;
3611 return -1;
3615 sal_uLong ScTable::GetColOffset( SCCOL nCol, bool bHiddenAsZero ) const
3617 sal_uLong n = 0;
3618 if ( pColWidth )
3620 SCCOL i;
3621 for( i = 0; i < nCol; i++ )
3622 if (!( bHiddenAsZero && ColHidden(i) ))
3623 n += pColWidth[i];
3625 else
3627 OSL_FAIL("GetColumnOffset: Data missing");
3629 return n;
3632 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */