1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 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 #define _ZFORLIST_DECLARE_TABLE 34 #include "scitems.hxx" 35 #include <editeng/eeitem.hxx> 36 37 #include <editeng/boxitem.hxx> 38 #include <editeng/frmdiritem.hxx> 39 #include <svx/pageitem.hxx> 40 #include <editeng/editeng.hxx> 41 #include <svx/svditer.hxx> 42 #include <svx/svdpage.hxx> 43 #include <svx/svdocapt.hxx> 44 #include <sfx2/app.hxx> 45 #include <sfx2/objsh.hxx> 46 #include <svl/poolcach.hxx> 47 #include <unotools/saveopt.hxx> 48 #include <svl/zforlist.hxx> 49 #include <unotools/charclass.hxx> 50 #include <unotools/transliterationwrapper.hxx> 51 #include <tools/tenccvt.hxx> 52 53 #include <com/sun/star/text/WritingMode2.hpp> 54 #include <com/sun/star/script/vba/XVBACompatibility.hpp> 55 #include <com/sun/star/sheet/TablePageBreakData.hpp> 56 57 #include "document.hxx" 58 #include "table.hxx" 59 #include "attrib.hxx" 60 #include "attarray.hxx" 61 #include "markarr.hxx" 62 #include "patattr.hxx" 63 #include "rangenam.hxx" 64 #include "poolhelp.hxx" 65 #include "docpool.hxx" 66 #include "stlpool.hxx" 67 #include "stlsheet.hxx" 68 #include "globstr.hrc" 69 #include "rechead.hxx" 70 #include "dbcolect.hxx" 71 #include "pivot.hxx" 72 #include "chartlis.hxx" 73 #include "rangelst.hxx" 74 #include "markdata.hxx" 75 #include "drwlayer.hxx" 76 #include "conditio.hxx" 77 #include "validat.hxx" 78 #include "prnsave.hxx" 79 #include "chgtrack.hxx" 80 #include "sc.hrc" 81 #include "scresid.hxx" 82 #include "hints.hxx" 83 #include "detdata.hxx" 84 #include "cell.hxx" 85 #include "dpobject.hxx" 86 #include "detfunc.hxx" // for UpdateAllComments 87 #include "scmod.hxx" 88 #include "dociter.hxx" 89 #include "progress.hxx" 90 #include "autonamecache.hxx" 91 #include "bcaslot.hxx" 92 #include "postit.hxx" 93 #include "externalrefmgr.hxx" 94 #include "tabprotection.hxx" 95 #include "clipparam.hxx" 96 97 #include <map> 98 #include <limits> 99 100 namespace WritingMode2 = ::com::sun::star::text::WritingMode2; 101 using ::com::sun::star::uno::Sequence; 102 using ::com::sun::star::sheet::TablePageBreakData; 103 using ::std::set; 104 105 struct ScDefaultAttr 106 { 107 const ScPatternAttr* pAttr; 108 SCROW nFirst; 109 SCSIZE nCount; 110 ScDefaultAttr(const ScPatternAttr* pPatAttr) : pAttr(pPatAttr), nFirst(0), nCount(0) {} 111 }; 112 113 struct ScLessDefaultAttr 114 { 115 sal_Bool operator() (const ScDefaultAttr& rValue1, const ScDefaultAttr& rValue2) const 116 { 117 return rValue1.pAttr < rValue2.pAttr; 118 } 119 }; 120 121 typedef std::set<ScDefaultAttr, ScLessDefaultAttr> ScDefaultAttrSet; 122 123 void ScDocument::MakeTable( SCTAB nTab,bool _bNeedsNameCheck ) 124 { 125 if ( ValidTab(nTab) && !pTab[nTab] ) 126 { 127 String aString = ScGlobal::GetRscString(STR_TABLE_DEF); //"Tabelle" 128 aString += String::CreateFromInt32(nTab+1); 129 if ( _bNeedsNameCheck ) 130 CreateValidTabName( aString ); // keine doppelten 131 132 pTab[nTab] = new ScTable(this, nTab, aString); 133 pTab[nTab]->SetLoadingMedium(bLoadingMedium); 134 ++nMaxTableNumber; 135 } 136 } 137 138 139 sal_Bool ScDocument::HasTable( SCTAB nTab ) const 140 { 141 if (VALIDTAB(nTab)) 142 if (pTab[nTab]) 143 return sal_True; 144 145 return sal_False; 146 } 147 148 149 sal_Bool ScDocument::GetName( SCTAB nTab, String& rName ) const 150 { 151 if (VALIDTAB(nTab)) 152 if (pTab[nTab]) 153 { 154 pTab[nTab]->GetName( rName ); 155 return sal_True; 156 } 157 rName.Erase(); 158 return sal_False; 159 } 160 161 sal_Bool ScDocument::SetCodeName( SCTAB nTab, const String& rName ) 162 { 163 if (VALIDTAB(nTab)) 164 { 165 if (pTab[nTab]) 166 { 167 pTab[nTab]->SetCodeName( rName ); 168 return sal_True; 169 } 170 } 171 OSL_TRACE( "**** can't set code name %s", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() ); 172 return sal_False; 173 } 174 175 sal_Bool ScDocument::GetCodeName( SCTAB nTab, String& rName ) const 176 { 177 if (VALIDTAB(nTab)) 178 if (pTab[nTab]) 179 { 180 pTab[nTab]->GetCodeName( rName ); 181 return sal_True; 182 } 183 rName.Erase(); 184 return sal_False; 185 } 186 187 188 sal_Bool ScDocument::GetTable( const String& rName, SCTAB& rTab ) const 189 { 190 String aUpperName = rName; 191 ScGlobal::pCharClass->toUpper(aUpperName); 192 193 for (SCTAB i=0; i<=MAXTAB; i++) 194 if (pTab[i]) 195 { 196 if ( pTab[i]->GetUpperName() == aUpperName ) 197 { 198 rTab = i; 199 return sal_True; 200 } 201 } 202 rTab = 0; 203 return sal_False; 204 } 205 206 207 sal_Bool ScDocument::ValidTabName( const String& rName ) const 208 { 209 xub_StrLen nLen = rName.Len(); 210 if (!nLen) 211 return false; 212 213 #if 1 214 // Restrict sheet names to what Excel accepts. 215 /* TODO: We may want to remove this restriction for full ODFF compliance. 216 * Merely loading and calculating ODF documents using these characters in 217 * sheet names is not affected by this, but all sheet name editing and 218 * copying functionality is, maybe falling back to "Sheet4" or similar. */ 219 for (xub_StrLen i = 0; i < nLen; ++i) 220 { 221 const sal_Unicode c = rName.GetChar(i); 222 switch (c) 223 { 224 case ':': 225 case '\\': 226 case '/': 227 case '?': 228 case '*': 229 case '[': 230 case ']': 231 // these characters are not allowed to match XL's convention. 232 return false; 233 case '\'': 234 if (i == 0 || i == nLen - 1) 235 // single quote is not allowed at the first or last 236 // character position. 237 return false; 238 break; 239 } 240 } 241 #endif 242 243 return true; 244 } 245 246 247 sal_Bool ScDocument::ValidNewTabName( const String& rName ) const 248 { 249 sal_Bool bValid = ValidTabName(rName); 250 for (SCTAB i=0; (i<=MAXTAB) && bValid; i++) 251 if (pTab[i]) 252 { 253 String aOldName; 254 pTab[i]->GetName(aOldName); 255 bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName ); 256 } 257 return bValid; 258 } 259 260 261 void ScDocument::CreateValidTabName(String& rName) const 262 { 263 if ( !ValidTabName(rName) ) 264 { 265 // neu erzeugen 266 267 const String aStrTable( ScResId(SCSTR_TABLE) ); 268 sal_Bool bOk = sal_False; 269 270 // vorneweg testen, ob der Prefix als gueltig erkannt wird 271 // wenn nicht, nur doppelte vermeiden 272 sal_Bool bPrefix = ValidTabName( aStrTable ); 273 DBG_ASSERT(bPrefix, "ungueltiger Tabellenname"); 274 SCTAB nDummy; 275 276 SCTAB nLoops = 0; // "zur Sicherheit" 277 for ( SCTAB i = nMaxTableNumber+1; !bOk && nLoops <= MAXTAB; i++ ) 278 { 279 rName = aStrTable; 280 rName += String::CreateFromInt32(i); 281 if (bPrefix) 282 bOk = ValidNewTabName( rName ); 283 else 284 bOk = !GetTable( rName, nDummy ); 285 ++nLoops; 286 } 287 288 DBG_ASSERT(bOk, "kein gueltiger Tabellenname gefunden"); 289 if ( !bOk ) 290 rName = aStrTable; 291 } 292 else 293 { 294 // uebergebenen Namen ueberpruefen 295 296 if ( !ValidNewTabName(rName) ) 297 { 298 SCTAB i = 1; 299 String aName; 300 do 301 { 302 i++; 303 aName = rName; 304 aName += '_'; 305 aName += String::CreateFromInt32(static_cast<sal_Int32>(i)); 306 } 307 while (!ValidNewTabName(aName) && (i < MAXTAB+1)); 308 rName = aName; 309 } 310 } 311 } 312 313 314 sal_Bool ScDocument::InsertTab( SCTAB nPos, const String& rName, 315 sal_Bool bExternalDocument ) 316 { 317 SCTAB nTabCount = GetTableCount(); 318 sal_Bool bValid = ValidTab(nTabCount); 319 if ( !bExternalDocument ) // sonst rName == "'Doc'!Tab", vorher pruefen 320 bValid = (bValid && ValidNewTabName(rName)); 321 if (bValid) 322 { 323 if (nPos == SC_TAB_APPEND || nPos == nTabCount) 324 { 325 pTab[nTabCount] = new ScTable(this, nTabCount, rName); 326 pTab[nTabCount]->SetCodeName( rName ); 327 ++nMaxTableNumber; 328 if ( bExternalDocument ) 329 pTab[nTabCount]->SetVisible( sal_False ); 330 } 331 else 332 { 333 if (VALIDTAB(nPos) && (nPos < nTabCount)) 334 { 335 ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB ); 336 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 ); 337 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 ); 338 pRangeName->UpdateTabRef( nPos, 1 ); 339 pDBCollection->UpdateReference( 340 URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 ); 341 if (pDPCollection) 342 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 ); 343 if (pDetOpList) 344 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 ); 345 UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 ); 346 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 ); 347 if ( pUnoBroadcaster ) 348 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) ); 349 350 SCTAB i; 351 for (i = 0; i <= MAXTAB; i++) 352 if (pTab[i]) 353 pTab[i]->UpdateInsertTab(nPos); 354 355 for (i = nTabCount; i > nPos; i--) 356 { 357 pTab[i] = pTab[i - 1]; 358 } 359 360 pTab[nPos] = new ScTable(this, nPos, rName); 361 pTab[nPos]->SetCodeName( rName ); 362 ++nMaxTableNumber; 363 364 // UpdateBroadcastAreas must be called between UpdateInsertTab, 365 // which ends listening, and StartAllListeners, to not modify 366 // areas that are to be inserted by starting listeners. 367 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,1); 368 for (i = 0; i <= MAXTAB; i++) 369 if (pTab[i]) 370 pTab[i]->UpdateCompile(); 371 for (i = 0; i <= MAXTAB; i++) 372 if (pTab[i]) 373 pTab[i]->StartAllListeners(); 374 375 // update conditional formats after table is inserted 376 if ( pCondFormList ) 377 pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,1 ); 378 if ( pValidationList ) 379 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,1 ); 380 // #81844# sheet names of references are not valid until sheet is inserted 381 if ( pChartListenerCollection ) 382 pChartListenerCollection->UpdateScheduledSeriesRanges(); 383 384 SetDirty(); 385 bValid = sal_True; 386 } 387 else 388 bValid = sal_False; 389 } 390 } 391 return bValid; 392 } 393 394 395 sal_Bool ScDocument::DeleteTab( SCTAB nTab, ScDocument* pRefUndoDoc ) 396 { 397 sal_Bool bValid = sal_False; 398 if (VALIDTAB(nTab)) 399 { 400 if (pTab[nTab]) 401 { 402 SCTAB nTabCount = GetTableCount(); 403 if (nTabCount > 1) 404 { 405 sal_Bool bOldAutoCalc = GetAutoCalc(); 406 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 407 ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab ); 408 DelBroadcastAreasInRange( aRange ); 409 410 // #i8180# remove database ranges etc. that are on the deleted tab 411 // (restored in undo with ScRefUndoData) 412 413 xColNameRanges->DeleteOnTab( nTab ); 414 xRowNameRanges->DeleteOnTab( nTab ); 415 pDBCollection->DeleteOnTab( nTab ); 416 if (pDPCollection) 417 pDPCollection->DeleteOnTab( nTab ); 418 if (pDetOpList) 419 pDetOpList->DeleteOnTab( nTab ); 420 DeleteAreaLinksOnTab( nTab ); 421 422 // normal reference update 423 424 aRange.aEnd.SetTab( MAXTAB ); 425 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 ); 426 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 ); 427 pRangeName->UpdateTabRef( nTab, 2 ); 428 pDBCollection->UpdateReference( 429 URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 ); 430 if (pDPCollection) 431 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1 ); 432 if (pDetOpList) 433 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1 ); 434 UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 ); 435 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1 ); 436 if ( pCondFormList ) 437 pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,-1 ); 438 if ( pValidationList ) 439 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,-1 ); 440 if ( pUnoBroadcaster ) 441 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1 ) ); 442 443 SCTAB i; 444 for (i=0; i<=MAXTAB; i++) 445 if (pTab[i]) 446 pTab[i]->UpdateDeleteTab(nTab,sal_False, 447 pRefUndoDoc ? pRefUndoDoc->pTab[i] : 0); 448 delete pTab[nTab]; 449 for (i=nTab + 1; i < nTabCount; i++) 450 pTab[i - 1] = pTab[i]; 451 pTab[nTabCount - 1] = NULL; 452 --nMaxTableNumber; 453 // UpdateBroadcastAreas must be called between UpdateDeleteTab, 454 // which ends listening, and StartAllListeners, to not modify 455 // areas that are to be inserted by starting listeners. 456 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1); 457 for (i = 0; i <= MAXTAB; i++) 458 if (pTab[i]) 459 pTab[i]->UpdateCompile(); 460 // Excel-Filter loescht einige Tables waehrend des Ladens, 461 // Listener werden erst nach dem Laden aufgesetzt 462 if ( !bInsertingFromOtherDoc ) 463 { 464 for (i = 0; i <= MAXTAB; i++) 465 if (pTab[i]) 466 pTab[i]->StartAllListeners(); 467 SetDirty(); 468 } 469 // #81844# sheet names of references are not valid until sheet is deleted 470 pChartListenerCollection->UpdateScheduledSeriesRanges(); 471 472 SetAutoCalc( bOldAutoCalc ); 473 bValid = sal_True; 474 } 475 } 476 } 477 return bValid; 478 } 479 480 481 sal_Bool ScDocument::RenameTab( SCTAB nTab, const String& rName, sal_Bool /* bUpdateRef */, 482 sal_Bool bExternalDocument ) 483 { 484 sal_Bool bValid = sal_False; 485 SCTAB i; 486 if VALIDTAB(nTab) 487 if (pTab[nTab]) 488 { 489 if ( bExternalDocument ) 490 bValid = sal_True; // zusammengesetzter Name 491 else 492 bValid = ValidTabName(rName); 493 for (i=0; (i<=MAXTAB) && bValid; i++) 494 if (pTab[i] && (i != nTab)) 495 { 496 String aOldName; 497 pTab[i]->GetName(aOldName); 498 bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName ); 499 } 500 if (bValid) 501 { 502 // #i75258# update charts before renaming, so they can get their live data objects. 503 // Once the charts are live, the sheet can be renamed without problems. 504 if ( pChartListenerCollection ) 505 pChartListenerCollection->UpdateChartsContainingTab( nTab ); 506 pTab[nTab]->SetName(rName); 507 508 // If formulas refer to the renamed sheet, the TokenArray remains valid, 509 // but the XML stream must be re-generated. 510 for (i=0; i<=MAXTAB; ++i) 511 if (pTab[i] && pTab[i]->IsStreamValid()) 512 pTab[i]->SetStreamValid( sal_False ); 513 } 514 } 515 return bValid; 516 } 517 518 519 void ScDocument::SetVisible( SCTAB nTab, sal_Bool bVisible ) 520 { 521 if (VALIDTAB(nTab)) 522 if (pTab[nTab]) 523 pTab[nTab]->SetVisible(bVisible); 524 } 525 526 527 sal_Bool ScDocument::IsVisible( SCTAB nTab ) const 528 { 529 if (VALIDTAB(nTab)) 530 if (pTab[nTab]) 531 return pTab[nTab]->IsVisible(); 532 533 return sal_False; 534 } 535 536 537 sal_Bool ScDocument::IsStreamValid( SCTAB nTab ) const 538 { 539 if ( ValidTab(nTab) && pTab[nTab] ) 540 return pTab[nTab]->IsStreamValid(); 541 542 return sal_False; 543 } 544 545 546 void ScDocument::SetStreamValid( SCTAB nTab, sal_Bool bSet, sal_Bool bIgnoreLock ) 547 { 548 if ( ValidTab(nTab) && pTab[nTab] ) 549 pTab[nTab]->SetStreamValid( bSet, bIgnoreLock ); 550 } 551 552 553 void ScDocument::LockStreamValid( bool bLock ) 554 { 555 mbStreamValidLocked = bLock; 556 } 557 558 559 sal_Bool ScDocument::IsPendingRowHeights( SCTAB nTab ) const 560 { 561 if ( ValidTab(nTab) && pTab[nTab] ) 562 return pTab[nTab]->IsPendingRowHeights(); 563 564 return sal_False; 565 } 566 567 568 void ScDocument::SetPendingRowHeights( SCTAB nTab, sal_Bool bSet ) 569 { 570 if ( ValidTab(nTab) && pTab[nTab] ) 571 pTab[nTab]->SetPendingRowHeights( bSet ); 572 } 573 574 575 void ScDocument::SetLayoutRTL( SCTAB nTab, sal_Bool bRTL ) 576 { 577 if ( ValidTab(nTab) && pTab[nTab] ) 578 { 579 if ( bImportingXML ) 580 { 581 // #i57869# only set the LoadingRTL flag, the real setting (including mirroring) 582 // is applied in SetImportingXML(sal_False). This is so the shapes can be loaded in 583 // normal LTR mode. 584 585 pTab[nTab]->SetLoadingRTL( bRTL ); 586 return; 587 } 588 589 pTab[nTab]->SetLayoutRTL( bRTL ); // only sets the flag 590 pTab[nTab]->SetDrawPageSize(); 591 592 // mirror existing objects: 593 594 if (pDrawLayer) 595 { 596 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); 597 DBG_ASSERT(pPage,"Page ?"); 598 if (pPage) 599 { 600 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); 601 SdrObject* pObject = aIter.Next(); 602 while (pObject) 603 { 604 // objects with ScDrawObjData are re-positioned in SetPageSize, 605 // don't mirror again 606 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject ); 607 if ( !pData ) 608 pDrawLayer->MirrorRTL( pObject ); 609 610 pObject->SetContextWritingMode( bRTL ? WritingMode2::RL_TB : WritingMode2::LR_TB ); 611 612 pObject = aIter.Next(); 613 } 614 } 615 } 616 } 617 } 618 619 620 sal_Bool ScDocument::IsLayoutRTL( SCTAB nTab ) const 621 { 622 if ( ValidTab(nTab) && pTab[nTab] ) 623 return pTab[nTab]->IsLayoutRTL(); 624 625 return sal_False; 626 } 627 628 629 sal_Bool ScDocument::IsNegativePage( SCTAB nTab ) const 630 { 631 // Negative page area is always used for RTL layout. 632 // The separate method is used to find all RTL handling of drawing objects. 633 return IsLayoutRTL( nTab ); 634 } 635 636 637 /* ---------------------------------------------------------------------------- 638 benutzten Bereich suchen: 639 640 GetCellArea - nur Daten 641 GetTableArea - Daten / Attribute 642 GetPrintArea - beruecksichtigt auch Zeichenobjekte, 643 streicht Attribute bis ganz rechts / unten 644 ---------------------------------------------------------------------------- */ 645 646 647 sal_Bool ScDocument::GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const 648 { 649 if (VALIDTAB(nTab)) 650 if (pTab[nTab]) 651 return pTab[nTab]->GetCellArea( rEndCol, rEndRow ); 652 653 rEndCol = 0; 654 rEndRow = 0; 655 return sal_False; 656 } 657 658 659 sal_Bool ScDocument::GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const 660 { 661 if (VALIDTAB(nTab)) 662 if (pTab[nTab]) 663 return pTab[nTab]->GetTableArea( rEndCol, rEndRow ); 664 665 rEndCol = 0; 666 rEndRow = 0; 667 return sal_False; 668 } 669 670 bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow) const 671 { 672 if (!ValidTab(nTab) || !pTab[nTab]) 673 return false; 674 675 SCCOL nCol1, nCol2; 676 SCROW nRow1, nRow2; 677 pTab[nTab]->GetFirstDataPos(nCol1, nRow1); 678 pTab[nTab]->GetLastDataPos(nCol2, nRow2); 679 680 if (nCol1 > nCol2 || nRow1 > nRow2) 681 // invalid range. 682 return false; 683 684 // Make sure the area only shrinks, and doesn't grow. 685 if (rStartCol < nCol1) 686 rStartCol = nCol1; 687 if (nCol2 < rEndCol) 688 rEndCol = nCol2; 689 if (rStartRow < nRow1) 690 rStartRow = nRow1; 691 if (nRow2 < rEndRow) 692 rEndRow = nRow2; 693 694 if (rStartCol > rEndCol || rStartRow > rEndRow) 695 // invalid range. 696 return false; 697 698 return true; // success! 699 } 700 701 bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol, 702 SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const 703 { 704 if (!ValidTab(nTab) || !pTab[nTab]) 705 { 706 o_bShrunk = false; 707 return false; 708 } 709 return pTab[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly); 710 } 711 712 // zusammenhaengender Bereich 713 714 void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, 715 SCCOL& rEndCol, SCROW& rEndRow, sal_Bool bIncludeOld, bool bOnlyDown ) const 716 { 717 if (ValidTab(nTab) && pTab[nTab]) 718 pTab[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown ); 719 } 720 721 722 void ScDocument::LimitChartArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, 723 SCCOL& rEndCol, SCROW& rEndRow ) 724 { 725 if (VALIDTAB(nTab)) 726 if (pTab[nTab]) 727 pTab[nTab]->LimitChartArea( rStartCol, rStartRow, rEndCol, rEndRow ); 728 } 729 730 731 void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList ) 732 { 733 ScRangeListRef aNew = new ScRangeList; 734 if (rRangeList.Is()) 735 { 736 sal_uLong nCount = rRangeList->Count(); 737 for (sal_uLong i=0; i<nCount; i++) 738 { 739 ScRange aRange(*rRangeList->GetObject( i )); 740 if ( ( aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL ) || 741 ( aRange.aStart.Row() == 0 && aRange.aEnd.Row() == MAXROW ) ) 742 { 743 SCCOL nStartCol = aRange.aStart.Col(); 744 SCROW nStartRow = aRange.aStart.Row(); 745 SCCOL nEndCol = aRange.aEnd.Col(); 746 SCROW nEndRow = aRange.aEnd.Row(); 747 SCTAB nTab = aRange.aStart.Tab(); 748 if (pTab[nTab]) 749 pTab[nTab]->LimitChartArea(nStartCol, nStartRow, nEndCol, nEndRow); 750 aRange.aStart.SetCol( nStartCol ); 751 aRange.aStart.SetRow( nStartRow ); 752 aRange.aEnd.SetCol( nEndCol ); 753 aRange.aEnd.SetRow( nEndRow ); 754 } 755 aNew->Append(aRange); 756 } 757 } 758 else 759 { 760 DBG_ERROR("LimitChartIfAll: Ref==0"); 761 } 762 rRangeList = aNew; 763 } 764 765 766 void lcl_GetFirstTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark ) 767 { 768 // without ScMarkData, leave start/end unchanged 769 if ( pTabMark ) 770 { 771 for (SCTAB nTab=0; nTab<=MAXTAB; ++nTab) 772 if (pTabMark->GetTableSelect(nTab)) 773 { 774 // find first range of consecutive selected sheets 775 rTabRangeStart = nTab; 776 while ( nTab+1 <= MAXTAB && pTabMark->GetTableSelect(nTab+1) ) 777 ++nTab; 778 rTabRangeEnd = nTab; 779 return; 780 } 781 } 782 } 783 784 bool lcl_GetNextTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark ) 785 { 786 if ( pTabMark ) 787 { 788 // find next range of consecutive selected sheets after rTabRangeEnd 789 for (SCTAB nTab=rTabRangeEnd+1; nTab<=MAXTAB; ++nTab) 790 if (pTabMark->GetTableSelect(nTab)) 791 { 792 rTabRangeStart = nTab; 793 while ( nTab+1 <= MAXTAB && pTabMark->GetTableSelect(nTab+1) ) 794 ++nTab; 795 rTabRangeEnd = nTab; 796 return true; 797 } 798 } 799 return false; 800 } 801 802 803 sal_Bool ScDocument::CanInsertRow( const ScRange& rRange ) const 804 { 805 SCCOL nStartCol = rRange.aStart.Col(); 806 SCROW nStartRow = rRange.aStart.Row(); 807 SCTAB nStartTab = rRange.aStart.Tab(); 808 SCCOL nEndCol = rRange.aEnd.Col(); 809 SCROW nEndRow = rRange.aEnd.Row(); 810 SCTAB nEndTab = rRange.aEnd.Tab(); 811 PutInOrder( nStartCol, nEndCol ); 812 PutInOrder( nStartRow, nEndRow ); 813 PutInOrder( nStartTab, nEndTab ); 814 SCSIZE nSize = static_cast<SCSIZE>(nEndRow - nStartRow + 1); 815 816 sal_Bool bTest = sal_True; 817 for (SCTAB i=nStartTab; i<=nEndTab && bTest; i++) 818 if (pTab[i]) 819 bTest &= pTab[i]->TestInsertRow( nStartCol, nEndCol, nSize ); 820 821 return bTest; 822 } 823 824 825 sal_Bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab, 826 SCCOL nEndCol, SCTAB nEndTab, 827 SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc, 828 const ScMarkData* pTabMark ) 829 { 830 SCTAB i; 831 832 PutInOrder( nStartCol, nEndCol ); 833 PutInOrder( nStartTab, nEndTab ); 834 if ( pTabMark ) 835 { 836 nStartTab = 0; 837 nEndTab = MAXTAB; 838 } 839 840 sal_Bool bTest = sal_True; 841 sal_Bool bRet = sal_False; 842 sal_Bool bOldAutoCalc = GetAutoCalc(); 843 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 844 for ( i = nStartTab; i <= nEndTab && bTest; i++) 845 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) 846 bTest &= pTab[i]->TestInsertRow( nStartCol, nEndCol, nSize ); 847 if (bTest) 848 { 849 // UpdateBroadcastAreas muss vor UpdateReference gerufen werden, damit nicht 850 // Eintraege verschoben werden, die erst bei UpdateReference neu erzeugt werden 851 852 // handle chunks of consecutive selected sheets together 853 SCTAB nTabRangeStart = nStartTab; 854 SCTAB nTabRangeEnd = nEndTab; 855 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 856 do 857 { 858 UpdateBroadcastAreas( URM_INSDEL, ScRange( 859 ScAddress( nStartCol, nStartRow, nTabRangeStart ), 860 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, static_cast<SCsROW>(nSize), 0 ); 861 } 862 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 863 864 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 865 do 866 { 867 UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart, 868 nEndCol, MAXROW, nTabRangeEnd, 869 0, static_cast<SCsROW>(nSize), 0, pRefUndoDoc, sal_False ); // without drawing objects 870 } 871 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 872 873 for (i=nStartTab; i<=nEndTab; i++) 874 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) 875 pTab[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize ); 876 877 // #82991# UpdateRef for drawing layer must be after inserting, 878 // when the new row heights are known. 879 for (i=nStartTab; i<=nEndTab; i++) 880 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) 881 pTab[i]->UpdateDrawRef( URM_INSDEL, 882 nStartCol, nStartRow, nStartTab, nEndCol, MAXROW, nEndTab, 883 0, static_cast<SCsROW>(nSize), 0 ); 884 885 if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() ) 886 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist 887 // ein neues Listening faellig, bisherige Listener wurden in 888 // FormulaCell UpdateReference abgehaengt 889 StartAllListeners(); 890 } 891 else 892 { // Listeners have been removed in UpdateReference 893 for (i=0; i<=MAXTAB; i++) 894 if (pTab[i]) 895 pTab[i]->StartNeededListeners(); 896 // #69592# at least all cells using range names pointing relative 897 // to the moved range must recalculate 898 for (i=0; i<=MAXTAB; i++) 899 if (pTab[i]) 900 pTab[i]->SetRelNameDirty(); 901 } 902 bRet = sal_True; 903 } 904 SetAutoCalc( bOldAutoCalc ); 905 if ( bRet ) 906 pChartListenerCollection->UpdateDirtyCharts(); 907 return bRet; 908 } 909 910 911 sal_Bool ScDocument::InsertRow( const ScRange& rRange, ScDocument* pRefUndoDoc ) 912 { 913 return InsertRow( rRange.aStart.Col(), rRange.aStart.Tab(), 914 rRange.aEnd.Col(), rRange.aEnd.Tab(), 915 rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1), 916 pRefUndoDoc ); 917 } 918 919 920 void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab, 921 SCCOL nEndCol, SCTAB nEndTab, 922 SCROW nStartRow, SCSIZE nSize, 923 ScDocument* pRefUndoDoc, sal_Bool* pUndoOutline, 924 const ScMarkData* pTabMark ) 925 { 926 SCTAB i; 927 928 PutInOrder( nStartCol, nEndCol ); 929 PutInOrder( nStartTab, nEndTab ); 930 if ( pTabMark ) 931 { 932 nStartTab = 0; 933 nEndTab = MAXTAB; 934 } 935 936 sal_Bool bOldAutoCalc = GetAutoCalc(); 937 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 938 939 // handle chunks of consecutive selected sheets together 940 SCTAB nTabRangeStart = nStartTab; 941 SCTAB nTabRangeEnd = nEndTab; 942 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 943 do 944 { 945 if ( ValidRow(nStartRow+nSize) ) 946 { 947 DelBroadcastAreasInRange( ScRange( 948 ScAddress( nStartCol, nStartRow, nTabRangeStart ), 949 ScAddress( nEndCol, nStartRow+nSize-1, nTabRangeEnd ) ) ); 950 UpdateBroadcastAreas( URM_INSDEL, ScRange( 951 ScAddress( nStartCol, nStartRow+nSize, nTabRangeStart ), 952 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, -(static_cast<SCsROW>(nSize)), 0 ); 953 } 954 else 955 DelBroadcastAreasInRange( ScRange( 956 ScAddress( nStartCol, nStartRow, nTabRangeStart ), 957 ScAddress( nEndCol, MAXROW, nTabRangeEnd ) ) ); 958 } 959 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 960 961 if ( ValidRow(nStartRow+nSize) ) 962 { 963 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 964 do 965 { 966 UpdateReference( URM_INSDEL, nStartCol, nStartRow+nSize, nTabRangeStart, 967 nEndCol, MAXROW, nTabRangeEnd, 968 0, -(static_cast<SCsROW>(nSize)), 0, pRefUndoDoc, sal_True, false ); 969 } 970 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 971 } 972 973 if (pUndoOutline) 974 *pUndoOutline = sal_False; 975 976 for ( i = nStartTab; i <= nEndTab; i++) 977 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) 978 pTab[i]->DeleteRow( nStartCol, nEndCol, nStartRow, nSize, pUndoOutline ); 979 980 if ( ValidRow(nStartRow+nSize) ) 981 { // Listeners have been removed in UpdateReference 982 for (i=0; i<=MAXTAB; i++) 983 if (pTab[i]) 984 pTab[i]->StartNeededListeners(); 985 // #69592# at least all cells using range names pointing relative to 986 // the moved range must recalculate 987 for (i=0; i<=MAXTAB; i++) 988 if (pTab[i]) 989 pTab[i]->SetRelNameDirty(); 990 } 991 992 SetAutoCalc( bOldAutoCalc ); 993 pChartListenerCollection->UpdateDirtyCharts(); 994 } 995 996 997 void ScDocument::DeleteRow( const ScRange& rRange, ScDocument* pRefUndoDoc, sal_Bool* pUndoOutline ) 998 { 999 DeleteRow( rRange.aStart.Col(), rRange.aStart.Tab(), 1000 rRange.aEnd.Col(), rRange.aEnd.Tab(), 1001 rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1), 1002 pRefUndoDoc, pUndoOutline ); 1003 } 1004 1005 1006 sal_Bool ScDocument::CanInsertCol( const ScRange& rRange ) const 1007 { 1008 SCCOL nStartCol = rRange.aStart.Col(); 1009 SCROW nStartRow = rRange.aStart.Row(); 1010 SCTAB nStartTab = rRange.aStart.Tab(); 1011 SCCOL nEndCol = rRange.aEnd.Col(); 1012 SCROW nEndRow = rRange.aEnd.Row(); 1013 SCTAB nEndTab = rRange.aEnd.Tab(); 1014 PutInOrder( nStartCol, nEndCol ); 1015 PutInOrder( nStartRow, nEndRow ); 1016 PutInOrder( nStartTab, nEndTab ); 1017 SCSIZE nSize = static_cast<SCSIZE>(nEndCol - nStartCol + 1); 1018 1019 sal_Bool bTest = sal_True; 1020 for (SCTAB i=nStartTab; i<=nEndTab && bTest; i++) 1021 if (pTab[i]) 1022 bTest &= pTab[i]->TestInsertCol( nStartRow, nEndRow, nSize ); 1023 1024 return bTest; 1025 } 1026 1027 1028 sal_Bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab, 1029 SCROW nEndRow, SCTAB nEndTab, 1030 SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc, 1031 const ScMarkData* pTabMark ) 1032 { 1033 SCTAB i; 1034 1035 PutInOrder( nStartRow, nEndRow ); 1036 PutInOrder( nStartTab, nEndTab ); 1037 if ( pTabMark ) 1038 { 1039 nStartTab = 0; 1040 nEndTab = MAXTAB; 1041 } 1042 1043 sal_Bool bTest = sal_True; 1044 sal_Bool bRet = sal_False; 1045 sal_Bool bOldAutoCalc = GetAutoCalc(); 1046 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1047 for ( i = nStartTab; i <= nEndTab && bTest; i++) 1048 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) 1049 bTest &= pTab[i]->TestInsertCol( nStartRow, nEndRow, nSize ); 1050 if (bTest) 1051 { 1052 // handle chunks of consecutive selected sheets together 1053 SCTAB nTabRangeStart = nStartTab; 1054 SCTAB nTabRangeEnd = nEndTab; 1055 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 1056 do 1057 { 1058 UpdateBroadcastAreas( URM_INSDEL, ScRange( 1059 ScAddress( nStartCol, nStartRow, nTabRangeStart ), 1060 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), static_cast<SCsCOL>(nSize), 0, 0 ); 1061 } 1062 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 1063 1064 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 1065 do 1066 { 1067 UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart, 1068 MAXCOL, nEndRow, nTabRangeEnd, 1069 static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc, sal_True, false ); 1070 } 1071 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 1072 1073 for (i=nStartTab; i<=nEndTab; i++) 1074 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) 1075 pTab[i]->InsertCol( nStartCol, nStartRow, nEndRow, nSize ); 1076 1077 if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() ) 1078 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist 1079 // ein neues Listening faellig, bisherige Listener wurden in 1080 // FormulaCell UpdateReference abgehaengt 1081 StartAllListeners(); 1082 } 1083 else 1084 { // Listeners have been removed in UpdateReference 1085 for (i=0; i<=MAXTAB; i++) 1086 if (pTab[i]) 1087 pTab[i]->StartNeededListeners(); 1088 // #69592# at least all cells using range names pointing relative 1089 // to the moved range must recalculate 1090 for (i=0; i<=MAXTAB; i++) 1091 if (pTab[i]) 1092 pTab[i]->SetRelNameDirty(); 1093 } 1094 bRet = sal_True; 1095 } 1096 SetAutoCalc( bOldAutoCalc ); 1097 if ( bRet ) 1098 pChartListenerCollection->UpdateDirtyCharts(); 1099 return bRet; 1100 } 1101 1102 1103 sal_Bool ScDocument::InsertCol( const ScRange& rRange, ScDocument* pRefUndoDoc ) 1104 { 1105 return InsertCol( rRange.aStart.Row(), rRange.aStart.Tab(), 1106 rRange.aEnd.Row(), rRange.aEnd.Tab(), 1107 rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1), 1108 pRefUndoDoc ); 1109 } 1110 1111 1112 void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab, 1113 SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc, 1114 sal_Bool* pUndoOutline, const ScMarkData* pTabMark ) 1115 { 1116 SCTAB i; 1117 1118 PutInOrder( nStartRow, nEndRow ); 1119 PutInOrder( nStartTab, nEndTab ); 1120 if ( pTabMark ) 1121 { 1122 nStartTab = 0; 1123 nEndTab = MAXTAB; 1124 } 1125 1126 sal_Bool bOldAutoCalc = GetAutoCalc(); 1127 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1128 1129 // handle chunks of consecutive selected sheets together 1130 SCTAB nTabRangeStart = nStartTab; 1131 SCTAB nTabRangeEnd = nEndTab; 1132 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 1133 do 1134 { 1135 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) 1136 { 1137 DelBroadcastAreasInRange( ScRange( 1138 ScAddress( nStartCol, nStartRow, nTabRangeStart ), 1139 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nTabRangeEnd ) ) ); 1140 UpdateBroadcastAreas( URM_INSDEL, ScRange( 1141 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart ), 1142 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), -static_cast<SCsCOL>(nSize), 0, 0 ); 1143 } 1144 else 1145 DelBroadcastAreasInRange( ScRange( 1146 ScAddress( nStartCol, nStartRow, nTabRangeStart ), 1147 ScAddress( MAXCOL, nEndRow, nTabRangeEnd ) ) ); 1148 } 1149 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 1150 1151 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) 1152 { 1153 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); 1154 do 1155 { 1156 UpdateReference( URM_INSDEL, sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart, 1157 MAXCOL, nEndRow, nTabRangeEnd, 1158 -static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc, sal_True, false ); 1159 } 1160 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); 1161 } 1162 1163 if (pUndoOutline) 1164 *pUndoOutline = sal_False; 1165 1166 for ( i = nStartTab; i <= nEndTab; i++) 1167 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) 1168 pTab[i]->DeleteCol( nStartCol, nStartRow, nEndRow, nSize, pUndoOutline ); 1169 1170 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) 1171 { // Listeners have been removed in UpdateReference 1172 for (i=0; i<=MAXTAB; i++) 1173 if (pTab[i]) 1174 pTab[i]->StartNeededListeners(); 1175 // #69592# at least all cells using range names pointing relative to 1176 // the moved range must recalculate 1177 for (i=0; i<=MAXTAB; i++) 1178 if (pTab[i]) 1179 pTab[i]->SetRelNameDirty(); 1180 } 1181 1182 SetAutoCalc( bOldAutoCalc ); 1183 pChartListenerCollection->UpdateDirtyCharts(); 1184 } 1185 1186 1187 void ScDocument::DeleteCol( const ScRange& rRange, ScDocument* pRefUndoDoc, sal_Bool* pUndoOutline ) 1188 { 1189 DeleteCol( rRange.aStart.Row(), rRange.aStart.Tab(), 1190 rRange.aEnd.Row(), rRange.aEnd.Tab(), 1191 rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1), 1192 pRefUndoDoc, pUndoOutline ); 1193 } 1194 1195 1196 // fuer Area-Links: Zellen einuegen/loeschen, wenn sich der Bereich veraendert 1197 // (ohne Paint) 1198 1199 1200 void lcl_GetInsDelRanges( const ScRange& rOld, const ScRange& rNew, 1201 ScRange& rColRange, sal_Bool& rInsCol, sal_Bool& rDelCol, 1202 ScRange& rRowRange, sal_Bool& rInsRow, sal_Bool& rDelRow ) 1203 { 1204 DBG_ASSERT( rOld.aStart == rNew.aStart, "FitBlock: Anfang unterschiedlich" ); 1205 1206 rInsCol = rDelCol = rInsRow = rDelRow = sal_False; 1207 1208 SCCOL nStartX = rOld.aStart.Col(); 1209 SCROW nStartY = rOld.aStart.Row(); 1210 SCCOL nOldEndX = rOld.aEnd.Col(); 1211 SCROW nOldEndY = rOld.aEnd.Row(); 1212 SCCOL nNewEndX = rNew.aEnd.Col(); 1213 SCROW nNewEndY = rNew.aEnd.Row(); 1214 SCTAB nTab = rOld.aStart.Tab(); 1215 1216 // wenn es mehr Zeilen werden, werden Spalten auf der alten Hoehe eingefuegt/geloescht 1217 sal_Bool bGrowY = ( nNewEndY > nOldEndY ); 1218 SCROW nColEndY = bGrowY ? nOldEndY : nNewEndY; 1219 SCCOL nRowEndX = bGrowY ? nNewEndX : nOldEndX; 1220 1221 // Spalten 1222 1223 if ( nNewEndX > nOldEndX ) // Spalten einfuegen 1224 { 1225 rColRange = ScRange( nOldEndX+1, nStartY, nTab, nNewEndX, nColEndY, nTab ); 1226 rInsCol = sal_True; 1227 } 1228 else if ( nNewEndX < nOldEndX ) // Spalten loeschen 1229 { 1230 rColRange = ScRange( nNewEndX+1, nStartY, nTab, nOldEndX, nColEndY, nTab ); 1231 rDelCol = sal_True; 1232 } 1233 1234 // Zeilen 1235 1236 if ( nNewEndY > nOldEndY ) // Zeilen einfuegen 1237 { 1238 rRowRange = ScRange( nStartX, nOldEndY+1, nTab, nRowEndX, nNewEndY, nTab ); 1239 rInsRow = sal_True; 1240 } 1241 else if ( nNewEndY < nOldEndY ) // Zeilen loeschen 1242 { 1243 rRowRange = ScRange( nStartX, nNewEndY+1, nTab, nRowEndX, nOldEndY, nTab ); 1244 rDelRow = sal_True; 1245 } 1246 } 1247 1248 1249 sal_Bool ScDocument::HasPartOfMerged( const ScRange& rRange ) 1250 { 1251 sal_Bool bPart = sal_False; 1252 SCTAB nTab = rRange.aStart.Tab(); 1253 1254 SCCOL nStartX = rRange.aStart.Col(); 1255 SCROW nStartY = rRange.aStart.Row(); 1256 SCCOL nEndX = rRange.aEnd.Col(); 1257 SCROW nEndY = rRange.aEnd.Row(); 1258 1259 if (HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab, 1260 HASATTR_MERGED | HASATTR_OVERLAPPED )) 1261 { 1262 ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab ); 1263 ExtendOverlapped( nStartX, nStartY, nEndX, nEndY, nTab ); 1264 1265 bPart = ( nStartX != rRange.aStart.Col() || nEndX != rRange.aEnd.Col() || 1266 nStartY != rRange.aStart.Row() || nEndY != rRange.aEnd.Row() ); 1267 } 1268 return bPart; 1269 } 1270 1271 1272 sal_Bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew ) 1273 { 1274 if ( rOld == rNew ) 1275 return sal_True; 1276 1277 sal_Bool bOk = sal_True; 1278 sal_Bool bInsCol,bDelCol,bInsRow,bDelRow; 1279 ScRange aColRange,aRowRange; 1280 lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow ); 1281 1282 if ( bInsCol && !CanInsertCol( aColRange ) ) // Zellen am Rand ? 1283 bOk = sal_False; 1284 if ( bInsRow && !CanInsertRow( aRowRange ) ) // Zellen am Rand ? 1285 bOk = sal_False; 1286 1287 if ( bInsCol || bDelCol ) 1288 { 1289 aColRange.aEnd.SetCol(MAXCOL); 1290 if ( HasPartOfMerged(aColRange) ) 1291 bOk = sal_False; 1292 } 1293 if ( bInsRow || bDelRow ) 1294 { 1295 aRowRange.aEnd.SetRow(MAXROW); 1296 if ( HasPartOfMerged(aRowRange) ) 1297 bOk = sal_False; 1298 } 1299 1300 return bOk; 1301 } 1302 1303 1304 void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, sal_Bool bClear ) 1305 { 1306 if (bClear) 1307 DeleteAreaTab( rOld, IDF_ALL ); 1308 1309 sal_Bool bInsCol,bDelCol,bInsRow,bDelRow; 1310 ScRange aColRange,aRowRange; 1311 lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow ); 1312 1313 if ( bInsCol ) 1314 InsertCol( aColRange ); // Spalten zuerst einfuegen 1315 if ( bInsRow ) 1316 InsertRow( aRowRange ); 1317 1318 if ( bDelRow ) 1319 DeleteRow( aRowRange ); // Zeilen zuerst loeschen 1320 if ( bDelCol ) 1321 DeleteCol( aColRange ); 1322 1323 // Referenzen um eingefuegte Zeilen erweitern 1324 1325 if ( bInsCol || bInsRow ) 1326 { 1327 ScRange aGrowSource = rOld; 1328 aGrowSource.aEnd.SetCol(Min( rOld.aEnd.Col(), rNew.aEnd.Col() )); 1329 aGrowSource.aEnd.SetRow(Min( rOld.aEnd.Row(), rNew.aEnd.Row() )); 1330 SCCOL nGrowX = bInsCol ? ( rNew.aEnd.Col() - rOld.aEnd.Col() ) : 0; 1331 SCROW nGrowY = bInsRow ? ( rNew.aEnd.Row() - rOld.aEnd.Row() ) : 0; 1332 UpdateGrow( aGrowSource, nGrowX, nGrowY ); 1333 } 1334 } 1335 1336 1337 void ScDocument::DeleteArea(SCCOL nCol1, SCROW nRow1, 1338 SCCOL nCol2, SCROW nRow2, 1339 const ScMarkData& rMark, sal_uInt16 nDelFlag) 1340 { 1341 PutInOrder( nCol1, nCol2 ); 1342 PutInOrder( nRow1, nRow2 ); 1343 sal_Bool bOldAutoCalc = GetAutoCalc(); 1344 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1345 for (SCTAB i = 0; i <= MAXTAB; i++) 1346 if (pTab[i]) 1347 if ( rMark.GetTableSelect(i) || bIsUndo ) 1348 pTab[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag); 1349 SetAutoCalc( bOldAutoCalc ); 1350 } 1351 1352 1353 void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1, 1354 SCCOL nCol2, SCROW nRow2, 1355 SCTAB nTab, sal_uInt16 nDelFlag) 1356 { 1357 PutInOrder( nCol1, nCol2 ); 1358 PutInOrder( nRow1, nRow2 ); 1359 if ( VALIDTAB(nTab) && pTab[nTab] ) 1360 { 1361 sal_Bool bOldAutoCalc = GetAutoCalc(); 1362 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1363 pTab[nTab]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag); 1364 SetAutoCalc( bOldAutoCalc ); 1365 } 1366 } 1367 1368 1369 void ScDocument::DeleteAreaTab( const ScRange& rRange, sal_uInt16 nDelFlag ) 1370 { 1371 for ( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); nTab++ ) 1372 DeleteAreaTab( rRange.aStart.Col(), rRange.aStart.Row(), 1373 rRange.aEnd.Col(), rRange.aEnd.Row(), 1374 nTab, nDelFlag ); 1375 } 1376 1377 1378 void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSelection, 1379 sal_Bool bColInfo, sal_Bool bRowInfo ) 1380 { 1381 if (bIsUndo) 1382 { 1383 Clear(); 1384 1385 xPoolHelper = pSrcDoc->xPoolHelper; 1386 1387 String aString; 1388 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) 1389 if ( rTabSelection.GetTableSelect( nTab ) ) 1390 { 1391 pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo); 1392 nMaxTableNumber = nTab + 1; 1393 } 1394 } 1395 else 1396 { 1397 DBG_ERROR("InitUndo"); 1398 } 1399 } 1400 1401 1402 void ScDocument::InitUndo( ScDocument* pSrcDoc, SCTAB nTab1, SCTAB nTab2, 1403 sal_Bool bColInfo, sal_Bool bRowInfo ) 1404 { 1405 if (bIsUndo) 1406 { 1407 Clear(); 1408 1409 xPoolHelper = pSrcDoc->xPoolHelper; 1410 1411 String aString; 1412 for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++) 1413 pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo); 1414 1415 nMaxTableNumber = nTab2 + 1; 1416 } 1417 else 1418 { 1419 DBG_ERROR("InitUndo"); 1420 } 1421 } 1422 1423 1424 void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, sal_Bool bColInfo, sal_Bool bRowInfo ) 1425 { 1426 if (bIsUndo) 1427 { 1428 String aString; 1429 for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++) 1430 if (!pTab[nTab]) 1431 pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo); 1432 1433 if ( nMaxTableNumber <= nTab2 ) 1434 nMaxTableNumber = nTab2 + 1; 1435 } 1436 else 1437 { 1438 DBG_ERROR("InitUndo"); 1439 } 1440 } 1441 1442 1443 void ScDocument::SetCutMode( sal_Bool bVal ) 1444 { 1445 if (bIsClip) 1446 GetClipParam().mbCutMode = bVal; 1447 else 1448 { 1449 DBG_ERROR("SetCutMode without bIsClip"); 1450 } 1451 } 1452 1453 1454 sal_Bool ScDocument::IsCutMode() 1455 { 1456 if (bIsClip) 1457 return GetClipParam().mbCutMode; 1458 else 1459 { 1460 DBG_ERROR("IsCutMode ohne bIsClip"); 1461 return sal_False; 1462 } 1463 } 1464 1465 1466 void ScDocument::CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 1467 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, 1468 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc, 1469 const ScMarkData* pMarks, sal_Bool bColRowFlags ) 1470 { 1471 PutInOrder( nCol1, nCol2 ); 1472 PutInOrder( nRow1, nRow2 ); 1473 PutInOrder( nTab1, nTab2 ); 1474 if( !pDestDoc->aDocName.Len() ) 1475 pDestDoc->aDocName = aDocName; 1476 if (VALIDTAB(nTab1) && VALIDTAB(nTab2)) 1477 { 1478 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc(); 1479 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1480 for (SCTAB i = nTab1; i <= nTab2; i++) 1481 { 1482 if (pTab[i] && pDestDoc->pTab[i]) 1483 pTab[i]->CopyToTable( nCol1, nRow1, nCol2, nRow2, nFlags, 1484 bOnlyMarked, pDestDoc->pTab[i], pMarks, 1485 sal_False, bColRowFlags ); 1486 } 1487 pDestDoc->SetAutoCalc( bOldAutoCalc ); 1488 } 1489 } 1490 1491 1492 void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 1493 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, 1494 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc, 1495 const ScMarkData* pMarks) 1496 { 1497 PutInOrder( nCol1, nCol2 ); 1498 PutInOrder( nRow1, nRow2 ); 1499 PutInOrder( nTab1, nTab2 ); 1500 if (VALIDTAB(nTab1) && VALIDTAB(nTab2)) 1501 { 1502 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc(); 1503 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1504 if (nTab1 > 0) 1505 CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, sal_False, pDestDoc, pMarks ); 1506 1507 for (SCTAB i = nTab1; i <= nTab2; i++) 1508 { 1509 if (pTab[i] && pDestDoc->pTab[i]) 1510 pTab[i]->UndoToTable(nCol1, nRow1, nCol2, nRow2, nFlags, 1511 bOnlyMarked, pDestDoc->pTab[i], pMarks); 1512 } 1513 1514 if (nTab2 < MAXTAB) 1515 CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, sal_False, pDestDoc, pMarks ); 1516 pDestDoc->SetAutoCalc( bOldAutoCalc ); 1517 } 1518 } 1519 1520 1521 void ScDocument::CopyToDocument(const ScRange& rRange, 1522 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc, 1523 const ScMarkData* pMarks, sal_Bool bColRowFlags) 1524 { 1525 ScRange aNewRange = rRange; 1526 aNewRange.Justify(); 1527 1528 if( !pDestDoc->aDocName.Len() ) 1529 pDestDoc->aDocName = aDocName; 1530 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc(); 1531 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1532 for (SCTAB i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab(); i++) 1533 if (pTab[i] && pDestDoc->pTab[i]) 1534 pTab[i]->CopyToTable(aNewRange.aStart.Col(), aNewRange.aStart.Row(), 1535 aNewRange.aEnd.Col(), aNewRange.aEnd.Row(), 1536 nFlags, bOnlyMarked, pDestDoc->pTab[i], 1537 pMarks, sal_False, bColRowFlags); 1538 pDestDoc->SetAutoCalc( bOldAutoCalc ); 1539 } 1540 1541 1542 void ScDocument::UndoToDocument(const ScRange& rRange, 1543 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc, 1544 const ScMarkData* pMarks) 1545 { 1546 ScRange aNewRange = rRange; 1547 aNewRange.Justify(); 1548 SCTAB nTab1 = aNewRange.aStart.Tab(); 1549 SCTAB nTab2 = aNewRange.aEnd.Tab(); 1550 1551 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc(); 1552 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 1553 if (nTab1 > 0) 1554 CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, sal_False, pDestDoc, pMarks ); 1555 1556 for (SCTAB i = nTab1; i <= nTab2; i++) 1557 { 1558 if (pTab[i] && pDestDoc->pTab[i]) 1559 pTab[i]->UndoToTable(aNewRange.aStart.Col(), aNewRange.aStart.Row(), 1560 aNewRange.aEnd.Col(), aNewRange.aEnd.Row(), 1561 nFlags, bOnlyMarked, pDestDoc->pTab[i], pMarks); 1562 } 1563 1564 if (nTab2 < MAXTAB) 1565 CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, sal_False, pDestDoc, pMarks ); 1566 pDestDoc->SetAutoCalc( bOldAutoCalc ); 1567 } 1568 1569 void ScDocument::CopyToClip(const ScClipParam& rClipParam, 1570 ScDocument* pClipDoc, const ScMarkData* pMarks, 1571 bool bAllTabs, bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions) 1572 { 1573 DBG_ASSERT( bAllTabs || pMarks, "CopyToClip: ScMarkData fehlt" ); 1574 1575 if (bIsClip) 1576 return; 1577 1578 if (!pClipDoc) 1579 { 1580 DBG_ERROR("CopyToClip: no ClipDoc"); 1581 pClipDoc = SC_MOD()->GetClipDoc(); 1582 } 1583 1584 pClipDoc->aDocName = aDocName; 1585 pClipDoc->SetClipParam(rClipParam); 1586 pClipDoc->ResetClip(this, pMarks); 1587 1588 ScRange aClipRange = rClipParam.getWholeRange(); 1589 CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs); 1590 1591 for (SCTAB i = 0; i <= MAXTAB; ++i) 1592 { 1593 if (!pTab[i] || !pClipDoc->pTab[i]) 1594 continue; 1595 1596 if (pMarks && !pMarks->GetTableSelect(i)) 1597 continue; 1598 1599 pTab[i]->CopyToClip(rClipParam.maRanges, pClipDoc->pTab[i], bKeepScenarioFlags, bCloneNoteCaptions); 1600 1601 if (pDrawLayer && bIncludeObjects) 1602 { 1603 // also copy drawing objects 1604 Rectangle aObjRect = GetMMRect( 1605 aClipRange.aStart.Col(), aClipRange.aStart.Row(), aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i); 1606 pDrawLayer->CopyToClip(pClipDoc, i, aObjRect); 1607 } 1608 } 1609 1610 // Make sure to mark overlapped cells. 1611 pClipDoc->ExtendMerge(aClipRange, true); 1612 } 1613 1614 void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1, 1615 SCCOL nCol2, SCROW nRow2, 1616 SCTAB nTab, ScDocument* pClipDoc) 1617 { 1618 if (!bIsClip) 1619 { 1620 PutInOrder( nCol1, nCol2 ); 1621 PutInOrder( nRow1, nRow2 ); 1622 if (!pClipDoc) 1623 { 1624 DBG_ERROR("CopyTabToClip: no ClipDoc"); 1625 pClipDoc = SC_MOD()->GetClipDoc(); 1626 } 1627 1628 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 1629 pClipDoc->aDocName = aDocName; 1630 rClipParam.maRanges.RemoveAll(); 1631 rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0)); 1632 pClipDoc->ResetClip( this, nTab ); 1633 1634 if (pTab[nTab] && pClipDoc->pTab[nTab]) 1635 pTab[nTab]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[nTab], sal_False, sal_True); 1636 1637 pClipDoc->GetClipParam().mbCutMode = false; 1638 } 1639 } 1640 1641 1642 void ScDocument::TransposeClip( ScDocument* pTransClip, sal_uInt16 nFlags, sal_Bool bAsLink ) 1643 { 1644 DBG_ASSERT( bIsClip && pTransClip && pTransClip->bIsClip, 1645 "TransposeClip mit falschem Dokument" ); 1646 1647 // initialisieren 1648 // -> pTransClip muss vor dem Original-Dokument geloescht werden! 1649 1650 pTransClip->ResetClip(this, (ScMarkData*)NULL); // alle 1651 1652 // Bereiche uebernehmen 1653 1654 pTransClip->pRangeName->FreeAll(); 1655 for (sal_uInt16 i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!! 1656 { 1657 sal_uInt16 nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex(); 1658 ScRangeData* pData = new ScRangeData(*((*pRangeName)[i])); 1659 if (!pTransClip->pRangeName->Insert(pData)) 1660 delete pData; 1661 else 1662 pData->SetIndex(nIndex); 1663 } 1664 1665 // Daten 1666 1667 ScRange aClipRange = GetClipParam().getWholeRange(); 1668 if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) ) 1669 { 1670 for (SCTAB i=0; i<=MAXTAB; i++) 1671 if (pTab[i]) 1672 { 1673 DBG_ASSERT( pTransClip->pTab[i], "TransposeClip: Tabelle nicht da" ); 1674 pTab[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(), 1675 aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), 1676 pTransClip->pTab[i], nFlags, bAsLink ); 1677 1678 if ( pDrawLayer && ( nFlags & IDF_OBJECTS ) ) 1679 { 1680 // Drawing objects are copied to the new area without transposing. 1681 // CopyFromClip is used to adjust the objects to the transposed block's 1682 // cell range area. 1683 // (pDrawLayer in the original clipboard document is set only if there 1684 // are drawing objects to copy) 1685 1686 pTransClip->InitDrawLayer(); 1687 Rectangle aSourceRect = GetMMRect( aClipRange.aStart.Col(), aClipRange.aStart.Row(), 1688 aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i ); 1689 Rectangle aDestRect = pTransClip->GetMMRect( 0, 0, 1690 static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()), 1691 static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()), i ); 1692 pTransClip->pDrawLayer->CopyFromClip( pDrawLayer, i, aSourceRect, ScAddress(0,0,i), aDestRect ); 1693 } 1694 } 1695 1696 pTransClip->SetClipParam(GetClipParam()); 1697 pTransClip->GetClipParam().transpose(); 1698 } 1699 else 1700 { 1701 DBG_ERROR("TransposeClip: zu gross"); 1702 } 1703 1704 // Dies passiert erst beim Einfuegen... 1705 1706 GetClipParam().mbCutMode = false; 1707 } 1708 1709 void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs) 1710 { 1711 std::set<sal_uInt16> aUsedNames; // indexes of named ranges that are used in the copied cells 1712 for (SCTAB i = 0; i <= MAXTAB; ++i) 1713 if (pTab[i] && pClipDoc->pTab[i]) 1714 if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) ) 1715 pTab[i]->FindRangeNamesInUse( 1716 rClipRange.aStart.Col(), rClipRange.aStart.Row(), 1717 rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames); 1718 1719 pClipDoc->pRangeName->FreeAll(); 1720 for (sal_uInt16 i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!! 1721 { 1722 sal_uInt16 nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex(); 1723 bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() ); 1724 if (bInUse) 1725 { 1726 ScRangeData* pData = new ScRangeData(*((*pRangeName)[i])); 1727 if (!pClipDoc->pRangeName->Insert(pData)) 1728 delete pData; 1729 else 1730 pData->SetIndex(nIndex); 1731 } 1732 } 1733 } 1734 1735 ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) : 1736 mpDoc(pDoc) 1737 { 1738 mpDoc->MergeNumberFormatter(pSrcDoc); 1739 } 1740 1741 ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler() 1742 { 1743 mpDoc->pFormatExchangeList = NULL; 1744 } 1745 1746 void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc) 1747 { 1748 SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable(); 1749 SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable(); 1750 if (pOtherFormatter && pOtherFormatter != pThisFormatter) 1751 { 1752 SvNumberFormatterIndexTable* pExchangeList = 1753 pThisFormatter->MergeFormatter(*(pOtherFormatter)); 1754 if (pExchangeList->Count() > 0) 1755 pFormatExchangeList = pExchangeList; 1756 } 1757 } 1758 1759 void ScDocument::CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames) 1760 { 1761 sal_uInt16 nClipRangeNameCount = pClipDoc->pRangeName->GetCount(); 1762 ScClipRangeNameData aClipRangeNames; 1763 1764 // array containing range names which might need update of indices 1765 aClipRangeNames.mpRangeNames.resize(nClipRangeNameCount, NULL); 1766 1767 for (sal_uInt16 i = 0; i < nClipRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch 1768 { 1769 /* Copy only if the name doesn't exist in this document. 1770 If it exists we use the already existing name instead, 1771 another possibility could be to create new names if 1772 documents differ. 1773 A proper solution would ask the user how to proceed. 1774 The adjustment of the indices in the formulas is done later. 1775 */ 1776 ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i]; 1777 sal_uInt16 k; 1778 if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) ) 1779 { 1780 aClipRangeNames.mpRangeNames[i] = NULL; // range name not inserted 1781 sal_uInt16 nOldIndex = pClipRangeData->GetIndex(); 1782 sal_uInt16 nNewIndex = ((*pRangeName)[k])->GetIndex(); 1783 aClipRangeNames.insert(nOldIndex, nNewIndex); 1784 if ( !aClipRangeNames.mbReplace ) 1785 aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex ); 1786 } 1787 else 1788 { 1789 ScRangeData* pData = new ScRangeData( *pClipRangeData ); 1790 pData->SetDocument(this); 1791 if ( pRangeName->FindIndex( pData->GetIndex() ) ) 1792 pData->SetIndex(0); // need new index, done in Insert 1793 if ( pRangeName->Insert( pData ) ) 1794 { 1795 aClipRangeNames.mpRangeNames[i] = pData; 1796 sal_uInt16 nOldIndex = pClipRangeData->GetIndex(); 1797 sal_uInt16 nNewIndex = pData->GetIndex(); 1798 aClipRangeNames.insert(nOldIndex, nNewIndex); 1799 if ( !aClipRangeNames.mbReplace ) 1800 aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex ); 1801 } 1802 else 1803 { // must be an overflow 1804 delete pData; 1805 aClipRangeNames.mpRangeNames[i] = NULL; 1806 aClipRangeNames.insert(pClipRangeData->GetIndex(), 0); 1807 aClipRangeNames.mbReplace = true; 1808 } 1809 } 1810 } 1811 rRangeNames = aClipRangeNames; 1812 } 1813 1814 void ScDocument::UpdateRangeNamesInFormulas( 1815 ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark, 1816 SCCOL nXw, SCROW nYw) 1817 { 1818 // nXw and nYw are the extra width and height of the destination range 1819 // extended due to presence of merged cell(s). 1820 1821 if (!rRangeNames.mbReplace) 1822 return; 1823 1824 // first update all inserted named formulas if they contain other 1825 // range names and used indices changed 1826 size_t nRangeNameCount = rRangeNames.mpRangeNames.size(); 1827 for (size_t i = 0; i < nRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch 1828 { 1829 if ( rRangeNames.mpRangeNames[i] ) 1830 rRangeNames.mpRangeNames[i]->ReplaceRangeNamesInUse(rRangeNames.maRangeMap); 1831 } 1832 // then update the formulas, they might need just the updated range names 1833 for (sal_uLong nRange = 0; nRange < rDestRanges.Count(); ++nRange) 1834 { 1835 const ScRange* pRange = rDestRanges.GetObject( nRange); 1836 SCCOL nCol1 = pRange->aStart.Col(); 1837 SCROW nRow1 = pRange->aStart.Row(); 1838 SCCOL nCol2 = pRange->aEnd.Col(); 1839 SCROW nRow2 = pRange->aEnd.Row(); 1840 1841 SCCOL nC1 = nCol1; 1842 SCROW nR1 = nRow1; 1843 SCCOL nC2 = nC1 + nXw; 1844 if (nC2 > nCol2) 1845 nC2 = nCol2; 1846 SCROW nR2 = nR1 + nYw; 1847 if (nR2 > nRow2) 1848 nR2 = nRow2; 1849 do 1850 { 1851 do 1852 { 1853 for (SCTAB k = 0; k <= MAXTAB; k++) 1854 { 1855 if ( pTab[k] && rMark.GetTableSelect(k) ) 1856 pTab[k]->ReplaceRangeNamesInUse(nC1, nR1, 1857 nC2, nR2, rRangeNames.maRangeMap); 1858 } 1859 nC1 = nC2 + 1; 1860 nC2 = Min((SCCOL)(nC1 + nXw), nCol2); 1861 } while (nC1 <= nCol2); 1862 nC1 = nCol1; 1863 nC2 = nC1 + nXw; 1864 if (nC2 > nCol2) 1865 nC2 = nCol2; 1866 nR1 = nR2 + 1; 1867 nR2 = Min((SCROW)(nR1 + nYw), nRow2); 1868 } while (nR1 <= nRow2); 1869 } 1870 } 1871 1872 ScClipParam& ScDocument::GetClipParam() 1873 { 1874 if (!mpClipParam.get()) 1875 mpClipParam.reset(new ScClipParam); 1876 1877 return *mpClipParam; 1878 } 1879 1880 void ScDocument::SetClipParam(const ScClipParam& rParam) 1881 { 1882 mpClipParam.reset(new ScClipParam(rParam)); 1883 } 1884 1885 sal_Bool ScDocument::IsClipboardSource() const 1886 { 1887 ScDocument* pClipDoc = SC_MOD()->GetClipDoc(); 1888 return pClipDoc && pClipDoc->xPoolHelper.isValid() && 1889 xPoolHelper->GetDocPool() == pClipDoc->xPoolHelper->GetDocPool(); 1890 } 1891 1892 1893 void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1, 1894 SCCOL nCol2, SCROW nRow2, 1895 const ScMarkData& rMark, sal_uInt16 nInsFlag ) 1896 { 1897 if (nInsFlag & IDF_CONTENTS) 1898 { 1899 for (SCTAB i = 0; i <= MAXTAB; i++) 1900 if (pTab[i]) 1901 if (rMark.GetTableSelect(i)) 1902 pTab[i]->StartListeningInArea( nCol1, nRow1, nCol2, nRow2 ); 1903 } 1904 } 1905 1906 1907 void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1, 1908 SCCOL nCol2, SCROW nRow2, 1909 const ScMarkData& rMark, sal_uInt16 nInsFlag ) 1910 { 1911 if (nInsFlag & IDF_CONTENTS) 1912 { 1913 ScBulkBroadcast aBulkBroadcast( GetBASM()); 1914 for (SCTAB i = 0; i <= MAXTAB; i++) 1915 if (pTab[i]) 1916 if (rMark.GetTableSelect(i)) 1917 pTab[i]->BroadcastInArea( nCol1, nRow1, nCol2, nRow2 ); 1918 } 1919 } 1920 1921 1922 void ScDocument::CopyBlockFromClip( SCCOL nCol1, SCROW nRow1, 1923 SCCOL nCol2, SCROW nRow2, 1924 const ScMarkData& rMark, 1925 SCsCOL nDx, SCsROW nDy, 1926 const ScCopyBlockFromClipParams* pCBFCP ) 1927 { 1928 ScTable** ppClipTab = pCBFCP->pClipDoc->pTab; 1929 SCTAB nTabEnd = pCBFCP->nTabEnd; 1930 SCTAB nClipTab = 0; 1931 for (SCTAB i = pCBFCP->nTabStart; i <= nTabEnd; i++) 1932 { 1933 if (pTab[i] && rMark.GetTableSelect(i) ) 1934 { 1935 while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1); 1936 1937 pTab[i]->CopyFromClip( nCol1, nRow1, nCol2, nRow2, nDx, nDy, 1938 pCBFCP->nInsFlag, pCBFCP->bAsLink, pCBFCP->bSkipAttrForEmpty, ppClipTab[nClipTab] ); 1939 1940 if ( pCBFCP->pClipDoc->pDrawLayer && ( pCBFCP->nInsFlag & IDF_OBJECTS ) ) 1941 { 1942 // also copy drawing objects 1943 1944 // drawing layer must be created before calling CopyFromClip 1945 // (ScDocShell::MakeDrawLayer also does InitItems etc.) 1946 DBG_ASSERT( pDrawLayer, "CopyBlockFromClip: No drawing layer" ); 1947 if ( pDrawLayer ) 1948 { 1949 // For GetMMRect, the row heights in the target document must already be valid 1950 // (copied in an extra step before pasting, or updated after pasting cells, but 1951 // before pasting objects). 1952 1953 Rectangle aSourceRect = pCBFCP->pClipDoc->GetMMRect( 1954 nCol1-nDx, nRow1-nDy, nCol2-nDx, nRow2-nDy, nClipTab ); 1955 Rectangle aDestRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, i ); 1956 pDrawLayer->CopyFromClip( pCBFCP->pClipDoc->pDrawLayer, nClipTab, aSourceRect, 1957 ScAddress( nCol1, nRow1, i ), aDestRect ); 1958 } 1959 } 1960 1961 nClipTab = (nClipTab+1) % (MAXTAB+1); 1962 } 1963 } 1964 if ( pCBFCP->nInsFlag & IDF_CONTENTS ) 1965 { 1966 nClipTab = 0; 1967 for (SCTAB i = pCBFCP->nTabStart; i <= nTabEnd; i++) 1968 { 1969 if (pTab[i] && rMark.GetTableSelect(i) ) 1970 { 1971 while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1); 1972 SCsTAB nDz = ((SCsTAB)i) - nClipTab; 1973 1974 // #89081# ranges of consecutive selected tables (in clipboard and dest. doc) 1975 // must be handled in one UpdateReference call 1976 SCTAB nFollow = 0; 1977 while ( i + nFollow < nTabEnd 1978 && rMark.GetTableSelect( i + nFollow + 1 ) 1979 && nClipTab + nFollow < MAXTAB 1980 && ppClipTab[nClipTab + nFollow + 1] ) 1981 ++nFollow; 1982 1983 if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode ) 1984 { 1985 sal_Bool bOldInserting = IsInsertingFromOtherDoc(); 1986 SetInsertingFromOtherDoc( sal_True); 1987 UpdateReference( URM_MOVE, 1988 nCol1, nRow1, i, nCol2, nRow2, i+nFollow, 1989 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False ); 1990 SetInsertingFromOtherDoc( bOldInserting); 1991 } 1992 else 1993 UpdateReference( URM_COPY, 1994 nCol1, nRow1, i, nCol2, nRow2, i+nFollow, 1995 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False ); 1996 1997 nClipTab = (nClipTab+nFollow+1) % (MAXTAB+1); 1998 i = sal::static_int_cast<SCTAB>( i + nFollow ); 1999 } 2000 } 2001 } 2002 } 2003 2004 2005 void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1, 2006 SCCOL nCol2, SCROW nRow2, 2007 const ScMarkData& rMark, 2008 SCsCOL nDx, SCsROW /* nDy */, 2009 const ScCopyBlockFromClipParams* pCBFCP, 2010 SCROW & rClipStartRow ) 2011 { 2012 // call CopyBlockFromClip for ranges of consecutive non-filtered rows 2013 // nCol1/nRow1 etc. is in target doc 2014 2015 // filtered state is taken from first used table in clipboard (as in GetClipArea) 2016 SCTAB nFlagTab = 0; 2017 ScTable** ppClipTab = pCBFCP->pClipDoc->pTab; 2018 while ( nFlagTab < MAXTAB && !ppClipTab[nFlagTab] ) 2019 ++nFlagTab; 2020 2021 SCROW nSourceRow = rClipStartRow; 2022 SCROW nSourceEnd = 0; 2023 if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count()) 2024 nSourceEnd = pCBFCP->pClipDoc->GetClipParam().maRanges.First()->aEnd.Row(); 2025 SCROW nDestRow = nRow1; 2026 2027 while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 ) 2028 { 2029 // skip filtered rows 2030 nSourceRow = pCBFCP->pClipDoc->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab); 2031 2032 if ( nSourceRow <= nSourceEnd ) 2033 { 2034 // look for more non-filtered rows following 2035 SCROW nLastRow = nSourceRow; 2036 pCBFCP->pClipDoc->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow); 2037 SCROW nFollow = nLastRow - nSourceRow; 2038 2039 if (nFollow > nSourceEnd - nSourceRow) 2040 nFollow = nSourceEnd - nSourceRow; 2041 if (nFollow > nRow2 - nDestRow) 2042 nFollow = nRow2 - nDestRow; 2043 2044 SCsROW nNewDy = ((SCsROW)nDestRow) - nSourceRow; 2045 CopyBlockFromClip( nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy, pCBFCP ); 2046 2047 nSourceRow += nFollow + 1; 2048 nDestRow += nFollow + 1; 2049 } 2050 } 2051 rClipStartRow = nSourceRow; 2052 } 2053 2054 2055 void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark, 2056 sal_uInt16 nInsFlag, 2057 ScDocument* pRefUndoDoc, ScDocument* pClipDoc, sal_Bool bResetCut, 2058 sal_Bool bAsLink, sal_Bool bIncludeFiltered, sal_Bool bSkipAttrForEmpty, 2059 const ScRangeList * pDestRanges ) 2060 { 2061 if (!bIsClip) 2062 { 2063 if (!pClipDoc) 2064 { 2065 DBG_ERROR("CopyFromClip: no ClipDoc"); 2066 pClipDoc = SC_MOD()->GetClipDoc(); 2067 } 2068 if (pClipDoc->bIsClip && pClipDoc->GetTableCount()) 2069 { 2070 sal_Bool bOldAutoCalc = GetAutoCalc(); 2071 SetAutoCalc( sal_False ); // avoid multiple recalculations 2072 2073 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc); 2074 2075 ScClipRangeNameData aClipRangeNames; 2076 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames); 2077 2078 SCCOL nAllCol1 = rDestRange.aStart.Col(); 2079 SCROW nAllRow1 = rDestRange.aStart.Row(); 2080 SCCOL nAllCol2 = rDestRange.aEnd.Col(); 2081 SCROW nAllRow2 = rDestRange.aEnd.Row(); 2082 2083 SCCOL nXw = 0; 2084 SCROW nYw = 0; 2085 ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange(); 2086 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) // find largest merge overlap 2087 if (pClipDoc->pTab[nTab]) // all sheets of the clipboard content 2088 { 2089 SCCOL nThisEndX = aClipRange.aEnd.Col(); 2090 SCROW nThisEndY = aClipRange.aEnd.Row(); 2091 pClipDoc->ExtendMerge( aClipRange.aStart.Col(), 2092 aClipRange.aStart.Row(), 2093 nThisEndX, nThisEndY, nTab ); 2094 // only extra value from ExtendMerge 2095 nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() ); 2096 nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() ); 2097 if ( nThisEndX > nXw ) 2098 nXw = nThisEndX; 2099 if ( nThisEndY > nYw ) 2100 nYw = nThisEndY; 2101 } 2102 2103 SCCOL nDestAddX; 2104 SCROW nDestAddY; 2105 pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered ); 2106 nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX ); 2107 nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value 2108 2109 /* Decide which contents to delete before copying. Delete all 2110 contents if nInsFlag contains any real content flag. 2111 #i102056# Notes are pasted from clipboard in a second pass, 2112 together with the special flag IDF_ADDNOTES that states to not 2113 overwrite/delete existing cells but to insert the notes into 2114 these cells. In this case, just delete old notes from the 2115 destination area. */ 2116 sal_uInt16 nDelFlag = IDF_NONE; 2117 if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) ) 2118 nDelFlag |= IDF_NOTE; 2119 else if ( nInsFlag & IDF_CONTENTS ) 2120 nDelFlag |= IDF_CONTENTS; 2121 // With bSkipAttrForEmpty, don't remove attributes, copy 2122 // on top of existing attributes instead. 2123 if ( ( nInsFlag & IDF_ATTRIB ) && !bSkipAttrForEmpty ) 2124 nDelFlag |= IDF_ATTRIB; 2125 2126 ScCopyBlockFromClipParams aCBFCP; 2127 aCBFCP.pRefUndoDoc = pRefUndoDoc; 2128 aCBFCP.pClipDoc = pClipDoc; 2129 aCBFCP.nInsFlag = nInsFlag; 2130 aCBFCP.bAsLink = bAsLink; 2131 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty; 2132 aCBFCP.nTabStart = MAXTAB; // wird in der Schleife angepasst 2133 aCBFCP.nTabEnd = 0; // wird in der Schleife angepasst 2134 2135 // Inc/DecRecalcLevel einmal aussen, damit nicht fuer jeden Block 2136 // die Draw-Seitengroesse neu berechnet werden muss 2137 //! nur wenn ganze Zeilen/Spalten kopiert werden? 2138 2139 for (SCTAB j = 0; j <= MAXTAB; j++) 2140 if (pTab[j] && rMark.GetTableSelect(j)) 2141 { 2142 if ( j < aCBFCP.nTabStart ) 2143 aCBFCP.nTabStart = j; 2144 aCBFCP.nTabEnd = j; 2145 pTab[j]->IncRecalcLevel(); 2146 } 2147 2148 ScRangeList aLocalRangeList; 2149 if (!pDestRanges) 2150 { 2151 aLocalRangeList.Append( rDestRange); 2152 pDestRanges = &aLocalRangeList; 2153 } 2154 2155 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert 2156 2157 // bei mindestens 64 Zeilen wird in ScColumn::CopyFromClip voralloziert 2158 sal_Bool bDoDouble = ( nYw < 64 && nAllRow2 - nAllRow1 > 64); 2159 sal_Bool bOldDouble = ScColumn::bDoubleAlloc; 2160 if (bDoDouble) 2161 ScColumn::bDoubleAlloc = sal_True; 2162 2163 SCCOL nClipStartCol = aClipRange.aStart.Col(); 2164 SCROW nClipStartRow = aClipRange.aStart.Row(); 2165 // WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col(); 2166 SCROW nClipEndRow = aClipRange.aEnd.Row(); 2167 for (sal_uLong nRange = 0; nRange < pDestRanges->Count(); ++nRange) 2168 { 2169 const ScRange* pRange = pDestRanges->GetObject( nRange); 2170 SCCOL nCol1 = pRange->aStart.Col(); 2171 SCROW nRow1 = pRange->aStart.Row(); 2172 SCCOL nCol2 = pRange->aEnd.Col(); 2173 SCROW nRow2 = pRange->aEnd.Row(); 2174 2175 DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag); 2176 2177 SCCOL nC1 = nCol1; 2178 SCROW nR1 = nRow1; 2179 SCCOL nC2 = nC1 + nXw; 2180 if (nC2 > nCol2) 2181 nC2 = nCol2; 2182 SCROW nR2 = nR1 + nYw; 2183 if (nR2 > nRow2) 2184 nR2 = nRow2; 2185 2186 do 2187 { 2188 // Pasting is done column-wise, when pasting to a filtered 2189 // area this results in partitioning and we have to 2190 // remember and reset the start row for each column until 2191 // it can be advanced for the next chunk of unfiltered 2192 // rows. 2193 SCROW nSaveClipStartRow = nClipStartRow; 2194 do 2195 { 2196 nClipStartRow = nSaveClipStartRow; 2197 SCsCOL nDx = ((SCsCOL)nC1) - nClipStartCol; 2198 SCsROW nDy = ((SCsROW)nR1) - nClipStartRow; 2199 if ( bIncludeFiltered ) 2200 { 2201 CopyBlockFromClip( nC1, nR1, nC2, nR2, rMark, nDx, 2202 nDy, &aCBFCP ); 2203 nClipStartRow += nR2 - nR1 + 1; 2204 } 2205 else 2206 { 2207 CopyNonFilteredFromClip( nC1, nR1, nC2, nR2, rMark, 2208 nDx, nDy, &aCBFCP, nClipStartRow ); 2209 } 2210 // Not needed for columns, but if it was this would be how to. 2211 //if (nClipStartCol > nClipEndCol) 2212 // nClipStartCol = pClipDoc->aClipRange.aStart.Col(); 2213 nC1 = nC2 + 1; 2214 nC2 = Min((SCCOL)(nC1 + nXw), nCol2); 2215 } while (nC1 <= nCol2); 2216 if (nClipStartRow > nClipEndRow) 2217 nClipStartRow = aClipRange.aStart.Row(); 2218 nC1 = nCol1; 2219 nC2 = nC1 + nXw; 2220 if (nC2 > nCol2) 2221 nC2 = nCol2; 2222 nR1 = nR2 + 1; 2223 nR2 = Min((SCROW)(nR1 + nYw), nRow2); 2224 } while (nR1 <= nRow2); 2225 } 2226 2227 ScColumn::bDoubleAlloc = bOldDouble; 2228 2229 for (SCTAB k = 0; k <= MAXTAB; k++) 2230 if (pTab[k] && rMark.GetTableSelect(k)) 2231 pTab[k]->DecRecalcLevel(); 2232 2233 bInsertingFromOtherDoc = sal_False; 2234 2235 UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw); 2236 2237 // Listener aufbauen nachdem alles inserted wurde 2238 StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag ); 2239 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden 2240 BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag ); 2241 if (bResetCut) 2242 pClipDoc->GetClipParam().mbCutMode = false; 2243 SetAutoCalc( bOldAutoCalc ); 2244 } 2245 } 2246 } 2247 2248 static SCROW lcl_getLastNonFilteredRow( 2249 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags, SCROW nBegRow, SCROW nEndRow, 2250 SCROW nRowCount) 2251 { 2252 SCROW nFilteredRow = rFlags.GetFirstForCondition( 2253 nBegRow, nEndRow, CR_FILTERED, CR_FILTERED); 2254 2255 SCROW nRow = nFilteredRow - 1; 2256 if (nRow - nBegRow + 1 > nRowCount) 2257 // make sure the row range stays within the data size. 2258 nRow = nBegRow + nRowCount - 1; 2259 2260 return nRow; 2261 } 2262 2263 void ScDocument::CopyMultiRangeFromClip( 2264 const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc, 2265 bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty) 2266 { 2267 if (bIsClip) 2268 return; 2269 2270 if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount()) 2271 // There is nothing in the clip doc to copy. 2272 return; 2273 2274 sal_Bool bOldAutoCalc = GetAutoCalc(); 2275 SetAutoCalc( sal_False ); // avoid multiple recalculations 2276 2277 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc); 2278 2279 ScClipRangeNameData aClipRangeNames; 2280 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames); 2281 2282 SCCOL nCol1 = rDestPos.Col(); 2283 SCROW nRow1 = rDestPos.Row(); 2284 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 2285 2286 ScCopyBlockFromClipParams aCBFCP; 2287 aCBFCP.pRefUndoDoc = NULL; 2288 aCBFCP.pClipDoc = pClipDoc; 2289 aCBFCP.nInsFlag = nInsFlag; 2290 aCBFCP.bAsLink = bAsLink; 2291 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty; 2292 aCBFCP.nTabStart = MAXTAB; 2293 aCBFCP.nTabEnd = 0; 2294 2295 for (SCTAB j = 0; j <= MAXTAB; ++j) 2296 { 2297 if (pTab[j] && rMark.GetTableSelect(j)) 2298 { 2299 if ( j < aCBFCP.nTabStart ) 2300 aCBFCP.nTabStart = j; 2301 aCBFCP.nTabEnd = j; 2302 pTab[j]->IncRecalcLevel(); 2303 } 2304 } 2305 2306 ScRange aDestRange; 2307 rMark.GetMarkArea(aDestRange); 2308 SCROW nLastMarkedRow = aDestRange.aEnd.Row(); 2309 2310 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert 2311 2312 SCROW nBegRow = nRow1; 2313 sal_uInt16 nDelFlag = IDF_CONTENTS; 2314 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags = GetRowFlagsArray(aCBFCP.nTabStart); 2315 2316 for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next()) 2317 { 2318 // The begin row must not be filtered. 2319 2320 SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1; 2321 2322 SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col()); 2323 SCsROW nDy = static_cast<SCsROW>(nBegRow - p->aStart.Row()); 2324 SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col(); 2325 2326 SCROW nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount); 2327 2328 if (!bSkipAttrForEmpty) 2329 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag); 2330 2331 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP); 2332 nRowCount -= nEndRow - nBegRow + 1; 2333 2334 while (nRowCount > 0) 2335 { 2336 // Get the first non-filtered row. 2337 SCROW nNonFilteredRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0); 2338 if (nNonFilteredRow > nLastMarkedRow) 2339 return; 2340 2341 SCROW nRowsSkipped = nNonFilteredRow - nEndRow - 1; 2342 nDy += nRowsSkipped; 2343 2344 nBegRow = nNonFilteredRow; 2345 nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount); 2346 2347 if (!bSkipAttrForEmpty) 2348 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag); 2349 2350 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP); 2351 nRowCount -= nEndRow - nBegRow + 1; 2352 } 2353 2354 if (rClipParam.meDirection == ScClipParam::Row) 2355 // Begin row for the next range being pasted. 2356 nBegRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0); 2357 else 2358 nBegRow = nRow1; 2359 2360 if (rClipParam.meDirection == ScClipParam::Column) 2361 nCol1 += p->aEnd.Col() - p->aStart.Col() + 1; 2362 } 2363 2364 for (SCTAB i = 0; i <= MAXTAB; i++) 2365 if (pTab[i] && rMark.GetTableSelect(i)) 2366 pTab[i]->DecRecalcLevel(); 2367 2368 bInsertingFromOtherDoc = sal_False; 2369 2370 ScRangeList aRanges; 2371 aRanges.Append(aDestRange); 2372 SCCOL nCols = aDestRange.aEnd.Col() - aDestRange.aStart.Col() + 1; 2373 SCROW nRows = aDestRange.aEnd.Row() - aDestRange.aStart.Row() + 1; 2374 UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1); 2375 2376 // Listener aufbauen nachdem alles inserted wurde 2377 StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(), 2378 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag ); 2379 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden 2380 BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(), 2381 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag ); 2382 2383 if (bResetCut) 2384 pClipDoc->GetClipParam().mbCutMode = false; 2385 SetAutoCalc( bOldAutoCalc ); 2386 } 2387 2388 void ScDocument::SetClipArea( const ScRange& rArea, sal_Bool bCut ) 2389 { 2390 if (bIsClip) 2391 { 2392 ScClipParam& rClipParam = GetClipParam(); 2393 rClipParam.maRanges.RemoveAll(); 2394 rClipParam.maRanges.Append(rArea); 2395 rClipParam.mbCutMode = bCut; 2396 } 2397 else 2398 { 2399 DBG_ERROR("SetClipArea: kein Clip"); 2400 } 2401 } 2402 2403 2404 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, sal_Bool bIncludeFiltered) 2405 { 2406 if (!bIsClip) 2407 { 2408 DBG_ERROR("GetClipArea: kein Clip"); 2409 return; 2410 } 2411 2412 ScRangeList& rClipRanges = GetClipParam().maRanges; 2413 if (!rClipRanges.Count()) 2414 // No clip range. Bail out. 2415 return; 2416 2417 ScRangePtr p = rClipRanges.First(); 2418 SCCOL nStartCol = p->aStart.Col(); 2419 SCCOL nEndCol = p->aEnd.Col(); 2420 SCROW nStartRow = p->aStart.Row(); 2421 SCROW nEndRow = p->aEnd.Row(); 2422 for (p = rClipRanges.Next(); p; p = rClipRanges.Next()) 2423 { 2424 if (p->aStart.Col() < nStartCol) 2425 nStartCol = p->aStart.Col(); 2426 if (p->aStart.Row() < nStartRow) 2427 nStartRow = p->aStart.Row(); 2428 if (p->aEnd.Col() > nEndCol) 2429 nEndCol = p->aEnd.Col(); 2430 if (p->aEnd.Row() < nEndRow) 2431 nEndRow = p->aEnd.Row(); 2432 } 2433 2434 nClipX = nEndCol - nStartCol; 2435 2436 if ( bIncludeFiltered ) 2437 nClipY = nEndRow - nStartRow; 2438 else 2439 { 2440 // count non-filtered rows 2441 // count on first used table in clipboard 2442 SCTAB nCountTab = 0; 2443 while ( nCountTab < MAXTAB && !pTab[nCountTab] ) 2444 ++nCountTab; 2445 2446 SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab); 2447 2448 if ( nResult > 0 ) 2449 nClipY = nResult - 1; 2450 else 2451 nClipY = 0; // always return at least 1 row 2452 } 2453 } 2454 2455 2456 void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY) 2457 { 2458 if (bIsClip) 2459 { 2460 ScRangeList& rClipRanges = GetClipParam().maRanges; 2461 if (rClipRanges.Count()) 2462 { 2463 nClipX = rClipRanges.First()->aStart.Col(); 2464 nClipY = rClipRanges.First()->aStart.Row(); 2465 } 2466 } 2467 else 2468 { 2469 DBG_ERROR("GetClipStart: kein Clip"); 2470 } 2471 } 2472 2473 2474 sal_Bool ScDocument::HasClipFilteredRows() 2475 { 2476 // count on first used table in clipboard 2477 SCTAB nCountTab = 0; 2478 while ( nCountTab < MAXTAB && !pTab[nCountTab] ) 2479 ++nCountTab; 2480 2481 ScRangeList& rClipRanges = GetClipParam().maRanges; 2482 if (!rClipRanges.Count()) 2483 return false; 2484 2485 for (ScRange* p = rClipRanges.First(); p; p = rClipRanges.Next()) 2486 { 2487 bool bAnswer = pTab[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row()); 2488 if (bAnswer) 2489 return true; 2490 } 2491 return false; 2492 } 2493 2494 2495 void ScDocument::MixDocument( const ScRange& rRange, sal_uInt16 nFunction, sal_Bool bSkipEmpty, 2496 ScDocument* pSrcDoc ) 2497 { 2498 SCTAB nTab1 = rRange.aStart.Tab(); 2499 SCTAB nTab2 = rRange.aEnd.Tab(); 2500 for (SCTAB i = nTab1; i <= nTab2; i++) 2501 if (pTab[i] && pSrcDoc->pTab[i]) 2502 pTab[i]->MixData( rRange.aStart.Col(), rRange.aStart.Row(), 2503 rRange.aEnd.Col(), rRange.aEnd.Row(), 2504 nFunction, bSkipEmpty, pSrcDoc->pTab[i] ); 2505 } 2506 2507 2508 void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark, 2509 sal_uInt16 nFlags, sal_uInt16 nFunction, 2510 sal_Bool bSkipEmpty, sal_Bool bAsLink ) 2511 { 2512 sal_uInt16 nDelFlags = nFlags; 2513 if (nDelFlags & IDF_CONTENTS) 2514 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen! 2515 2516 SCTAB nSrcTab = rSrcArea.aStart.Tab(); 2517 2518 if (ValidTab(nSrcTab) && pTab[nSrcTab]) 2519 { 2520 SCCOL nStartCol = rSrcArea.aStart.Col(); 2521 SCROW nStartRow = rSrcArea.aStart.Row(); 2522 SCCOL nEndCol = rSrcArea.aEnd.Col(); 2523 SCROW nEndRow = rSrcArea.aEnd.Row(); 2524 ScDocument* pMixDoc = NULL; 2525 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS ); 2526 2527 sal_Bool bOldAutoCalc = GetAutoCalc(); 2528 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 2529 2530 SCTAB nCount = GetTableCount(); 2531 for (SCTAB i=0; i<nCount; i++) 2532 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) ) 2533 { 2534 if (bDoMix) 2535 { 2536 if (!pMixDoc) 2537 { 2538 pMixDoc = new ScDocument( SCDOCMODE_UNDO ); 2539 pMixDoc->InitUndo( this, i, i ); 2540 } 2541 else 2542 pMixDoc->AddUndoTab( i, i ); 2543 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2544 IDF_CONTENTS, sal_False, pMixDoc->pTab[i] ); 2545 } 2546 pTab[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags); 2547 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2548 nFlags, sal_False, pTab[i], NULL, bAsLink ); 2549 2550 if (bDoMix) 2551 pTab[i]->MixData( nStartCol,nStartRow, nEndCol,nEndRow, 2552 nFunction, bSkipEmpty, pMixDoc->pTab[i] ); 2553 } 2554 2555 delete pMixDoc; 2556 2557 SetAutoCalc( bOldAutoCalc ); 2558 } 2559 else 2560 { 2561 DBG_ERROR("falsche Tabelle"); 2562 } 2563 } 2564 2565 2566 void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark, 2567 sal_uInt16 nFlags, sal_uInt16 nFunction, 2568 sal_Bool bSkipEmpty, sal_Bool bAsLink ) 2569 { 2570 sal_uInt16 nDelFlags = nFlags; 2571 if (nDelFlags & IDF_CONTENTS) 2572 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen! 2573 2574 if (ValidTab(nSrcTab) && pTab[nSrcTab]) 2575 { 2576 ScDocument* pMixDoc = NULL; 2577 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS ); 2578 2579 sal_Bool bOldAutoCalc = GetAutoCalc(); 2580 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 2581 2582 ScRange aArea; 2583 rMark.GetMultiMarkArea( aArea ); 2584 SCCOL nStartCol = aArea.aStart.Col(); 2585 SCROW nStartRow = aArea.aStart.Row(); 2586 SCCOL nEndCol = aArea.aEnd.Col(); 2587 SCROW nEndRow = aArea.aEnd.Row(); 2588 2589 SCTAB nCount = GetTableCount(); 2590 for (SCTAB i=0; i<nCount; i++) 2591 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) ) 2592 { 2593 if (bDoMix) 2594 { 2595 if (!pMixDoc) 2596 { 2597 pMixDoc = new ScDocument( SCDOCMODE_UNDO ); 2598 pMixDoc->InitUndo( this, i, i ); 2599 } 2600 else 2601 pMixDoc->AddUndoTab( i, i ); 2602 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2603 IDF_CONTENTS, sal_True, pMixDoc->pTab[i], &rMark ); 2604 } 2605 2606 pTab[i]->DeleteSelection( nDelFlags, rMark ); 2607 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2608 nFlags, sal_True, pTab[i], &rMark, bAsLink ); 2609 2610 if (bDoMix) 2611 pTab[i]->MixMarked( rMark, nFunction, bSkipEmpty, pMixDoc->pTab[i] ); 2612 } 2613 2614 delete pMixDoc; 2615 2616 SetAutoCalc( bOldAutoCalc ); 2617 } 2618 else 2619 { 2620 DBG_ERROR("falsche Tabelle"); 2621 } 2622 } 2623 2624 2625 void ScDocument::PutCell( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* pCell, sal_Bool bForceTab ) 2626 { 2627 if (VALIDTAB(nTab)) 2628 { 2629 if ( bForceTab && !pTab[nTab] ) 2630 { 2631 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags 2632 2633 pTab[nTab] = new ScTable(this, nTab, 2634 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")), 2635 bExtras, bExtras); 2636 ++nMaxTableNumber; 2637 } 2638 2639 if (pTab[nTab]) 2640 pTab[nTab]->PutCell( nCol, nRow, pCell ); 2641 } 2642 } 2643 2644 2645 void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell, sal_Bool bForceTab ) 2646 { 2647 SCTAB nTab = rPos.Tab(); 2648 if ( bForceTab && !pTab[nTab] ) 2649 { 2650 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags 2651 2652 pTab[nTab] = new ScTable(this, nTab, 2653 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")), 2654 bExtras, bExtras); 2655 ++nMaxTableNumber; 2656 } 2657 2658 if (pTab[nTab]) 2659 pTab[nTab]->PutCell( rPos, pCell ); 2660 } 2661 2662 2663 sal_Bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString, 2664 SvNumberFormatter* pFormatter, bool bDetectNumberFormat ) 2665 { 2666 if ( ValidTab(nTab) && pTab[nTab] ) 2667 return pTab[nTab]->SetString( nCol, nRow, nTab, rString, pFormatter, bDetectNumberFormat ); 2668 else 2669 return sal_False; 2670 } 2671 2672 2673 void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal ) 2674 { 2675 if (VALIDTAB(nTab)) 2676 if (pTab[nTab]) 2677 pTab[nTab]->SetValue( nCol, nRow, rVal ); 2678 } 2679 2680 2681 void ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString ) 2682 { 2683 if ( VALIDTAB(nTab) && pTab[nTab] ) 2684 pTab[nTab]->GetString( nCol, nRow, rString ); 2685 else 2686 rString.Erase(); 2687 } 2688 2689 2690 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString ) 2691 { 2692 if ( VALIDTAB(nTab) && pTab[nTab] ) 2693 pTab[nTab]->GetInputString( nCol, nRow, rString ); 2694 else 2695 rString.Erase(); 2696 } 2697 2698 2699 sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, rtl::OUString& rString ) 2700 { 2701 // Used in formulas (add-in parameters etc), so it must use the same semantics as 2702 // ScInterpreter::GetCellString: always format values as numbers. 2703 // The return value is the error code. 2704 2705 sal_uInt16 nErr = 0; 2706 String aStr; 2707 ScBaseCell* pCell = GetCell( rPos ); 2708 if (pCell) 2709 { 2710 SvNumberFormatter* pFormatter = GetFormatTable(); 2711 switch (pCell->GetCellType()) 2712 { 2713 case CELLTYPE_STRING: 2714 static_cast<ScStringCell*>(pCell)->GetString(aStr); 2715 break; 2716 case CELLTYPE_EDIT: 2717 static_cast<ScEditCell*>(pCell)->GetString(aStr); 2718 break; 2719 case CELLTYPE_FORMULA: 2720 { 2721 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); 2722 nErr = pFCell->GetErrCode(); 2723 if (pFCell->IsValue()) 2724 { 2725 double fVal = pFCell->GetValue(); 2726 sal_uInt32 nIndex = pFormatter->GetStandardFormat( 2727 NUMBERFORMAT_NUMBER, 2728 ScGlobal::eLnge); 2729 pFormatter->GetInputLineString(fVal, nIndex, aStr); 2730 } 2731 else 2732 pFCell->GetString(aStr); 2733 } 2734 break; 2735 case CELLTYPE_VALUE: 2736 { 2737 double fVal = static_cast<ScValueCell*>(pCell)->GetValue(); 2738 sal_uInt32 nIndex = pFormatter->GetStandardFormat( 2739 NUMBERFORMAT_NUMBER, 2740 ScGlobal::eLnge); 2741 pFormatter->GetInputLineString(fVal, nIndex, aStr); 2742 } 2743 break; 2744 default: 2745 ; 2746 } 2747 } 2748 rString = aStr; 2749 return nErr; 2750 } 2751 2752 2753 void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue ) 2754 { 2755 if ( VALIDTAB(nTab) && pTab[nTab] ) 2756 rValue = pTab[nTab]->GetValue( nCol, nRow ); 2757 else 2758 rValue = 0.0; 2759 } 2760 2761 2762 double ScDocument::GetValue( const ScAddress& rPos ) 2763 { 2764 SCTAB nTab = rPos.Tab(); 2765 if ( pTab[nTab] ) 2766 return pTab[nTab]->GetValue( rPos ); 2767 return 0.0; 2768 } 2769 2770 2771 void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab, 2772 sal_uInt32& rFormat ) 2773 { 2774 if (VALIDTAB(nTab)) 2775 if (pTab[nTab]) 2776 { 2777 rFormat = pTab[nTab]->GetNumberFormat( nCol, nRow ); 2778 return ; 2779 } 2780 rFormat = 0; 2781 } 2782 2783 2784 sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const 2785 { 2786 SCTAB nTab = rPos.Tab(); 2787 if ( pTab[nTab] ) 2788 return pTab[nTab]->GetNumberFormat( rPos ); 2789 return 0; 2790 } 2791 2792 2793 void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex, 2794 const ScAddress& rPos, const ScBaseCell* pCell ) const 2795 { 2796 SCTAB nTab = rPos.Tab(); 2797 if ( pTab[nTab] ) 2798 { 2799 nIndex = pTab[nTab]->GetNumberFormat( rPos ); 2800 if ( (nIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && pCell && 2801 pCell->GetCellType() == CELLTYPE_FORMULA ) 2802 static_cast<const ScFormulaCell*>(pCell)->GetFormatInfo( nType, nIndex ); 2803 else 2804 nType = GetFormatTable()->GetType( nIndex ); 2805 } 2806 else 2807 { 2808 nType = NUMBERFORMAT_UNDEFINED; 2809 nIndex = 0; 2810 } 2811 } 2812 2813 2814 void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rFormula, 2815 sal_Bool bAsciiExport ) const 2816 { 2817 if ( VALIDTAB(nTab) && pTab[nTab] ) 2818 pTab[nTab]->GetFormula( nCol, nRow, rFormula, bAsciiExport ); 2819 else 2820 rFormula.Erase(); 2821 } 2822 2823 2824 CellType ScDocument::GetCellType( const ScAddress& rPos ) const 2825 { 2826 SCTAB nTab = rPos.Tab(); 2827 if ( pTab[nTab] ) 2828 return pTab[nTab]->GetCellType( rPos ); 2829 return CELLTYPE_NONE; 2830 } 2831 2832 2833 void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab, 2834 CellType& rCellType ) const 2835 { 2836 if (ValidTab(nTab) && pTab[nTab]) 2837 rCellType = pTab[nTab]->GetCellType( nCol, nRow ); 2838 else 2839 rCellType = CELLTYPE_NONE; 2840 } 2841 2842 2843 void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab, 2844 ScBaseCell*& rpCell ) const 2845 { 2846 if (ValidTab(nTab) && pTab[nTab]) 2847 rpCell = pTab[nTab]->GetCell( nCol, nRow ); 2848 else 2849 { 2850 DBG_ERROR("GetCell ohne Tabelle"); 2851 rpCell = NULL; 2852 } 2853 } 2854 2855 2856 ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const 2857 { 2858 SCTAB nTab = rPos.Tab(); 2859 if (ValidTab(nTab) && pTab[nTab]) 2860 return pTab[nTab]->GetCell( rPos ); 2861 2862 DBG_ERROR("GetCell ohne Tabelle"); 2863 return NULL; 2864 } 2865 2866 2867 sal_Bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2868 { 2869 if ( VALIDTAB(nTab) && pTab[nTab] ) 2870 return pTab[nTab]->HasStringData( nCol, nRow ); 2871 else 2872 return sal_False; 2873 } 2874 2875 2876 sal_Bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2877 { 2878 if ( VALIDTAB(nTab) && pTab[nTab] ) 2879 return pTab[nTab]->HasValueData( nCol, nRow ); 2880 else 2881 return sal_False; 2882 } 2883 2884 2885 sal_Bool ScDocument::HasStringCells( const ScRange& rRange ) const 2886 { 2887 // sal_True, wenn String- oder Editzellen im Bereich 2888 2889 SCCOL nStartCol = rRange.aStart.Col(); 2890 SCROW nStartRow = rRange.aStart.Row(); 2891 SCTAB nStartTab = rRange.aStart.Tab(); 2892 SCCOL nEndCol = rRange.aEnd.Col(); 2893 SCROW nEndRow = rRange.aEnd.Row(); 2894 SCTAB nEndTab = rRange.aEnd.Tab(); 2895 2896 for ( SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++ ) 2897 if ( pTab[nTab] && pTab[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) ) 2898 return sal_True; 2899 2900 return sal_False; 2901 } 2902 2903 2904 sal_Bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2905 { 2906 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue(); 2907 if( nValidation ) 2908 { 2909 const ScValidationData* pData = GetValidationEntry( nValidation ); 2910 if( pData && pData->HasSelectionList() ) 2911 return sal_True; 2912 } 2913 return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) ); 2914 } 2915 2916 2917 ScPostIt* ScDocument::GetNote( const ScAddress& rPos ) 2918 { 2919 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0; 2920 return pTable ? pTable->GetNote( rPos.Col(), rPos.Row() ) : 0; 2921 } 2922 2923 2924 void ScDocument::TakeNote( const ScAddress& rPos, ScPostIt*& rpNote ) 2925 { 2926 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] ) 2927 pTab[ rPos.Tab() ]->TakeNote( rPos.Col(), rPos.Row(), rpNote ); 2928 else 2929 DELETEZ( rpNote ); 2930 } 2931 2932 2933 ScPostIt* ScDocument::ReleaseNote( const ScAddress& rPos ) 2934 { 2935 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0; 2936 return pTable ? pTable->ReleaseNote( rPos.Col(), rPos.Row() ) : 0; 2937 } 2938 2939 2940 ScPostIt* ScDocument::GetOrCreateNote( const ScAddress& rPos ) 2941 { 2942 ScPostIt* pNote = GetNote( rPos ); 2943 if( !pNote ) 2944 { 2945 pNote = new ScPostIt( *this, rPos, false ); 2946 TakeNote( rPos, pNote ); 2947 } 2948 return pNote; 2949 } 2950 2951 2952 void ScDocument::DeleteNote( const ScAddress& rPos ) 2953 { 2954 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] ) 2955 pTab[ rPos.Tab() ]->DeleteNote( rPos.Col(), rPos.Row() ); 2956 } 2957 2958 2959 void ScDocument::InitializeNoteCaptions( SCTAB nTab, bool bForced ) 2960 { 2961 if( ValidTab( nTab ) && pTab[ nTab ] ) 2962 pTab[ nTab ]->InitializeNoteCaptions( bForced ); 2963 } 2964 2965 void ScDocument::InitializeAllNoteCaptions( bool bForced ) 2966 { 2967 for( SCTAB nTab = 0; nTab < GetTableCount(); ++nTab ) 2968 InitializeNoteCaptions( nTab, bForced ); 2969 } 2970 2971 void ScDocument::SetDirty() 2972 { 2973 sal_Bool bOldAutoCalc = GetAutoCalc(); 2974 bAutoCalc = sal_False; // keine Mehrfachberechnung 2975 { // scope for bulk broadcast 2976 ScBulkBroadcast aBulkBroadcast( GetBASM()); 2977 for (SCTAB i=0; i<=MAXTAB; i++) 2978 if (pTab[i]) pTab[i]->SetDirty(); 2979 } 2980 2981 // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt, 2982 // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt 2983 // (#45205#) - darum alle Charts nochmal explizit 2984 if (pChartListenerCollection) 2985 pChartListenerCollection->SetDirty(); 2986 2987 SetAutoCalc( bOldAutoCalc ); 2988 } 2989 2990 2991 void ScDocument::SetDirty( const ScRange& rRange ) 2992 { 2993 sal_Bool bOldAutoCalc = GetAutoCalc(); 2994 bAutoCalc = sal_False; // keine Mehrfachberechnung 2995 { // scope for bulk broadcast 2996 ScBulkBroadcast aBulkBroadcast( GetBASM()); 2997 SCTAB nTab2 = rRange.aEnd.Tab(); 2998 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++) 2999 if (pTab[i]) pTab[i]->SetDirty( rRange ); 3000 } 3001 SetAutoCalc( bOldAutoCalc ); 3002 } 3003 3004 3005 void ScDocument::SetTableOpDirty( const ScRange& rRange ) 3006 { 3007 sal_Bool bOldAutoCalc = GetAutoCalc(); 3008 bAutoCalc = sal_False; // no multiple recalculation 3009 SCTAB nTab2 = rRange.aEnd.Tab(); 3010 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++) 3011 if (pTab[i]) pTab[i]->SetTableOpDirty( rRange ); 3012 SetAutoCalc( bOldAutoCalc ); 3013 } 3014 3015 3016 void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges ) 3017 { 3018 sal_uLong nRangeCount = rRanges.Count(); 3019 for (sal_uLong nPos=0; nPos<nRangeCount; nPos++) 3020 { 3021 ScCellIterator aIter( this, *rRanges.GetObject(nPos) ); 3022 ScBaseCell* pCell = aIter.GetFirst(); 3023 while (pCell) 3024 { 3025 if (pCell->GetCellType() == CELLTYPE_FORMULA) 3026 { 3027 if ( static_cast<ScFormulaCell*>(pCell)->GetDirty() && GetAutoCalc() ) 3028 static_cast<ScFormulaCell*>(pCell)->Interpret(); 3029 } 3030 pCell = aIter.GetNext(); 3031 } 3032 } 3033 } 3034 3035 3036 void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell ) 3037 { 3038 ScInterpreterTableOpParams* p = aTableOpList.Last(); 3039 if ( p && p->bCollectNotifications ) 3040 { 3041 if ( p->bRefresh ) 3042 { // refresh pointers only 3043 p->aNotifiedFormulaCells.push_back( pCell ); 3044 } 3045 else 3046 { // init both, address and pointer 3047 p->aNotifiedFormulaCells.push_back( pCell ); 3048 p->aNotifiedFormulaPos.push_back( pCell->aPos ); 3049 } 3050 } 3051 } 3052 3053 3054 void ScDocument::CalcAll() 3055 { 3056 ClearLookupCaches(); // Ensure we don't deliver zombie data. 3057 sal_Bool bOldAutoCalc = GetAutoCalc(); 3058 SetAutoCalc( sal_True ); 3059 SCTAB i; 3060 for (i=0; i<=MAXTAB; i++) 3061 if (pTab[i]) pTab[i]->SetDirtyVar(); 3062 for (i=0; i<=MAXTAB; i++) 3063 if (pTab[i]) pTab[i]->CalcAll(); 3064 ClearFormulaTree(); 3065 SetAutoCalc( bOldAutoCalc ); 3066 } 3067 3068 3069 void ScDocument::CompileAll() 3070 { 3071 if ( pCondFormList ) 3072 pCondFormList->CompileAll(); 3073 3074 for (SCTAB i=0; i<=MAXTAB; i++) 3075 if (pTab[i]) pTab[i]->CompileAll(); 3076 SetDirty(); 3077 } 3078 3079 3080 void ScDocument::CompileXML() 3081 { 3082 sal_Bool bOldAutoCalc = GetAutoCalc(); 3083 SetAutoCalc( sal_False ); 3084 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString( 3085 STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() ); 3086 3087 // #b6355215# set AutoNameCache to speed up automatic name lookup 3088 DBG_ASSERT( !pAutoNameCache, "AutoNameCache already set" ); 3089 pAutoNameCache = new ScAutoNameCache( this ); 3090 3091 for (SCTAB i=0; i<=MAXTAB; i++) 3092 if (pTab[i]) pTab[i]->CompileXML( aProgress ); 3093 3094 DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change 3095 3096 if ( pCondFormList ) 3097 pCondFormList->CompileXML(); 3098 if ( pValidationList ) 3099 pValidationList->CompileXML(); 3100 3101 SetDirty(); 3102 SetAutoCalc( bOldAutoCalc ); 3103 } 3104 3105 3106 void ScDocument::CalcAfterLoad() 3107 { 3108 SCTAB i; 3109 3110 if (bIsClip) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen 3111 return; // dann wird erst beim Einfuegen in das richtige Doc berechnet 3112 3113 bCalcingAfterLoad = sal_True; 3114 for ( i = 0; i <= MAXTAB; i++) 3115 if (pTab[i]) pTab[i]->CalcAfterLoad(); 3116 for (i=0; i<=MAXTAB; i++) 3117 if (pTab[i]) pTab[i]->SetDirtyAfterLoad(); 3118 bCalcingAfterLoad = sal_False; 3119 3120 SetDetectiveDirty(sal_False); // noch keine wirklichen Aenderungen 3121 3122 // #i112436# If formula cells are already dirty, they don't broadcast further changes. 3123 // So the source ranges of charts must be interpreted even if they are not visible, 3124 // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899). 3125 if (pChartListenerCollection) 3126 { 3127 sal_uInt16 nChartCount = pChartListenerCollection->GetCount(); 3128 for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ ) 3129 { 3130 ScChartListener* pChartListener = static_cast<ScChartListener*>(pChartListenerCollection->At(nIndex)); 3131 InterpretDirtyCells(*pChartListener->GetRangeList()); 3132 } 3133 } 3134 } 3135 3136 3137 sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const 3138 { 3139 SCTAB nTab = rPos.Tab(); 3140 if ( pTab[nTab] ) 3141 return pTab[nTab]->GetErrCode( rPos ); 3142 return 0; 3143 } 3144 3145 3146 void ScDocument::ResetChanged( const ScRange& rRange ) 3147 { 3148 SCTAB nStartTab = rRange.aStart.Tab(); 3149 SCTAB nEndTab = rRange.aEnd.Tab(); 3150 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3151 if (pTab[nTab]) 3152 pTab[nTab]->ResetChanged( rRange ); 3153 } 3154 3155 // 3156 // Spaltenbreiten / Zeilenhoehen -------------------------------------- 3157 // 3158 3159 3160 void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth ) 3161 { 3162 if ( ValidTab(nTab) && pTab[nTab] ) 3163 pTab[nTab]->SetColWidth( nCol, nNewWidth ); 3164 } 3165 3166 3167 void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3168 { 3169 if ( ValidTab(nTab) && pTab[nTab] ) 3170 pTab[nTab]->SetRowHeight( nRow, nNewHeight ); 3171 } 3172 3173 3174 void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3175 { 3176 if ( ValidTab(nTab) && pTab[nTab] ) 3177 pTab[nTab]->SetRowHeightRange 3178 ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 ); 3179 } 3180 3181 void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3182 { 3183 if ( ValidTab(nTab) && pTab[nTab] ) 3184 pTab[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight ); 3185 } 3186 3187 void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_Bool bManual ) 3188 { 3189 if ( ValidTab(nTab) && pTab[nTab] ) 3190 pTab[nTab]->SetManualHeight( nStartRow, nEndRow, bManual ); 3191 } 3192 3193 3194 sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab ) const 3195 { 3196 if ( ValidTab(nTab) && pTab[nTab] ) 3197 return pTab[nTab]->GetColWidth( nCol ); 3198 DBG_ERROR("Falsche Tabellennummer"); 3199 return 0; 3200 } 3201 3202 3203 sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const 3204 { 3205 if ( ValidTab(nTab) && pTab[nTab] ) 3206 return pTab[nTab]->GetOriginalWidth( nCol ); 3207 DBG_ERROR("Falsche Tabellennummer"); 3208 return 0; 3209 } 3210 3211 3212 sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const 3213 { 3214 if ( ValidTab(nTab) && pTab[nTab] ) 3215 return pTab[nTab]->GetCommonWidth( nEndCol ); 3216 DBG_ERROR("Wrong table number"); 3217 return 0; 3218 } 3219 3220 3221 sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const 3222 { 3223 if ( ValidTab(nTab) && pTab[nTab] ) 3224 return pTab[nTab]->GetOriginalHeight( nRow ); 3225 DBG_ERROR("Wrong table number"); 3226 return 0; 3227 } 3228 3229 3230 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const 3231 { 3232 if ( ValidTab(nTab) && pTab[nTab] ) 3233 return pTab[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero ); 3234 DBG_ERROR("Wrong sheet number"); 3235 return 0; 3236 } 3237 3238 3239 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const 3240 { 3241 if ( ValidTab(nTab) && pTab[nTab] ) 3242 return pTab[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero ); 3243 DBG_ERROR("Wrong sheet number"); 3244 return 0; 3245 } 3246 3247 3248 sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const 3249 { 3250 if (nStartRow == nEndRow) 3251 return GetRowHeight( nStartRow, nTab); // faster for a single row 3252 3253 // check bounds because this method replaces former for(i=start;i<=end;++i) loops 3254 if (nStartRow > nEndRow) 3255 return 0; 3256 3257 if ( ValidTab(nTab) && pTab[nTab] ) 3258 return pTab[nTab]->GetRowHeight( nStartRow, nEndRow); 3259 3260 DBG_ERROR("wrong sheet number"); 3261 return 0; 3262 } 3263 3264 SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const 3265 { 3266 return pTab[nTab]->GetRowForHeight(nHeight); 3267 } 3268 3269 sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, 3270 SCTAB nTab, double fScale ) const 3271 { 3272 // faster for a single row 3273 if (nStartRow == nEndRow) 3274 return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale); 3275 3276 // check bounds because this method replaces former for(i=start;i<=end;++i) loops 3277 if (nStartRow > nEndRow) 3278 return 0; 3279 3280 if ( ValidTab(nTab) && pTab[nTab] ) 3281 return pTab[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale); 3282 3283 DBG_ERROR("wrong sheet number"); 3284 return 0; 3285 } 3286 3287 SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const 3288 { 3289 if ( ValidTab(nTab) && pTab[nTab] ) 3290 return pTab[nTab]->GetHiddenRowCount( nRow ); 3291 DBG_ERROR("Falsche Tabellennummer"); 3292 return 0; 3293 } 3294 3295 3296 sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab ) const 3297 { 3298 if ( ValidTab(nTab) && pTab[nTab] ) 3299 return pTab[nTab]->GetColOffset( nCol ); 3300 DBG_ERROR("Falsche Tabellennummer"); 3301 return 0; 3302 } 3303 3304 3305 sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab ) const 3306 { 3307 if ( ValidTab(nTab) && pTab[nTab] ) 3308 return pTab[nTab]->GetRowOffset( nRow ); 3309 DBG_ERROR("Falsche Tabellennummer"); 3310 return 0; 3311 } 3312 3313 3314 sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev, 3315 double nPPTX, double nPPTY, 3316 const Fraction& rZoomX, const Fraction& rZoomY, 3317 sal_Bool bFormula, const ScMarkData* pMarkData, 3318 sal_Bool bSimpleTextImport ) 3319 { 3320 if ( ValidTab(nTab) && pTab[nTab] ) 3321 return pTab[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY, 3322 rZoomX, rZoomY, bFormula, pMarkData, bSimpleTextImport ); 3323 DBG_ERROR("Falsche Tabellennummer"); 3324 return 0; 3325 } 3326 3327 3328 long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab, 3329 OutputDevice* pDev, 3330 double nPPTX, double nPPTY, 3331 const Fraction& rZoomX, const Fraction& rZoomY, 3332 sal_Bool bWidth, sal_Bool bTotalSize ) 3333 { 3334 if ( ValidTab(nTab) && pTab[nTab] ) 3335 return pTab[nTab]->GetNeededSize 3336 ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize ); 3337 DBG_ERROR("Falsche Tabellennummer"); 3338 return 0; 3339 } 3340 3341 3342 sal_Bool ScDocument::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nExtra, 3343 OutputDevice* pDev, 3344 double nPPTX, double nPPTY, 3345 const Fraction& rZoomX, const Fraction& rZoomY, 3346 sal_Bool bShrink ) 3347 { 3348 //! MarkToMulti(); 3349 if ( ValidTab(nTab) && pTab[nTab] ) 3350 return pTab[nTab]->SetOptimalHeight( nStartRow, nEndRow, nExtra, 3351 pDev, nPPTX, nPPTY, rZoomX, rZoomY, bShrink ); 3352 DBG_ERROR("Falsche Tabellennummer"); 3353 return sal_False; 3354 } 3355 3356 3357 void ScDocument::UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY, 3358 const Fraction& rZoomX, const Fraction& rZoomY, const ScMarkData* pTabMark ) 3359 { 3360 // one progress across all (selected) sheets 3361 3362 sal_uLong nCellCount = 0; 3363 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 3364 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) 3365 nCellCount += pTab[nTab]->GetWeightedCount(); 3366 3367 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount ); 3368 3369 sal_uLong nProgressStart = 0; 3370 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 3371 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) 3372 { 3373 pTab[nTab]->SetOptimalHeight( 0, MAXROW, 0, 3374 pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False, &aProgress, nProgressStart ); 3375 nProgressStart += pTab[nTab]->GetWeightedCount(); 3376 } 3377 } 3378 3379 3380 // 3381 // Spalten-/Zeilen-Flags ---------------------------------------------- 3382 // 3383 3384 void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, sal_Bool bShow) 3385 { 3386 if ( ValidTab(nTab) && pTab[nTab] ) 3387 pTab[nTab]->ShowCol( nCol, bShow ); 3388 } 3389 3390 3391 void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, sal_Bool bShow) 3392 { 3393 if ( ValidTab(nTab) && pTab[nTab] ) 3394 pTab[nTab]->ShowRow( nRow, bShow ); 3395 } 3396 3397 3398 void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, sal_Bool bShow) 3399 { 3400 if ( ValidTab(nTab) && pTab[nTab] ) 3401 pTab[nTab]->ShowRows( nRow1, nRow2, bShow ); 3402 } 3403 3404 3405 void ScDocument::SetColFlags( SCCOL nCol, SCTAB nTab, sal_uInt8 nNewFlags ) 3406 { 3407 if ( ValidTab(nTab) && pTab[nTab] ) 3408 pTab[nTab]->SetColFlags( nCol, nNewFlags ); 3409 } 3410 3411 3412 void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags ) 3413 { 3414 if ( ValidTab(nTab) && pTab[nTab] ) 3415 pTab[nTab]->SetRowFlags( nRow, nNewFlags ); 3416 } 3417 3418 3419 void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags ) 3420 { 3421 if ( ValidTab(nTab) && pTab[nTab] ) 3422 pTab[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags ); 3423 } 3424 3425 3426 sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const 3427 { 3428 if ( ValidTab(nTab) && pTab[nTab] ) 3429 return pTab[nTab]->GetColFlags( nCol ); 3430 DBG_ERROR("Falsche Tabellennummer"); 3431 return 0; 3432 } 3433 3434 sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const 3435 { 3436 if ( ValidTab(nTab) && pTab[nTab] ) 3437 return pTab[nTab]->GetRowFlags( nRow ); 3438 DBG_ERROR("Falsche Tabellennummer"); 3439 return 0; 3440 } 3441 3442 ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArrayModifiable( 3443 SCTAB nTab ) 3444 { 3445 return const_cast< ScBitMaskCompressedArray< SCROW, sal_uInt8> & >( 3446 GetRowFlagsArray( nTab)); 3447 } 3448 3449 const ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArray( 3450 SCTAB nTab ) const 3451 { 3452 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pFlags; 3453 if ( ValidTab(nTab) && pTab[nTab] ) 3454 pFlags = pTab[nTab]->GetRowFlagsArray(); 3455 else 3456 { 3457 DBG_ERROR("wrong sheet number"); 3458 pFlags = 0; 3459 } 3460 if (!pFlags) 3461 { 3462 DBG_ERROR("no row flags at sheet"); 3463 static ScBitMaskCompressedArray< SCROW, sal_uInt8> aDummy( MAXROW, 0); 3464 pFlags = &aDummy; 3465 } 3466 return *pFlags; 3467 } 3468 3469 void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const 3470 { 3471 if (!ValidTab(nTab) || !pTab[nTab]) 3472 return; 3473 3474 pTab[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual); 3475 } 3476 3477 void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const 3478 { 3479 if (!ValidTab(nTab) || !pTab[nTab]) 3480 return; 3481 3482 pTab[nTab]->GetAllColBreaks(rBreaks, bPage, bManual); 3483 } 3484 3485 ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const 3486 { 3487 ScBreakType nType = BREAK_NONE; 3488 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3489 return nType; 3490 3491 if (pTab[nTab]->HasRowPageBreak(nRow)) 3492 nType |= BREAK_PAGE; 3493 3494 if (pTab[nTab]->HasRowManualBreak(nRow)) 3495 nType |= BREAK_MANUAL; 3496 3497 return nType; 3498 } 3499 3500 ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const 3501 { 3502 ScBreakType nType = BREAK_NONE; 3503 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3504 return nType; 3505 3506 if (pTab[nTab]->HasColPageBreak(nCol)) 3507 nType |= BREAK_PAGE; 3508 3509 if (pTab[nTab]->HasColManualBreak(nCol)) 3510 nType |= BREAK_MANUAL; 3511 3512 return nType; 3513 } 3514 3515 void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) 3516 { 3517 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3518 return; 3519 3520 pTab[nTab]->SetRowBreak(nRow, bPage, bManual); 3521 } 3522 3523 void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) 3524 { 3525 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3526 return; 3527 3528 pTab[nTab]->SetColBreak(nCol, bPage, bManual); 3529 } 3530 3531 void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) 3532 { 3533 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3534 return; 3535 3536 pTab[nTab]->RemoveRowBreak(nRow, bPage, bManual); 3537 } 3538 3539 void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) 3540 { 3541 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3542 return; 3543 3544 pTab[nTab]->RemoveColBreak(nCol, bPage, bManual); 3545 } 3546 3547 Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const 3548 { 3549 if (!ValidTab(nTab) || !pTab[nTab]) 3550 return Sequence<TablePageBreakData>(); 3551 3552 return pTab[nTab]->GetRowBreakData(); 3553 } 3554 3555 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) 3556 { 3557 if (!ValidTab(nTab) || !pTab[nTab]) 3558 return false; 3559 3560 return pTab[nTab]->RowHidden(nRow, pFirstRow, pLastRow); 3561 } 3562 3563 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastRow) 3564 { 3565 if (!ValidTab(nTab) || !pTab[nTab]) 3566 { 3567 rLastRow = nRow; 3568 return false; 3569 } 3570 3571 return pTab[nTab]->RowHidden(nRow, rLastRow); 3572 } 3573 3574 3575 bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3576 { 3577 if (!ValidTab(nTab) || !pTab[nTab]) 3578 return false; 3579 3580 return pTab[nTab]->HasHiddenRows(nStartRow, nEndRow); 3581 } 3582 3583 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL& rLastCol) 3584 { 3585 if (!ValidTab(nTab) || !pTab[nTab]) 3586 { 3587 rLastCol = nCol; 3588 return false; 3589 } 3590 3591 return pTab[nTab]->ColHidden(nCol, rLastCol); 3592 } 3593 3594 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) 3595 { 3596 if (!ValidTab(nTab) || !pTab[nTab]) 3597 { 3598 if (pFirstCol) 3599 *pFirstCol = nCol; 3600 if (pLastCol) 3601 *pLastCol = nCol; 3602 return false; 3603 } 3604 3605 return pTab[nTab]->ColHidden(nCol, pFirstCol, pLastCol); 3606 } 3607 3608 void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden) 3609 { 3610 if (!ValidTab(nTab) || !pTab[nTab]) 3611 return; 3612 3613 pTab[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden); 3614 } 3615 3616 void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden) 3617 { 3618 if (!ValidTab(nTab) || !pTab[nTab]) 3619 return; 3620 3621 pTab[nTab]->SetColHidden(nStartCol, nEndCol, bHidden); 3622 } 3623 3624 SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3625 { 3626 if (!ValidTab(nTab) || !pTab[nTab]) 3627 return ::std::numeric_limits<SCROW>::max();; 3628 3629 return pTab[nTab]->FirstVisibleRow(nStartRow, nEndRow); 3630 } 3631 3632 SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3633 { 3634 if (!ValidTab(nTab) || !pTab[nTab]) 3635 return ::std::numeric_limits<SCROW>::max();; 3636 3637 return pTab[nTab]->LastVisibleRow(nStartRow, nEndRow); 3638 } 3639 3640 SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3641 { 3642 if (!ValidTab(nTab) || !pTab[nTab]) 3643 return 0; 3644 3645 return pTab[nTab]->CountVisibleRows(nStartRow, nEndRow); 3646 } 3647 3648 bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) 3649 { 3650 if (!ValidTab(nTab) || !pTab[nTab]) 3651 return false; 3652 3653 return pTab[nTab]->RowFiltered(nRow, pFirstRow, pLastRow); 3654 } 3655 3656 bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3657 { 3658 if (!ValidTab(nTab) || !pTab[nTab]) 3659 return false; 3660 3661 return pTab[nTab]->HasFilteredRows(nStartRow, nEndRow); 3662 } 3663 3664 bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) 3665 { 3666 if (!ValidTab(nTab) || !pTab[nTab]) 3667 return false; 3668 3669 return pTab[nTab]->ColFiltered(nCol, pFirstCol, pLastCol); 3670 } 3671 3672 void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered) 3673 { 3674 if (!ValidTab(nTab) || !pTab[nTab]) 3675 return; 3676 3677 pTab[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered); 3678 } 3679 3680 void ScDocument::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bFiltered) 3681 { 3682 if (!ValidTab(nTab) || !pTab[nTab]) 3683 return; 3684 3685 pTab[nTab]->SetColFiltered(nStartCol, nEndCol, bFiltered); 3686 } 3687 3688 SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3689 { 3690 if (!ValidTab(nTab) || !pTab[nTab]) 3691 return ::std::numeric_limits<SCROW>::max();; 3692 3693 return pTab[nTab]->FirstNonFilteredRow(nStartRow, nEndRow); 3694 } 3695 3696 SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3697 { 3698 if (!ValidTab(nTab) || !pTab[nTab]) 3699 return ::std::numeric_limits<SCROW>::max();; 3700 3701 return pTab[nTab]->LastNonFilteredRow(nStartRow, nEndRow); 3702 } 3703 3704 SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3705 { 3706 if (!ValidTab(nTab) || !pTab[nTab]) 3707 return 0; 3708 3709 return pTab[nTab]->CountNonFilteredRows(nStartRow, nEndRow); 3710 } 3711 3712 void ScDocument::SyncColRowFlags() 3713 { 3714 for (SCTAB i = 0; i <= nMaxTableNumber; ++i) 3715 { 3716 if (!ValidTab(i) || !pTab[i]) 3717 continue; 3718 3719 pTab[i]->SyncColRowFlags(); 3720 } 3721 } 3722 3723 SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const 3724 { 3725 if ( ValidTab(nTab) && pTab[nTab] ) 3726 return pTab[nTab]->GetLastFlaggedRow(); 3727 return 0; 3728 } 3729 3730 3731 SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const 3732 { 3733 if ( ValidTab(nTab) && pTab[nTab] ) 3734 return pTab[nTab]->GetLastChangedCol(); 3735 return 0; 3736 } 3737 3738 SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const 3739 { 3740 if ( ValidTab(nTab) && pTab[nTab] ) 3741 return pTab[nTab]->GetLastChangedRow(); 3742 return 0; 3743 } 3744 3745 3746 SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const 3747 { 3748 if ( ValidTab(nTab) && pTab[nTab] ) 3749 { 3750 sal_uInt8 nStartFlags = pTab[nTab]->GetColFlags(nStart); 3751 sal_uInt16 nStartWidth = pTab[nTab]->GetOriginalWidth(nStart); 3752 for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++) 3753 { 3754 if (((nStartFlags & CR_MANUALBREAK) != (pTab[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) || 3755 (nStartWidth != pTab[nTab]->GetOriginalWidth(nCol)) || 3756 ((nStartFlags & CR_HIDDEN) != (pTab[nTab]->GetColFlags(nCol) & CR_HIDDEN)) ) 3757 return nCol; 3758 } 3759 return MAXCOL+1; 3760 } 3761 return 0; 3762 } 3763 3764 SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const 3765 { 3766 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pRowFlagsArray; 3767 if ( ValidTab(nTab) && pTab[nTab] && ((pRowFlagsArray = pTab[nTab]->GetRowFlagsArray()) != NULL) && 3768 pTab[nTab]->mpRowHeights && pTab[nTab]->mpHiddenRows ) 3769 { 3770 size_t nIndex; // ignored 3771 SCROW nFlagsEndRow; 3772 SCROW nHiddenEndRow; 3773 SCROW nHeightEndRow; 3774 sal_uInt8 nFlags; 3775 bool bHidden; 3776 sal_uInt16 nHeight; 3777 sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow); 3778 bool bStartHidden = bHidden = pTab[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow); 3779 sal_uInt16 nStartHeight = nHeight = pTab[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false); 3780 SCROW nRow; 3781 while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW) 3782 { 3783 if (nFlagsEndRow < nRow) 3784 nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow); 3785 if (nHiddenEndRow < nRow) 3786 bHidden = pTab[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow); 3787 if (nHeightEndRow < nRow) 3788 nHeight = pTab[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false); 3789 if ( ((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) || 3790 ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) || 3791 (bStartHidden != bHidden) || 3792 (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) || 3793 (!bCareManualSize && ((nStartHeight != nHeight)))) 3794 return nRow; 3795 } 3796 return MAXROW+1; 3797 } 3798 return 0; 3799 } 3800 3801 sal_Bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault) 3802 { 3803 sal_Bool bRet(sal_False); 3804 nDefault = 0; 3805 ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow); 3806 SCCOL nColumn; 3807 SCROW nStartRow; 3808 SCROW nEndRow; 3809 const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); 3810 if (nEndRow < nLastRow) 3811 { 3812 ScDefaultAttrSet aSet; 3813 ScDefaultAttrSet::iterator aItr = aSet.end(); 3814 while (pAttr) 3815 { 3816 ScDefaultAttr aAttr(pAttr); 3817 aItr = aSet.find(aAttr); 3818 if (aItr == aSet.end()) 3819 { 3820 aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1); 3821 aAttr.nFirst = nStartRow; 3822 aSet.insert(aAttr); 3823 } 3824 else 3825 { 3826 aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1); 3827 aAttr.nFirst = aItr->nFirst; 3828 aSet.erase(aItr); 3829 aSet.insert(aAttr); 3830 } 3831 pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); 3832 } 3833 ScDefaultAttrSet::iterator aDefaultItr = aSet.begin(); 3834 aItr = aDefaultItr; 3835 aItr++; 3836 while (aItr != aSet.end()) 3837 { 3838 // for entries with equal count, use the one with the lowest start row, 3839 // don't use the random order of pointer comparisons 3840 if ( aItr->nCount > aDefaultItr->nCount || 3841 ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) ) 3842 aDefaultItr = aItr; 3843 aItr++; 3844 } 3845 nDefault = aDefaultItr->nFirst; 3846 bRet = sal_True; 3847 } 3848 else 3849 bRet = sal_True; 3850 return bRet; 3851 } 3852 3853 sal_Bool ScDocument::GetRowDefault( SCTAB /* nTab */, SCROW /* nRow */, SCCOL /* nLastCol */, SCCOL& /* nDefault */ ) 3854 { 3855 sal_Bool bRet(sal_False); 3856 return bRet; 3857 } 3858 3859 void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) 3860 { 3861 if ( ValidTab(nTab) && pTab[nTab] ) 3862 pTab[nTab]->StripHidden( rX1, rY1, rX2, rY2 ); 3863 } 3864 3865 3866 void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) 3867 { 3868 if ( ValidTab(nTab) && pTab[nTab] ) 3869 pTab[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 ); 3870 } 3871 3872 // 3873 // Attribute ---------------------------------------------------------- 3874 // 3875 3876 const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const 3877 { 3878 if ( ValidTab(nTab) && pTab[nTab] ) 3879 { 3880 const SfxPoolItem* pTemp = pTab[nTab]->GetAttr( nCol, nRow, nWhich ); 3881 if (pTemp) 3882 return pTemp; 3883 else 3884 { 3885 DBG_ERROR( "Attribut Null" ); 3886 } 3887 } 3888 return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich ); 3889 } 3890 3891 3892 const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 3893 { 3894 if ( ValidTab(nTab) && pTab[nTab] ) 3895 return pTab[nTab]->GetPattern( nCol, nRow ); 3896 return NULL; 3897 } 3898 3899 3900 const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const 3901 { 3902 if ( ValidTab(nTab) && pTab[nTab] ) 3903 return pTab[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow ); 3904 return NULL; 3905 } 3906 3907 3908 void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr ) 3909 { 3910 if ( ValidTab(nTab) && pTab[nTab] ) 3911 pTab[nTab]->ApplyAttr( nCol, nRow, rAttr ); 3912 } 3913 3914 3915 void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr ) 3916 { 3917 if ( ValidTab(nTab) && pTab[nTab] ) 3918 pTab[nTab]->ApplyPattern( nCol, nRow, rAttr ); 3919 } 3920 3921 3922 void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, 3923 SCCOL nEndCol, SCROW nEndRow, 3924 const ScMarkData& rMark, 3925 const ScPatternAttr& rAttr ) 3926 { 3927 for (SCTAB i=0; i <= MAXTAB; i++) 3928 if (pTab[i]) 3929 if (rMark.GetTableSelect(i)) 3930 pTab[i]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr ); 3931 } 3932 3933 3934 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow, 3935 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr ) 3936 { 3937 if (VALIDTAB(nTab)) 3938 if (pTab[nTab]) 3939 pTab[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr ); 3940 } 3941 3942 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange, 3943 const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType ) 3944 { 3945 for (SCTAB i=0; i <= MAXTAB; i++) 3946 if (pTab[i]) 3947 if (rMark.GetTableSelect(i)) 3948 pTab[i]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType ); 3949 } 3950 3951 3952 void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle) 3953 { 3954 if (VALIDTAB(nTab)) 3955 if (pTab[nTab]) 3956 pTab[nTab]->ApplyStyle( nCol, nRow, rStyle ); 3957 } 3958 3959 3960 void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, 3961 SCCOL nEndCol, SCROW nEndRow, 3962 const ScMarkData& rMark, 3963 const ScStyleSheet& rStyle) 3964 { 3965 for (SCTAB i=0; i <= MAXTAB; i++) 3966 if (pTab[i]) 3967 if (rMark.GetTableSelect(i)) 3968 pTab[i]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); 3969 } 3970 3971 3972 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow, 3973 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle) 3974 { 3975 if (VALIDTAB(nTab)) 3976 if (pTab[nTab]) 3977 pTab[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); 3978 } 3979 3980 3981 void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark) 3982 { 3983 // ApplySelectionStyle needs multi mark 3984 if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) 3985 { 3986 ScRange aRange; 3987 rMark.GetMarkArea( aRange ); 3988 ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(), 3989 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle ); 3990 } 3991 else 3992 { 3993 for (SCTAB i=0; i<=MAXTAB; i++) 3994 if ( pTab[i] && rMark.GetTableSelect(i) ) 3995 pTab[i]->ApplySelectionStyle( rStyle, rMark ); 3996 } 3997 } 3998 3999 4000 void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark, 4001 const SvxBorderLine* pLine, sal_Bool bColorOnly ) 4002 { 4003 if ( bColorOnly && !pLine ) 4004 return; 4005 4006 for (SCTAB i=0; i<=MAXTAB; i++) 4007 if (pTab[i]) 4008 if (rMark.GetTableSelect(i)) 4009 pTab[i]->ApplySelectionLineStyle( rMark, pLine, bColorOnly ); 4010 } 4011 4012 4013 const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4014 { 4015 if ( VALIDTAB(nTab) && pTab[nTab] ) 4016 return pTab[nTab]->GetStyle(nCol, nRow); 4017 else 4018 return NULL; 4019 } 4020 4021 4022 const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const 4023 { 4024 sal_Bool bEqual = sal_True; 4025 sal_Bool bFound; 4026 4027 const ScStyleSheet* pStyle = NULL; 4028 const ScStyleSheet* pNewStyle; 4029 4030 if ( rMark.IsMultiMarked() ) 4031 for (SCTAB i=0; i<=MAXTAB && bEqual; i++) 4032 if (pTab[i] && rMark.GetTableSelect(i)) 4033 { 4034 pNewStyle = pTab[i]->GetSelectionStyle( rMark, bFound ); 4035 if (bFound) 4036 { 4037 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 4038 bEqual = sal_False; // unterschiedliche 4039 pStyle = pNewStyle; 4040 } 4041 } 4042 if ( rMark.IsMarked() ) 4043 { 4044 ScRange aRange; 4045 rMark.GetMarkArea( aRange ); 4046 for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual; i++) 4047 if (pTab[i] && rMark.GetTableSelect(i)) 4048 { 4049 pNewStyle = pTab[i]->GetAreaStyle( bFound, 4050 aRange.aStart.Col(), aRange.aStart.Row(), 4051 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4052 if (bFound) 4053 { 4054 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 4055 bEqual = sal_False; // unterschiedliche 4056 pStyle = pNewStyle; 4057 } 4058 } 4059 } 4060 4061 return bEqual ? pStyle : NULL; 4062 } 4063 4064 4065 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved, 4066 OutputDevice* pDev, 4067 double nPPTX, double nPPTY, 4068 const Fraction& rZoomX, const Fraction& rZoomY ) 4069 { 4070 for (SCTAB i=0; i <= MAXTAB; i++) 4071 if (pTab[i]) 4072 pTab[i]->StyleSheetChanged 4073 ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY ); 4074 4075 if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) ) 4076 { 4077 // update attributes for all note objects 4078 ScDetectiveFunc::UpdateAllComments( *this ); 4079 } 4080 } 4081 4082 4083 sal_Bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const 4084 { 4085 if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN ) 4086 { 4087 if ( bGatherAllStyles ) 4088 { 4089 SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(), 4090 SFX_STYLE_FAMILY_PARA ); 4091 for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle; 4092 pStyle = aIter.Next() ) 4093 { 4094 const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle ); 4095 if ( pScStyle ) 4096 pScStyle->SetUsage( ScStyleSheet::NOTUSED ); 4097 } 4098 } 4099 4100 sal_Bool bIsUsed = sal_False; 4101 4102 for ( SCTAB i=0; i<=MAXTAB; i++ ) 4103 { 4104 if ( pTab[i] ) 4105 { 4106 if ( pTab[i]->IsStyleSheetUsed( rStyle, bGatherAllStyles ) ) 4107 { 4108 if ( !bGatherAllStyles ) 4109 return sal_True; 4110 bIsUsed = sal_True; 4111 } 4112 } 4113 } 4114 4115 if ( bGatherAllStyles ) 4116 bStyleSheetUsageInvalid = sal_False; 4117 4118 return bIsUsed; 4119 } 4120 4121 return rStyle.GetUsage() == ScStyleSheet::USED; 4122 } 4123 4124 4125 sal_Bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow, 4126 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ) 4127 { 4128 if (VALIDTAB(nTab)) 4129 if (pTab[nTab]) 4130 return pTab[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); 4131 4132 DBG_ERROR("ApplyFlags: falsche Tabelle"); 4133 return sal_False; 4134 } 4135 4136 4137 sal_Bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow, 4138 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ) 4139 { 4140 if (VALIDTAB(nTab)) 4141 if (pTab[nTab]) 4142 return pTab[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); 4143 4144 DBG_ERROR("RemoveFlags: falsche Tabelle"); 4145 return sal_False; 4146 } 4147 4148 4149 void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr, 4150 sal_Bool bPutToPool ) 4151 { 4152 if (VALIDTAB(nTab)) 4153 if (pTab[nTab]) 4154 pTab[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool ); 4155 } 4156 4157 4158 void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr, 4159 sal_Bool bPutToPool ) 4160 { 4161 SCTAB nTab = rPos.Tab(); 4162 if (pTab[nTab]) 4163 pTab[nTab]->SetPattern( rPos, rAttr, bPutToPool ); 4164 } 4165 4166 4167 ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep ) 4168 { 4169 ScMergePatternState aState; 4170 4171 if ( rMark.IsMultiMarked() ) // multi selection 4172 { 4173 for (SCTAB i=0; i<=MAXTAB; i++) 4174 if (pTab[i] && rMark.GetTableSelect(i)) 4175 pTab[i]->MergeSelectionPattern( aState, rMark, bDeep ); 4176 } 4177 if ( rMark.IsMarked() ) // simle selection 4178 { 4179 ScRange aRange; 4180 rMark.GetMarkArea(aRange); 4181 for (SCTAB i=0; i<=MAXTAB; i++) 4182 if (pTab[i] && rMark.GetTableSelect(i)) 4183 pTab[i]->MergePatternArea( aState, 4184 aRange.aStart.Col(), aRange.aStart.Row(), 4185 aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep ); 4186 } 4187 4188 DBG_ASSERT( aState.pItemSet, "SelectionPattern Null" ); 4189 if (aState.pItemSet) 4190 return new ScPatternAttr( aState.pItemSet ); 4191 else 4192 return new ScPatternAttr( GetPool() ); // empty 4193 } 4194 4195 4196 const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep ) 4197 { 4198 delete pSelectionAttr; 4199 pSelectionAttr = CreateSelectionPattern( rMark, bDeep ); 4200 return pSelectionAttr; 4201 } 4202 4203 4204 void ScDocument::GetSelectionFrame( const ScMarkData& rMark, 4205 SvxBoxItem& rLineOuter, 4206 SvxBoxInfoItem& rLineInner ) 4207 { 4208 rLineOuter.SetLine(NULL, BOX_LINE_TOP); 4209 rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM); 4210 rLineOuter.SetLine(NULL, BOX_LINE_LEFT); 4211 rLineOuter.SetLine(NULL, BOX_LINE_RIGHT); 4212 rLineOuter.SetDistance(0); 4213 4214 rLineInner.SetLine(NULL, BOXINFO_LINE_HORI); 4215 rLineInner.SetLine(NULL, BOXINFO_LINE_VERT); 4216 rLineInner.SetTable(sal_True); 4217 rLineInner.SetDist(sal_True); 4218 rLineInner.SetMinDist(sal_False); 4219 4220 ScLineFlags aFlags; 4221 4222 if (rMark.IsMarked()) 4223 { 4224 ScRange aRange; 4225 rMark.GetMarkArea(aRange); 4226 rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() ); 4227 rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() ); 4228 for (SCTAB i=0; i<=MAXTAB; i++) 4229 if (pTab[i] && rMark.GetTableSelect(i)) 4230 pTab[i]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags, 4231 aRange.aStart.Col(), aRange.aStart.Row(), 4232 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4233 } 4234 4235 // Don't care Status auswerten 4236 4237 rLineInner.SetValid( VALID_LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) ); 4238 rLineInner.SetValid( VALID_RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) ); 4239 rLineInner.SetValid( VALID_TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) ); 4240 rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) ); 4241 rLineInner.SetValid( VALID_HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) ); 4242 rLineInner.SetValid( VALID_VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) ); 4243 } 4244 4245 4246 bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 4247 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask ) 4248 { 4249 if ( nMask & HASATTR_ROTATE ) 4250 { 4251 // Attribut im Dokument ueberhaupt verwendet? 4252 // (wie in fillinfo) 4253 4254 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 4255 4256 sal_Bool bAnyItem = sal_False; 4257 sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE ); 4258 for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++) 4259 { 4260 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem ); 4261 if ( pItem ) 4262 { 4263 // 90 or 270 degrees is former SvxOrientationItem - only look for other values 4264 // (see ScPatternAttr::GetCellOrientation) 4265 sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue(); 4266 if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 ) 4267 { 4268 bAnyItem = sal_True; 4269 break; 4270 } 4271 } 4272 } 4273 if (!bAnyItem) 4274 nMask &= ~HASATTR_ROTATE; 4275 } 4276 4277 if ( nMask & HASATTR_RTL ) 4278 { 4279 // first check if right-to left is in the pool at all 4280 // (the same item is used in cell and page format) 4281 4282 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 4283 4284 sal_Bool bHasRtl = sal_False; 4285 sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR ); 4286 for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++) 4287 { 4288 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem ); 4289 if ( pItem && ((const SvxFrameDirectionItem*)pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP ) 4290 { 4291 bHasRtl = sal_True; 4292 break; 4293 } 4294 } 4295 if (!bHasRtl) 4296 nMask &= ~HASATTR_RTL; 4297 } 4298 4299 if (!nMask) 4300 return false; 4301 4302 bool bFound = false; 4303 for (SCTAB i=nTab1; i<=nTab2 && !bFound; i++) 4304 if (pTab[i]) 4305 { 4306 if ( nMask & HASATTR_RTL ) 4307 { 4308 if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L ) // sheet default 4309 bFound = true; 4310 } 4311 if ( nMask & HASATTR_RIGHTORCENTER ) 4312 { 4313 // On a RTL sheet, don't start to look for the default left value 4314 // (which is then logically right), instead always assume sal_True. 4315 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets. 4316 4317 if ( IsLayoutRTL(i) ) 4318 bFound = true; 4319 } 4320 4321 if ( !bFound ) 4322 bFound = pTab[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask ); 4323 } 4324 4325 return bFound; 4326 } 4327 4328 bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask ) 4329 { 4330 return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(), 4331 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), 4332 nMask ); 4333 } 4334 4335 void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount, 4336 SCCOL nX1, SCCOL nX2 ) const 4337 { 4338 if ( ValidTab(nTab) && pTab[nTab] ) 4339 pTab[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 ); 4340 else 4341 { 4342 DBG_ERRORFILE("FindMaxRotCol: falsche Tabelle"); 4343 } 4344 } 4345 4346 void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab, 4347 const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop, 4348 const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const 4349 { 4350 //! Seitengrenzen fuer Druck beruecksichtigen !!!!! 4351 4352 const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER ); 4353 DBG_ASSERT(pThisAttr,"wo ist das Attribut?"); 4354 4355 const SvxBorderLine* pLeftLine = pThisAttr->GetLeft(); 4356 const SvxBorderLine* pTopLine = pThisAttr->GetTop(); 4357 const SvxBorderLine* pRightLine = pThisAttr->GetRight(); 4358 const SvxBorderLine* pBottomLine = pThisAttr->GetBottom(); 4359 4360 if ( nCol > 0 ) 4361 { 4362 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4363 GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight(); 4364 if ( ScHasPriority( pOther, pLeftLine ) ) 4365 pLeftLine = pOther; 4366 } 4367 if ( nRow > 0 ) 4368 { 4369 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4370 GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom(); 4371 if ( ScHasPriority( pOther, pTopLine ) ) 4372 pTopLine = pOther; 4373 } 4374 if ( nCol < MAXCOL ) 4375 { 4376 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4377 GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft(); 4378 if ( ScHasPriority( pOther, pRightLine ) ) 4379 pRightLine = pOther; 4380 } 4381 if ( nRow < MAXROW ) 4382 { 4383 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4384 GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop(); 4385 if ( ScHasPriority( pOther, pBottomLine ) ) 4386 pBottomLine = pOther; 4387 } 4388 4389 if (ppLeft) 4390 *ppLeft = pLeftLine; 4391 if (ppTop) 4392 *ppTop = pTopLine; 4393 if (ppRight) 4394 *ppRight = pRightLine; 4395 if (ppBottom) 4396 *ppBottom = pBottomLine; 4397 } 4398 4399 sal_Bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 4400 SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const 4401 { 4402 if (VALIDTAB(nTab)) 4403 if (pTab[nTab]) 4404 return pTab[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes ); 4405 4406 DBG_ERROR("Falsche Tabellennummer"); 4407 return sal_False; 4408 } 4409 4410 4411 void ScDocument::LockTable(SCTAB nTab) 4412 { 4413 if ( ValidTab(nTab) && pTab[nTab] ) 4414 pTab[nTab]->LockTable(); 4415 else 4416 { 4417 DBG_ERROR("Falsche Tabellennummer"); 4418 } 4419 } 4420 4421 4422 void ScDocument::UnlockTable(SCTAB nTab) 4423 { 4424 if ( ValidTab(nTab) && pTab[nTab] ) 4425 pTab[nTab]->UnlockTable(); 4426 else 4427 { 4428 DBG_ERROR("Falsche Tabellennummer"); 4429 } 4430 } 4431 4432 4433 sal_Bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 4434 SCCOL nEndCol, SCROW nEndRow, 4435 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 4436 { 4437 // import into read-only document is possible 4438 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() ) 4439 { 4440 if ( pOnlyNotBecauseOfMatrix ) 4441 *pOnlyNotBecauseOfMatrix = sal_False; 4442 return sal_False; 4443 } 4444 4445 if (VALIDTAB(nTab)) 4446 if (pTab[nTab]) 4447 return pTab[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol, 4448 nEndRow, pOnlyNotBecauseOfMatrix ); 4449 4450 DBG_ERROR("Falsche Tabellennummer"); 4451 if ( pOnlyNotBecauseOfMatrix ) 4452 *pOnlyNotBecauseOfMatrix = sal_False; 4453 return sal_False; 4454 } 4455 4456 4457 sal_Bool ScDocument::IsSelectionEditable( const ScMarkData& rMark, 4458 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 4459 { 4460 // import into read-only document is possible 4461 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() ) 4462 { 4463 if ( pOnlyNotBecauseOfMatrix ) 4464 *pOnlyNotBecauseOfMatrix = sal_False; 4465 return sal_False; 4466 } 4467 4468 ScRange aRange; 4469 rMark.GetMarkArea(aRange); 4470 4471 sal_Bool bOk = sal_True; 4472 sal_Bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL ); 4473 for ( SCTAB i=0; i<=MAXTAB && (bOk || bMatrix); i++ ) 4474 { 4475 if ( pTab[i] && rMark.GetTableSelect(i) ) 4476 { 4477 if (rMark.IsMarked()) 4478 { 4479 if ( !pTab[i]->IsBlockEditable( aRange.aStart.Col(), 4480 aRange.aStart.Row(), aRange.aEnd.Col(), 4481 aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) ) 4482 { 4483 bOk = sal_False; 4484 if ( pOnlyNotBecauseOfMatrix ) 4485 bMatrix = *pOnlyNotBecauseOfMatrix; 4486 } 4487 } 4488 if (rMark.IsMultiMarked()) 4489 { 4490 if ( !pTab[i]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) ) 4491 { 4492 bOk = sal_False; 4493 if ( pOnlyNotBecauseOfMatrix ) 4494 bMatrix = *pOnlyNotBecauseOfMatrix; 4495 } 4496 } 4497 } 4498 } 4499 4500 if ( pOnlyNotBecauseOfMatrix ) 4501 *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix ); 4502 4503 return bOk; 4504 } 4505 4506 4507 sal_Bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow, 4508 SCCOL nEndCol, SCROW nEndRow, 4509 const ScMarkData& rMark ) const 4510 { 4511 sal_Bool bOk = sal_True; 4512 for (SCTAB i=0; i<=MAXTAB && bOk; i++) 4513 if (pTab[i]) 4514 if (rMark.GetTableSelect(i)) 4515 if (pTab[i]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow )) 4516 bOk = sal_False; 4517 4518 return !bOk; 4519 } 4520 4521 4522 sal_Bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix ) 4523 { 4524 // if rCell is part of a matrix formula, return its complete range 4525 4526 sal_Bool bRet = sal_False; 4527 ScBaseCell* pCell = GetCell( rCellPos ); 4528 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) 4529 { 4530 ScAddress aOrigin = rCellPos; 4531 if ( ((ScFormulaCell*)pCell)->GetMatrixOrigin( aOrigin ) ) 4532 { 4533 if ( aOrigin != rCellPos ) 4534 pCell = GetCell( aOrigin ); 4535 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) 4536 { 4537 SCCOL nSizeX; 4538 SCROW nSizeY; 4539 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY); 4540 if ( !(nSizeX > 0 && nSizeY > 0) ) 4541 { 4542 // GetMatrixEdge computes also dimensions of the matrix 4543 // if not already done (may occur if document is loaded 4544 // from old file format). 4545 // Needs an "invalid" initialized address. 4546 aOrigin.SetInvalid(); 4547 ((ScFormulaCell*)pCell)->GetMatrixEdge(aOrigin); 4548 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY); 4549 } 4550 if ( nSizeX > 0 && nSizeY > 0 ) 4551 { 4552 ScAddress aEnd( aOrigin.Col() + nSizeX - 1, 4553 aOrigin.Row() + nSizeY - 1, 4554 aOrigin.Tab() ); 4555 4556 rMatrix.aStart = aOrigin; 4557 rMatrix.aEnd = aEnd; 4558 bRet = sal_True; 4559 } 4560 } 4561 } 4562 } 4563 return bRet; 4564 } 4565 4566 4567 sal_Bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow, 4568 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 4569 { 4570 sal_Bool bFound = sal_False; 4571 if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) ) 4572 { 4573 if (pTab[nTab]) 4574 { 4575 SCCOL nCol; 4576 SCCOL nOldCol = rStartCol; 4577 SCROW nOldRow = rStartRow; 4578 for (nCol=nOldCol; nCol<=nEndCol; nCol++) 4579 while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))-> 4580 IsVerOverlapped()) 4581 --rStartRow; 4582 4583 //! weiterreichen ? 4584 4585 ScAttrArray* pAttrArray = pTab[nTab]->aCol[nOldCol].pAttrArray; 4586 SCSIZE nIndex; 4587 pAttrArray->Search( nOldRow, nIndex ); 4588 SCROW nAttrPos = nOldRow; 4589 while (nAttrPos<=nEndRow) 4590 { 4591 DBG_ASSERT( nIndex < pAttrArray->nCount, "Falscher Index im AttrArray" ); 4592 4593 if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern-> 4594 GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped()) 4595 { 4596 SCROW nLoopEndRow = Min( nEndRow, pAttrArray->pData[nIndex].nRow ); 4597 for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++) 4598 { 4599 SCCOL nTempCol = nOldCol; 4600 do 4601 --nTempCol; 4602 while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG)) 4603 ->IsHorOverlapped()); 4604 if (nTempCol < rStartCol) 4605 rStartCol = nTempCol; 4606 } 4607 } 4608 nAttrPos = pAttrArray->pData[nIndex].nRow + 1; 4609 ++nIndex; 4610 } 4611 } 4612 } 4613 else 4614 { 4615 DBG_ERROR("ExtendOverlapped: falscher Bereich"); 4616 } 4617 4618 return bFound; 4619 } 4620 4621 4622 sal_Bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow, 4623 SCCOL& rEndCol, SCROW& rEndRow, 4624 const ScMarkData& rMark, sal_Bool bRefresh, sal_Bool bAttrs ) 4625 { 4626 // use all selected sheets from rMark 4627 4628 sal_Bool bFound = sal_False; 4629 SCCOL nOldEndCol = rEndCol; 4630 SCROW nOldEndRow = rEndRow; 4631 4632 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) 4633 if ( pTab[nTab] && rMark.GetTableSelect(nTab) ) 4634 { 4635 SCCOL nThisEndCol = nOldEndCol; 4636 SCROW nThisEndRow = nOldEndRow; 4637 if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, nTab, bRefresh, bAttrs ) ) 4638 bFound = sal_True; 4639 if ( nThisEndCol > rEndCol ) 4640 rEndCol = nThisEndCol; 4641 if ( nThisEndRow > rEndRow ) 4642 rEndRow = nThisEndRow; 4643 } 4644 4645 return bFound; 4646 } 4647 4648 4649 sal_Bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow, 4650 SCCOL& rEndCol, SCROW& rEndRow, 4651 SCTAB nTab, sal_Bool bRefresh, sal_Bool bAttrs ) 4652 { 4653 sal_Bool bFound = sal_False; 4654 if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) ) 4655 { 4656 if (pTab[nTab]) 4657 bFound = pTab[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh, bAttrs ); 4658 4659 if (bRefresh) 4660 RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab ); 4661 } 4662 else 4663 { 4664 DBG_ERROR("ExtendMerge: falscher Bereich"); 4665 } 4666 4667 return bFound; 4668 } 4669 4670 4671 sal_Bool ScDocument::ExtendMerge( ScRange& rRange, sal_Bool bRefresh, sal_Bool bAttrs ) 4672 { 4673 sal_Bool bFound = sal_False; 4674 SCTAB nStartTab = rRange.aStart.Tab(); 4675 SCTAB nEndTab = rRange.aEnd.Tab(); 4676 SCCOL nEndCol = rRange.aEnd.Col(); 4677 SCROW nEndRow = rRange.aEnd.Row(); 4678 4679 PutInOrder( nStartTab, nEndTab ); 4680 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ ) 4681 { 4682 SCCOL nExtendCol = rRange.aEnd.Col(); 4683 SCROW nExtendRow = rRange.aEnd.Row(); 4684 if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(), 4685 nExtendCol, nExtendRow, 4686 nTab, bRefresh, bAttrs ) ) 4687 { 4688 bFound = sal_True; 4689 if (nExtendCol > nEndCol) nEndCol = nExtendCol; 4690 if (nExtendRow > nEndRow) nEndRow = nExtendRow; 4691 } 4692 } 4693 4694 rRange.aEnd.SetCol(nEndCol); 4695 rRange.aEnd.SetRow(nEndRow); 4696 4697 return bFound; 4698 } 4699 4700 sal_Bool ScDocument::ExtendTotalMerge( ScRange& rRange ) 4701 { 4702 // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn 4703 // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden 4704 4705 sal_Bool bRet = sal_False; 4706 ScRange aExt = rRange; 4707 if (ExtendMerge(aExt)) 4708 { 4709 if ( aExt.aEnd.Row() > rRange.aEnd.Row() ) 4710 { 4711 ScRange aTest = aExt; 4712 aTest.aStart.SetRow( rRange.aEnd.Row() + 1 ); 4713 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) ) 4714 aExt.aEnd.SetRow(rRange.aEnd.Row()); 4715 } 4716 if ( aExt.aEnd.Col() > rRange.aEnd.Col() ) 4717 { 4718 ScRange aTest = aExt; 4719 aTest.aStart.SetCol( rRange.aEnd.Col() + 1 ); 4720 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) ) 4721 aExt.aEnd.SetCol(rRange.aEnd.Col()); 4722 } 4723 4724 bRet = ( aExt.aEnd != rRange.aEnd ); 4725 rRange = aExt; 4726 } 4727 return bRet; 4728 } 4729 4730 sal_Bool ScDocument::ExtendOverlapped( ScRange& rRange ) 4731 { 4732 sal_Bool bFound = sal_False; 4733 SCTAB nStartTab = rRange.aStart.Tab(); 4734 SCTAB nEndTab = rRange.aEnd.Tab(); 4735 SCCOL nStartCol = rRange.aStart.Col(); 4736 SCROW nStartRow = rRange.aStart.Row(); 4737 4738 PutInOrder( nStartTab, nEndTab ); 4739 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ ) 4740 { 4741 SCCOL nExtendCol = rRange.aStart.Col(); 4742 SCROW nExtendRow = rRange.aStart.Row(); 4743 ExtendOverlapped( nExtendCol, nExtendRow, 4744 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab ); 4745 if (nExtendCol < nStartCol) 4746 { 4747 nStartCol = nExtendCol; 4748 bFound = sal_True; 4749 } 4750 if (nExtendRow < nStartRow) 4751 { 4752 nStartRow = nExtendRow; 4753 bFound = sal_True; 4754 } 4755 } 4756 4757 rRange.aStart.SetCol(nStartCol); 4758 rRange.aStart.SetRow(nStartRow); 4759 4760 return bFound; 4761 } 4762 4763 sal_Bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow, 4764 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 4765 { 4766 sal_uInt16 nCount = pDBCollection->GetCount(); 4767 sal_uInt16 i; 4768 ScDBData* pData; 4769 SCTAB nDBTab; 4770 SCCOL nDBStartCol; 4771 SCROW nDBStartRow; 4772 SCCOL nDBEndCol; 4773 SCROW nDBEndRow; 4774 4775 // Autofilter loeschen 4776 4777 sal_Bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO ); 4778 4779 // Autofilter setzen 4780 4781 for (i=0; i<nCount; i++) 4782 { 4783 pData = (*pDBCollection)[i]; 4784 if (pData->HasAutoFilter()) 4785 { 4786 pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow ); 4787 if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow && 4788 nDBStartCol<=nEndCol && nDBEndCol>=nStartCol ) 4789 { 4790 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow, 4791 nDBTab, SC_MF_AUTO )) 4792 bChange = sal_True; 4793 } 4794 } 4795 } 4796 return bChange; 4797 } 4798 4799 4800 sal_Bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4801 { 4802 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*) 4803 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); 4804 if (pAttr) 4805 return pAttr->IsHorOverlapped(); 4806 else 4807 { 4808 DBG_ERROR("Overlapped: Attr==0"); 4809 return sal_False; 4810 } 4811 } 4812 4813 4814 sal_Bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4815 { 4816 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*) 4817 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); 4818 if (pAttr) 4819 return pAttr->IsVerOverlapped(); 4820 else 4821 { 4822 DBG_ERROR("Overlapped: Attr==0"); 4823 return sal_False; 4824 } 4825 } 4826 4827 4828 void ScDocument::ApplySelectionFrame( const ScMarkData& rMark, 4829 const SvxBoxItem* pLineOuter, 4830 const SvxBoxInfoItem* pLineInner ) 4831 { 4832 ScRangeList aRangeList; 4833 rMark.FillRangeListWithMarks( &aRangeList, sal_False ); 4834 sal_uLong nRangeCount = aRangeList.Count(); 4835 for (SCTAB i=0; i<=MAXTAB; i++) 4836 { 4837 if (pTab[i] && rMark.GetTableSelect(i)) 4838 { 4839 for (sal_uLong j=0; j<nRangeCount; j++) 4840 { 4841 ScRange aRange = *aRangeList.GetObject(j); 4842 pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner, 4843 aRange.aStart.Col(), aRange.aStart.Row(), 4844 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4845 } 4846 } 4847 } 4848 } 4849 4850 4851 void ScDocument::ApplyFrameAreaTab( const ScRange& rRange, 4852 const SvxBoxItem* pLineOuter, 4853 const SvxBoxInfoItem* pLineInner ) 4854 { 4855 SCTAB nStartTab = rRange.aStart.Tab(); 4856 SCTAB nEndTab = rRange.aStart.Tab(); 4857 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 4858 if (pTab[nTab]) 4859 pTab[nTab]->ApplyBlockFrame( pLineOuter, pLineInner, 4860 rRange.aStart.Col(), rRange.aStart.Row(), 4861 rRange.aEnd.Col(), rRange.aEnd.Row() ); 4862 } 4863 4864 4865 void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark ) 4866 { 4867 const SfxItemSet* pSet = &rAttr.GetItemSet(); 4868 sal_Bool bSet = sal_False; 4869 sal_uInt16 i; 4870 for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++) 4871 if (pSet->GetItemState(i) == SFX_ITEM_SET) 4872 bSet = sal_True; 4873 4874 if (bSet) 4875 { 4876 // ApplySelectionCache needs multi mark 4877 if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) 4878 { 4879 ScRange aRange; 4880 rMark.GetMarkArea( aRange ); 4881 ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(), 4882 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr ); 4883 } 4884 else 4885 { 4886 SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet ); 4887 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++) 4888 if (pTab[nTab]) 4889 if (rMark.GetTableSelect(nTab)) 4890 pTab[nTab]->ApplySelectionCache( &aCache, rMark ); 4891 } 4892 } 4893 } 4894 4895 4896 void ScDocument::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark ) 4897 { 4898 for (SCTAB i=0; i<=MAXTAB; i++) 4899 if (pTab[i] && rMark.GetTableSelect(i)) 4900 pTab[i]->ChangeSelectionIndent( bIncrement, rMark ); 4901 } 4902 4903 4904 void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark ) 4905 { 4906 for (SCTAB i=0; i<=MAXTAB; i++) 4907 if (pTab[i] && rMark.GetTableSelect(i)) 4908 pTab[i]->ClearSelectionItems( pWhich, rMark ); 4909 } 4910 4911 4912 void ScDocument::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark ) 4913 { 4914 for (SCTAB i=0; i<=MAXTAB; i++) 4915 if (pTab[i] && rMark.GetTableSelect(i)) 4916 pTab[i]->DeleteSelection( nDelFlag, rMark ); 4917 } 4918 4919 4920 void ScDocument::DeleteSelectionTab( SCTAB nTab, sal_uInt16 nDelFlag, const ScMarkData& rMark ) 4921 { 4922 if (ValidTab(nTab) && pTab[nTab]) 4923 pTab[nTab]->DeleteSelection( nDelFlag, rMark ); 4924 else 4925 { 4926 DBG_ERROR("Falsche Tabelle"); 4927 } 4928 } 4929 4930 4931 ScPatternAttr* ScDocument::GetDefPattern() const 4932 { 4933 return (ScPatternAttr*) &xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN); 4934 } 4935 4936 4937 ScDocumentPool* ScDocument::GetPool() 4938 { 4939 return xPoolHelper->GetDocPool(); 4940 } 4941 4942 4943 4944 ScStyleSheetPool* ScDocument::GetStyleSheetPool() const 4945 { 4946 return xPoolHelper->GetStylePool(); 4947 } 4948 4949 4950 SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, 4951 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir ) 4952 { 4953 PutInOrder(nStartCol, nEndCol); 4954 PutInOrder(nStartRow, nEndRow); 4955 PutInOrder(nStartTab, nEndTab); 4956 if (VALIDTAB(nStartTab)) 4957 { 4958 if (pTab[nStartTab]) 4959 return pTab[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir); 4960 else 4961 return 0; 4962 } 4963 else 4964 return 0; 4965 } 4966 4967 4968 void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY ) 4969 { 4970 if (ValidTab(nTab) && pTab[nTab]) 4971 pTab[nTab]->FindAreaPos( rCol, rRow, nMovX, nMovY ); 4972 } 4973 4974 4975 void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY, 4976 sal_Bool bMarked, sal_Bool bUnprotected, const ScMarkData& rMark ) 4977 { 4978 DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" ); 4979 4980 ScMarkData aCopyMark = rMark; 4981 aCopyMark.SetMarking(sal_False); 4982 aCopyMark.MarkToMulti(); 4983 4984 if (ValidTab(nTab) && pTab[nTab]) 4985 pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark ); 4986 } 4987 4988 // 4989 // Datei-Operationen 4990 // 4991 4992 4993 void ScDocument::UpdStlShtPtrsFrmNms() 4994 { 4995 ScPatternAttr::pDoc = this; 4996 4997 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 4998 4999 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN); 5000 ScPatternAttr* pPattern; 5001 for (sal_uInt32 i=0; i<nCount; i++) 5002 { 5003 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i); 5004 if (pPattern) 5005 pPattern->UpdateStyleSheet(); 5006 } 5007 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet(); 5008 } 5009 5010 5011 void ScDocument::StylesToNames() 5012 { 5013 ScPatternAttr::pDoc = this; 5014 5015 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 5016 5017 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN); 5018 ScPatternAttr* pPattern; 5019 for (sal_uInt32 i=0; i<nCount; i++) 5020 { 5021 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i); 5022 if (pPattern) 5023 pPattern->StyleToName(); 5024 } 5025 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName(); 5026 } 5027 5028 5029 sal_uLong ScDocument::GetCellCount() const 5030 { 5031 sal_uLong nCellCount = 0L; 5032 5033 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5034 if ( pTab[nTab] ) 5035 nCellCount += pTab[nTab]->GetCellCount(); 5036 5037 return nCellCount; 5038 } 5039 5040 SCSIZE ScDocument::GetCellCount(SCTAB nTab, SCCOL nCol) const 5041 { 5042 if (!ValidTab(nTab) || !pTab[nTab]) 5043 return 0; 5044 5045 return pTab[nTab]->GetCellCount(nCol); 5046 } 5047 5048 sal_uLong ScDocument::GetCodeCount() const 5049 { 5050 sal_uLong nCodeCount = 0; 5051 5052 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5053 if ( pTab[nTab] ) 5054 nCodeCount += pTab[nTab]->GetCodeCount(); 5055 5056 return nCodeCount; 5057 } 5058 5059 5060 sal_uLong ScDocument::GetWeightedCount() const 5061 { 5062 sal_uLong nCellCount = 0L; 5063 5064 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5065 if ( pTab[nTab] ) 5066 nCellCount += pTab[nTab]->GetWeightedCount(); 5067 5068 return nCellCount; 5069 } 5070 5071 5072 void ScDocument::PageStyleModified( SCTAB nTab, const String& rNewName ) 5073 { 5074 if ( ValidTab(nTab) && pTab[nTab] ) 5075 pTab[nTab]->PageStyleModified( rNewName ); 5076 } 5077 5078 5079 void ScDocument::SetPageStyle( SCTAB nTab, const String& rName ) 5080 { 5081 if ( ValidTab(nTab) && pTab[nTab] ) 5082 pTab[nTab]->SetPageStyle( rName ); 5083 } 5084 5085 5086 const String& ScDocument::GetPageStyle( SCTAB nTab ) const 5087 { 5088 if ( ValidTab(nTab) && pTab[nTab] ) 5089 return pTab[nTab]->GetPageStyle(); 5090 5091 return EMPTY_STRING; 5092 } 5093 5094 5095 void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize ) 5096 { 5097 if ( ValidTab(nTab) && pTab[nTab] ) 5098 pTab[nTab]->SetPageSize( rSize ); 5099 } 5100 5101 Size ScDocument::GetPageSize( SCTAB nTab ) const 5102 { 5103 if ( ValidTab(nTab) && pTab[nTab] ) 5104 return pTab[nTab]->GetPageSize(); 5105 5106 DBG_ERROR("falsche Tab"); 5107 return Size(); 5108 } 5109 5110 5111 void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ) 5112 { 5113 if ( ValidTab(nTab) && pTab[nTab] ) 5114 pTab[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow ); 5115 } 5116 5117 void ScDocument::InvalidatePageBreaks(SCTAB nTab) 5118 { 5119 if (ValidTab(nTab) && pTab[nTab]) 5120 pTab[nTab]->InvalidatePageBreaks(); 5121 } 5122 5123 void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea ) 5124 { 5125 if ( ValidTab(nTab) && pTab[nTab] ) 5126 pTab[nTab]->UpdatePageBreaks( pUserArea ); 5127 } 5128 5129 void ScDocument::RemoveManualBreaks( SCTAB nTab ) 5130 { 5131 if ( ValidTab(nTab) && pTab[nTab] ) 5132 pTab[nTab]->RemoveManualBreaks(); 5133 } 5134 5135 sal_Bool ScDocument::HasManualBreaks( SCTAB nTab ) const 5136 { 5137 if ( ValidTab(nTab) && pTab[nTab] ) 5138 return pTab[nTab]->HasManualBreaks(); 5139 5140 DBG_ERROR("falsche Tab"); 5141 return sal_False; 5142 } 5143 5144 5145 void ScDocument::GetDocStat( ScDocStat& rDocStat ) 5146 { 5147 rDocStat.nTableCount = GetTableCount(); 5148 rDocStat.aDocName = aDocName; 5149 rDocStat.nCellCount = GetCellCount(); 5150 } 5151 5152 5153 sal_Bool ScDocument::HasPrintRange() 5154 { 5155 sal_Bool bResult = sal_False; 5156 5157 for ( SCTAB i=0; !bResult && i<nMaxTableNumber; i++ ) 5158 if ( pTab[i] ) 5159 bResult = pTab[i]->IsPrintEntireSheet() || (pTab[i]->GetPrintRangeCount() > 0); 5160 5161 return bResult; 5162 } 5163 5164 5165 sal_Bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const 5166 { 5167 return (ValidTab(nTab) ) && pTab[nTab] && pTab[nTab]->IsPrintEntireSheet(); 5168 } 5169 5170 5171 sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab ) 5172 { 5173 if (ValidTab(nTab) && pTab[nTab]) 5174 return pTab[nTab]->GetPrintRangeCount(); 5175 5176 return 0; 5177 } 5178 5179 5180 const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos ) 5181 { 5182 if (ValidTab(nTab) && pTab[nTab]) 5183 return pTab[nTab]->GetPrintRange(nPos); 5184 5185 return NULL; 5186 } 5187 5188 5189 const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab ) 5190 { 5191 if (ValidTab(nTab) && pTab[nTab]) 5192 return pTab[nTab]->GetRepeatColRange(); 5193 5194 return NULL; 5195 } 5196 5197 5198 const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab ) 5199 { 5200 if (ValidTab(nTab) && pTab[nTab]) 5201 return pTab[nTab]->GetRepeatRowRange(); 5202 5203 return NULL; 5204 } 5205 5206 5207 void ScDocument::ClearPrintRanges( SCTAB nTab ) 5208 { 5209 if (ValidTab(nTab) && pTab[nTab]) 5210 pTab[nTab]->ClearPrintRanges(); 5211 } 5212 5213 5214 void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew ) 5215 { 5216 if (ValidTab(nTab) && pTab[nTab]) 5217 pTab[nTab]->AddPrintRange( rNew ); 5218 } 5219 5220 5221 //UNUSED2009-05 void ScDocument::SetPrintRange( SCTAB nTab, const ScRange& rNew ) 5222 //UNUSED2009-05 { 5223 //UNUSED2009-05 if (ValidTab(nTab) && pTab[nTab]) 5224 //UNUSED2009-05 pTab[nTab]->SetPrintRange( rNew ); 5225 //UNUSED2009-05 } 5226 5227 5228 void ScDocument::SetPrintEntireSheet( SCTAB nTab ) 5229 { 5230 if (ValidTab(nTab) && pTab[nTab]) 5231 pTab[nTab]->SetPrintEntireSheet(); 5232 } 5233 5234 5235 void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew ) 5236 { 5237 if (ValidTab(nTab) && pTab[nTab]) 5238 pTab[nTab]->SetRepeatColRange( pNew ); 5239 } 5240 5241 5242 void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew ) 5243 { 5244 if (ValidTab(nTab) && pTab[nTab]) 5245 pTab[nTab]->SetRepeatRowRange( pNew ); 5246 } 5247 5248 5249 ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const 5250 { 5251 SCTAB nCount = GetTableCount(); 5252 ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount ); 5253 for (SCTAB i=0; i<nCount; i++) 5254 if (pTab[i]) 5255 pTab[i]->FillPrintSaver( pNew->GetTabData(i) ); 5256 return pNew; 5257 } 5258 5259 5260 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver ) 5261 { 5262 SCTAB nCount = rSaver.GetTabCount(); 5263 for (SCTAB i=0; i<nCount; i++) 5264 if (pTab[i]) 5265 pTab[i]->RestorePrintRanges( rSaver.GetTabData(i) ); 5266 } 5267 5268 5269 sal_Bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const 5270 { 5271 // Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine 5272 // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen) 5273 // und eine Seitennummer angegeben ist (nicht 0) 5274 5275 if ( nTab < MAXTAB && pTab[nTab] && pTab[nTab+1] ) 5276 { 5277 String aNew = pTab[nTab+1]->GetPageStyle(); 5278 if ( aNew != pTab[nTab]->GetPageStyle() ) 5279 { 5280 SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE ); 5281 if ( pStyle ) 5282 { 5283 const SfxItemSet& rSet = pStyle->GetItemSet(); 5284 sal_uInt16 nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue(); 5285 if ( nFirst != 0 ) 5286 return sal_True; // Seitennummer in neuer Vorlage angegeben 5287 } 5288 } 5289 } 5290 5291 return sal_False; // sonst nicht 5292 } 5293 5294 SfxUndoManager* ScDocument::GetUndoManager() 5295 { 5296 if (!mpUndoManager) 5297 mpUndoManager = new SfxUndoManager; 5298 return mpUndoManager; 5299 } 5300 5301 ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const 5302 { 5303 if (ValidTab(nTab) && pTab[nTab]) 5304 return new ScRowBreakIterator(pTab[nTab]->maRowPageBreaks); 5305 return NULL; 5306 } 5307 5308 void ScDocument::EnableUndo( bool bVal ) 5309 { 5310 GetUndoManager()->EnableUndo(bVal); 5311 if( pDrawLayer ) pDrawLayer->EnableUndo(bVal); 5312 mbUndoEnabled = bVal; 5313 } 5314 5315 bool ScDocument::IsInVBAMode() const 5316 { 5317 bool bResult = false; 5318 if ( pShell ) 5319 { 5320 com::sun::star::uno::Reference< com::sun::star::script::vba::XVBACompatibility > xVBA( pShell->GetBasicContainer(), com::sun::star::uno::UNO_QUERY ); 5321 bResult = xVBA.is() && xVBA->getVBACompatibilityMode(); 5322 } 5323 return bResult; 5324 } 5325