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