1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2011 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 // INCLUDE --------------------------------------------------------------- 32 33 #include "scitems.hxx" 34 #include <editeng/boxitem.hxx> 35 #include <tools/urlobj.hxx> 36 #include <svl/poolcach.hxx> 37 #include <unotools/charclass.hxx> 38 #include <math.h> 39 #include <svl/PasswordHelper.hxx> 40 #include <unotools/transliterationwrapper.hxx> 41 42 #include "patattr.hxx" 43 #include "docpool.hxx" 44 #include "cell.hxx" 45 #include "document.hxx" 46 #include "drwlayer.hxx" 47 #include "olinetab.hxx" 48 #include "rechead.hxx" 49 #include "stlpool.hxx" 50 #include "attarray.hxx" // Iterator 51 #include "markdata.hxx" 52 #include "progress.hxx" 53 #include "dociter.hxx" 54 #include "conditio.hxx" 55 #include "chartlis.hxx" 56 #include "fillinfo.hxx" 57 #include "bcaslot.hxx" 58 #include "postit.hxx" 59 #include "sheetevents.hxx" 60 #include "globstr.hrc" 61 #include "segmenttree.hxx" 62 #include "dbcolect.hxx" 63 64 #include <math.h> 65 66 // STATIC DATA ----------------------------------------------------------- 67 68 69 sal_Bool ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline ) 70 { 71 sal_uInt16 nOldSizeX = 0; 72 sal_uInt16 nOldSizeY = 0; 73 sal_uInt16 nNewSizeX = 0; 74 sal_uInt16 nNewSizeY = 0; 75 76 if (pOutlineTable) 77 { 78 nOldSizeX = pOutlineTable->GetColArray()->GetDepth(); 79 nOldSizeY = pOutlineTable->GetRowArray()->GetDepth(); 80 delete pOutlineTable; 81 } 82 83 if (pNewOutline) 84 { 85 pOutlineTable = new ScOutlineTable( *pNewOutline ); 86 nNewSizeX = pOutlineTable->GetColArray()->GetDepth(); 87 nNewSizeY = pOutlineTable->GetRowArray()->GetDepth(); 88 } 89 else 90 pOutlineTable = NULL; 91 92 return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY ); // Groesse geaendert ? 93 } 94 95 96 void ScTable::StartOutlineTable() 97 { 98 if (!pOutlineTable) 99 pOutlineTable = new ScOutlineTable; 100 } 101 102 103 void ScTable::SetSheetEvents( const ScSheetEvents* pNew ) 104 { 105 delete pSheetEvents; 106 if (pNew) 107 pSheetEvents = new ScSheetEvents(*pNew); 108 else 109 pSheetEvents = NULL; 110 111 SetCalcNotification( sal_False ); // discard notifications before the events were set 112 113 if (IsStreamValid()) 114 SetStreamValid(sal_False); 115 } 116 117 118 void ScTable::SetCalcNotification( sal_Bool bSet ) 119 { 120 bCalcNotification = bSet; 121 } 122 123 124 sal_Bool ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize ) 125 { 126 sal_Bool bTest = sal_True; 127 128 if ( nStartCol==0 && nEndCol==MAXCOL && pOutlineTable ) 129 bTest = pOutlineTable->TestInsertRow(nSize); 130 131 for (SCCOL i=nStartCol; (i<=nEndCol) && bTest; i++) 132 bTest = aCol[i].TestInsertRow( nSize ); 133 134 return bTest; 135 } 136 137 138 void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ) 139 { 140 IncRecalcLevel(); 141 InitializeNoteCaptions(); 142 if (nStartCol==0 && nEndCol==MAXCOL) 143 { 144 if (mpRowHeights && pRowFlags) 145 { 146 mpRowHeights->insertSegment(nStartRow, nSize, false); 147 sal_uInt8 nNewFlags = pRowFlags->Insert( nStartRow, nSize); 148 // only copy manual size flag, clear all others 149 if (nNewFlags && (nNewFlags != CR_MANUALSIZE)) 150 pRowFlags->SetValue( nStartRow, nStartRow + nSize - 1, 151 nNewFlags & CR_MANUALSIZE); 152 } 153 154 if (pOutlineTable) 155 pOutlineTable->InsertRow( nStartRow, nSize ); 156 157 mpFilteredRows->insertSegment(nStartRow, nSize, true); 158 mpHiddenRows->insertSegment(nStartRow, nSize, true); 159 160 if (!maRowManualBreaks.empty()) 161 { 162 std::set<SCROW>::reverse_iterator rit = maRowManualBreaks.rbegin(); 163 while (rit != maRowManualBreaks.rend()) 164 { 165 SCROW nRow = *rit; 166 if (nRow < nStartRow) 167 break; // while 168 else 169 { 170 maRowManualBreaks.erase( (++rit).base()); 171 maRowManualBreaks.insert( static_cast<SCROW>( nRow + nSize)); 172 } 173 } 174 } 175 } 176 177 for (SCCOL j=nStartCol; j<=nEndCol; j++) 178 aCol[j].InsertRow( nStartRow, nSize ); 179 DecRecalcLevel( false ); 180 181 InvalidatePageBreaks(); 182 } 183 184 185 void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize, 186 sal_Bool* pUndoOutline ) 187 { 188 IncRecalcLevel(); 189 InitializeNoteCaptions(); 190 if (nStartCol==0 && nEndCol==MAXCOL) 191 { 192 if (pRowFlags) 193 pRowFlags->Remove( nStartRow, nSize); 194 195 if (mpRowHeights) 196 mpRowHeights->removeSegment(nStartRow, nStartRow+nSize); 197 198 if (pOutlineTable) 199 if (pOutlineTable->DeleteRow( nStartRow, nSize )) 200 if (pUndoOutline) 201 *pUndoOutline = sal_True; 202 203 mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize); 204 mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize); 205 206 if (!maRowManualBreaks.empty()) 207 { 208 std::set<SCROW>::iterator it = maRowManualBreaks.upper_bound( static_cast<SCROW>( nStartRow + nSize - 1)); 209 maRowManualBreaks.erase( maRowManualBreaks.lower_bound( nStartRow), it); 210 while (it != maRowManualBreaks.end()) 211 { 212 SCROW nRow = *it; 213 maRowManualBreaks.erase( it++); 214 maRowManualBreaks.insert( static_cast<SCROW>( nRow - nSize)); 215 } 216 } 217 } 218 219 { // scope for bulk broadcast 220 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM()); 221 for (SCCOL j=nStartCol; j<=nEndCol; j++) 222 aCol[j].DeleteRow( nStartRow, nSize ); 223 } 224 DecRecalcLevel(); 225 226 InvalidatePageBreaks(); 227 } 228 229 230 sal_Bool ScTable::TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) 231 { 232 sal_Bool bTest = sal_True; 233 234 if ( nStartRow==0 && nEndRow==MAXROW && pOutlineTable ) 235 bTest = pOutlineTable->TestInsertCol(nSize); 236 237 if ( nSize > static_cast<SCSIZE>(MAXCOL) ) 238 bTest = sal_False; 239 240 for (SCCOL i=MAXCOL; (i+static_cast<SCCOL>(nSize)>MAXCOL) && bTest; i--) 241 bTest = aCol[i].TestInsertCol(nStartRow, nEndRow); 242 243 return bTest; 244 } 245 246 247 void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) 248 { 249 IncRecalcLevel(); 250 InitializeNoteCaptions(); 251 if (nStartRow==0 && nEndRow==MAXROW) 252 { 253 if (pColWidth && pColFlags) 254 { 255 memmove( &pColWidth[nStartCol+nSize], &pColWidth[nStartCol], 256 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) ); 257 memmove( &pColFlags[nStartCol+nSize], &pColFlags[nStartCol], 258 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) ); 259 } 260 if (pOutlineTable) 261 pOutlineTable->InsertCol( nStartCol, nSize ); 262 263 mpHiddenCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true); 264 mpFilteredCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true); 265 266 if (!maColManualBreaks.empty()) 267 { 268 std::set<SCCOL>::reverse_iterator rit = maColManualBreaks.rbegin(); 269 while (rit != maColManualBreaks.rend()) 270 { 271 SCCOL nCol = *rit; 272 if (nCol < nStartCol) 273 break; // while 274 else 275 { 276 maColManualBreaks.erase( (++rit).base()); 277 maColManualBreaks.insert( static_cast<SCCOL>( nCol + nSize)); 278 } 279 } 280 } 281 } 282 283 284 if ((nStartRow == 0) && (nEndRow == MAXROW)) 285 { 286 for (SCSIZE i=0; i < nSize; i++) 287 for (SCCOL nCol = MAXCOL; nCol > nStartCol; nCol--) 288 aCol[nCol].SwapCol(aCol[nCol-1]); 289 } 290 else 291 { 292 for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++) 293 aCol[MAXCOL - nSize - i].MoveTo(nStartRow, nEndRow, aCol[MAXCOL - i]); 294 } 295 296 if (nStartCol>0) // copy old attributes 297 { 298 sal_uInt16 nWhichArray[2]; 299 nWhichArray[0] = ATTR_MERGE; 300 nWhichArray[1] = 0; 301 302 for (SCSIZE i=0; i<nSize; i++) 303 { 304 aCol[nStartCol-1].CopyToColumn( nStartRow, nEndRow, IDF_ATTRIB, 305 sal_False, aCol[nStartCol+i] ); 306 aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow, 307 SC_MF_HOR | SC_MF_VER | SC_MF_AUTO ); 308 aCol[nStartCol+i].ClearItems( nStartRow, nEndRow, nWhichArray ); 309 } 310 } 311 DecRecalcLevel(); 312 313 InvalidatePageBreaks(); 314 } 315 316 317 void ScTable::DeleteCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize, 318 sal_Bool* pUndoOutline ) 319 { 320 IncRecalcLevel(); 321 InitializeNoteCaptions(); 322 if (nStartRow==0 && nEndRow==MAXROW) 323 { 324 if (pColWidth && pColFlags) 325 { 326 memmove( &pColWidth[nStartCol], &pColWidth[nStartCol+nSize], 327 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) ); 328 memmove( &pColFlags[nStartCol], &pColFlags[nStartCol+nSize], 329 (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) ); 330 } 331 if (pOutlineTable) 332 if (pOutlineTable->DeleteCol( nStartCol, nSize )) 333 if (pUndoOutline) 334 *pUndoOutline = sal_True; 335 336 SCCOL nRmSize = nStartCol + static_cast<SCCOL>(nSize); 337 mpHiddenCols->removeSegment(nStartCol, nRmSize); 338 mpFilteredCols->removeSegment(nStartCol, nRmSize); 339 340 if (!maColManualBreaks.empty()) 341 { 342 std::set<SCCOL>::iterator it = maColManualBreaks.upper_bound( static_cast<SCCOL>( nStartCol + nSize - 1)); 343 maColManualBreaks.erase( maColManualBreaks.lower_bound( nStartCol), it); 344 while (it != maColManualBreaks.end()) 345 { 346 SCCOL nCol = *it; 347 maColManualBreaks.erase( it++); 348 maColManualBreaks.insert( static_cast<SCCOL>( nCol - nSize)); 349 } 350 } 351 } 352 353 354 { // scope for bulk broadcast 355 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM()); 356 for (SCSIZE i = 0; i < nSize; i++) 357 aCol[nStartCol + i].DeleteArea(nStartRow, nEndRow, IDF_ALL); 358 } 359 360 if ((nStartRow == 0) && (nEndRow == MAXROW)) 361 { 362 for (SCSIZE i=0; i < nSize; i++) 363 for (SCCOL nCol = nStartCol; nCol < MAXCOL; nCol++) 364 aCol[nCol].SwapCol(aCol[nCol+1]); 365 } 366 else 367 { 368 for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++) 369 aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]); 370 } 371 DecRecalcLevel(); 372 373 InvalidatePageBreaks(); 374 } 375 376 377 void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nDelFlag) 378 { 379 if (nCol2 > MAXCOL) nCol2 = MAXCOL; 380 if (nRow2 > MAXROW) nRow2 = MAXROW; 381 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) 382 { 383 // IncRecalcLevel(); 384 385 { // scope for bulk broadcast 386 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM()); 387 for (SCCOL i = nCol1; i <= nCol2; i++) 388 aCol[i].DeleteArea(nRow1, nRow2, nDelFlag); 389 } 390 391 // 392 // Zellschutz auf geschuetzter Tabelle nicht setzen 393 // 394 395 if ( IsProtected() && (nDelFlag & IDF_ATTRIB) ) 396 { 397 ScPatternAttr aPattern(pDocument->GetPool()); 398 aPattern.GetItemSet().Put( ScProtectionAttr( sal_False ) ); 399 ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern ); 400 } 401 402 // DecRecalcLevel(); 403 } 404 } 405 406 407 void ScTable::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark ) 408 { 409 { // scope for bulk broadcast 410 ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM()); 411 for (SCCOL i=0; i<=MAXCOL; i++) 412 aCol[i].DeleteSelection( nDelFlag, rMark ); 413 } 414 415 // 416 // Zellschutz auf geschuetzter Tabelle nicht setzen 417 // 418 419 if ( IsProtected() && (nDelFlag & IDF_ATTRIB) ) 420 { 421 ScDocumentPool* pPool = pDocument->GetPool(); 422 SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END ); 423 aSet.Put( ScProtectionAttr( sal_False ) ); 424 SfxItemPoolCache aCache( pPool, &aSet ); 425 ApplySelectionCache( &aCache, rMark ); 426 } 427 } 428 429 430 // pTable = Clipboard 431 void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 432 ScTable* pTable, sal_Bool bKeepScenarioFlags, sal_Bool bCloneNoteCaptions) 433 { 434 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) 435 { 436 // Inhalte kopieren 437 SCCOL i; 438 439 for ( i = nCol1; i <= nCol2; i++) 440 aCol[i].CopyToClip(nRow1, nRow2, pTable->aCol[i], bKeepScenarioFlags, bCloneNoteCaptions); 441 442 // copy widths/heights, and only "hidden", "filtered" and "manual" flags 443 // also for all preceding columns/rows, to have valid positions for drawing objects 444 445 if (pColWidth && pTable->pColWidth) 446 for (i=0; i<=nCol2; i++) 447 pTable->pColWidth[i] = pColWidth[i]; 448 449 pTable->CopyColHidden(*this, 0, nCol2); 450 pTable->CopyColFiltered(*this, 0, nCol2); 451 452 if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights) 453 { 454 pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CR_MANUALSIZE); 455 pTable->CopyRowHeight(*this, 0, nRow2, 0); 456 } 457 458 pTable->CopyRowHidden(*this, 0, nRow2); 459 pTable->CopyRowFiltered(*this, 0, nRow2); 460 461 // ggf. Formeln durch Werte ersetzen 462 463 if ( IsProtected() ) 464 for (i = nCol1; i <= nCol2; i++) 465 pTable->aCol[i].RemoveProtected(nRow1, nRow2); 466 } 467 } 468 469 void ScTable::CopyToClip(const ScRangeList& rRanges, ScTable* pTable, 470 bool bKeepScenarioFlags, bool bCloneNoteCaptions) 471 { 472 ScRangeList aRanges(rRanges); 473 for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next()) 474 { 475 CopyToClip(p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), 476 pTable, bKeepScenarioFlags, bCloneNoteCaptions); 477 } 478 } 479 480 void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 481 SCsCOL nDx, SCsROW nDy, sal_uInt16 nInsFlag, 482 sal_Bool bAsLink, sal_Bool bSkipAttrForEmpty, ScTable* pTable) 483 { 484 SCCOL i; 485 486 if (nCol2 > MAXCOL) nCol2 = MAXCOL; 487 if (nRow2 > MAXROW) nRow2 = MAXROW; 488 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) 489 { 490 IncRecalcLevel(); 491 for ( i = nCol1; i <= nCol2; i++) 492 aCol[i].CopyFromClip(nRow1, nRow2, nDy, nInsFlag, bAsLink, bSkipAttrForEmpty, pTable->aCol[i - nDx]); 493 494 if ((nInsFlag & IDF_ATTRIB) != 0) 495 { 496 if (nRow1==0 && nRow2==MAXROW && pColWidth && pTable->pColWidth) 497 for (i=nCol1; i<=nCol2; i++) 498 pColWidth[i] = pTable->pColWidth[i-nDx]; 499 500 if (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pTable->mpRowHeights && 501 pRowFlags && pTable->pRowFlags) 502 { 503 CopyRowHeight(*pTable, nRow1, nRow2, -nDy); 504 // Must copy CR_MANUALSIZE bit too, otherwise pRowHeight doesn't make sense 505 for (SCROW j=nRow1; j<=nRow2; j++) 506 { 507 if ( pTable->pRowFlags->GetValue(j-nDy) & CR_MANUALSIZE ) 508 pRowFlags->OrValue( j, CR_MANUALSIZE); 509 else 510 pRowFlags->AndValue( j, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE)); 511 } 512 } 513 514 // 515 // Zellschutz auf geschuetzter Tabelle nicht setzen 516 // 517 518 if ( IsProtected() && (nInsFlag & IDF_ATTRIB) ) 519 { 520 ScPatternAttr aPattern(pDocument->GetPool()); 521 aPattern.GetItemSet().Put( ScProtectionAttr( sal_False ) ); 522 ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern ); 523 } 524 } 525 DecRecalcLevel(); 526 } 527 } 528 529 530 void ScTable::MixData( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 531 sal_uInt16 nFunction, sal_Bool bSkipEmpty, ScTable* pSrcTab ) 532 { 533 for (SCCOL i=nCol1; i<=nCol2; i++) 534 aCol[i].MixData( nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i] ); 535 } 536 537 538 // Markierung von diesem Dokument 539 void ScTable::MixMarked( const ScMarkData& rMark, sal_uInt16 nFunction, 540 sal_Bool bSkipEmpty, ScTable* pSrcTab ) 541 { 542 for (SCCOL i=0; i<=MAXCOL; i++) 543 aCol[i].MixMarked( rMark, nFunction, bSkipEmpty, pSrcTab->aCol[i] ); 544 } 545 546 547 void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 548 ScTable* pTransClip, sal_uInt16 nFlags, sal_Bool bAsLink ) 549 { 550 sal_Bool bWasCut = pDocument->IsCutMode(); 551 552 ScDocument* pDestDoc = pTransClip->pDocument; 553 554 for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++) 555 { 556 SCROW nRow; 557 ScBaseCell* pCell; 558 559 if ( bAsLink && nFlags == IDF_ALL ) 560 { 561 // #68989# with IDF_ALL, also create links (formulas) for empty cells 562 563 for ( nRow=nRow1; nRow<=nRow2; nRow++ ) 564 { 565 // create simple formula, as in ScColumn::CreateRefCell 566 567 ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab ); 568 ScSingleRefData aRef; 569 aRef.nCol = nCol; 570 aRef.nRow = nRow; 571 aRef.nTab = nTab; 572 aRef.InitFlags(); // -> all absolute 573 aRef.SetFlag3D(sal_True); 574 aRef.CalcRelFromAbs( aDestPos ); 575 ScTokenArray aArr; 576 aArr.AddSingleReference( aRef ); 577 578 ScBaseCell* pNew = new ScFormulaCell( pDestDoc, aDestPos, &aArr ); 579 pTransClip->PutCell( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pNew ); 580 } 581 } 582 else 583 { 584 ScColumnIterator aIter( &aCol[nCol], nRow1, nRow2 ); 585 while (aIter.Next( nRow, pCell )) 586 { 587 ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab ); 588 ScBaseCell* pNew; 589 if ( bAsLink ) // Referenz erzeugen ? 590 { 591 pNew = aCol[nCol].CreateRefCell( pDestDoc, aDestPos, aIter.GetIndex(), nFlags ); 592 } 593 else // kopieren 594 { 595 ScAddress aOwnPos( nCol, nRow, nTab ); 596 if (pCell->GetCellType() == CELLTYPE_FORMULA) 597 { 598 pNew = pCell->CloneWithNote( aOwnPos, *pDestDoc, aDestPos, SC_CLONECELL_STARTLISTENING ); 599 600 // Referenzen drehen 601 // bei Cut werden Referenzen spaeter per UpdateTranspose angepasst 602 603 if (!bWasCut) 604 ((ScFormulaCell*)pNew)->TransposeReference(); 605 } 606 else 607 { 608 pNew = pCell->CloneWithNote( aOwnPos, *pDestDoc, aDestPos ); 609 } 610 } 611 pTransClip->PutCell( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pNew ); 612 } 613 } 614 615 // Attribute 616 617 SCROW nAttrRow1; 618 SCROW nAttrRow2; 619 const ScPatternAttr* pPattern; 620 ScAttrIterator* pAttrIter = aCol[nCol].CreateAttrIterator( nRow1, nRow2 ); 621 while ( (pPattern = pAttrIter->Next( nAttrRow1, nAttrRow2 )) != 0 ) 622 { 623 if ( !IsDefaultItem( pPattern ) ) 624 { 625 const SfxItemSet& rSet = pPattern->GetItemSet(); 626 if ( rSet.GetItemState( ATTR_MERGE, sal_False ) == SFX_ITEM_DEFAULT && 627 rSet.GetItemState( ATTR_MERGE_FLAG, sal_False ) == SFX_ITEM_DEFAULT && 628 rSet.GetItemState( ATTR_BORDER, sal_False ) == SFX_ITEM_DEFAULT ) 629 { 630 // no borders or merge items involved - use pattern as-is 631 for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++) 632 pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), *pPattern, sal_True ); 633 } 634 else 635 { 636 // transpose borders and merge values, remove merge flags (refreshed after pasting) 637 ScPatternAttr aNewPattern( *pPattern ); 638 SfxItemSet& rNewSet = aNewPattern.GetItemSet(); 639 640 const SvxBoxItem& rOldBox = (const SvxBoxItem&)rSet.Get(ATTR_BORDER); 641 if ( rOldBox.GetTop() || rOldBox.GetBottom() || rOldBox.GetLeft() || rOldBox.GetRight() ) 642 { 643 SvxBoxItem aNew( ATTR_BORDER ); 644 aNew.SetLine( rOldBox.GetLine( BOX_LINE_TOP ), BOX_LINE_LEFT ); 645 aNew.SetLine( rOldBox.GetLine( BOX_LINE_LEFT ), BOX_LINE_TOP ); 646 aNew.SetLine( rOldBox.GetLine( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT ); 647 aNew.SetLine( rOldBox.GetLine( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM ); 648 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_TOP ), BOX_LINE_LEFT ); 649 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_LEFT ), BOX_LINE_TOP ); 650 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT ); 651 aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM ); 652 rNewSet.Put( aNew ); 653 } 654 655 const ScMergeAttr& rOldMerge = (const ScMergeAttr&)rSet.Get(ATTR_MERGE); 656 if (rOldMerge.IsMerged()) 657 rNewSet.Put( ScMergeAttr( Min( 658 static_cast<SCsCOL>(rOldMerge.GetRowMerge()), 659 static_cast<SCsCOL>(MAXCOL+1 - (nAttrRow2-nRow1))), 660 Min( 661 static_cast<SCsROW>(rOldMerge.GetColMerge()), 662 static_cast<SCsROW>(MAXROW+1 - (nCol-nCol1))))); 663 const ScMergeFlagAttr& rOldFlag = (const ScMergeFlagAttr&)rSet.Get(ATTR_MERGE_FLAG); 664 if (rOldFlag.IsOverlapped()) 665 { 666 sal_Int16 nNewFlags = rOldFlag.GetValue() & ~( SC_MF_HOR | SC_MF_VER ); 667 if ( nNewFlags ) 668 rNewSet.Put( ScMergeFlagAttr( nNewFlags ) ); 669 else 670 rNewSet.ClearItem( ATTR_MERGE_FLAG ); 671 } 672 673 for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++) 674 pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), 675 static_cast<SCROW>(nCol-nCol1), aNewPattern, sal_True); 676 } 677 } 678 } 679 680 delete pAttrIter; 681 } 682 } 683 684 685 void ScTable::StartAllListeners() 686 { 687 for (SCCOL i=0; i<=MAXCOL; i++) 688 aCol[i].StartAllListeners(); 689 } 690 691 692 void ScTable::StartNeededListeners() 693 { 694 for (SCCOL i=0; i<=MAXCOL; i++) 695 aCol[i].StartNeededListeners(); 696 } 697 698 699 void ScTable::BroadcastInArea( SCCOL nCol1, SCROW nRow1, 700 SCCOL nCol2, SCROW nRow2 ) 701 { 702 if (nCol2 > MAXCOL) nCol2 = MAXCOL; 703 if (nRow2 > MAXROW) nRow2 = MAXROW; 704 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) 705 for (SCCOL i = nCol1; i <= nCol2; i++) 706 aCol[i].BroadcastInArea( nRow1, nRow2 ); 707 } 708 709 710 void ScTable::StartListeningInArea( SCCOL nCol1, SCROW nRow1, 711 SCCOL nCol2, SCROW nRow2 ) 712 { 713 if (nCol2 > MAXCOL) nCol2 = MAXCOL; 714 if (nRow2 > MAXROW) nRow2 = MAXROW; 715 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) 716 for (SCCOL i = nCol1; i <= nCol2; i++) 717 aCol[i].StartListeningInArea( nRow1, nRow2 ); 718 } 719 720 721 void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 722 sal_uInt16 nFlags, sal_Bool bMarked, ScTable* pDestTab, 723 const ScMarkData* pMarkData, 724 sal_Bool bAsLink, sal_Bool bColRowFlags) 725 { 726 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) 727 { 728 if (nFlags) 729 for (SCCOL i = nCol1; i <= nCol2; i++) 730 aCol[i].CopyToColumn(nRow1, nRow2, nFlags, bMarked, 731 pDestTab->aCol[i], pMarkData, bAsLink); 732 733 if (bColRowFlags) // Spaltenbreiten/Zeilenhoehen/Flags 734 { 735 // Charts muessen beim Ein-/Ausblenden angepasst werden 736 ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection(); 737 738 bool bFlagChange = false; 739 740 sal_Bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth); 741 sal_Bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights); 742 743 if (bWidth||bHeight) 744 { 745 pDestTab->IncRecalcLevel(); 746 747 if (bWidth) 748 { 749 for (SCCOL i=nCol1; i<=nCol2; i++) 750 { 751 bool bThisHidden = ColHidden(i); 752 bool bHiddenChange = (pDestTab->ColHidden(i) != bThisHidden); 753 bool bChange = bHiddenChange || (pDestTab->pColWidth[i] != pColWidth[i]); 754 pDestTab->pColWidth[i] = pColWidth[i]; 755 pDestTab->pColFlags[i] = pColFlags[i]; 756 pDestTab->SetColHidden(i, i, bThisHidden); 757 //! Aenderungen zusammenfassen? 758 if (bHiddenChange && pCharts) 759 pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab )); 760 761 if (bChange) 762 bFlagChange = true; 763 } 764 pDestTab->SetColManualBreaks( maColManualBreaks); 765 } 766 767 if (bHeight) 768 { 769 bool bChange = pDestTab->GetRowHeight(nRow1, nRow2) != GetRowHeight(nRow1, nRow2); 770 771 if (bChange) 772 bFlagChange = true; 773 774 pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0); 775 pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2); 776 777 // Hidden flags. 778 // #i116164# Collect information first, then apply the changes, 779 // so RowHidden doesn't rebuild the tree for each row range. 780 std::vector<ScShowRowsEntry> aEntries; 781 for (SCROW i = nRow1; i <= nRow2; ++i) 782 { 783 SCROW nThisLastRow, nDestLastRow; 784 bool bThisHidden = RowHidden(i, NULL, &nThisLastRow); 785 bool bDestHidden = pDestTab->RowHidden(i, NULL, &nDestLastRow); 786 787 // If the segment sizes differ, we take the shorter segment of the two. 788 SCROW nLastRow = ::std::min(nThisLastRow, nDestLastRow); 789 if (nLastRow >= nRow2) 790 // the last row shouldn't exceed the upper bound the caller specified. 791 nLastRow = nRow2; 792 793 //pDestTab->SetRowHidden(i, nLastRow, bThisHidden); 794 aEntries.push_back(ScShowRowsEntry(i, nLastRow, !bThisHidden)); 795 796 bool bThisHiddenChange = (bThisHidden != bDestHidden); 797 if (bThisHiddenChange && pCharts) 798 { 799 // Hidden flags differ. 800 pCharts->SetRangeDirty(ScRange(0, i, nTab, MAXCOL, nLastRow, nTab)); 801 } 802 803 if (bThisHiddenChange) 804 bFlagChange = true; 805 806 // Jump to the last row of the identical flag segment. 807 i = nLastRow; 808 } 809 810 std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end(); 811 std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin(); 812 if ( aIter != aEnd ) 813 { 814 pDestTab->mpHiddenRows->setInsertFromBack(true); // important for undo document 815 while (aIter != aEnd) 816 { 817 pDestTab->SetRowHidden(aIter->mnRow1, aIter->mnRow2, !aIter->mbShow); 818 ++aIter; 819 } 820 pDestTab->mpHiddenRows->setInsertFromBack(false); 821 } 822 823 // Filtered flags. 824 for (SCROW i = nRow1; i <= nRow2; ++i) 825 { 826 SCROW nLastRow; 827 bool bFiltered = RowFiltered(i, NULL, &nLastRow); 828 if (nLastRow >= nRow2) 829 // the last row shouldn't exceed the upper bound the caller specified. 830 nLastRow = nRow2; 831 pDestTab->SetRowFiltered(i, nLastRow, bFiltered); 832 i = nLastRow; 833 } 834 pDestTab->SetRowManualBreaks( maRowManualBreaks); 835 } 836 pDestTab->DecRecalcLevel(); 837 } 838 839 if (bFlagChange) 840 pDestTab->InvalidatePageBreaks(); 841 842 pDestTab->SetOutlineTable( pOutlineTable ); // auch nur wenn bColRowFlags 843 } 844 } 845 } 846 847 848 void ScTable::UndoToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 849 sal_uInt16 nFlags, sal_Bool bMarked, ScTable* pDestTab, 850 const ScMarkData* pMarkData) 851 { 852 if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) 853 { 854 sal_Bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth); 855 sal_Bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights); 856 857 if (bWidth||bHeight) 858 IncRecalcLevel(); 859 860 for ( SCCOL i = 0; i <= MAXCOL; i++) 861 { 862 if ( i >= nCol1 && i <= nCol2 ) 863 aCol[i].UndoToColumn(nRow1, nRow2, nFlags, bMarked, pDestTab->aCol[i], 864 pMarkData); 865 else 866 aCol[i].CopyToColumn(0, MAXROW, IDF_FORMULA, sal_False, pDestTab->aCol[i]); 867 } 868 869 if (bWidth||bHeight) 870 { 871 if (bWidth) 872 { 873 for (SCCOL i=nCol1; i<=nCol2; i++) 874 pDestTab->pColWidth[i] = pColWidth[i]; 875 pDestTab->SetColManualBreaks( maColManualBreaks); 876 } 877 if (bHeight) 878 { 879 pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0); 880 pDestTab->SetRowManualBreaks( maRowManualBreaks); 881 } 882 DecRecalcLevel(); 883 } 884 } 885 } 886 887 888 void ScTable::CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const 889 { 890 for (SCCOL i=0; i<=MAXCOL; i++) 891 aCol[i].CopyUpdated( pPosTab->aCol[i], pDestTab->aCol[i] ); 892 } 893 894 void ScTable::InvalidateTableArea() 895 { 896 bTableAreaValid = sal_False; 897 } 898 899 void ScTable::InvalidatePageBreaks() 900 { 901 mbPageBreaksValid = false; 902 } 903 904 void ScTable::CopyScenarioTo( ScTable* pDestTab ) const 905 { 906 DBG_ASSERT( bScenario, "bScenario == FALSE" ); 907 908 for (SCCOL i=0; i<=MAXCOL; i++) 909 aCol[i].CopyScenarioTo( pDestTab->aCol[i] ); 910 } 911 912 void ScTable::CopyScenarioFrom( const ScTable* pSrcTab ) 913 { 914 DBG_ASSERT( bScenario, "bScenario == FALSE" ); 915 916 for (SCCOL i=0; i<=MAXCOL; i++) 917 aCol[i].CopyScenarioFrom( pSrcTab->aCol[i] ); 918 } 919 920 void ScTable::MarkScenarioIn( ScMarkData& rDestMark, sal_uInt16 nNeededBits ) const 921 { 922 DBG_ASSERT( bScenario, "bScenario == FALSE" ); 923 924 if ( ( nScenarioFlags & nNeededBits ) != nNeededBits ) // alle Bits gesetzt? 925 return; 926 927 for (SCCOL i=0; i<=MAXCOL; i++) 928 aCol[i].MarkScenarioIn( rDestMark ); 929 } 930 931 sal_Bool ScTable::HasScenarioRange( const ScRange& rRange ) const 932 { 933 DBG_ASSERT( bScenario, "bScenario == FALSE" ); 934 935 // ScMarkData aMark; 936 // MarkScenarioIn( aMark, 0 ); //! Bits als Parameter von HasScenarioRange? 937 // return aMark.IsAllMarked( rRange ); 938 939 ScRange aTabRange = rRange; 940 aTabRange.aStart.SetTab( nTab ); 941 aTabRange.aEnd.SetTab( nTab ); 942 943 const ScRangeList* pList = GetScenarioRanges(); 944 // return ( pList && pList->Find( aTabRange ) ); 945 946 if (pList) 947 { 948 sal_uLong nCount = pList->Count(); 949 for ( sal_uLong j = 0; j < nCount; j++ ) 950 { 951 ScRange* pR = pList->GetObject( j ); 952 if ( pR->Intersects( aTabRange ) ) 953 return sal_True; 954 } 955 } 956 957 return sal_False; 958 } 959 960 void ScTable::InvalidateScenarioRanges() 961 { 962 delete pScenarioRanges; 963 pScenarioRanges = NULL; 964 } 965 966 const ScRangeList* ScTable::GetScenarioRanges() const 967 { 968 DBG_ASSERT( bScenario, "bScenario == FALSE" ); 969 970 if (!pScenarioRanges) 971 { 972 ((ScTable*)this)->pScenarioRanges = new ScRangeList; 973 ScMarkData aMark; 974 MarkScenarioIn( aMark, 0 ); // immer 975 aMark.FillRangeListWithMarks( pScenarioRanges, sal_False ); 976 } 977 return pScenarioRanges; 978 } 979 980 sal_Bool ScTable::TestCopyScenarioTo( const ScTable* pDestTab ) const 981 { 982 DBG_ASSERT( bScenario, "bScenario == FALSE" ); 983 984 if (!pDestTab->IsProtected()) 985 return sal_True; 986 987 sal_Bool bOk = sal_True; 988 for (SCCOL i=0; i<=MAXCOL && bOk; i++) 989 bOk = aCol[i].TestCopyScenarioTo( pDestTab->aCol[i] ); 990 return bOk; 991 } 992 993 void ScTable::PutCell( SCCOL nCol, SCROW nRow, ScBaseCell* pCell ) 994 { 995 if (ValidColRow(nCol,nRow)) 996 { 997 if (pCell) 998 aCol[nCol].Insert( nRow, pCell ); 999 else 1000 aCol[nCol].Delete( nRow ); 1001 } 1002 } 1003 1004 1005 void ScTable::PutCell( SCCOL nCol, SCROW nRow, sal_uLong nFormatIndex, ScBaseCell* pCell ) 1006 { 1007 if (ValidColRow(nCol,nRow)) 1008 { 1009 if (pCell) 1010 aCol[nCol].Insert( nRow, nFormatIndex, pCell ); 1011 else 1012 aCol[nCol].Delete( nRow ); 1013 } 1014 } 1015 1016 1017 void ScTable::PutCell( const ScAddress& rPos, ScBaseCell* pCell ) 1018 { 1019 if (pCell) 1020 aCol[rPos.Col()].Insert( rPos.Row(), pCell ); 1021 else 1022 aCol[rPos.Col()].Delete( rPos.Row() ); 1023 } 1024 1025 1026 //UNUSED2009-05 void ScTable::PutCell( const ScAddress& rPos, sal_uLong nFormatIndex, ScBaseCell* pCell ) 1027 //UNUSED2009-05 { 1028 //UNUSED2009-05 if (pCell) 1029 //UNUSED2009-05 aCol[rPos.Col()].Insert( rPos.Row(), nFormatIndex, pCell ); 1030 //UNUSED2009-05 else 1031 //UNUSED2009-05 aCol[rPos.Col()].Delete( rPos.Row() ); 1032 //UNUSED2009-05 } 1033 1034 1035 sal_Bool ScTable::SetString( SCCOL nCol, SCROW nRow, SCTAB nTabP, const String& rString, 1036 SvNumberFormatter* pFormatter, bool bDetectNumberFormat ) 1037 { 1038 if (ValidColRow(nCol,nRow)) 1039 return aCol[nCol].SetString( 1040 nRow, nTabP, rString, pDocument->GetAddressConvention(), pFormatter, bDetectNumberFormat ); 1041 else 1042 return sal_False; 1043 } 1044 1045 1046 void ScTable::SetValue( SCCOL nCol, SCROW nRow, const double& rVal ) 1047 { 1048 if (ValidColRow(nCol, nRow)) 1049 aCol[nCol].SetValue( nRow, rVal ); 1050 } 1051 1052 1053 void ScTable::GetString( SCCOL nCol, SCROW nRow, String& rString ) 1054 { 1055 if (ValidColRow(nCol,nRow)) 1056 aCol[nCol].GetString( nRow, rString ); 1057 else 1058 rString.Erase(); 1059 } 1060 1061 1062 void ScTable::GetInputString( SCCOL nCol, SCROW nRow, String& rString ) 1063 { 1064 if (ValidColRow(nCol,nRow)) 1065 aCol[nCol].GetInputString( nRow, rString ); 1066 else 1067 rString.Erase(); 1068 } 1069 1070 1071 double ScTable::GetValue( SCCOL nCol, SCROW nRow ) 1072 { 1073 if (ValidColRow( nCol, nRow )) 1074 return aCol[nCol].GetValue( nRow ); 1075 return 0.0; 1076 } 1077 1078 1079 void ScTable::GetFormula( SCCOL nCol, SCROW nRow, String& rFormula, 1080 sal_Bool bAsciiExport ) 1081 { 1082 if (ValidColRow(nCol,nRow)) 1083 aCol[nCol].GetFormula( nRow, rFormula, bAsciiExport ); 1084 else 1085 rFormula.Erase(); 1086 } 1087 1088 1089 ScPostIt* ScTable::GetNote( SCCOL nCol, SCROW nRow ) 1090 { 1091 return ValidColRow( nCol, nRow ) ? aCol[ nCol ].GetNote( nRow ) : 0; 1092 } 1093 1094 1095 void ScTable::TakeNote( SCCOL nCol, SCROW nRow, ScPostIt*& rpNote ) 1096 { 1097 if( ValidColRow( nCol, nRow ) ) 1098 { 1099 aCol[ nCol ].TakeNote( nRow, rpNote ); 1100 if( rpNote && rpNote->GetNoteData().mxInitData.get() ) 1101 { 1102 if( !mxUninitNotes.get() ) 1103 mxUninitNotes.reset( new ScAddress2DVec ); 1104 mxUninitNotes->push_back( ScAddress2D( nCol, nRow ) ); 1105 } 1106 } 1107 else 1108 DELETEZ( rpNote ); 1109 } 1110 1111 1112 ScPostIt* ScTable::ReleaseNote( SCCOL nCol, SCROW nRow ) 1113 { 1114 return ValidColRow( nCol, nRow ) ? aCol[ nCol ].ReleaseNote( nRow ) : 0; 1115 } 1116 1117 1118 void ScTable::DeleteNote( SCCOL nCol, SCROW nRow ) 1119 { 1120 if( ValidColRow( nCol, nRow ) ) 1121 aCol[ nCol ].DeleteNote( nRow ); 1122 } 1123 1124 1125 void ScTable::InitializeNoteCaptions( bool bForced ) 1126 { 1127 if( mxUninitNotes.get() && (bForced || pDocument->IsUndoEnabled()) ) 1128 { 1129 for( ScAddress2DVec::iterator aIt = mxUninitNotes->begin(), aEnd = mxUninitNotes->end(); aIt != aEnd; ++aIt ) 1130 if( ScPostIt* pNote = GetNote( aIt->first, aIt->second ) ) 1131 pNote->GetOrCreateCaption( ScAddress( aIt->first, aIt->second, nTab ) ); 1132 mxUninitNotes.reset(); 1133 } 1134 } 1135 1136 CellType ScTable::GetCellType( SCCOL nCol, SCROW nRow ) const 1137 { 1138 if (ValidColRow( nCol, nRow )) 1139 return aCol[nCol].GetCellType( nRow ); 1140 return CELLTYPE_NONE; 1141 } 1142 1143 1144 ScBaseCell* ScTable::GetCell( SCCOL nCol, SCROW nRow ) const 1145 { 1146 if (ValidColRow( nCol, nRow )) 1147 return aCol[nCol].GetCell( nRow ); 1148 1149 DBG_ERROR("GetCell ausserhalb"); 1150 return NULL; 1151 } 1152 1153 void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const 1154 { 1155 rCol = 0; 1156 rRow = MAXROW+1; 1157 while (aCol[rCol].IsEmptyData() && rCol < MAXCOL) 1158 ++rCol; 1159 SCCOL nCol = rCol; 1160 while (nCol <= MAXCOL && rRow > 0) 1161 { 1162 if (!aCol[nCol].IsEmptyData()) 1163 rRow = ::std::min( rRow, aCol[nCol].GetFirstDataPos()); 1164 ++nCol; 1165 } 1166 } 1167 1168 void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const 1169 { 1170 rCol = MAXCOL; 1171 rRow = 0; 1172 while (aCol[rCol].IsEmptyData() && (rCol > 0)) 1173 rCol--; 1174 SCCOL nCol = rCol; 1175 while (nCol >= 0 && rRow < MAXROW) 1176 rRow = ::std::max( rRow, aCol[nCol--].GetLastDataPos()); 1177 } 1178 1179 1180 sal_Bool ScTable::HasData( SCCOL nCol, SCROW nRow ) 1181 { 1182 if (ValidColRow(nCol,nRow)) 1183 return aCol[nCol].HasDataAt( nRow ); 1184 else 1185 return sal_False; 1186 } 1187 1188 1189 sal_Bool ScTable::HasStringData( SCCOL nCol, SCROW nRow ) 1190 { 1191 if (ValidColRow(nCol,nRow)) 1192 return aCol[nCol].HasStringData( nRow ); 1193 else 1194 return sal_False; 1195 } 1196 1197 1198 sal_Bool ScTable::HasValueData( SCCOL nCol, SCROW nRow ) 1199 { 1200 if (ValidColRow(nCol,nRow)) 1201 return aCol[nCol].HasValueData( nRow ); 1202 else 1203 return sal_False; 1204 } 1205 1206 1207 sal_Bool ScTable::HasStringCells( SCCOL nStartCol, SCROW nStartRow, 1208 SCCOL nEndCol, SCROW nEndRow ) const 1209 { 1210 if ( ValidCol(nEndCol) ) 1211 for ( SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++ ) 1212 if (aCol[nCol].HasStringCells(nStartRow, nEndRow)) 1213 return sal_True; 1214 1215 return sal_False; 1216 } 1217 1218 1219 //UNUSED2008-05 sal_uInt16 ScTable::GetErrCode( SCCOL nCol, SCROW nRow ) const 1220 //UNUSED2008-05 { 1221 //UNUSED2008-05 if (ValidColRow( nCol, nRow )) 1222 //UNUSED2008-05 return aCol[nCol].GetErrCode( nRow ); 1223 //UNUSED2008-05 return 0; 1224 //UNUSED2008-05 } 1225 1226 1227 void ScTable::SetDirtyVar() 1228 { 1229 for (SCCOL i=0; i<=MAXCOL; i++) 1230 aCol[i].SetDirtyVar(); 1231 } 1232 1233 1234 void ScTable::SetDirty() 1235 { 1236 sal_Bool bOldAutoCalc = pDocument->GetAutoCalc(); 1237 pDocument->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1238 for (SCCOL i=0; i<=MAXCOL; i++) 1239 aCol[i].SetDirty(); 1240 pDocument->SetAutoCalc( bOldAutoCalc ); 1241 } 1242 1243 1244 void ScTable::SetDirty( const ScRange& rRange ) 1245 { 1246 sal_Bool bOldAutoCalc = pDocument->GetAutoCalc(); 1247 pDocument->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1248 SCCOL nCol2 = rRange.aEnd.Col(); 1249 for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++) 1250 aCol[i].SetDirty( rRange ); 1251 pDocument->SetAutoCalc( bOldAutoCalc ); 1252 } 1253 1254 1255 void ScTable::SetTableOpDirty( const ScRange& rRange ) 1256 { 1257 sal_Bool bOldAutoCalc = pDocument->GetAutoCalc(); 1258 pDocument->SetAutoCalc( sal_False ); // no multiple recalculation 1259 SCCOL nCol2 = rRange.aEnd.Col(); 1260 for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++) 1261 aCol[i].SetTableOpDirty( rRange ); 1262 pDocument->SetAutoCalc( bOldAutoCalc ); 1263 } 1264 1265 1266 void ScTable::SetDirtyAfterLoad() 1267 { 1268 sal_Bool bOldAutoCalc = pDocument->GetAutoCalc(); 1269 pDocument->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1270 for (SCCOL i=0; i<=MAXCOL; i++) 1271 aCol[i].SetDirtyAfterLoad(); 1272 pDocument->SetAutoCalc( bOldAutoCalc ); 1273 } 1274 1275 1276 void ScTable::SetRelNameDirty() 1277 { 1278 sal_Bool bOldAutoCalc = pDocument->GetAutoCalc(); 1279 pDocument->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1280 for (SCCOL i=0; i<=MAXCOL; i++) 1281 aCol[i].SetRelNameDirty(); 1282 pDocument->SetAutoCalc( bOldAutoCalc ); 1283 } 1284 1285 1286 void ScTable::SetLoadingMedium(bool bLoading) 1287 { 1288 mpRowHeights->enableTreeSearch(!bLoading); 1289 1290 // When loading a medium, prefer inserting row heights from the back 1291 // position since the row heights are stored and read in ascending order 1292 // during import. 1293 mpRowHeights->setInsertFromBack(bLoading); 1294 } 1295 1296 1297 void ScTable::CalcAll() 1298 { 1299 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CalcAll(); 1300 } 1301 1302 1303 void ScTable::CompileAll() 1304 { 1305 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CompileAll(); 1306 } 1307 1308 1309 void ScTable::CompileXML( ScProgress& rProgress ) 1310 { 1311 for (SCCOL i=0; i <= MAXCOL; i++) 1312 { 1313 aCol[i].CompileXML( rProgress ); 1314 } 1315 } 1316 1317 void ScTable::CalcAfterLoad() 1318 { 1319 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad(); 1320 } 1321 1322 1323 void ScTable::ResetChanged( const ScRange& rRange ) 1324 { 1325 SCCOL nStartCol = rRange.aStart.Col(); 1326 SCROW nStartRow = rRange.aStart.Row(); 1327 SCCOL nEndCol = rRange.aEnd.Col(); 1328 SCROW nEndRow = rRange.aEnd.Row(); 1329 1330 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) 1331 aCol[nCol].ResetChanged(nStartRow, nEndRow); 1332 } 1333 1334 // Attribute 1335 1336 const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) const 1337 { 1338 if (ValidColRow(nCol,nRow)) 1339 return aCol[nCol].GetAttr( nRow, nWhich ); 1340 else 1341 return NULL; 1342 } 1343 1344 1345 sal_uLong ScTable::GetNumberFormat( SCCOL nCol, SCROW nRow ) const 1346 { 1347 if (ValidColRow(nCol,nRow)) 1348 return aCol[nCol].GetNumberFormat( nRow ); 1349 else 1350 return 0; 1351 } 1352 1353 1354 const ScPatternAttr* ScTable::GetPattern( SCCOL nCol, SCROW nRow ) const 1355 { 1356 if (ValidColRow(nCol,nRow)) 1357 return aCol[nCol].GetPattern( nRow ); 1358 else 1359 { 1360 DBG_ERROR("wrong column or row"); 1361 return pDocument->GetDefPattern(); // for safety 1362 } 1363 } 1364 1365 1366 const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const 1367 { 1368 if ( ValidColRow( nCol, nStartRow ) && ValidRow( nEndRow ) && (nStartRow <= nEndRow) ) 1369 return aCol[nCol].GetMostUsedPattern( nStartRow, nEndRow ); 1370 else 1371 return NULL; 1372 } 1373 1374 1375 bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nMask ) const 1376 { 1377 bool bFound = false; 1378 for (SCCOL i=nCol1; i<=nCol2 && !bFound; i++) 1379 bFound |= aCol[i].HasAttrib( nRow1, nRow2, nMask ); 1380 return bFound; 1381 } 1382 1383 1384 //UNUSED2009-05 sal_Bool ScTable::HasLines( const ScRange& rRange, Rectangle& rSizes ) const 1385 //UNUSED2009-05 { 1386 //UNUSED2009-05 SCCOL nCol1 = rRange.aStart.Col(); 1387 //UNUSED2009-05 SCROW nRow1 = rRange.aStart.Row(); 1388 //UNUSED2009-05 SCCOL nCol2 = rRange.aEnd.Col(); 1389 //UNUSED2009-05 SCROW nRow2 = rRange.aEnd.Row(); 1390 //UNUSED2009-05 PutInOrder( nCol1, nCol2 ); 1391 //UNUSED2009-05 PutInOrder( nRow1, nRow2 ); 1392 //UNUSED2009-05 1393 //UNUSED2009-05 sal_Bool bFound = sal_False; 1394 //UNUSED2009-05 for (SCCOL i=nCol1; i<=nCol2; i++) 1395 //UNUSED2009-05 if (aCol[i].HasLines( nRow1, nRow2, rSizes, (i==nCol1), (i==nCol2) )) 1396 //UNUSED2009-05 bFound = sal_True; 1397 //UNUSED2009-05 1398 //UNUSED2009-05 return bFound; 1399 //UNUSED2009-05 } 1400 1401 1402 sal_Bool ScTable::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const 1403 { 1404 sal_Bool bFound=sal_False; 1405 for (SCCOL i=0; i<=MAXCOL && !bFound; i++) 1406 bFound |= aCol[i].HasAttribSelection( rMark, nMask ); 1407 return bFound; 1408 } 1409 1410 1411 sal_Bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow, 1412 SCCOL& rEndCol, SCROW& rEndRow, 1413 sal_Bool bRefresh, sal_Bool bAttrs ) 1414 { 1415 if (!(ValidCol(nStartCol) && ValidCol(rEndCol))) 1416 { 1417 DBG_ERRORFILE("ScTable::ExtendMerge: invalid column number"); 1418 return sal_False; 1419 } 1420 sal_Bool bFound=sal_False; 1421 SCCOL nOldEndX = rEndCol; 1422 SCROW nOldEndY = rEndRow; 1423 for (SCCOL i=nStartCol; i<=nOldEndX; i++) 1424 bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh, bAttrs ); 1425 return bFound; 1426 } 1427 1428 1429 sal_Bool ScTable::IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bIgnoreNotes ) const 1430 { 1431 if (!(ValidCol(nCol1) && ValidCol(nCol2))) 1432 { 1433 DBG_ERRORFILE("ScTable::IsBlockEmpty: invalid column number"); 1434 return sal_False; 1435 } 1436 sal_Bool bEmpty = sal_True; 1437 for (SCCOL i=nCol1; i<=nCol2 && bEmpty; i++) 1438 bEmpty = aCol[i].IsEmptyBlock( nRow1, nRow2, bIgnoreNotes ); 1439 return bEmpty; 1440 } 1441 1442 SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2, 1443 SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY, 1444 const ScPatternAttr* pPattern, const SfxItemSet* pCondSet ) 1445 { 1446 // Rueckgabe = neues nArrY 1447 1448 sal_uInt8 nRotDir = pPattern->GetRotateDir( pCondSet ); 1449 if ( nRotDir != SC_ROTDIR_NONE ) 1450 { 1451 sal_Bool bHit = sal_True; 1452 if ( nCol+1 < nX1 ) // column to the left 1453 bHit = ( nRotDir != SC_ROTDIR_LEFT ); 1454 else if ( nCol > nX2+1 ) // column to the right 1455 bHit = ( nRotDir != SC_ROTDIR_RIGHT ); // SC_ROTDIR_STANDARD may now also be extended to the left 1456 1457 if ( bHit ) 1458 { 1459 double nFactor = 0.0; 1460 if ( nCol > nX2+1 ) 1461 { 1462 long nRotVal = ((const SfxInt32Item&) pPattern-> 1463 GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue(); 1464 double nRealOrient = nRotVal * F_PI18000; // 1/100 Grad 1465 double nCos = cos( nRealOrient ); 1466 double nSin = sin( nRealOrient ); 1467 //! begrenzen !!! 1468 //! zusaetzlich Faktor fuer unterschiedliche PPT X/Y !!! 1469 1470 // bei SC_ROTDIR_LEFT kommt immer ein negativer Wert heraus, 1471 // wenn der Modus beruecksichtigt wird 1472 nFactor = -fabs( nCos / nSin ); 1473 } 1474 1475 for ( SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ ) 1476 { 1477 if (!RowHidden(nRow)) 1478 { 1479 sal_Bool bHitOne = sal_True; 1480 if ( nCol > nX2+1 ) 1481 { 1482 // reicht die gedrehte Zelle bis in den sichtbaren Bereich? 1483 1484 SCCOL nTouchedCol = nCol; 1485 long nWidth = static_cast<long>(mpRowHeights->getValue(nRow) * nFactor); 1486 DBG_ASSERT(nWidth <= 0, "Richtung falsch"); 1487 while ( nWidth < 0 && nTouchedCol > 0 ) 1488 { 1489 --nTouchedCol; 1490 nWidth += GetColWidth( nTouchedCol ); 1491 } 1492 if ( nTouchedCol > nX2 ) 1493 bHitOne = sal_False; 1494 } 1495 1496 if (bHitOne) 1497 { 1498 while ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo < nRow ) 1499 ++nArrY; 1500 if ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo == nRow ) 1501 pRowInfo[nArrY].nRotMaxCol = nCol; 1502 } 1503 } 1504 } 1505 } 1506 } 1507 1508 return nArrY; 1509 } 1510 1511 void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 ) 1512 { 1513 if ( !pColWidth || !mpRowHeights || !pColFlags || !pRowFlags ) 1514 { 1515 DBG_ERROR( "Spalten-/Zeileninfo fehlt" ); 1516 return; 1517 } 1518 1519 // nRotMaxCol ist auf SC_ROTMAX_NONE initialisiert, nRowNo ist schon gesetzt 1520 1521 SCROW nY1 = pRowInfo[0].nRowNo; 1522 SCROW nY2 = pRowInfo[nArrCount-1].nRowNo; 1523 1524 for (SCCOL nCol=0; nCol<=MAXCOL; nCol++) 1525 { 1526 if (!ColHidden(nCol)) 1527 { 1528 SCSIZE nArrY = 0; 1529 ScDocAttrIterator aIter( pDocument, nTab, nCol, nY1, nCol, nY2 ); 1530 SCCOL nAttrCol; 1531 SCROW nAttrRow1, nAttrRow2; 1532 const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 ); 1533 while ( pPattern ) 1534 { 1535 const SfxPoolItem* pCondItem; 1536 if ( pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, sal_True, &pCondItem ) 1537 == SFX_ITEM_SET ) 1538 { 1539 // alle Formate durchgehen, damit die Zellen nicht einzeln 1540 // angeschaut werden muessen 1541 1542 sal_uLong nIndex = ((const SfxUInt32Item*)pCondItem)->GetValue(); 1543 ScConditionalFormatList* pList = pDocument->GetCondFormList(); 1544 ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool(); 1545 if (pList && pStylePool && nIndex) 1546 { 1547 const ScConditionalFormat* pFormat = pList->GetFormat(nIndex); 1548 if ( pFormat ) 1549 { 1550 sal_uInt16 nEntryCount = pFormat->Count(); 1551 for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++) 1552 { 1553 String aStyleName = pFormat->GetEntry(nEntry)->GetStyle(); 1554 if (aStyleName.Len()) 1555 { 1556 SfxStyleSheetBase* pStyleSheet = 1557 pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PARA ); 1558 if ( pStyleSheet ) 1559 { 1560 FillMaxRot( pRowInfo, nArrCount, nX1, nX2, 1561 nCol, nAttrRow1, nAttrRow2, 1562 nArrY, pPattern, &pStyleSheet->GetItemSet() ); 1563 // nArrY nicht veraendern 1564 } 1565 } 1566 } 1567 } 1568 } 1569 } 1570 1571 nArrY = FillMaxRot( pRowInfo, nArrCount, nX1, nX2, 1572 nCol, nAttrRow1, nAttrRow2, 1573 nArrY, pPattern, NULL ); 1574 1575 pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 ); 1576 } 1577 } 1578 } 1579 } 1580 1581 sal_Bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const 1582 { 1583 // nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32 1584 sal_uInt16 nEdges; 1585 1586 if ( nCol1 == nCol2 ) 1587 { // linke und rechte Spalte 1588 const sal_uInt16 n = 4 | 16; 1589 nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n ); 1590 // nicht (4 und 16) oder 1 oder 32 1591 if ( nEdges && (((nEdges & n) != n) || (nEdges & 33)) ) 1592 return sal_True; // linke oder rechte Kante fehlt oder offen 1593 } 1594 else 1595 { // linke Spalte 1596 nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, 4 ); 1597 // nicht 4 oder 1 oder 32 1598 if ( nEdges && (((nEdges & 4) != 4) || (nEdges & 33)) ) 1599 return sal_True; // linke Kante fehlt oder offen 1600 // rechte Spalte 1601 nEdges = aCol[nCol2].GetBlockMatrixEdges( nRow1, nRow2, 16 ); 1602 // nicht 16 oder 1 oder 32 1603 if ( nEdges && (((nEdges & 16) != 16) || (nEdges & 33)) ) 1604 return sal_True; // rechte Kante fehlt oder offen 1605 } 1606 1607 if ( nRow1 == nRow2 ) 1608 { // obere und untere Zeile 1609 sal_Bool bOpen = sal_False; 1610 const sal_uInt16 n = 2 | 8; 1611 for ( SCCOL i=nCol1; i<=nCol2; i++) 1612 { 1613 nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n ); 1614 if ( nEdges ) 1615 { 1616 if ( (nEdges & n) != n ) 1617 return sal_True; // obere oder untere Kante fehlt 1618 if ( nEdges & 4 ) 1619 bOpen = sal_True; // linke Kante oeffnet, weitersehen 1620 else if ( !bOpen ) 1621 return sal_True; // es gibt was, was nicht geoeffnet wurde 1622 if ( nEdges & 16 ) 1623 bOpen = sal_False; // rechte Kante schliesst 1624 } 1625 } 1626 if ( bOpen ) 1627 return sal_True; // es geht noch weiter 1628 } 1629 else 1630 { 1631 sal_uInt16 j, n; 1632 SCROW nR; 1633 // erst obere Zeile, dann untere Zeile 1634 for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 ) 1635 { 1636 sal_Bool bOpen = sal_False; 1637 for ( SCCOL i=nCol1; i<=nCol2; i++) 1638 { 1639 nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n ); 1640 if ( nEdges ) 1641 { 1642 // in oberere Zeile keine obere Kante bzw. 1643 // in unterer Zeile keine untere Kante 1644 if ( (nEdges & n) != n ) 1645 return sal_True; 1646 if ( nEdges & 4 ) 1647 bOpen = sal_True; // linke Kante oeffnet, weitersehen 1648 else if ( !bOpen ) 1649 return sal_True; // es gibt was, was nicht geoeffnet wurde 1650 if ( nEdges & 16 ) 1651 bOpen = sal_False; // rechte Kante schliesst 1652 } 1653 } 1654 if ( bOpen ) 1655 return sal_True; // es geht noch weiter 1656 } 1657 } 1658 return sal_False; 1659 } 1660 1661 1662 sal_Bool ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const 1663 { 1664 sal_Bool bFound=sal_False; 1665 for (SCCOL i=0; i<=MAXCOL && !bFound; i++) 1666 bFound |= aCol[i].HasSelectionMatrixFragment(rMark); 1667 return bFound; 1668 } 1669 1670 1671 sal_Bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, 1672 SCROW nRow2, sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 1673 { 1674 if ( !ValidColRow( nCol2, nRow2 ) ) 1675 { 1676 DBG_ERRORFILE("IsBlockEditable: invalid column or row"); 1677 if (pOnlyNotBecauseOfMatrix) 1678 *pOnlyNotBecauseOfMatrix = sal_False; 1679 return sal_False; 1680 } 1681 1682 sal_Bool bIsEditable = sal_True; 1683 if ( nLockCount ) 1684 bIsEditable = sal_False; 1685 else if ( IsProtected() && !pDocument->IsScenario(nTab) ) 1686 { 1687 if((bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED )) != sal_False) 1688 { 1689 // If Sheet is protected and cells are not protected then 1690 // check the active scenario protect flag if this range is 1691 // on the active scenario range. Note the 'copy back' must also 1692 // be set to apply protection. 1693 sal_uInt16 nScenTab = nTab+1; 1694 while(pDocument->IsScenario(nScenTab)) 1695 { 1696 ScRange aEditRange(nCol1, nRow1, nScenTab, nCol2, nRow2, nScenTab); 1697 if(pDocument->IsActiveScenario(nScenTab) && pDocument->HasScenarioRange(nScenTab, aEditRange)) 1698 { 1699 sal_uInt16 nFlags; 1700 pDocument->GetScenarioFlags(nScenTab,nFlags); 1701 bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY)); 1702 break; 1703 } 1704 nScenTab++; 1705 } 1706 } 1707 } 1708 else if (pDocument->IsScenario(nTab)) 1709 { 1710 // Determine if the preceding sheet is protected 1711 SCTAB nActualTab = nTab; 1712 do 1713 { 1714 nActualTab--; 1715 } 1716 while(pDocument->IsScenario(nActualTab)); 1717 1718 if(pDocument->IsTabProtected(nActualTab)) 1719 { 1720 ScRange aEditRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab); 1721 if(pDocument->HasScenarioRange(nTab, aEditRange)) 1722 { 1723 sal_uInt16 nFlags; 1724 pDocument->GetScenarioFlags(nTab,nFlags); 1725 bIsEditable = !(nFlags & SC_SCENARIO_PROTECT); 1726 } 1727 } 1728 } 1729 if ( bIsEditable ) 1730 { 1731 if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) ) 1732 { 1733 bIsEditable = sal_False; 1734 if ( pOnlyNotBecauseOfMatrix ) 1735 *pOnlyNotBecauseOfMatrix = sal_True; 1736 } 1737 else if ( pOnlyNotBecauseOfMatrix ) 1738 *pOnlyNotBecauseOfMatrix = sal_False; 1739 } 1740 else if ( pOnlyNotBecauseOfMatrix ) 1741 *pOnlyNotBecauseOfMatrix = sal_False; 1742 return bIsEditable; 1743 } 1744 1745 1746 sal_Bool ScTable::IsSelectionEditable( const ScMarkData& rMark, 1747 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 1748 { 1749 sal_Bool bIsEditable = sal_True; 1750 if ( nLockCount ) 1751 bIsEditable = sal_False; 1752 else if ( IsProtected() && !pDocument->IsScenario(nTab) ) 1753 { 1754 if((bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED )) != sal_False) 1755 { 1756 // If Sheet is protected and cells are not protected then 1757 // check the active scenario protect flag if this area is 1758 // in the active scenario range. 1759 ScRangeList aRanges; 1760 rMark.FillRangeListWithMarks( &aRanges, sal_False ); 1761 sal_uLong nRangeCount = aRanges.Count(); 1762 SCTAB nScenTab = nTab+1; 1763 while(pDocument->IsScenario(nScenTab) && bIsEditable) 1764 { 1765 if(pDocument->IsActiveScenario(nScenTab)) 1766 { 1767 for (sal_uLong i=0; i<nRangeCount && bIsEditable; i++) 1768 { 1769 ScRange aRange = *aRanges.GetObject(i); 1770 if(pDocument->HasScenarioRange(nScenTab, aRange)) 1771 { 1772 sal_uInt16 nFlags; 1773 pDocument->GetScenarioFlags(nScenTab,nFlags); 1774 bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY)); 1775 } 1776 } 1777 } 1778 nScenTab++; 1779 } 1780 } 1781 } 1782 else if (pDocument->IsScenario(nTab)) 1783 { 1784 // Determine if the preceding sheet is protected 1785 SCTAB nActualTab = nTab; 1786 do 1787 { 1788 nActualTab--; 1789 } 1790 while(pDocument->IsScenario(nActualTab)); 1791 1792 if(pDocument->IsTabProtected(nActualTab)) 1793 { 1794 ScRangeList aRanges; 1795 rMark.FillRangeListWithMarks( &aRanges, sal_False ); 1796 sal_uLong nRangeCount = aRanges.Count(); 1797 for (sal_uLong i=0; i<nRangeCount && bIsEditable; i++) 1798 { 1799 ScRange aRange = *aRanges.GetObject(i); 1800 if(pDocument->HasScenarioRange(nTab, aRange)) 1801 { 1802 sal_uInt16 nFlags; 1803 pDocument->GetScenarioFlags(nTab,nFlags); 1804 bIsEditable = !(nFlags & SC_SCENARIO_PROTECT); 1805 } 1806 } 1807 } 1808 } 1809 if ( bIsEditable ) 1810 { 1811 if ( HasSelectionMatrixFragment( rMark ) ) 1812 { 1813 bIsEditable = sal_False; 1814 if ( pOnlyNotBecauseOfMatrix ) 1815 *pOnlyNotBecauseOfMatrix = sal_True; 1816 } 1817 else if ( pOnlyNotBecauseOfMatrix ) 1818 *pOnlyNotBecauseOfMatrix = sal_False; 1819 } 1820 else if ( pOnlyNotBecauseOfMatrix ) 1821 *pOnlyNotBecauseOfMatrix = sal_False; 1822 return bIsEditable; 1823 } 1824 1825 1826 1827 void ScTable::LockTable() 1828 { 1829 ++nLockCount; 1830 } 1831 1832 1833 void ScTable::UnlockTable() 1834 { 1835 if (nLockCount) 1836 --nLockCount; 1837 else 1838 { 1839 DBG_ERROR("UnlockTable ohne LockTable"); 1840 } 1841 } 1842 1843 1844 void ScTable::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, sal_Bool bDeep ) const 1845 { 1846 for (SCCOL i=0; i<=MAXCOL; i++) 1847 aCol[i].MergeSelectionPattern( rState, rMark, bDeep ); 1848 } 1849 1850 1851 void ScTable::MergePatternArea( ScMergePatternState& rState, SCCOL nCol1, SCROW nRow1, 1852 SCCOL nCol2, SCROW nRow2, sal_Bool bDeep ) const 1853 { 1854 for (SCCOL i=nCol1; i<=nCol2; i++) 1855 aCol[i].MergePatternArea( rState, nRow1, nRow2, bDeep ); 1856 } 1857 1858 1859 void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags, 1860 SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const 1861 { 1862 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 1863 { 1864 PutInOrder(nStartCol, nEndCol); 1865 PutInOrder(nStartRow, nEndRow); 1866 for (SCCOL i=nStartCol; i<=nEndCol; i++) 1867 aCol[i].MergeBlockFrame( pLineOuter, pLineInner, rFlags, 1868 nStartRow, nEndRow, (i==nStartCol), nEndCol-i ); 1869 } 1870 } 1871 1872 1873 void ScTable::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner, 1874 SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) 1875 { 1876 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 1877 { 1878 PutInOrder(nStartCol, nEndCol); 1879 PutInOrder(nStartRow, nEndRow); 1880 for (SCCOL i=nStartCol; i<=nEndCol; i++) 1881 aCol[i].ApplyBlockFrame( pLineOuter, pLineInner, 1882 nStartRow, nEndRow, (i==nStartCol), nEndCol-i ); 1883 } 1884 } 1885 1886 1887 void ScTable::ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr ) 1888 { 1889 if (ValidColRow(nCol,nRow)) 1890 aCol[nCol].ApplyPattern( nRow, rAttr ); 1891 } 1892 1893 1894 void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1895 const ScPatternAttr& rAttr ) 1896 { 1897 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 1898 { 1899 PutInOrder(nStartCol, nEndCol); 1900 PutInOrder(nStartRow, nEndRow); 1901 for (SCCOL i = nStartCol; i <= nEndCol; i++) 1902 aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr); 1903 } 1904 } 1905 1906 void ScTable::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange, 1907 const ScPatternAttr& rPattern, short nNewType ) 1908 { 1909 SCCOL nEndCol = rRange.aEnd.Col(); 1910 for ( SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ ) 1911 { 1912 aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType ); 1913 } 1914 } 1915 1916 1917 1918 void ScTable::ApplyStyle( SCCOL nCol, SCROW nRow, const ScStyleSheet& rStyle ) 1919 { 1920 if (ValidColRow(nCol,nRow)) 1921 aCol[nCol].ApplyStyle( nRow, rStyle ); 1922 } 1923 1924 1925 void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet& rStyle ) 1926 { 1927 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 1928 { 1929 PutInOrder(nStartCol, nEndCol); 1930 PutInOrder(nStartRow, nEndRow); 1931 for (SCCOL i = nStartCol; i <= nEndCol; i++) 1932 aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle); 1933 } 1934 } 1935 1936 1937 void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark) 1938 { 1939 for (SCCOL i=0; i<=MAXCOL; i++) 1940 aCol[i].ApplySelectionStyle( rStyle, rMark ); 1941 } 1942 1943 1944 void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark, 1945 const SvxBorderLine* pLine, sal_Bool bColorOnly ) 1946 { 1947 if ( bColorOnly && !pLine ) 1948 return; 1949 1950 for (SCCOL i=0; i<=MAXCOL; i++) 1951 aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly ); 1952 } 1953 1954 1955 const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW nRow ) const 1956 { 1957 if (ValidColRow(nCol, nRow)) 1958 return aCol[nCol].GetStyle(nRow); 1959 else 1960 return NULL; 1961 } 1962 1963 1964 const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, sal_Bool& rFound ) const 1965 { 1966 rFound = sal_False; 1967 1968 sal_Bool bEqual = sal_True; 1969 sal_Bool bColFound; 1970 1971 const ScStyleSheet* pStyle = NULL; 1972 const ScStyleSheet* pNewStyle; 1973 1974 for (SCCOL i=0; i<=MAXCOL && bEqual; i++) 1975 if (rMark.HasMultiMarks(i)) 1976 { 1977 pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound ); 1978 if (bColFound) 1979 { 1980 rFound = sal_True; 1981 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 1982 bEqual = sal_False; // unterschiedliche 1983 pStyle = pNewStyle; 1984 } 1985 } 1986 1987 return bEqual ? pStyle : NULL; 1988 } 1989 1990 1991 const ScStyleSheet* ScTable::GetAreaStyle( sal_Bool& rFound, SCCOL nCol1, SCROW nRow1, 1992 SCCOL nCol2, SCROW nRow2 ) const 1993 { 1994 rFound = sal_False; 1995 1996 sal_Bool bEqual = sal_True; 1997 sal_Bool bColFound; 1998 1999 const ScStyleSheet* pStyle = NULL; 2000 const ScStyleSheet* pNewStyle; 2001 2002 for (SCCOL i=nCol1; i<=nCol2 && bEqual; i++) 2003 { 2004 pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2); 2005 if (bColFound) 2006 { 2007 rFound = sal_True; 2008 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 2009 bEqual = sal_False; // unterschiedliche 2010 pStyle = pNewStyle; 2011 } 2012 } 2013 2014 return bEqual ? pStyle : NULL; 2015 } 2016 2017 2018 sal_Bool ScTable::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const 2019 { 2020 sal_Bool bIsUsed = sal_False; 2021 2022 for ( SCCOL i=0; i<=MAXCOL; i++ ) 2023 { 2024 if ( aCol[i].IsStyleSheetUsed( rStyle, bGatherAllStyles ) ) 2025 { 2026 if ( !bGatherAllStyles ) 2027 return sal_True; 2028 bIsUsed = sal_True; 2029 } 2030 } 2031 2032 return bIsUsed; 2033 } 2034 2035 2036 void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved, 2037 OutputDevice* pDev, 2038 double nPPTX, double nPPTY, 2039 const Fraction& rZoomX, const Fraction& rZoomY ) 2040 { 2041 ScFlatBoolRowSegments aUsedRows; 2042 for (SCCOL i = 0; i <= MAXCOL; ++i) 2043 aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved); 2044 2045 SCROW nRow = 0; 2046 while (nRow <= MAXROW) 2047 { 2048 ScFlatBoolRowSegments::RangeData aData; 2049 if (!aUsedRows.getRangeData(nRow, aData)) 2050 // search failed! 2051 return; 2052 2053 SCROW nEndRow = aData.mnRow2; 2054 if (aData.mbValue) 2055 SetOptimalHeight(nRow, nEndRow, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False); 2056 2057 nRow = nEndRow + 1; 2058 } 2059 } 2060 2061 2062 sal_Bool ScTable::ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 2063 sal_Int16 nFlags ) 2064 { 2065 sal_Bool bChanged = sal_False; 2066 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 2067 for (SCCOL i = nStartCol; i <= nEndCol; i++) 2068 bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags); 2069 return bChanged; 2070 } 2071 2072 2073 sal_Bool ScTable::RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 2074 sal_Int16 nFlags ) 2075 { 2076 sal_Bool bChanged = sal_False; 2077 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 2078 for (SCCOL i = nStartCol; i <= nEndCol; i++) 2079 bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags); 2080 return bChanged; 2081 } 2082 2083 2084 void ScTable::SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, sal_Bool bPutToPool ) 2085 { 2086 if (ValidColRow(nCol,nRow)) 2087 aCol[nCol].SetPattern( nRow, rAttr, bPutToPool ); 2088 } 2089 2090 2091 void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const SfxPoolItem& rAttr ) 2092 { 2093 if (ValidColRow(nCol,nRow)) 2094 aCol[nCol].ApplyAttr( nRow, rAttr ); 2095 } 2096 2097 2098 void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark ) 2099 { 2100 for (SCCOL i=0; i<=MAXCOL; i++) 2101 aCol[i].ApplySelectionCache( pCache, rMark ); 2102 } 2103 2104 2105 void ScTable::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark ) 2106 { 2107 for (SCCOL i=0; i<=MAXCOL; i++) 2108 aCol[i].ChangeSelectionIndent( bIncrement, rMark ); 2109 } 2110 2111 2112 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark ) 2113 { 2114 for (SCCOL i=0; i<=MAXCOL; i++) 2115 aCol[i].ClearSelectionItems( pWhich, rMark ); 2116 } 2117 2118 2119 // Spaltenbreiten / Zeilenhoehen 2120 2121 void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth ) 2122 { 2123 if (VALIDCOL(nCol) && pColWidth) 2124 { 2125 if (!nNewWidth) 2126 { 2127 // DBG_ERROR("Spaltenbreite 0 in SetColWidth"); 2128 nNewWidth = STD_COL_WIDTH; 2129 } 2130 2131 if ( nNewWidth != pColWidth[nCol] ) 2132 { 2133 IncRecalcLevel(); 2134 InitializeNoteCaptions(); 2135 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2136 if (pDrawLayer) 2137 pDrawLayer->WidthChanged( nTab, nCol, ((long) nNewWidth) - (long) pColWidth[nCol] ); 2138 pColWidth[nCol] = nNewWidth; 2139 DecRecalcLevel(); 2140 2141 InvalidatePageBreaks(); 2142 } 2143 } 2144 else 2145 { 2146 DBG_ERROR("Falsche Spaltennummer oder keine Breiten"); 2147 } 2148 } 2149 2150 2151 void ScTable::SetRowHeight( SCROW nRow, sal_uInt16 nNewHeight ) 2152 { 2153 if (VALIDROW(nRow) && mpRowHeights) 2154 { 2155 if (!nNewHeight) 2156 { 2157 DBG_ERROR("Zeilenhoehe 0 in SetRowHeight"); 2158 nNewHeight = ScGlobal::nStdRowHeight; 2159 } 2160 2161 sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow); 2162 if ( nNewHeight != nOldHeight ) 2163 { 2164 IncRecalcLevel(); 2165 InitializeNoteCaptions(); 2166 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2167 if (pDrawLayer) 2168 pDrawLayer->HeightChanged( nTab, nRow, ((long) nNewHeight) - (long) nOldHeight ); 2169 mpRowHeights->setValue(nRow, nRow, nNewHeight); 2170 DecRecalcLevel(); 2171 2172 InvalidatePageBreaks(); 2173 } 2174 } 2175 else 2176 { 2177 DBG_ERROR("Falsche Zeilennummer oder keine Hoehen"); 2178 } 2179 } 2180 2181 namespace { 2182 2183 /** 2184 * Check if the new pixel size is different from the old size between 2185 * specified ranges. 2186 */ 2187 bool lcl_pixelSizeChanged( 2188 ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow, 2189 sal_uInt16 nNewHeight, double nPPTY) 2190 { 2191 long nNewPix = static_cast<long>(nNewHeight * nPPTY); 2192 2193 ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights); 2194 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow) 2195 { 2196 sal_uInt16 nHeight; 2197 if (!aFwdIter.getValue(nRow, nHeight)) 2198 break; 2199 2200 if (nHeight != nNewHeight) 2201 { 2202 bool bChanged = (nNewPix != static_cast<long>(nHeight * nPPTY)); 2203 if (bChanged) 2204 return true; 2205 } 2206 2207 // Skip ahead to the last position of the current range. 2208 nRow = aFwdIter.getLastPos(); 2209 } 2210 return false; 2211 } 2212 2213 } 2214 2215 sal_Bool ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight, 2216 double /* nPPTX */, double nPPTY ) 2217 { 2218 sal_Bool bChanged = sal_False; 2219 if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights) 2220 { 2221 IncRecalcLevel(); 2222 InitializeNoteCaptions(); 2223 if (!nNewHeight) 2224 { 2225 DBG_ERROR("Zeilenhoehe 0 in SetRowHeight"); 2226 nNewHeight = ScGlobal::nStdRowHeight; 2227 } 2228 2229 sal_Bool bSingle = sal_False; // sal_True = process every row for its own 2230 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2231 if (pDrawLayer) 2232 if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow )) 2233 bSingle = sal_True; 2234 2235 if (bSingle) 2236 { 2237 ScFlatUInt16RowSegments::RangeData aData; 2238 mpRowHeights->getRangeData(nStartRow, aData); 2239 if (nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2) 2240 bSingle = sal_False; // no difference in this range 2241 } 2242 if (bSingle) 2243 { 2244 if (nEndRow-nStartRow < 20) 2245 { 2246 if (!bChanged) 2247 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY); 2248 2249 /* #i94028# #i94991# If drawing objects are involved, each row 2250 has to be changed for its own, because each call to 2251 ScDrawLayer::HeightChanged expects correct row heights 2252 above passed row in the document. Cannot use array iterator 2253 because array changes in every cycle. */ 2254 if( pDrawLayer ) 2255 { 2256 for( SCROW nRow = nStartRow; nRow <= nEndRow ; ++nRow ) 2257 { 2258 pDrawLayer->HeightChanged( nTab, nRow, 2259 static_cast<long>(nNewHeight) - static_cast<long>(mpRowHeights->getValue(nRow))); 2260 mpRowHeights->setValue(nRow, nRow, nNewHeight); 2261 } 2262 } 2263 else 2264 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight); 2265 } 2266 else 2267 { 2268 SCROW nMid = (nStartRow+nEndRow) / 2; 2269 if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 )) 2270 bChanged = sal_True; 2271 if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 )) 2272 bChanged = sal_True; 2273 } 2274 } 2275 else 2276 { 2277 if (pDrawLayer) 2278 { 2279 // #i115025# When comparing to nNewHeight for the whole range, the height 2280 // including hidden rows has to be used (same behavior as 3.2). 2281 unsigned long nOldHeights = mpRowHeights->getSumValue(nStartRow, nEndRow); 2282 // FIXME: should we test for overflows? 2283 long nHeightDif = (long) (unsigned long) nNewHeight * 2284 (nEndRow - nStartRow + 1) - nOldHeights; 2285 pDrawLayer->HeightChanged( nTab, nEndRow, nHeightDif ); 2286 } 2287 2288 if (!bChanged) 2289 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY); 2290 2291 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight); 2292 } 2293 DecRecalcLevel(); 2294 2295 if (bChanged) 2296 InvalidatePageBreaks(); 2297 } 2298 else 2299 { 2300 DBG_ERROR("Falsche Zeilennummer oder keine Hoehen"); 2301 } 2302 2303 return bChanged; 2304 } 2305 2306 void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight ) 2307 { 2308 if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights) 2309 return; 2310 2311 if (!nNewHeight) 2312 nNewHeight = ScGlobal::nStdRowHeight; 2313 2314 mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight); 2315 } 2316 2317 void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, sal_Bool bManual ) 2318 { 2319 if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags) 2320 { 2321 if (bManual) 2322 pRowFlags->OrValue( nStartRow, nEndRow, CR_MANUALSIZE); 2323 else 2324 pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE)); 2325 } 2326 else 2327 { 2328 DBG_ERROR("Falsche Zeilennummer oder keine Zeilenflags"); 2329 } 2330 } 2331 2332 2333 sal_uInt16 ScTable::GetColWidth( SCCOL nCol ) const 2334 { 2335 DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer"); 2336 2337 if (VALIDCOL(nCol) && pColFlags && pColWidth) 2338 { 2339 if (ColHidden(nCol)) 2340 return 0; 2341 else 2342 return pColWidth[nCol]; 2343 } 2344 else 2345 return (sal_uInt16) STD_COL_WIDTH; 2346 } 2347 2348 2349 sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const // immer die eingestellte 2350 { 2351 DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer"); 2352 2353 if (VALIDCOL(nCol) && pColWidth) 2354 return pColWidth[nCol]; 2355 else 2356 return (sal_uInt16) STD_COL_WIDTH; 2357 } 2358 2359 2360 sal_uInt16 ScTable::GetCommonWidth( SCCOL nEndCol ) 2361 { 2362 // get the width that is used in the largest continuous column range (up to nEndCol) 2363 2364 if ( !ValidCol(nEndCol) ) 2365 { 2366 DBG_ERROR("wrong column"); 2367 nEndCol = MAXCOL; 2368 } 2369 2370 sal_uInt16 nMaxWidth = 0; 2371 sal_uInt16 nMaxCount = 0; 2372 SCCOL nRangeStart = 0; 2373 while ( nRangeStart <= nEndCol ) 2374 { 2375 // skip hidden columns 2376 while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) ) 2377 ++nRangeStart; 2378 if ( nRangeStart <= nEndCol ) 2379 { 2380 sal_uInt16 nThisCount = 0; 2381 sal_uInt16 nThisWidth = pColWidth[nRangeStart]; 2382 SCCOL nRangeEnd = nRangeStart; 2383 while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth ) 2384 { 2385 ++nThisCount; 2386 ++nRangeEnd; 2387 2388 // skip hidden columns 2389 while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) ) 2390 ++nRangeEnd; 2391 } 2392 2393 if ( nThisCount > nMaxCount ) 2394 { 2395 nMaxCount = nThisCount; 2396 nMaxWidth = nThisWidth; 2397 } 2398 2399 nRangeStart = nRangeEnd; // next range 2400 } 2401 } 2402 2403 return nMaxWidth; 2404 } 2405 2406 2407 sal_uInt16 ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const 2408 { 2409 DBG_ASSERT(VALIDROW(nRow),"Invalid row number"); 2410 2411 if (VALIDROW(nRow) && mpRowHeights) 2412 { 2413 if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow)) 2414 return 0; 2415 else 2416 { 2417 ScFlatUInt16RowSegments::RangeData aData; 2418 if (!mpRowHeights->getRangeData(nRow, aData)) 2419 { 2420 if (pStartRow) 2421 *pStartRow = nRow; 2422 if (pEndRow) 2423 *pEndRow = nRow; 2424 // TODO: What should we return in case the search fails? 2425 return 0; 2426 } 2427 2428 // If bHiddenAsZero, pStartRow and pEndRow were initialized to 2429 // boundaries of a non-hidden segment. Assume that the previous and 2430 // next segment are hidden then and limit the current height 2431 // segment. 2432 if (pStartRow) 2433 *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1); 2434 if (pEndRow) 2435 *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2); 2436 return aData.mnValue; 2437 } 2438 } 2439 else 2440 { 2441 if (pStartRow) 2442 *pStartRow = nRow; 2443 if (pEndRow) 2444 *pEndRow = nRow; 2445 return (sal_uInt16) ScGlobal::nStdRowHeight; 2446 } 2447 } 2448 2449 2450 sal_uLong ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) const 2451 { 2452 DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer"); 2453 2454 if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights) 2455 { 2456 sal_uLong nHeight = 0; 2457 SCROW nRow = nStartRow; 2458 while (nRow <= nEndRow) 2459 { 2460 SCROW nLastRow = -1; 2461 if (!RowHidden(nRow, nLastRow)) 2462 { 2463 if (nLastRow > nEndRow) 2464 nLastRow = nEndRow; 2465 nHeight += mpRowHeights->getSumValue(nRow, nLastRow); 2466 } 2467 nRow = nLastRow + 1; 2468 } 2469 return nHeight; 2470 } 2471 else 2472 return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight); 2473 } 2474 2475 2476 sal_uLong ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const 2477 { 2478 DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer"); 2479 2480 if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights) 2481 { 2482 sal_uLong nHeight = 0; 2483 SCROW nRow = nStartRow; 2484 while (nRow <= nEndRow) 2485 { 2486 SCROW nLastRow = -1; 2487 if (!RowHidden(nRow, nLastRow)) 2488 { 2489 if (nLastRow > nEndRow) 2490 nLastRow = nEndRow; 2491 2492 // #i117315# can't use getSumValue, because individual values must be rounded 2493 while (nRow <= nLastRow) 2494 { 2495 ScFlatUInt16RowSegments::RangeData aData; 2496 if (!mpRowHeights->getRangeData(nRow, aData)) 2497 return nHeight; // shouldn't happen 2498 2499 SCROW nSegmentEnd = std::min( nLastRow, aData.mnRow2 ); 2500 2501 // round-down a single height value, multiply resulting (pixel) values 2502 sal_uLong nOneHeight = static_cast<sal_uLong>( aData.mnValue * fScale ); 2503 nHeight += nOneHeight * ( nSegmentEnd + 1 - nRow ); 2504 2505 nRow = nSegmentEnd + 1; 2506 } 2507 } 2508 nRow = nLastRow + 1; 2509 } 2510 return nHeight; 2511 } 2512 else 2513 return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale); 2514 } 2515 2516 2517 sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const // non-0 even if hidden 2518 { 2519 DBG_ASSERT(VALIDROW(nRow),"wrong row number"); 2520 2521 if (VALIDROW(nRow) && mpRowHeights) 2522 return mpRowHeights->getValue(nRow); 2523 else 2524 return (sal_uInt16) ScGlobal::nStdRowHeight; 2525 } 2526 2527 2528 // Spalten-/Zeilen-Flags 2529 2530 2531 SCROW ScTable::GetHiddenRowCount( SCROW nRow ) 2532 { 2533 if (!ValidRow(nRow)) 2534 return 0; 2535 2536 SCROW nLastRow = -1; 2537 if (!RowHidden(nRow, nLastRow) || !ValidRow(nLastRow)) 2538 return 0; 2539 2540 return nLastRow - nRow + 1; 2541 } 2542 2543 2544 //! ShowRows / DBShowRows zusammenfassen 2545 2546 void ScTable::ShowCol(SCCOL nCol, bool bShow) 2547 { 2548 if (VALIDCOL(nCol)) 2549 { 2550 bool bWasVis = !ColHidden(nCol); 2551 if (bWasVis != bShow) 2552 { 2553 IncRecalcLevel(); 2554 InitializeNoteCaptions(); 2555 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2556 if (pDrawLayer) 2557 { 2558 if (bShow) 2559 pDrawLayer->WidthChanged( nTab, nCol, (long) pColWidth[nCol] ); 2560 else 2561 pDrawLayer->WidthChanged( nTab, nCol, -(long) pColWidth[nCol] ); 2562 } 2563 2564 SetColHidden(nCol, nCol, !bShow); 2565 DecRecalcLevel(); 2566 2567 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); 2568 if ( pCharts ) 2569 pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, MAXROW, nTab )); 2570 } 2571 } 2572 else 2573 { 2574 DBG_ERROR("Falsche Spaltennummer oder keine Flags"); 2575 } 2576 } 2577 2578 2579 void ScTable::ShowRow(SCROW nRow, bool bShow) 2580 { 2581 if (VALIDROW(nRow) && pRowFlags) 2582 { 2583 bool bWasVis = !RowHidden(nRow); 2584 if (bWasVis != bShow) 2585 { 2586 IncRecalcLevel(); 2587 InitializeNoteCaptions(); 2588 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2589 if (pDrawLayer) 2590 { 2591 if (bShow) 2592 pDrawLayer->HeightChanged( 2593 nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow))); 2594 else 2595 pDrawLayer->HeightChanged( 2596 nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow))); 2597 } 2598 2599 SetRowHidden(nRow, nRow, !bShow); 2600 if (bShow) 2601 SetRowFiltered(nRow, nRow, false); 2602 DecRecalcLevel(); 2603 2604 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); 2605 if ( pCharts ) 2606 pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab )); 2607 2608 InvalidatePageBreaks(); 2609 } 2610 } 2611 else 2612 { 2613 DBG_ERROR("Falsche Zeilennummer oder keine Flags"); 2614 } 2615 } 2616 2617 2618 void ScTable::DBShowRow(SCROW nRow, bool bShow) 2619 { 2620 if (VALIDROW(nRow) && pRowFlags) 2621 { 2622 bool bWasVis = !RowHidden(nRow); 2623 IncRecalcLevel(); 2624 InitializeNoteCaptions(); 2625 if (bWasVis != bShow) 2626 { 2627 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2628 if (pDrawLayer) 2629 { 2630 if (bShow) 2631 pDrawLayer->HeightChanged( 2632 nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow))); 2633 else 2634 pDrawLayer->HeightChanged( 2635 nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow))); 2636 } 2637 } 2638 2639 // Filter-Flag immer setzen, auch wenn Hidden unveraendert 2640 SetRowHidden(nRow, nRow, !bShow); 2641 SetRowFiltered(nRow, nRow, !bShow); 2642 DecRecalcLevel(); 2643 2644 if (bWasVis != bShow) 2645 { 2646 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); 2647 if ( pCharts ) 2648 pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab )); 2649 2650 if (pOutlineTable) 2651 UpdateOutlineRow( nRow, nRow, bShow ); 2652 2653 InvalidatePageBreaks(); 2654 } 2655 } 2656 else 2657 { 2658 DBG_ERROR("Falsche Zeilennummer oder keine Flags"); 2659 } 2660 } 2661 2662 2663 void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags) 2664 { 2665 // #i116164# IncRecalcLevel/DecRecalcLevel is in ScTable::Query 2666 SCROW nStartRow = nRow1; 2667 InitializeNoteCaptions(); 2668 while (nStartRow <= nRow2) 2669 { 2670 SCROW nEndRow = -1; 2671 bool bWasVis = !RowHidden(nStartRow, nEndRow); 2672 if (nEndRow > nRow2) 2673 nEndRow = nRow2; 2674 2675 sal_Bool bChanged = ( bWasVis != bShow ); 2676 if ( bChanged && bSetFlags ) 2677 { 2678 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2679 if (pDrawLayer) 2680 { 2681 long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow)); 2682 if (bShow) 2683 pDrawLayer->HeightChanged( nTab, nStartRow, nHeight ); 2684 else 2685 pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight ); 2686 } 2687 } 2688 2689 // #i116164# Directly modify the flags only if there are drawing objects within the area. 2690 // Otherwise, all modifications are made together in ScTable::Query, so the tree isn't constantly rebuilt. 2691 if ( bSetFlags ) 2692 { 2693 SetRowHidden(nStartRow, nEndRow, !bShow); 2694 SetRowFiltered(nStartRow, nEndRow, !bShow); 2695 } 2696 2697 if ( bChanged ) 2698 { 2699 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); 2700 if ( pCharts ) 2701 pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab )); 2702 } 2703 2704 nStartRow = nEndRow + 1; 2705 } 2706 2707 // #i12341# For Show/Hide rows, the outlines are updated separately from the outside. 2708 // For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has 2709 // to be done here. 2710 if (pOutlineTable) 2711 UpdateOutlineRow( nRow1, nRow2, bShow ); 2712 } 2713 2714 2715 void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow) 2716 { 2717 SCROW nStartRow = nRow1; 2718 IncRecalcLevel(); 2719 InitializeNoteCaptions(); 2720 2721 // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough 2722 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 2723 bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2, false ); 2724 long nOldHeight = 0; 2725 if ( pDrawLayer && !bHasObjects ) 2726 nOldHeight = static_cast<long>(GetRowHeight(nRow1, nRow2)); 2727 2728 while (nStartRow <= nRow2) 2729 { 2730 SCROW nEndRow = -1; 2731 bool bWasVis = !RowHidden(nStartRow, nEndRow); 2732 if (nEndRow > nRow2) 2733 nEndRow = nRow2; 2734 2735 sal_Bool bChanged = ( bWasVis != bShow ); 2736 if ( bChanged && bHasObjects ) 2737 { 2738 if (pDrawLayer) 2739 { 2740 long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow)); 2741 if (bShow) 2742 pDrawLayer->HeightChanged( nTab, nStartRow, nHeight ); 2743 else 2744 pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight ); 2745 } 2746 } 2747 2748 // #i116164# Directly modify the flags only if there are drawing objects within the area. 2749 // Otherwise, all rows are modified together after the loop, so the tree isn't constantly rebuilt. 2750 if ( bHasObjects ) 2751 { 2752 SetRowHidden(nStartRow, nEndRow, !bShow); 2753 if (bShow) 2754 SetRowFiltered(nStartRow, nEndRow, false); 2755 } 2756 2757 if ( bChanged ) 2758 { 2759 ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection(); 2760 if ( pCharts ) 2761 pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab )); 2762 2763 InvalidatePageBreaks(); 2764 } 2765 2766 nStartRow = nEndRow + 1; 2767 } 2768 2769 if ( !bHasObjects ) 2770 { 2771 // #i116164# set the flags for the whole range at once 2772 SetRowHidden(nRow1, nRow2, !bShow); 2773 if (bShow) 2774 SetRowFiltered(nRow1, nRow2, false); 2775 2776 if ( pDrawLayer ) 2777 { 2778 // if there are no objects in the range, a single HeightChanged call is enough 2779 long nNewHeight = 0; 2780 if ( bShow ) 2781 nNewHeight = static_cast<long>(GetRowHeight(nRow1, nRow2)); 2782 if ( nNewHeight != nOldHeight ) 2783 pDrawLayer->HeightChanged( nTab, nRow1, nNewHeight - nOldHeight ); 2784 } 2785 } 2786 2787 DecRecalcLevel(); 2788 } 2789 2790 sal_Bool ScTable::IsDataFiltered() const 2791 { 2792 sal_Bool bAnyQuery = sal_False; 2793 ScDBData* pDBData = pDocument->GetFilterDBAtTable(nTab); 2794 if ( pDBData ) 2795 { 2796 ScQueryParam aParam; 2797 pDBData->GetQueryParam( aParam ); 2798 if ( aParam.GetEntry(0).bDoQuery ) 2799 bAnyQuery = sal_True; 2800 } 2801 return bAnyQuery; 2802 } 2803 2804 void ScTable::SetColFlags( SCCOL nCol, sal_uInt8 nNewFlags ) 2805 { 2806 if (VALIDCOL(nCol) && pColFlags) 2807 pColFlags[nCol] = nNewFlags; 2808 else 2809 { 2810 DBG_ERROR("Falsche Spaltennummer oder keine Flags"); 2811 } 2812 } 2813 2814 2815 void ScTable::SetRowFlags( SCROW nRow, sal_uInt8 nNewFlags ) 2816 { 2817 if (VALIDROW(nRow) && pRowFlags) 2818 pRowFlags->SetValue( nRow, nNewFlags); 2819 else 2820 { 2821 DBG_ERROR("Falsche Zeilennummer oder keine Flags"); 2822 } 2823 } 2824 2825 2826 void ScTable::SetRowFlags( SCROW nStartRow, SCROW nEndRow, sal_uInt8 nNewFlags ) 2827 { 2828 if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags) 2829 pRowFlags->SetValue( nStartRow, nEndRow, nNewFlags); 2830 else 2831 { 2832 DBG_ERROR("Falsche Zeilennummer(n) oder keine Flags"); 2833 } 2834 } 2835 2836 2837 sal_uInt8 ScTable::GetColFlags( SCCOL nCol ) const 2838 { 2839 if (VALIDCOL(nCol) && pColFlags) 2840 return pColFlags[nCol]; 2841 else 2842 return 0; 2843 } 2844 2845 2846 sal_uInt8 ScTable::GetRowFlags( SCROW nRow ) const 2847 { 2848 if (VALIDROW(nRow) && pRowFlags) 2849 return pRowFlags->GetValue(nRow); 2850 else 2851 return 0; 2852 } 2853 2854 2855 SCROW ScTable::GetLastFlaggedRow() const 2856 { 2857 SCROW nLastFound = 0; 2858 if (pRowFlags) 2859 { 2860 SCROW nRow = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<sal_uInt8>(CR_ALL) ); 2861 if (ValidRow(nRow)) 2862 nLastFound = nRow; 2863 } 2864 2865 if (!maRowManualBreaks.empty()) 2866 nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin()); 2867 2868 if (mpHiddenRows) 2869 { 2870 SCROW nRow = mpHiddenRows->findLastNotOf(false); 2871 if (ValidRow(nRow)) 2872 nLastFound = ::std::max(nLastFound, nRow); 2873 } 2874 2875 if (mpFilteredRows) 2876 { 2877 SCROW nRow = mpFilteredRows->findLastNotOf(false); 2878 if (ValidRow(nRow)) 2879 nLastFound = ::std::max(nLastFound, nRow); 2880 } 2881 2882 return nLastFound; 2883 } 2884 2885 2886 SCCOL ScTable::GetLastChangedCol() const 2887 { 2888 if ( !pColFlags ) 2889 return 0; 2890 2891 SCCOL nLastFound = 0; 2892 for (SCCOL nCol = 1; nCol <= MAXCOL; nCol++) 2893 if ((pColFlags[nCol] & CR_ALL) || (pColWidth[nCol] != STD_COL_WIDTH)) 2894 nLastFound = nCol; 2895 2896 return nLastFound; 2897 } 2898 2899 2900 SCROW ScTable::GetLastChangedRow() const 2901 { 2902 if ( !pRowFlags ) 2903 return 0; 2904 2905 SCROW nLastFlags = GetLastFlaggedRow(); 2906 2907 // Find the last row position where the height is NOT the standard row 2908 // height. 2909 // KOHEI: Test this to make sure it does what it's supposed to. 2910 SCROW nLastHeight = mpRowHeights->findLastNotOf(ScGlobal::nStdRowHeight); 2911 if (!ValidRow(nLastHeight)) 2912 nLastHeight = 0; 2913 2914 return std::max( nLastFlags, nLastHeight); 2915 } 2916 2917 2918 sal_Bool ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, sal_Bool bShow ) 2919 { 2920 if (pOutlineTable && pColFlags) 2921 { 2922 ScBitMaskCompressedArray< SCCOLROW, sal_uInt8> aArray( MAXCOL, pColFlags, MAXCOLCOUNT); 2923 return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, *this, true ); 2924 } 2925 else 2926 return sal_False; 2927 } 2928 2929 2930 sal_Bool ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, sal_Bool bShow ) 2931 { 2932 if (pOutlineTable && pRowFlags) 2933 return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *this, false ); 2934 else 2935 return sal_False; 2936 } 2937 2938 2939 void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ) 2940 { 2941 // Column-wise expansion 2942 2943 while (rX1 > 0 && ColHidden(rX1-1)) 2944 --rX1; 2945 2946 while (rX2 < MAXCOL && ColHidden(rX2+1)) 2947 ++rX2; 2948 2949 // Row-wise expansion 2950 2951 if (rY1 > 0) 2952 { 2953 ScFlatBoolRowSegments::RangeData aData; 2954 if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue) 2955 { 2956 SCROW nStartRow = aData.mnRow1; 2957 if (ValidRow(nStartRow)) 2958 rY1 = nStartRow; 2959 } 2960 } 2961 if (rY2 < MAXROW) 2962 { 2963 SCROW nEndRow = -1; 2964 if (RowHidden(rY2+1, nEndRow) && ValidRow(nEndRow)) 2965 rY2 = nEndRow; 2966 } 2967 } 2968 2969 2970 void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 ) 2971 { 2972 while ( rX2>rX1 && ColHidden(rX2) ) 2973 --rX2; 2974 while ( rX2>rX1 && ColHidden(rX1) ) 2975 ++rX1; 2976 2977 if (rY1 < rY2) 2978 { 2979 ScFlatBoolRowSegments::RangeData aData; 2980 if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue) 2981 { 2982 SCROW nStartRow = aData.mnRow1; 2983 if (ValidRow(nStartRow) && nStartRow >= rY1) 2984 rY2 = nStartRow; 2985 } 2986 } 2987 2988 if (rY1 < rY2) 2989 { 2990 SCROW nEndRow = -1; 2991 if (RowHidden(rY1, nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2) 2992 rY1 = nEndRow; 2993 } 2994 } 2995 2996 2997 // Auto-Outline 2998 2999 template< typename T > 3000 short DiffSign( T a, T b ) 3001 { 3002 return (a<b) ? -1 : 3003 (a>b) ? 1 : 0; 3004 } 3005 3006 3007 void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) 3008 { 3009 sal_Bool bSizeChanged = sal_False; 3010 sal_Bool bMissed = sal_False; 3011 3012 SCCOL nCol; 3013 SCROW nRow; 3014 SCROW i; 3015 sal_Bool bFound; 3016 ScOutlineArray* pArray; 3017 ScBaseCell* pCell; 3018 ScRange aRef; 3019 /* ScPatternAttr aBoldPattern( pDocument->GetPool() ); //! spezielle Format-Vorlage 3020 aBoldPattern.GetItemSet().Put( SvxWeightItem( WEIGHT_BOLD ) ); 3021 */ 3022 3023 StartOutlineTable(); 3024 3025 // Zeilen 3026 3027 SCROW nCount = nEndRow-nStartRow+1; 3028 sal_Bool* pUsed = new sal_Bool[nCount]; 3029 for (i=0; i<nCount; i++) 3030 pUsed[i] = sal_False; 3031 for (nCol=nStartCol; nCol<=nEndCol; nCol++) 3032 if (!aCol[nCol].IsEmptyData()) 3033 aCol[nCol].FindUsed( nStartRow, nEndRow, pUsed ); 3034 3035 pArray = pOutlineTable->GetRowArray(); 3036 for (nRow=nStartRow; nRow<=nEndRow; nRow++) 3037 if (pUsed[nRow-nStartRow]) 3038 { 3039 bFound = sal_False; 3040 for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++) 3041 if (!aCol[nCol].IsEmptyData()) 3042 { 3043 pCell = aCol[nCol].GetCell( nRow ); 3044 if (pCell) 3045 if ( pCell->GetCellType() == CELLTYPE_FORMULA ) 3046 if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef )) 3047 if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol && 3048 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab && 3049 DiffSign( aRef.aStart.Row(), nRow ) == 3050 DiffSign( aRef.aEnd.Row(), nRow ) ) 3051 { 3052 if (pArray->Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged )) 3053 { 3054 // ApplyPatternArea( nStartCol, nRow, nEndCol, nRow, aBoldPattern ); 3055 bFound = sal_True; 3056 } 3057 else 3058 bMissed = sal_True; 3059 } 3060 } 3061 } 3062 3063 delete[] pUsed; 3064 3065 // Spalten 3066 3067 pArray = pOutlineTable->GetColArray(); 3068 for (nCol=nStartCol; nCol<=nEndCol; nCol++) 3069 { 3070 if (!aCol[nCol].IsEmptyData()) 3071 { 3072 bFound = sal_False; 3073 ScColumnIterator aIter( &aCol[nCol], nStartRow, nEndRow ); 3074 while ( aIter.Next( nRow, pCell ) && !bFound ) 3075 { 3076 if ( pCell->GetCellType() == CELLTYPE_FORMULA ) 3077 if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef )) 3078 if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow && 3079 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab && 3080 DiffSign( aRef.aStart.Col(), nCol ) == 3081 DiffSign( aRef.aEnd.Col(), nCol ) ) 3082 { 3083 if (pArray->Insert( aRef.aStart.Col(), aRef.aEnd.Col(), bSizeChanged )) 3084 { 3085 // ApplyPatternArea( nCol, nStartRow, nCol, nEndRow, aBoldPattern ); 3086 bFound = sal_True; 3087 } 3088 else 3089 bMissed = sal_True; 3090 } 3091 } 3092 } 3093 } 3094 } 3095 3096 // CopyData - fuer Query in anderen Bereich 3097 3098 void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 3099 SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab ) 3100 { 3101 //! wenn fuer mehrere Zeilen benutzt, nach Spalten optimieren! 3102 3103 ScAddress aSrc( nStartCol, nStartRow, nTab ); 3104 ScAddress aDest( nDestCol, nDestRow, nDestTab ); 3105 ScRange aRange( aSrc, aDest ); 3106 sal_Bool bThisTab = ( nDestTab == nTab ); 3107 SCROW nDestY = nDestRow; 3108 for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++) 3109 { 3110 aSrc.SetRow( nRow ); 3111 aDest.SetRow( nDestY ); 3112 SCCOL nDestX = nDestCol; 3113 for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) 3114 { 3115 aSrc.SetCol( nCol ); 3116 aDest.SetCol( nDestX ); 3117 ScBaseCell* pCell = GetCell( nCol, nRow ); 3118 if (pCell) 3119 { 3120 pCell = pCell->CloneWithoutNote( *pDocument ); 3121 if (pCell->GetCellType() == CELLTYPE_FORMULA) 3122 { 3123 ((ScFormulaCell*)pCell)->UpdateReference( URM_COPY, aRange, 3124 ((SCsCOL) nDestCol) - ((SCsCOL) nStartCol), 3125 ((SCsROW) nDestRow) - ((SCsROW) nStartRow), 3126 ((SCsTAB) nDestTab) - ((SCsTAB) nTab) ); 3127 ((ScFormulaCell*)pCell)->aPos = aDest; 3128 } 3129 } 3130 if (bThisTab) 3131 { 3132 PutCell( nDestX, nDestY, pCell ); 3133 SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ), sal_True ); 3134 } 3135 else 3136 { 3137 pDocument->PutCell( aDest, pCell ); 3138 pDocument->SetPattern( aDest, *GetPattern( nCol, nRow ), sal_True ); 3139 } 3140 3141 ++nDestX; 3142 } 3143 ++nDestY; 3144 } 3145 } 3146 3147 3148 sal_Bool ScTable::RefVisible(ScFormulaCell* pCell) 3149 { 3150 ScRange aRef; 3151 3152 if (pCell->HasOneReference(aRef)) 3153 { 3154 if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab()) 3155 { 3156 SCROW nEndRow; 3157 if (!RowFiltered(aRef.aStart.Row(), NULL, &nEndRow)) 3158 // row not filtered. 3159 nEndRow = ::std::numeric_limits<SCROW>::max(); 3160 3161 if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row()) 3162 return sal_True; // at least partly visible 3163 return sal_False; // completely invisible 3164 } 3165 } 3166 3167 return sal_True; // irgendwie anders 3168 } 3169 3170 3171 void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, String& rStr) 3172 { 3173 GetInputString(nCol, nRow, rStr); 3174 rStr.EraseTrailingChars(); 3175 rStr.EraseLeadingChars(); 3176 ScGlobal::pCharClass->toUpper(rStr); 3177 } 3178 3179 3180 // Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage 3181 3182 void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos) 3183 { 3184 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); 3185 if( pDrawLayer ) 3186 { 3187 double fValX = GetColOffset( MAXCOL + 1 ) * HMM_PER_TWIPS; 3188 double fValY = GetRowOffset( MAXROW + 1 ) * HMM_PER_TWIPS; 3189 const long nMax = ::std::numeric_limits<long>::max(); 3190 // #i113884# Avoid int32 overflow with possible negative results than can cause bad effects. 3191 // If the draw page size is smaller than all rows, only the bottom of the sheet is affected. 3192 long x = ( fValX > (double)nMax ) ? nMax : (long) fValX; 3193 long y = ( fValY > (double)nMax ) ? nMax : (long) fValY; 3194 3195 if ( IsLayoutRTL() ) // IsNegativePage 3196 x = -x; 3197 3198 pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( x, y ), bUpdateNoteCaptionPos ); 3199 } 3200 3201 // #i102616# actions that modify the draw page size count as sheet modification 3202 // (exception: InitDrawLayer) 3203 if (bResetStreamValid && IsStreamValid()) 3204 SetStreamValid(sal_False); 3205 } 3206 3207 3208 sal_uLong ScTable::GetRowOffset( SCROW nRow ) const 3209 { 3210 sal_uLong n = 0; 3211 if ( mpHiddenRows && mpRowHeights ) 3212 { 3213 if (nRow == 0) 3214 return 0; 3215 else if (nRow == 1) 3216 return GetRowHeight(0); 3217 3218 n = GetTotalRowHeight(0, nRow-1); 3219 #ifdef DBG_UTIL 3220 if (n == ::std::numeric_limits<unsigned long>::max()) 3221 DBG_ERRORFILE("ScTable::GetRowOffset: row heights overflow"); 3222 #endif 3223 } 3224 else 3225 { 3226 DBG_ERROR("GetRowOffset: Daten fehlen"); 3227 } 3228 return n; 3229 } 3230 3231 SCROW ScTable::GetRowForHeight(sal_uLong nHeight) const 3232 { 3233 sal_uInt32 nSum = 0; 3234 3235 ScFlatBoolRowSegments::RangeData aData; 3236 for (SCROW nRow = 0; nRow <= MAXROW; ++nRow) 3237 { 3238 if (!mpHiddenRows->getRangeData(nRow, aData)) 3239 break; 3240 3241 if (aData.mbValue) 3242 { 3243 nRow = aData.mnRow2; 3244 continue; 3245 } 3246 3247 sal_uInt32 nNew = mpRowHeights->getValue(nRow); 3248 nSum += nNew; 3249 if (nSum > nHeight) 3250 { 3251 return nRow < MAXROW ? nRow + 1 : MAXROW; 3252 } 3253 } 3254 return -1; 3255 } 3256 3257 3258 sal_uLong ScTable::GetColOffset( SCCOL nCol ) const 3259 { 3260 sal_uLong n = 0; 3261 if ( pColWidth ) 3262 { 3263 SCCOL i; 3264 for( i = 0; i < nCol; i++ ) 3265 if (!ColHidden(i)) 3266 n += pColWidth[i]; 3267 } 3268 else 3269 { 3270 DBG_ERROR("GetColumnOffset: Daten fehlen"); 3271 } 3272 return n; 3273 } 3274 3275