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() == GetDocumentID()) ) // #118023# only update references for *intra-document* cut and paste 1970 { 1971 nClipTab = 0; 1972 for (SCTAB i = pCBFCP->nTabStart; i <= nTabEnd; i++) 1973 { 1974 if (pTab[i] && rMark.GetTableSelect(i) ) 1975 { 1976 while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1); 1977 SCsTAB nDz = ((SCsTAB)i) - nClipTab; 1978 1979 // #89081# ranges of consecutive selected tables (in clipboard and dest. doc) 1980 // must be handled in one UpdateReference call 1981 SCTAB nFollow = 0; 1982 while ( i + nFollow < nTabEnd 1983 && rMark.GetTableSelect( i + nFollow + 1 ) 1984 && nClipTab + nFollow < MAXTAB 1985 && ppClipTab[nClipTab + nFollow + 1] ) 1986 ++nFollow; 1987 1988 if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode ) 1989 { 1990 sal_Bool bOldInserting = IsInsertingFromOtherDoc(); 1991 SetInsertingFromOtherDoc( sal_True); 1992 UpdateReference( URM_MOVE, 1993 nCol1, nRow1, i, nCol2, nRow2, i+nFollow, 1994 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False ); 1995 SetInsertingFromOtherDoc( bOldInserting); 1996 } 1997 else 1998 UpdateReference( URM_COPY, 1999 nCol1, nRow1, i, nCol2, nRow2, i+nFollow, 2000 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False ); 2001 2002 nClipTab = (nClipTab+nFollow+1) % (MAXTAB+1); 2003 i = sal::static_int_cast<SCTAB>( i + nFollow ); 2004 } 2005 } 2006 } 2007 } 2008 2009 2010 void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1, 2011 SCCOL nCol2, SCROW nRow2, 2012 const ScMarkData& rMark, 2013 SCsCOL nDx, SCsROW /* nDy */, 2014 const ScCopyBlockFromClipParams* pCBFCP, 2015 SCROW & rClipStartRow ) 2016 { 2017 // call CopyBlockFromClip for ranges of consecutive non-filtered rows 2018 // nCol1/nRow1 etc. is in target doc 2019 2020 // filtered state is taken from first used table in clipboard (as in GetClipArea) 2021 SCTAB nFlagTab = 0; 2022 ScTable** ppClipTab = pCBFCP->pClipDoc->pTab; 2023 while ( nFlagTab < MAXTAB && !ppClipTab[nFlagTab] ) 2024 ++nFlagTab; 2025 2026 SCROW nSourceRow = rClipStartRow; 2027 SCROW nSourceEnd = 0; 2028 if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count()) 2029 nSourceEnd = pCBFCP->pClipDoc->GetClipParam().maRanges.First()->aEnd.Row(); 2030 SCROW nDestRow = nRow1; 2031 2032 while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 ) 2033 { 2034 // skip filtered rows 2035 nSourceRow = pCBFCP->pClipDoc->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab); 2036 2037 if ( nSourceRow <= nSourceEnd ) 2038 { 2039 // look for more non-filtered rows following 2040 SCROW nLastRow = nSourceRow; 2041 pCBFCP->pClipDoc->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow); 2042 SCROW nFollow = nLastRow - nSourceRow; 2043 2044 if (nFollow > nSourceEnd - nSourceRow) 2045 nFollow = nSourceEnd - nSourceRow; 2046 if (nFollow > nRow2 - nDestRow) 2047 nFollow = nRow2 - nDestRow; 2048 2049 SCsROW nNewDy = ((SCsROW)nDestRow) - nSourceRow; 2050 CopyBlockFromClip( nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy, pCBFCP ); 2051 2052 nSourceRow += nFollow + 1; 2053 nDestRow += nFollow + 1; 2054 } 2055 } 2056 rClipStartRow = nSourceRow; 2057 } 2058 2059 2060 void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark, 2061 sal_uInt16 nInsFlag, 2062 ScDocument* pRefUndoDoc, ScDocument* pClipDoc, sal_Bool bResetCut, 2063 sal_Bool bAsLink, sal_Bool bIncludeFiltered, sal_Bool bSkipAttrForEmpty, 2064 const ScRangeList * pDestRanges ) 2065 { 2066 if (!bIsClip) 2067 { 2068 if (!pClipDoc) 2069 { 2070 DBG_ERROR("CopyFromClip: no ClipDoc"); 2071 pClipDoc = SC_MOD()->GetClipDoc(); 2072 } 2073 if (pClipDoc->bIsClip && pClipDoc->GetTableCount()) 2074 { 2075 sal_Bool bOldAutoCalc = GetAutoCalc(); 2076 SetAutoCalc( sal_False ); // avoid multiple recalculations 2077 2078 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc); 2079 2080 ScClipRangeNameData aClipRangeNames; 2081 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames); 2082 2083 SCCOL nAllCol1 = rDestRange.aStart.Col(); 2084 SCROW nAllRow1 = rDestRange.aStart.Row(); 2085 SCCOL nAllCol2 = rDestRange.aEnd.Col(); 2086 SCROW nAllRow2 = rDestRange.aEnd.Row(); 2087 2088 SCCOL nXw = 0; 2089 SCROW nYw = 0; 2090 ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange(); 2091 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) // find largest merge overlap 2092 if (pClipDoc->pTab[nTab]) // all sheets of the clipboard content 2093 { 2094 SCCOL nThisEndX = aClipRange.aEnd.Col(); 2095 SCROW nThisEndY = aClipRange.aEnd.Row(); 2096 pClipDoc->ExtendMerge( aClipRange.aStart.Col(), 2097 aClipRange.aStart.Row(), 2098 nThisEndX, nThisEndY, nTab ); 2099 // only extra value from ExtendMerge 2100 nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() ); 2101 nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() ); 2102 if ( nThisEndX > nXw ) 2103 nXw = nThisEndX; 2104 if ( nThisEndY > nYw ) 2105 nYw = nThisEndY; 2106 } 2107 2108 SCCOL nDestAddX; 2109 SCROW nDestAddY; 2110 pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered ); 2111 nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX ); 2112 nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value 2113 2114 /* Decide which contents to delete before copying. Delete all 2115 contents if nInsFlag contains any real content flag. 2116 #i102056# Notes are pasted from clipboard in a second pass, 2117 together with the special flag IDF_ADDNOTES that states to not 2118 overwrite/delete existing cells but to insert the notes into 2119 these cells. In this case, just delete old notes from the 2120 destination area. */ 2121 sal_uInt16 nDelFlag = IDF_NONE; 2122 if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) ) 2123 nDelFlag |= IDF_NOTE; 2124 else if ( nInsFlag & IDF_CONTENTS ) 2125 nDelFlag |= IDF_CONTENTS; 2126 // With bSkipAttrForEmpty, don't remove attributes, copy 2127 // on top of existing attributes instead. 2128 if ( ( nInsFlag & IDF_ATTRIB ) && !bSkipAttrForEmpty ) 2129 nDelFlag |= IDF_ATTRIB; 2130 2131 ScCopyBlockFromClipParams aCBFCP; 2132 aCBFCP.pRefUndoDoc = pRefUndoDoc; 2133 aCBFCP.pClipDoc = pClipDoc; 2134 aCBFCP.nInsFlag = nInsFlag; 2135 aCBFCP.bAsLink = bAsLink; 2136 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty; 2137 aCBFCP.nTabStart = MAXTAB; // wird in der Schleife angepasst 2138 aCBFCP.nTabEnd = 0; // wird in der Schleife angepasst 2139 2140 // Inc/DecRecalcLevel einmal aussen, damit nicht fuer jeden Block 2141 // die Draw-Seitengroesse neu berechnet werden muss 2142 //! nur wenn ganze Zeilen/Spalten kopiert werden? 2143 2144 for (SCTAB j = 0; j <= MAXTAB; j++) 2145 if (pTab[j] && rMark.GetTableSelect(j)) 2146 { 2147 if ( j < aCBFCP.nTabStart ) 2148 aCBFCP.nTabStart = j; 2149 aCBFCP.nTabEnd = j; 2150 pTab[j]->IncRecalcLevel(); 2151 } 2152 2153 ScRangeList aLocalRangeList; 2154 if (!pDestRanges) 2155 { 2156 aLocalRangeList.Append( rDestRange); 2157 pDestRanges = &aLocalRangeList; 2158 } 2159 2160 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert 2161 2162 // bei mindestens 64 Zeilen wird in ScColumn::CopyFromClip voralloziert 2163 sal_Bool bDoDouble = ( nYw < 64 && nAllRow2 - nAllRow1 > 64); 2164 sal_Bool bOldDouble = ScColumn::bDoubleAlloc; 2165 if (bDoDouble) 2166 ScColumn::bDoubleAlloc = sal_True; 2167 2168 SCCOL nClipStartCol = aClipRange.aStart.Col(); 2169 SCROW nClipStartRow = aClipRange.aStart.Row(); 2170 // WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col(); 2171 SCROW nClipEndRow = aClipRange.aEnd.Row(); 2172 for (sal_uLong nRange = 0; nRange < pDestRanges->Count(); ++nRange) 2173 { 2174 const ScRange* pRange = pDestRanges->GetObject( nRange); 2175 SCCOL nCol1 = pRange->aStart.Col(); 2176 SCROW nRow1 = pRange->aStart.Row(); 2177 SCCOL nCol2 = pRange->aEnd.Col(); 2178 SCROW nRow2 = pRange->aEnd.Row(); 2179 2180 DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag); 2181 2182 SCCOL nC1 = nCol1; 2183 SCROW nR1 = nRow1; 2184 SCCOL nC2 = nC1 + nXw; 2185 if (nC2 > nCol2) 2186 nC2 = nCol2; 2187 SCROW nR2 = nR1 + nYw; 2188 if (nR2 > nRow2) 2189 nR2 = nRow2; 2190 2191 const unsigned PERFORMANCEOPTIMIZATION4PATTERNTHRESHOLD = 8192; 2192 bool bNeedPerformanceOptimization4Pattern = nRow2 - nRow1 > PERFORMANCEOPTIMIZATION4PATTERNTHRESHOLD; 2193 std::vector< std::vector< SCSIZE > > vvPatternCount( bNeedPerformanceOptimization4Pattern ? nCol2 - nCol1 + 1 : 0 ); 2194 std::vector< SCTAB > vTables; 2195 2196 if( bNeedPerformanceOptimization4Pattern ) 2197 { 2198 for (SCTAB i = aCBFCP.nTabStart; i <= aCBFCP.nTabEnd; i++) 2199 if (pTab[i] && rMark.GetTableSelect( i ) ) 2200 vTables.push_back( i ); 2201 2202 for( SCSIZE i = 0; i < vvPatternCount.size(); i++ ) 2203 { 2204 vvPatternCount[i].resize( vTables.size() ); 2205 2206 for( std::vector< SCTAB >::size_type j = 0; j<vTables.size(); j++ ) 2207 vvPatternCount[i][j] = this->GetPatternCount( vTables[j], nCol1+i ); 2208 } 2209 } 2210 2211 do 2212 { 2213 // Pasting is done column-wise, when pasting to a filtered 2214 // area this results in partitioning and we have to 2215 // remember and reset the start row for each column until 2216 // it can be advanced for the next chunk of unfiltered 2217 // rows. 2218 SCROW nSaveClipStartRow = nClipStartRow; 2219 do 2220 { 2221 nClipStartRow = nSaveClipStartRow; 2222 SCsCOL nDx = ((SCsCOL)nC1) - nClipStartCol; 2223 SCsROW nDy = ((SCsROW)nR1) - nClipStartRow; 2224 if ( bIncludeFiltered ) 2225 { 2226 CopyBlockFromClip( nC1, nR1, nC2, nR2, rMark, nDx, 2227 nDy, &aCBFCP ); 2228 nClipStartRow += nR2 - nR1 + 1; 2229 } 2230 else 2231 { 2232 CopyNonFilteredFromClip( nC1, nR1, nC2, nR2, rMark, 2233 nDx, nDy, &aCBFCP, nClipStartRow ); 2234 } 2235 // Not needed for columns, but if it was this would be how to. 2236 //if (nClipStartCol > nClipEndCol) 2237 // nClipStartCol = pClipDoc->aClipRange.aStart.Col(); 2238 nC1 = nC2 + 1; 2239 nC2 = Min((SCCOL)(nC1 + nXw), nCol2); 2240 } while (nC1 <= nCol2); 2241 if (nClipStartRow > nClipEndRow) 2242 nClipStartRow = aClipRange.aStart.Row(); 2243 nC1 = nCol1; 2244 nC2 = nC1 + nXw; 2245 if (nC2 > nCol2) 2246 nC2 = nCol2; 2247 2248 if( bNeedPerformanceOptimization4Pattern && vvPatternCount.size() ) 2249 { 2250 for( SCSIZE i = 0; i < vvPatternCount.size(); i++ ) 2251 { 2252 vvPatternCount[i].resize( vTables.size() ); 2253 2254 for( std::vector< SCTAB >::size_type j = 0; j<vTables.size(); j++ ) 2255 this->ReservedPatternCount( vTables[j], nCol1+i, vvPatternCount[i][j] + ( this->GetPatternCount( vTables[j], nCol1+i, nR1, nR2 ) ) * ( ( nRow2 - nRow1 + 1 ) / ( nYw + 1 ) ) ); 2256 } 2257 2258 bNeedPerformanceOptimization4Pattern = false; 2259 vvPatternCount.clear(); 2260 } 2261 2262 nR1 = nR2 + 1; 2263 nR2 = Min((SCROW)(nR1 + nYw), nRow2); 2264 } while (nR1 <= nRow2); 2265 } 2266 2267 ScColumn::bDoubleAlloc = bOldDouble; 2268 2269 for (SCTAB k = 0; k <= MAXTAB; k++) 2270 if (pTab[k] && rMark.GetTableSelect(k)) 2271 pTab[k]->DecRecalcLevel(); 2272 2273 bInsertingFromOtherDoc = sal_False; 2274 2275 UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw); 2276 2277 // Listener aufbauen nachdem alles inserted wurde 2278 StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag ); 2279 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden 2280 BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag ); 2281 if (bResetCut) 2282 pClipDoc->GetClipParam().mbCutMode = false; 2283 SetAutoCalc( bOldAutoCalc ); 2284 } 2285 } 2286 } 2287 2288 static SCROW lcl_getLastNonFilteredRow( 2289 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags, SCROW nBegRow, SCROW nEndRow, 2290 SCROW nRowCount) 2291 { 2292 SCROW nFilteredRow = rFlags.GetFirstForCondition( 2293 nBegRow, nEndRow, CR_FILTERED, CR_FILTERED); 2294 2295 SCROW nRow = nFilteredRow - 1; 2296 if (nRow - nBegRow + 1 > nRowCount) 2297 // make sure the row range stays within the data size. 2298 nRow = nBegRow + nRowCount - 1; 2299 2300 return nRow; 2301 } 2302 2303 void ScDocument::CopyMultiRangeFromClip( 2304 const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc, 2305 bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty) 2306 { 2307 if (bIsClip) 2308 return; 2309 2310 if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount()) 2311 // There is nothing in the clip doc to copy. 2312 return; 2313 2314 sal_Bool bOldAutoCalc = GetAutoCalc(); 2315 SetAutoCalc( sal_False ); // avoid multiple recalculations 2316 2317 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc); 2318 2319 ScClipRangeNameData aClipRangeNames; 2320 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames); 2321 2322 SCCOL nCol1 = rDestPos.Col(); 2323 SCROW nRow1 = rDestPos.Row(); 2324 ScClipParam& rClipParam = pClipDoc->GetClipParam(); 2325 2326 ScCopyBlockFromClipParams aCBFCP; 2327 aCBFCP.pRefUndoDoc = NULL; 2328 aCBFCP.pClipDoc = pClipDoc; 2329 aCBFCP.nInsFlag = nInsFlag; 2330 aCBFCP.bAsLink = bAsLink; 2331 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty; 2332 aCBFCP.nTabStart = MAXTAB; 2333 aCBFCP.nTabEnd = 0; 2334 2335 for (SCTAB j = 0; j <= MAXTAB; ++j) 2336 { 2337 if (pTab[j] && rMark.GetTableSelect(j)) 2338 { 2339 if ( j < aCBFCP.nTabStart ) 2340 aCBFCP.nTabStart = j; 2341 aCBFCP.nTabEnd = j; 2342 pTab[j]->IncRecalcLevel(); 2343 } 2344 } 2345 2346 ScRange aDestRange; 2347 rMark.GetMarkArea(aDestRange); 2348 SCROW nLastMarkedRow = aDestRange.aEnd.Row(); 2349 2350 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert 2351 2352 SCROW nBegRow = nRow1; 2353 sal_uInt16 nDelFlag = IDF_CONTENTS; 2354 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags = GetRowFlagsArray(aCBFCP.nTabStart); 2355 2356 for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next()) 2357 { 2358 // The begin row must not be filtered. 2359 2360 SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1; 2361 2362 SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col()); 2363 SCsROW nDy = static_cast<SCsROW>(nBegRow - p->aStart.Row()); 2364 SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col(); 2365 2366 SCROW nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount); 2367 2368 if (!bSkipAttrForEmpty) 2369 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag); 2370 2371 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP); 2372 nRowCount -= nEndRow - nBegRow + 1; 2373 2374 while (nRowCount > 0) 2375 { 2376 // Get the first non-filtered row. 2377 SCROW nNonFilteredRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0); 2378 if (nNonFilteredRow > nLastMarkedRow) 2379 return; 2380 2381 SCROW nRowsSkipped = nNonFilteredRow - nEndRow - 1; 2382 nDy += nRowsSkipped; 2383 2384 nBegRow = nNonFilteredRow; 2385 nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount); 2386 2387 if (!bSkipAttrForEmpty) 2388 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag); 2389 2390 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP); 2391 nRowCount -= nEndRow - nBegRow + 1; 2392 } 2393 2394 if (rClipParam.meDirection == ScClipParam::Row) 2395 // Begin row for the next range being pasted. 2396 nBegRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0); 2397 else 2398 nBegRow = nRow1; 2399 2400 if (rClipParam.meDirection == ScClipParam::Column) 2401 nCol1 += p->aEnd.Col() - p->aStart.Col() + 1; 2402 } 2403 2404 for (SCTAB i = 0; i <= MAXTAB; i++) 2405 if (pTab[i] && rMark.GetTableSelect(i)) 2406 pTab[i]->DecRecalcLevel(); 2407 2408 bInsertingFromOtherDoc = sal_False; 2409 2410 ScRangeList aRanges; 2411 aRanges.Append(aDestRange); 2412 SCCOL nCols = aDestRange.aEnd.Col() - aDestRange.aStart.Col() + 1; 2413 SCROW nRows = aDestRange.aEnd.Row() - aDestRange.aStart.Row() + 1; 2414 UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1); 2415 2416 // Listener aufbauen nachdem alles inserted wurde 2417 StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(), 2418 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag ); 2419 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden 2420 BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(), 2421 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag ); 2422 2423 if (bResetCut) 2424 pClipDoc->GetClipParam().mbCutMode = false; 2425 SetAutoCalc( bOldAutoCalc ); 2426 } 2427 2428 void ScDocument::SetClipArea( const ScRange& rArea, sal_Bool bCut ) 2429 { 2430 if (bIsClip) 2431 { 2432 ScClipParam& rClipParam = GetClipParam(); 2433 rClipParam.maRanges.RemoveAll(); 2434 rClipParam.maRanges.Append(rArea); 2435 rClipParam.mbCutMode = bCut; 2436 } 2437 else 2438 { 2439 DBG_ERROR("SetClipArea: kein Clip"); 2440 } 2441 } 2442 2443 2444 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, sal_Bool bIncludeFiltered) 2445 { 2446 if (!bIsClip) 2447 { 2448 DBG_ERROR("GetClipArea: kein Clip"); 2449 return; 2450 } 2451 2452 ScRangeList& rClipRanges = GetClipParam().maRanges; 2453 if (!rClipRanges.Count()) 2454 // No clip range. Bail out. 2455 return; 2456 2457 ScRangePtr p = rClipRanges.First(); 2458 SCCOL nStartCol = p->aStart.Col(); 2459 SCCOL nEndCol = p->aEnd.Col(); 2460 SCROW nStartRow = p->aStart.Row(); 2461 SCROW nEndRow = p->aEnd.Row(); 2462 for (p = rClipRanges.Next(); p; p = rClipRanges.Next()) 2463 { 2464 if (p->aStart.Col() < nStartCol) 2465 nStartCol = p->aStart.Col(); 2466 if (p->aStart.Row() < nStartRow) 2467 nStartRow = p->aStart.Row(); 2468 if (p->aEnd.Col() > nEndCol) 2469 nEndCol = p->aEnd.Col(); 2470 if (p->aEnd.Row() < nEndRow) 2471 nEndRow = p->aEnd.Row(); 2472 } 2473 2474 nClipX = nEndCol - nStartCol; 2475 2476 if ( bIncludeFiltered ) 2477 nClipY = nEndRow - nStartRow; 2478 else 2479 { 2480 // count non-filtered rows 2481 // count on first used table in clipboard 2482 SCTAB nCountTab = 0; 2483 while ( nCountTab < MAXTAB && !pTab[nCountTab] ) 2484 ++nCountTab; 2485 2486 SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab); 2487 2488 if ( nResult > 0 ) 2489 nClipY = nResult - 1; 2490 else 2491 nClipY = 0; // always return at least 1 row 2492 } 2493 } 2494 2495 2496 void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY) 2497 { 2498 if (bIsClip) 2499 { 2500 ScRangeList& rClipRanges = GetClipParam().maRanges; 2501 if (rClipRanges.Count()) 2502 { 2503 nClipX = rClipRanges.First()->aStart.Col(); 2504 nClipY = rClipRanges.First()->aStart.Row(); 2505 } 2506 } 2507 else 2508 { 2509 DBG_ERROR("GetClipStart: kein Clip"); 2510 } 2511 } 2512 2513 2514 sal_Bool ScDocument::HasClipFilteredRows() 2515 { 2516 // count on first used table in clipboard 2517 SCTAB nCountTab = 0; 2518 while ( nCountTab < MAXTAB && !pTab[nCountTab] ) 2519 ++nCountTab; 2520 2521 ScRangeList& rClipRanges = GetClipParam().maRanges; 2522 if (!rClipRanges.Count()) 2523 return false; 2524 2525 for (ScRange* p = rClipRanges.First(); p; p = rClipRanges.Next()) 2526 { 2527 bool bAnswer = pTab[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row()); 2528 if (bAnswer) 2529 return true; 2530 } 2531 return false; 2532 } 2533 2534 2535 void ScDocument::MixDocument( const ScRange& rRange, sal_uInt16 nFunction, sal_Bool bSkipEmpty, 2536 ScDocument* pSrcDoc ) 2537 { 2538 SCTAB nTab1 = rRange.aStart.Tab(); 2539 SCTAB nTab2 = rRange.aEnd.Tab(); 2540 for (SCTAB i = nTab1; i <= nTab2; i++) 2541 if (pTab[i] && pSrcDoc->pTab[i]) 2542 pTab[i]->MixData( rRange.aStart.Col(), rRange.aStart.Row(), 2543 rRange.aEnd.Col(), rRange.aEnd.Row(), 2544 nFunction, bSkipEmpty, pSrcDoc->pTab[i] ); 2545 } 2546 2547 2548 void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark, 2549 sal_uInt16 nFlags, sal_uInt16 nFunction, 2550 sal_Bool bSkipEmpty, sal_Bool bAsLink ) 2551 { 2552 sal_uInt16 nDelFlags = nFlags; 2553 if (nDelFlags & IDF_CONTENTS) 2554 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen! 2555 2556 SCTAB nSrcTab = rSrcArea.aStart.Tab(); 2557 2558 if (ValidTab(nSrcTab) && pTab[nSrcTab]) 2559 { 2560 SCCOL nStartCol = rSrcArea.aStart.Col(); 2561 SCROW nStartRow = rSrcArea.aStart.Row(); 2562 SCCOL nEndCol = rSrcArea.aEnd.Col(); 2563 SCROW nEndRow = rSrcArea.aEnd.Row(); 2564 ScDocument* pMixDoc = NULL; 2565 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS ); 2566 2567 sal_Bool bOldAutoCalc = GetAutoCalc(); 2568 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 2569 2570 SCTAB nCount = GetTableCount(); 2571 for (SCTAB i=0; i<nCount; i++) 2572 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) ) 2573 { 2574 if (bDoMix) 2575 { 2576 if (!pMixDoc) 2577 { 2578 pMixDoc = new ScDocument( SCDOCMODE_UNDO ); 2579 pMixDoc->InitUndo( this, i, i ); 2580 } 2581 else 2582 pMixDoc->AddUndoTab( i, i ); 2583 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2584 IDF_CONTENTS, sal_False, pMixDoc->pTab[i] ); 2585 } 2586 pTab[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags); 2587 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2588 nFlags, sal_False, pTab[i], NULL, bAsLink ); 2589 2590 if (bDoMix) 2591 pTab[i]->MixData( nStartCol,nStartRow, nEndCol,nEndRow, 2592 nFunction, bSkipEmpty, pMixDoc->pTab[i] ); 2593 } 2594 2595 delete pMixDoc; 2596 2597 SetAutoCalc( bOldAutoCalc ); 2598 } 2599 else 2600 { 2601 DBG_ERROR("falsche Tabelle"); 2602 } 2603 } 2604 2605 2606 void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark, 2607 sal_uInt16 nFlags, sal_uInt16 nFunction, 2608 sal_Bool bSkipEmpty, sal_Bool bAsLink ) 2609 { 2610 sal_uInt16 nDelFlags = nFlags; 2611 if (nDelFlags & IDF_CONTENTS) 2612 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen! 2613 2614 if (ValidTab(nSrcTab) && pTab[nSrcTab]) 2615 { 2616 ScDocument* pMixDoc = NULL; 2617 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS ); 2618 2619 sal_Bool bOldAutoCalc = GetAutoCalc(); 2620 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 2621 2622 ScRange aArea; 2623 rMark.GetMultiMarkArea( aArea ); 2624 SCCOL nStartCol = aArea.aStart.Col(); 2625 SCROW nStartRow = aArea.aStart.Row(); 2626 SCCOL nEndCol = aArea.aEnd.Col(); 2627 SCROW nEndRow = aArea.aEnd.Row(); 2628 2629 SCTAB nCount = GetTableCount(); 2630 for (SCTAB i=0; i<nCount; i++) 2631 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) ) 2632 { 2633 if (bDoMix) 2634 { 2635 if (!pMixDoc) 2636 { 2637 pMixDoc = new ScDocument( SCDOCMODE_UNDO ); 2638 pMixDoc->InitUndo( this, i, i ); 2639 } 2640 else 2641 pMixDoc->AddUndoTab( i, i ); 2642 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2643 IDF_CONTENTS, sal_True, pMixDoc->pTab[i], &rMark ); 2644 } 2645 2646 pTab[i]->DeleteSelection( nDelFlags, rMark ); 2647 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow, 2648 nFlags, sal_True, pTab[i], &rMark, bAsLink ); 2649 2650 if (bDoMix) 2651 pTab[i]->MixMarked( rMark, nFunction, bSkipEmpty, pMixDoc->pTab[i] ); 2652 } 2653 2654 delete pMixDoc; 2655 2656 SetAutoCalc( bOldAutoCalc ); 2657 } 2658 else 2659 { 2660 DBG_ERROR("falsche Tabelle"); 2661 } 2662 } 2663 2664 2665 void ScDocument::PutCell( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* pCell, sal_Bool bForceTab ) 2666 { 2667 if (VALIDTAB(nTab)) 2668 { 2669 if ( bForceTab && !pTab[nTab] ) 2670 { 2671 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags 2672 2673 pTab[nTab] = new ScTable(this, nTab, 2674 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")), 2675 bExtras, bExtras); 2676 ++nMaxTableNumber; 2677 } 2678 2679 if (pTab[nTab]) 2680 pTab[nTab]->PutCell( nCol, nRow, pCell ); 2681 } 2682 } 2683 2684 2685 void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell, sal_Bool bForceTab ) 2686 { 2687 SCTAB nTab = rPos.Tab(); 2688 if ( bForceTab && !pTab[nTab] ) 2689 { 2690 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags 2691 2692 pTab[nTab] = new ScTable(this, nTab, 2693 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")), 2694 bExtras, bExtras); 2695 ++nMaxTableNumber; 2696 } 2697 2698 if (pTab[nTab]) 2699 pTab[nTab]->PutCell( rPos, pCell ); 2700 } 2701 2702 2703 sal_Bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString, 2704 SvNumberFormatter* pFormatter, bool bDetectNumberFormat ) 2705 { 2706 if ( ValidTab(nTab) && pTab[nTab] ) 2707 return pTab[nTab]->SetString( nCol, nRow, nTab, rString, pFormatter, bDetectNumberFormat ); 2708 else 2709 return sal_False; 2710 } 2711 2712 2713 void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal ) 2714 { 2715 if (VALIDTAB(nTab)) 2716 if (pTab[nTab]) 2717 pTab[nTab]->SetValue( nCol, nRow, rVal ); 2718 } 2719 2720 2721 void ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString ) 2722 { 2723 if ( VALIDTAB(nTab) && pTab[nTab] ) 2724 pTab[nTab]->GetString( nCol, nRow, rString ); 2725 else 2726 rString.Erase(); 2727 } 2728 2729 void ScDocument::FillDPCache( ScDPTableDataCache * pCache, SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ) 2730 { 2731 if ( VALIDTAB(nTab) && pTab[nTab] ) 2732 pTab[nTab]->FillDPCache( pCache, nStartCol, nEndCol, nStartRow, nEndRow ); 2733 } 2734 2735 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString ) 2736 { 2737 if ( VALIDTAB(nTab) && pTab[nTab] ) 2738 pTab[nTab]->GetInputString( nCol, nRow, rString ); 2739 else 2740 rString.Erase(); 2741 } 2742 2743 2744 sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, rtl::OUString& rString ) 2745 { 2746 // Used in formulas (add-in parameters etc), so it must use the same semantics as 2747 // ScInterpreter::GetCellString: always format values as numbers. 2748 // The return value is the error code. 2749 2750 sal_uInt16 nErr = 0; 2751 String aStr; 2752 ScBaseCell* pCell = GetCell( rPos ); 2753 if (pCell) 2754 { 2755 SvNumberFormatter* pFormatter = GetFormatTable(); 2756 switch (pCell->GetCellType()) 2757 { 2758 case CELLTYPE_STRING: 2759 static_cast<ScStringCell*>(pCell)->GetString(aStr); 2760 break; 2761 case CELLTYPE_EDIT: 2762 static_cast<ScEditCell*>(pCell)->GetString(aStr); 2763 break; 2764 case CELLTYPE_FORMULA: 2765 { 2766 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); 2767 nErr = pFCell->GetErrCode(); 2768 if (pFCell->IsValue()) 2769 { 2770 double fVal = pFCell->GetValue(); 2771 sal_uInt32 nIndex = pFormatter->GetStandardFormat( 2772 NUMBERFORMAT_NUMBER, 2773 ScGlobal::eLnge); 2774 pFormatter->GetInputLineString(fVal, nIndex, aStr); 2775 } 2776 else 2777 pFCell->GetString(aStr); 2778 } 2779 break; 2780 case CELLTYPE_VALUE: 2781 { 2782 double fVal = static_cast<ScValueCell*>(pCell)->GetValue(); 2783 sal_uInt32 nIndex = pFormatter->GetStandardFormat( 2784 NUMBERFORMAT_NUMBER, 2785 ScGlobal::eLnge); 2786 pFormatter->GetInputLineString(fVal, nIndex, aStr); 2787 } 2788 break; 2789 default: 2790 ; 2791 } 2792 } 2793 rString = aStr; 2794 return nErr; 2795 } 2796 2797 2798 void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue ) 2799 { 2800 if ( VALIDTAB(nTab) && pTab[nTab] ) 2801 rValue = pTab[nTab]->GetValue( nCol, nRow ); 2802 else 2803 rValue = 0.0; 2804 } 2805 2806 2807 double ScDocument::GetValue( const ScAddress& rPos ) 2808 { 2809 SCTAB nTab = rPos.Tab(); 2810 if ( pTab[nTab] ) 2811 return pTab[nTab]->GetValue( rPos ); 2812 return 0.0; 2813 } 2814 2815 2816 void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab, 2817 sal_uInt32& rFormat ) 2818 { 2819 if (VALIDTAB(nTab)) 2820 if (pTab[nTab]) 2821 { 2822 rFormat = pTab[nTab]->GetNumberFormat( nCol, nRow ); 2823 return ; 2824 } 2825 rFormat = 0; 2826 } 2827 2828 2829 sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const 2830 { 2831 SCTAB nTab = rPos.Tab(); 2832 if ( pTab[nTab] ) 2833 return pTab[nTab]->GetNumberFormat( rPos ); 2834 return 0; 2835 } 2836 2837 2838 void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex, 2839 const ScAddress& rPos, const ScBaseCell* pCell ) const 2840 { 2841 SCTAB nTab = rPos.Tab(); 2842 if ( pTab[nTab] ) 2843 { 2844 nIndex = pTab[nTab]->GetNumberFormat( rPos ); 2845 if ( (nIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && pCell && 2846 pCell->GetCellType() == CELLTYPE_FORMULA ) 2847 static_cast<const ScFormulaCell*>(pCell)->GetFormatInfo( nType, nIndex ); 2848 else 2849 nType = GetFormatTable()->GetType( nIndex ); 2850 } 2851 else 2852 { 2853 nType = NUMBERFORMAT_UNDEFINED; 2854 nIndex = 0; 2855 } 2856 } 2857 2858 2859 void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rFormula, 2860 sal_Bool bAsciiExport ) const 2861 { 2862 if ( VALIDTAB(nTab) && pTab[nTab] ) 2863 pTab[nTab]->GetFormula( nCol, nRow, rFormula, bAsciiExport ); 2864 else 2865 rFormula.Erase(); 2866 } 2867 2868 2869 CellType ScDocument::GetCellType( const ScAddress& rPos ) const 2870 { 2871 SCTAB nTab = rPos.Tab(); 2872 if ( pTab[nTab] ) 2873 return pTab[nTab]->GetCellType( rPos ); 2874 return CELLTYPE_NONE; 2875 } 2876 2877 2878 void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab, 2879 CellType& rCellType ) const 2880 { 2881 if (ValidTab(nTab) && pTab[nTab]) 2882 rCellType = pTab[nTab]->GetCellType( nCol, nRow ); 2883 else 2884 rCellType = CELLTYPE_NONE; 2885 } 2886 2887 2888 void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab, 2889 ScBaseCell*& rpCell ) const 2890 { 2891 if (ValidTab(nTab) && pTab[nTab]) 2892 rpCell = pTab[nTab]->GetCell( nCol, nRow ); 2893 else 2894 { 2895 DBG_ERROR("GetCell ohne Tabelle"); 2896 rpCell = NULL; 2897 } 2898 } 2899 2900 2901 ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const 2902 { 2903 SCTAB nTab = rPos.Tab(); 2904 if (ValidTab(nTab) && pTab[nTab]) 2905 return pTab[nTab]->GetCell( rPos ); 2906 2907 DBG_ERROR("GetCell ohne Tabelle"); 2908 return NULL; 2909 } 2910 2911 2912 sal_Bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2913 { 2914 if ( VALIDTAB(nTab) && pTab[nTab] ) 2915 return pTab[nTab]->HasStringData( nCol, nRow ); 2916 else 2917 return sal_False; 2918 } 2919 2920 2921 sal_Bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2922 { 2923 if ( VALIDTAB(nTab) && pTab[nTab] ) 2924 return pTab[nTab]->HasValueData( nCol, nRow ); 2925 else 2926 return sal_False; 2927 } 2928 2929 2930 sal_Bool ScDocument::HasStringCells( const ScRange& rRange ) const 2931 { 2932 // sal_True, wenn String- oder Editzellen im Bereich 2933 2934 SCCOL nStartCol = rRange.aStart.Col(); 2935 SCROW nStartRow = rRange.aStart.Row(); 2936 SCTAB nStartTab = rRange.aStart.Tab(); 2937 SCCOL nEndCol = rRange.aEnd.Col(); 2938 SCROW nEndRow = rRange.aEnd.Row(); 2939 SCTAB nEndTab = rRange.aEnd.Tab(); 2940 2941 for ( SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++ ) 2942 if ( pTab[nTab] && pTab[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) ) 2943 return sal_True; 2944 2945 return sal_False; 2946 } 2947 2948 2949 sal_Bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2950 { 2951 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue(); 2952 if( nValidation ) 2953 { 2954 const ScValidationData* pData = GetValidationEntry( nValidation ); 2955 if( pData && pData->HasSelectionList() ) 2956 return sal_True; 2957 } 2958 return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) ); 2959 } 2960 2961 2962 ScPostIt* ScDocument::GetNote( const ScAddress& rPos ) 2963 { 2964 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0; 2965 return pTable ? pTable->GetNote( rPos.Col(), rPos.Row() ) : 0; 2966 } 2967 2968 2969 void ScDocument::TakeNote( const ScAddress& rPos, ScPostIt*& rpNote ) 2970 { 2971 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] ) 2972 pTab[ rPos.Tab() ]->TakeNote( rPos.Col(), rPos.Row(), rpNote ); 2973 else 2974 DELETEZ( rpNote ); 2975 } 2976 2977 2978 ScPostIt* ScDocument::ReleaseNote( const ScAddress& rPos ) 2979 { 2980 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0; 2981 return pTable ? pTable->ReleaseNote( rPos.Col(), rPos.Row() ) : 0; 2982 } 2983 2984 2985 ScPostIt* ScDocument::GetOrCreateNote( const ScAddress& rPos ) 2986 { 2987 ScPostIt* pNote = GetNote( rPos ); 2988 if( !pNote ) 2989 { 2990 pNote = new ScPostIt( *this, rPos, false ); 2991 TakeNote( rPos, pNote ); 2992 } 2993 return pNote; 2994 } 2995 2996 2997 void ScDocument::DeleteNote( const ScAddress& rPos ) 2998 { 2999 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] ) 3000 pTab[ rPos.Tab() ]->DeleteNote( rPos.Col(), rPos.Row() ); 3001 } 3002 3003 3004 void ScDocument::InitializeNoteCaptions( SCTAB nTab, bool bForced ) 3005 { 3006 if( ValidTab( nTab ) && pTab[ nTab ] ) 3007 pTab[ nTab ]->InitializeNoteCaptions( bForced ); 3008 } 3009 3010 void ScDocument::InitializeAllNoteCaptions( bool bForced ) 3011 { 3012 for( SCTAB nTab = 0; nTab < GetTableCount(); ++nTab ) 3013 InitializeNoteCaptions( nTab, bForced ); 3014 } 3015 3016 void ScDocument::SetDirty() 3017 { 3018 sal_Bool bOldAutoCalc = GetAutoCalc(); 3019 bAutoCalc = sal_False; // keine Mehrfachberechnung 3020 { // scope for bulk broadcast 3021 ScBulkBroadcast aBulkBroadcast( GetBASM()); 3022 for (SCTAB i=0; i<=MAXTAB; i++) 3023 if (pTab[i]) pTab[i]->SetDirty(); 3024 } 3025 3026 // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt, 3027 // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt 3028 // (#45205#) - darum alle Charts nochmal explizit 3029 if (pChartListenerCollection) 3030 pChartListenerCollection->SetDirty(); 3031 3032 SetAutoCalc( bOldAutoCalc ); 3033 } 3034 3035 3036 void ScDocument::SetDirty( const ScRange& rRange ) 3037 { 3038 sal_Bool bOldAutoCalc = GetAutoCalc(); 3039 bAutoCalc = sal_False; // keine Mehrfachberechnung 3040 { // scope for bulk broadcast 3041 ScBulkBroadcast aBulkBroadcast( GetBASM()); 3042 SCTAB nTab2 = rRange.aEnd.Tab(); 3043 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++) 3044 if (pTab[i]) pTab[i]->SetDirty( rRange ); 3045 } 3046 SetAutoCalc( bOldAutoCalc ); 3047 } 3048 3049 3050 void ScDocument::SetTableOpDirty( const ScRange& rRange ) 3051 { 3052 sal_Bool bOldAutoCalc = GetAutoCalc(); 3053 bAutoCalc = sal_False; // no multiple recalculation 3054 SCTAB nTab2 = rRange.aEnd.Tab(); 3055 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++) 3056 if (pTab[i]) pTab[i]->SetTableOpDirty( rRange ); 3057 SetAutoCalc( bOldAutoCalc ); 3058 } 3059 3060 3061 void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges ) 3062 { 3063 sal_uLong nRangeCount = rRanges.Count(); 3064 for (sal_uLong nPos=0; nPos<nRangeCount; nPos++) 3065 { 3066 ScCellIterator aIter( this, *rRanges.GetObject(nPos) ); 3067 ScBaseCell* pCell = aIter.GetFirst(); 3068 while (pCell) 3069 { 3070 if (pCell->GetCellType() == CELLTYPE_FORMULA) 3071 { 3072 if ( static_cast<ScFormulaCell*>(pCell)->GetDirty() && GetAutoCalc() ) 3073 static_cast<ScFormulaCell*>(pCell)->Interpret(); 3074 } 3075 pCell = aIter.GetNext(); 3076 } 3077 } 3078 } 3079 3080 3081 void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell ) 3082 { 3083 ScInterpreterTableOpParams* p = aTableOpList.Last(); 3084 if ( p && p->bCollectNotifications ) 3085 { 3086 if ( p->bRefresh ) 3087 { // refresh pointers only 3088 p->aNotifiedFormulaCells.push_back( pCell ); 3089 } 3090 else 3091 { // init both, address and pointer 3092 p->aNotifiedFormulaCells.push_back( pCell ); 3093 p->aNotifiedFormulaPos.push_back( pCell->aPos ); 3094 } 3095 } 3096 } 3097 3098 3099 void ScDocument::CalcAll() 3100 { 3101 ClearLookupCaches(); // Ensure we don't deliver zombie data. 3102 sal_Bool bOldAutoCalc = GetAutoCalc(); 3103 SetAutoCalc( sal_True ); 3104 SCTAB i; 3105 for (i=0; i<=MAXTAB; i++) 3106 if (pTab[i]) pTab[i]->SetDirtyVar(); 3107 for (i=0; i<=MAXTAB; i++) 3108 if (pTab[i]) pTab[i]->CalcAll(); 3109 ClearFormulaTree(); 3110 SetAutoCalc( bOldAutoCalc ); 3111 } 3112 3113 3114 void ScDocument::CompileAll() 3115 { 3116 if ( pCondFormList ) 3117 pCondFormList->CompileAll(); 3118 3119 for (SCTAB i=0; i<=MAXTAB; i++) 3120 if (pTab[i]) pTab[i]->CompileAll(); 3121 SetDirty(); 3122 } 3123 3124 3125 void ScDocument::CompileXML() 3126 { 3127 sal_Bool bOldAutoCalc = GetAutoCalc(); 3128 SetAutoCalc( sal_False ); 3129 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString( 3130 STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() ); 3131 3132 // #b6355215# set AutoNameCache to speed up automatic name lookup 3133 DBG_ASSERT( !pAutoNameCache, "AutoNameCache already set" ); 3134 pAutoNameCache = new ScAutoNameCache( this ); 3135 3136 for (SCTAB i=0; i<=MAXTAB; i++) 3137 if (pTab[i]) pTab[i]->CompileXML( aProgress ); 3138 3139 DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change 3140 3141 if ( pCondFormList ) 3142 pCondFormList->CompileXML(); 3143 if ( pValidationList ) 3144 pValidationList->CompileXML(); 3145 3146 SetDirty(); 3147 SetAutoCalc( bOldAutoCalc ); 3148 } 3149 3150 3151 void ScDocument::CalcAfterLoad() 3152 { 3153 SCTAB i; 3154 3155 if (bIsClip) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen 3156 return; // dann wird erst beim Einfuegen in das richtige Doc berechnet 3157 3158 bCalcingAfterLoad = sal_True; 3159 for ( i = 0; i <= MAXTAB; i++) 3160 if (pTab[i]) pTab[i]->CalcAfterLoad(); 3161 for (i=0; i<=MAXTAB; i++) 3162 if (pTab[i]) pTab[i]->SetDirtyAfterLoad(); 3163 bCalcingAfterLoad = sal_False; 3164 3165 SetDetectiveDirty(sal_False); // noch keine wirklichen Aenderungen 3166 3167 // #i112436# If formula cells are already dirty, they don't broadcast further changes. 3168 // So the source ranges of charts must be interpreted even if they are not visible, 3169 // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899). 3170 if (pChartListenerCollection) 3171 { 3172 sal_uInt16 nChartCount = pChartListenerCollection->GetCount(); 3173 for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ ) 3174 { 3175 ScChartListener* pChartListener = static_cast<ScChartListener*>(pChartListenerCollection->At(nIndex)); 3176 InterpretDirtyCells(*pChartListener->GetRangeList()); 3177 } 3178 } 3179 } 3180 3181 3182 sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const 3183 { 3184 SCTAB nTab = rPos.Tab(); 3185 if ( pTab[nTab] ) 3186 return pTab[nTab]->GetErrCode( rPos ); 3187 return 0; 3188 } 3189 3190 3191 void ScDocument::ResetChanged( const ScRange& rRange ) 3192 { 3193 SCTAB nStartTab = rRange.aStart.Tab(); 3194 SCTAB nEndTab = rRange.aEnd.Tab(); 3195 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3196 if (pTab[nTab]) 3197 pTab[nTab]->ResetChanged( rRange ); 3198 } 3199 3200 // 3201 // Spaltenbreiten / Zeilenhoehen -------------------------------------- 3202 // 3203 3204 3205 void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth ) 3206 { 3207 if ( ValidTab(nTab) && pTab[nTab] ) 3208 pTab[nTab]->SetColWidth( nCol, nNewWidth ); 3209 } 3210 3211 void ScDocument::SetColWidthOnly( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth ) 3212 { 3213 if ( ValidTab(nTab) && pTab[nTab] ) 3214 pTab[nTab]->SetColWidthOnly( nCol, nNewWidth ); 3215 } 3216 3217 void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3218 { 3219 if ( ValidTab(nTab) && pTab[nTab] ) 3220 pTab[nTab]->SetRowHeight( nRow, nNewHeight ); 3221 } 3222 3223 3224 void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3225 { 3226 if ( ValidTab(nTab) && pTab[nTab] ) 3227 pTab[nTab]->SetRowHeightRange 3228 ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 ); 3229 } 3230 3231 void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3232 { 3233 if ( ValidTab(nTab) && pTab[nTab] ) 3234 pTab[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight ); 3235 } 3236 3237 void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_Bool bManual ) 3238 { 3239 if ( ValidTab(nTab) && pTab[nTab] ) 3240 pTab[nTab]->SetManualHeight( nStartRow, nEndRow, bManual ); 3241 } 3242 3243 3244 sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab ) const 3245 { 3246 if ( ValidTab(nTab) && pTab[nTab] ) 3247 return pTab[nTab]->GetColWidth( nCol ); 3248 DBG_ERROR("Falsche Tabellennummer"); 3249 return 0; 3250 } 3251 3252 3253 sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const 3254 { 3255 if ( ValidTab(nTab) && pTab[nTab] ) 3256 return pTab[nTab]->GetOriginalWidth( nCol ); 3257 DBG_ERROR("Falsche Tabellennummer"); 3258 return 0; 3259 } 3260 3261 3262 sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const 3263 { 3264 if ( ValidTab(nTab) && pTab[nTab] ) 3265 return pTab[nTab]->GetCommonWidth( nEndCol ); 3266 DBG_ERROR("Wrong table number"); 3267 return 0; 3268 } 3269 3270 3271 sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const 3272 { 3273 if ( ValidTab(nTab) && pTab[nTab] ) 3274 return pTab[nTab]->GetOriginalHeight( nRow ); 3275 DBG_ERROR("Wrong table number"); 3276 return 0; 3277 } 3278 3279 3280 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const 3281 { 3282 if ( ValidTab(nTab) && pTab[nTab] ) 3283 return pTab[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero ); 3284 DBG_ERROR("Wrong sheet number"); 3285 return 0; 3286 } 3287 3288 3289 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const 3290 { 3291 if ( ValidTab(nTab) && pTab[nTab] ) 3292 return pTab[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero ); 3293 DBG_ERROR("Wrong sheet number"); 3294 return 0; 3295 } 3296 3297 3298 sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const 3299 { 3300 if (nStartRow == nEndRow) 3301 return GetRowHeight( nStartRow, nTab); // faster for a single row 3302 3303 // check bounds because this method replaces former for(i=start;i<=end;++i) loops 3304 if (nStartRow > nEndRow) 3305 return 0; 3306 3307 if ( ValidTab(nTab) && pTab[nTab] ) 3308 return pTab[nTab]->GetRowHeight( nStartRow, nEndRow); 3309 3310 DBG_ERROR("wrong sheet number"); 3311 return 0; 3312 } 3313 3314 SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const 3315 { 3316 return pTab[nTab]->GetRowForHeight(nHeight); 3317 } 3318 3319 sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, 3320 SCTAB nTab, double fScale ) const 3321 { 3322 // faster for a single row 3323 if (nStartRow == nEndRow) 3324 return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale); 3325 3326 // check bounds because this method replaces former for(i=start;i<=end;++i) loops 3327 if (nStartRow > nEndRow) 3328 return 0; 3329 3330 if ( ValidTab(nTab) && pTab[nTab] ) 3331 return pTab[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale); 3332 3333 DBG_ERROR("wrong sheet number"); 3334 return 0; 3335 } 3336 3337 SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const 3338 { 3339 if ( ValidTab(nTab) && pTab[nTab] ) 3340 return pTab[nTab]->GetHiddenRowCount( nRow ); 3341 DBG_ERROR("Falsche Tabellennummer"); 3342 return 0; 3343 } 3344 3345 3346 sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab ) const 3347 { 3348 if ( ValidTab(nTab) && pTab[nTab] ) 3349 return pTab[nTab]->GetColOffset( nCol ); 3350 DBG_ERROR("Falsche Tabellennummer"); 3351 return 0; 3352 } 3353 3354 3355 sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab ) const 3356 { 3357 if ( ValidTab(nTab) && pTab[nTab] ) 3358 return pTab[nTab]->GetRowOffset( nRow ); 3359 DBG_ERROR("Falsche Tabellennummer"); 3360 return 0; 3361 } 3362 3363 3364 sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev, 3365 double nPPTX, double nPPTY, 3366 const Fraction& rZoomX, const Fraction& rZoomY, 3367 sal_Bool bFormula, const ScMarkData* pMarkData, 3368 sal_Bool bSimpleTextImport ) 3369 { 3370 if ( ValidTab(nTab) && pTab[nTab] ) 3371 return pTab[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY, 3372 rZoomX, rZoomY, bFormula, pMarkData, bSimpleTextImport ); 3373 DBG_ERROR("Falsche Tabellennummer"); 3374 return 0; 3375 } 3376 3377 3378 long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab, 3379 OutputDevice* pDev, 3380 double nPPTX, double nPPTY, 3381 const Fraction& rZoomX, const Fraction& rZoomY, 3382 sal_Bool bWidth, sal_Bool bTotalSize ) 3383 { 3384 if ( ValidTab(nTab) && pTab[nTab] ) 3385 return pTab[nTab]->GetNeededSize 3386 ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize ); 3387 DBG_ERROR("Falsche Tabellennummer"); 3388 return 0; 3389 } 3390 3391 3392 sal_Bool ScDocument::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nExtra, 3393 OutputDevice* pDev, 3394 double nPPTX, double nPPTY, 3395 const Fraction& rZoomX, const Fraction& rZoomY, 3396 sal_Bool bShrink ) 3397 { 3398 //! MarkToMulti(); 3399 if ( ValidTab(nTab) && pTab[nTab] ) 3400 return pTab[nTab]->SetOptimalHeight( nStartRow, nEndRow, nExtra, 3401 pDev, nPPTX, nPPTY, rZoomX, rZoomY, bShrink ); 3402 DBG_ERROR("Falsche Tabellennummer"); 3403 return sal_False; 3404 } 3405 3406 3407 void ScDocument::UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY, 3408 const Fraction& rZoomX, const Fraction& rZoomY, const ScMarkData* pTabMark ) 3409 { 3410 // one progress across all (selected) sheets 3411 3412 sal_uLong nCellCount = 0; 3413 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 3414 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) 3415 nCellCount += pTab[nTab]->GetWeightedCount(); 3416 3417 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount ); 3418 3419 sal_uLong nProgressStart = 0; 3420 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 3421 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) 3422 { 3423 pTab[nTab]->SetOptimalHeight( 0, MAXROW, 0, 3424 pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False, &aProgress, nProgressStart ); 3425 nProgressStart += pTab[nTab]->GetWeightedCount(); 3426 } 3427 } 3428 3429 3430 // 3431 // Spalten-/Zeilen-Flags ---------------------------------------------- 3432 // 3433 3434 void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, sal_Bool bShow) 3435 { 3436 if ( ValidTab(nTab) && pTab[nTab] ) 3437 pTab[nTab]->ShowCol( nCol, bShow ); 3438 } 3439 3440 3441 void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, sal_Bool bShow) 3442 { 3443 if ( ValidTab(nTab) && pTab[nTab] ) 3444 pTab[nTab]->ShowRow( nRow, bShow ); 3445 } 3446 3447 3448 void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, sal_Bool bShow) 3449 { 3450 if ( ValidTab(nTab) && pTab[nTab] ) 3451 pTab[nTab]->ShowRows( nRow1, nRow2, bShow ); 3452 } 3453 3454 3455 void ScDocument::SetColFlags( SCCOL nCol, SCTAB nTab, sal_uInt8 nNewFlags ) 3456 { 3457 if ( ValidTab(nTab) && pTab[nTab] ) 3458 pTab[nTab]->SetColFlags( nCol, nNewFlags ); 3459 } 3460 3461 3462 void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags ) 3463 { 3464 if ( ValidTab(nTab) && pTab[nTab] ) 3465 pTab[nTab]->SetRowFlags( nRow, nNewFlags ); 3466 } 3467 3468 3469 void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags ) 3470 { 3471 if ( ValidTab(nTab) && pTab[nTab] ) 3472 pTab[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags ); 3473 } 3474 3475 3476 sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const 3477 { 3478 if ( ValidTab(nTab) && pTab[nTab] ) 3479 return pTab[nTab]->GetColFlags( nCol ); 3480 DBG_ERROR("Falsche Tabellennummer"); 3481 return 0; 3482 } 3483 3484 sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const 3485 { 3486 if ( ValidTab(nTab) && pTab[nTab] ) 3487 return pTab[nTab]->GetRowFlags( nRow ); 3488 DBG_ERROR("Falsche Tabellennummer"); 3489 return 0; 3490 } 3491 3492 ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArrayModifiable( 3493 SCTAB nTab ) 3494 { 3495 return const_cast< ScBitMaskCompressedArray< SCROW, sal_uInt8> & >( 3496 GetRowFlagsArray( nTab)); 3497 } 3498 3499 const ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArray( 3500 SCTAB nTab ) const 3501 { 3502 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pFlags; 3503 if ( ValidTab(nTab) && pTab[nTab] ) 3504 pFlags = pTab[nTab]->GetRowFlagsArray(); 3505 else 3506 { 3507 DBG_ERROR("wrong sheet number"); 3508 pFlags = 0; 3509 } 3510 if (!pFlags) 3511 { 3512 DBG_ERROR("no row flags at sheet"); 3513 static ScBitMaskCompressedArray< SCROW, sal_uInt8> aDummy( MAXROW, 0); 3514 pFlags = &aDummy; 3515 } 3516 return *pFlags; 3517 } 3518 3519 void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const 3520 { 3521 if (!ValidTab(nTab) || !pTab[nTab]) 3522 return; 3523 3524 pTab[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual); 3525 } 3526 3527 void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const 3528 { 3529 if (!ValidTab(nTab) || !pTab[nTab]) 3530 return; 3531 3532 pTab[nTab]->GetAllColBreaks(rBreaks, bPage, bManual); 3533 } 3534 3535 ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const 3536 { 3537 ScBreakType nType = BREAK_NONE; 3538 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3539 return nType; 3540 3541 if (pTab[nTab]->HasRowPageBreak(nRow)) 3542 nType |= BREAK_PAGE; 3543 3544 if (pTab[nTab]->HasRowManualBreak(nRow)) 3545 nType |= BREAK_MANUAL; 3546 3547 return nType; 3548 } 3549 3550 ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const 3551 { 3552 ScBreakType nType = BREAK_NONE; 3553 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3554 return nType; 3555 3556 if (pTab[nTab]->HasColPageBreak(nCol)) 3557 nType |= BREAK_PAGE; 3558 3559 if (pTab[nTab]->HasColManualBreak(nCol)) 3560 nType |= BREAK_MANUAL; 3561 3562 return nType; 3563 } 3564 3565 void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) 3566 { 3567 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3568 return; 3569 3570 pTab[nTab]->SetRowBreak(nRow, bPage, bManual); 3571 } 3572 3573 void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) 3574 { 3575 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3576 return; 3577 3578 pTab[nTab]->SetColBreak(nCol, bPage, bManual); 3579 } 3580 3581 void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) 3582 { 3583 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3584 return; 3585 3586 pTab[nTab]->RemoveRowBreak(nRow, bPage, bManual); 3587 } 3588 3589 void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) 3590 { 3591 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3592 return; 3593 3594 pTab[nTab]->RemoveColBreak(nCol, bPage, bManual); 3595 } 3596 3597 Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const 3598 { 3599 if (!ValidTab(nTab) || !pTab[nTab]) 3600 return Sequence<TablePageBreakData>(); 3601 3602 return pTab[nTab]->GetRowBreakData(); 3603 } 3604 3605 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) 3606 { 3607 if (!ValidTab(nTab) || !pTab[nTab]) 3608 return false; 3609 3610 return pTab[nTab]->RowHidden(nRow, pFirstRow, pLastRow); 3611 } 3612 3613 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastRow) 3614 { 3615 if (!ValidTab(nTab) || !pTab[nTab]) 3616 { 3617 rLastRow = nRow; 3618 return false; 3619 } 3620 3621 return pTab[nTab]->RowHidden(nRow, rLastRow); 3622 } 3623 3624 3625 bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3626 { 3627 if (!ValidTab(nTab) || !pTab[nTab]) 3628 return false; 3629 3630 return pTab[nTab]->HasHiddenRows(nStartRow, nEndRow); 3631 } 3632 3633 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL& rLastCol) 3634 { 3635 if (!ValidTab(nTab) || !pTab[nTab]) 3636 { 3637 rLastCol = nCol; 3638 return false; 3639 } 3640 3641 return pTab[nTab]->ColHidden(nCol, rLastCol); 3642 } 3643 3644 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) 3645 { 3646 if (!ValidTab(nTab) || !pTab[nTab]) 3647 { 3648 if (pFirstCol) 3649 *pFirstCol = nCol; 3650 if (pLastCol) 3651 *pLastCol = nCol; 3652 return false; 3653 } 3654 3655 return pTab[nTab]->ColHidden(nCol, pFirstCol, pLastCol); 3656 } 3657 3658 void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden) 3659 { 3660 if (!ValidTab(nTab) || !pTab[nTab]) 3661 return; 3662 3663 pTab[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden); 3664 } 3665 3666 void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden) 3667 { 3668 if (!ValidTab(nTab) || !pTab[nTab]) 3669 return; 3670 3671 pTab[nTab]->SetColHidden(nStartCol, nEndCol, bHidden); 3672 } 3673 3674 SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3675 { 3676 if (!ValidTab(nTab) || !pTab[nTab]) 3677 return ::std::numeric_limits<SCROW>::max();; 3678 3679 return pTab[nTab]->FirstVisibleRow(nStartRow, nEndRow); 3680 } 3681 3682 SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3683 { 3684 if (!ValidTab(nTab) || !pTab[nTab]) 3685 return ::std::numeric_limits<SCROW>::max();; 3686 3687 return pTab[nTab]->LastVisibleRow(nStartRow, nEndRow); 3688 } 3689 3690 SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3691 { 3692 if (!ValidTab(nTab) || !pTab[nTab]) 3693 return 0; 3694 3695 return pTab[nTab]->CountVisibleRows(nStartRow, nEndRow); 3696 } 3697 3698 bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) 3699 { 3700 if (!ValidTab(nTab) || !pTab[nTab]) 3701 return false; 3702 3703 return pTab[nTab]->RowFiltered(nRow, pFirstRow, pLastRow); 3704 } 3705 3706 bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3707 { 3708 if (!ValidTab(nTab) || !pTab[nTab]) 3709 return false; 3710 3711 return pTab[nTab]->HasFilteredRows(nStartRow, nEndRow); 3712 } 3713 3714 bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) 3715 { 3716 if (!ValidTab(nTab) || !pTab[nTab]) 3717 return false; 3718 3719 return pTab[nTab]->ColFiltered(nCol, pFirstCol, pLastCol); 3720 } 3721 3722 void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered) 3723 { 3724 if (!ValidTab(nTab) || !pTab[nTab]) 3725 return; 3726 3727 pTab[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered); 3728 } 3729 3730 void ScDocument::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bFiltered) 3731 { 3732 if (!ValidTab(nTab) || !pTab[nTab]) 3733 return; 3734 3735 pTab[nTab]->SetColFiltered(nStartCol, nEndCol, bFiltered); 3736 } 3737 3738 SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3739 { 3740 if (!ValidTab(nTab) || !pTab[nTab]) 3741 return ::std::numeric_limits<SCROW>::max();; 3742 3743 return pTab[nTab]->FirstNonFilteredRow(nStartRow, nEndRow); 3744 } 3745 3746 SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3747 { 3748 if (!ValidTab(nTab) || !pTab[nTab]) 3749 return ::std::numeric_limits<SCROW>::max();; 3750 3751 return pTab[nTab]->LastNonFilteredRow(nStartRow, nEndRow); 3752 } 3753 3754 SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3755 { 3756 if (!ValidTab(nTab) || !pTab[nTab]) 3757 return 0; 3758 3759 return pTab[nTab]->CountNonFilteredRows(nStartRow, nEndRow); 3760 } 3761 3762 void ScDocument::SyncColRowFlags() 3763 { 3764 for (SCTAB i = 0; i <= nMaxTableNumber; ++i) 3765 { 3766 if (!ValidTab(i) || !pTab[i]) 3767 continue; 3768 3769 pTab[i]->SyncColRowFlags(); 3770 } 3771 } 3772 3773 SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const 3774 { 3775 if ( ValidTab(nTab) && pTab[nTab] ) 3776 return pTab[nTab]->GetLastFlaggedRow(); 3777 return 0; 3778 } 3779 3780 3781 SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const 3782 { 3783 if ( ValidTab(nTab) && pTab[nTab] ) 3784 return pTab[nTab]->GetLastChangedCol(); 3785 return 0; 3786 } 3787 3788 SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const 3789 { 3790 if ( ValidTab(nTab) && pTab[nTab] ) 3791 return pTab[nTab]->GetLastChangedRow(); 3792 return 0; 3793 } 3794 3795 3796 SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const 3797 { 3798 if ( ValidTab(nTab) && pTab[nTab] ) 3799 { 3800 sal_uInt8 nStartFlags = pTab[nTab]->GetColFlags(nStart); 3801 sal_uInt16 nStartWidth = pTab[nTab]->GetOriginalWidth(nStart); 3802 for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++) 3803 { 3804 if (((nStartFlags & CR_MANUALBREAK) != (pTab[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) || 3805 (nStartWidth != pTab[nTab]->GetOriginalWidth(nCol)) || 3806 ((nStartFlags & CR_HIDDEN) != (pTab[nTab]->GetColFlags(nCol) & CR_HIDDEN)) ) 3807 return nCol; 3808 } 3809 return MAXCOL+1; 3810 } 3811 return 0; 3812 } 3813 3814 SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const 3815 { 3816 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pRowFlagsArray; 3817 if ( ValidTab(nTab) && pTab[nTab] && ((pRowFlagsArray = pTab[nTab]->GetRowFlagsArray()) != NULL) && 3818 pTab[nTab]->mpRowHeights && pTab[nTab]->mpHiddenRows ) 3819 { 3820 size_t nIndex; // ignored 3821 SCROW nFlagsEndRow; 3822 SCROW nHiddenEndRow; 3823 SCROW nHeightEndRow; 3824 sal_uInt8 nFlags; 3825 bool bHidden; 3826 sal_uInt16 nHeight; 3827 sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow); 3828 bool bStartHidden = bHidden = pTab[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow); 3829 sal_uInt16 nStartHeight = nHeight = pTab[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false); 3830 SCROW nRow; 3831 while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW) 3832 { 3833 if (nFlagsEndRow < nRow) 3834 nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow); 3835 if (nHiddenEndRow < nRow) 3836 bHidden = pTab[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow); 3837 if (nHeightEndRow < nRow) 3838 nHeight = pTab[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false); 3839 if ( ((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) || 3840 ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) || 3841 (bStartHidden != bHidden) || 3842 (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) || 3843 (!bCareManualSize && ((nStartHeight != nHeight)))) 3844 return nRow; 3845 } 3846 return MAXROW+1; 3847 } 3848 return 0; 3849 } 3850 3851 sal_Bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault) 3852 { 3853 sal_Bool bRet(sal_False); 3854 nDefault = 0; 3855 ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow); 3856 SCCOL nColumn; 3857 SCROW nStartRow; 3858 SCROW nEndRow; 3859 const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); 3860 if (nEndRow < nLastRow) 3861 { 3862 ScDefaultAttrSet aSet; 3863 ScDefaultAttrSet::iterator aItr = aSet.end(); 3864 while (pAttr) 3865 { 3866 ScDefaultAttr aAttr(pAttr); 3867 aItr = aSet.find(aAttr); 3868 if (aItr == aSet.end()) 3869 { 3870 aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1); 3871 aAttr.nFirst = nStartRow; 3872 aSet.insert(aAttr); 3873 } 3874 else 3875 { 3876 aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1); 3877 aAttr.nFirst = aItr->nFirst; 3878 aSet.erase(aItr); 3879 aSet.insert(aAttr); 3880 } 3881 pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); 3882 } 3883 ScDefaultAttrSet::iterator aDefaultItr = aSet.begin(); 3884 aItr = aDefaultItr; 3885 aItr++; 3886 while (aItr != aSet.end()) 3887 { 3888 // for entries with equal count, use the one with the lowest start row, 3889 // don't use the random order of pointer comparisons 3890 if ( aItr->nCount > aDefaultItr->nCount || 3891 ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) ) 3892 aDefaultItr = aItr; 3893 aItr++; 3894 } 3895 nDefault = aDefaultItr->nFirst; 3896 bRet = sal_True; 3897 } 3898 else 3899 bRet = sal_True; 3900 return bRet; 3901 } 3902 3903 sal_Bool ScDocument::GetRowDefault( SCTAB /* nTab */, SCROW /* nRow */, SCCOL /* nLastCol */, SCCOL& /* nDefault */ ) 3904 { 3905 sal_Bool bRet(sal_False); 3906 return bRet; 3907 } 3908 3909 void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) 3910 { 3911 if ( ValidTab(nTab) && pTab[nTab] ) 3912 pTab[nTab]->StripHidden( rX1, rY1, rX2, rY2 ); 3913 } 3914 3915 3916 void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) 3917 { 3918 if ( ValidTab(nTab) && pTab[nTab] ) 3919 pTab[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 ); 3920 } 3921 3922 // 3923 // Attribute ---------------------------------------------------------- 3924 // 3925 3926 const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const 3927 { 3928 if ( ValidTab(nTab) && pTab[nTab] ) 3929 { 3930 const SfxPoolItem* pTemp = pTab[nTab]->GetAttr( nCol, nRow, nWhich ); 3931 if (pTemp) 3932 return pTemp; 3933 else 3934 { 3935 DBG_ERROR( "Attribut Null" ); 3936 } 3937 } 3938 return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich ); 3939 } 3940 3941 3942 const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 3943 { 3944 if ( ValidTab(nTab) && pTab[nTab] ) 3945 return pTab[nTab]->GetPattern( nCol, nRow ); 3946 return NULL; 3947 } 3948 3949 3950 const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const 3951 { 3952 if ( ValidTab(nTab) && pTab[nTab] ) 3953 return pTab[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow ); 3954 return NULL; 3955 } 3956 3957 3958 void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr ) 3959 { 3960 if ( ValidTab(nTab) && pTab[nTab] ) 3961 pTab[nTab]->ApplyAttr( nCol, nRow, rAttr ); 3962 } 3963 3964 3965 void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr ) 3966 { 3967 if ( ValidTab(nTab) && pTab[nTab] ) 3968 pTab[nTab]->ApplyPattern( nCol, nRow, rAttr ); 3969 } 3970 3971 3972 void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, 3973 SCCOL nEndCol, SCROW nEndRow, 3974 const ScMarkData& rMark, 3975 const ScPatternAttr& rAttr ) 3976 { 3977 for (SCTAB i=0; i <= MAXTAB; i++) 3978 if (pTab[i]) 3979 if (rMark.GetTableSelect(i)) 3980 pTab[i]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr ); 3981 } 3982 3983 3984 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow, 3985 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr ) 3986 { 3987 if (VALIDTAB(nTab)) 3988 if (pTab[nTab]) 3989 pTab[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr ); 3990 } 3991 3992 void ScDocument::ApplyPooledPatternAreaTab( SCCOL nStartCol, SCROW nStartRow, 3993 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rPooledAttr, const ScPatternAttr& rAttr ) 3994 { 3995 if (VALIDTAB(nTab)) 3996 if (pTab[nTab]) 3997 pTab[nTab]->ApplyPooledPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rPooledAttr, rAttr ); 3998 } 3999 4000 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange, 4001 const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType ) 4002 { 4003 for (SCTAB i=0; i <= MAXTAB; i++) 4004 if (pTab[i]) 4005 if (rMark.GetTableSelect(i)) 4006 pTab[i]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType ); 4007 } 4008 4009 4010 void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle) 4011 { 4012 if (VALIDTAB(nTab)) 4013 if (pTab[nTab]) 4014 pTab[nTab]->ApplyStyle( nCol, nRow, rStyle ); 4015 } 4016 4017 4018 void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, 4019 SCCOL nEndCol, SCROW nEndRow, 4020 const ScMarkData& rMark, 4021 const ScStyleSheet& rStyle) 4022 { 4023 for (SCTAB i=0; i <= MAXTAB; i++) 4024 if (pTab[i]) 4025 if (rMark.GetTableSelect(i)) 4026 pTab[i]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); 4027 } 4028 4029 4030 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow, 4031 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle) 4032 { 4033 if (VALIDTAB(nTab)) 4034 if (pTab[nTab]) 4035 pTab[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); 4036 } 4037 4038 4039 void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark) 4040 { 4041 // ApplySelectionStyle needs multi mark 4042 if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) 4043 { 4044 ScRange aRange; 4045 rMark.GetMarkArea( aRange ); 4046 ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(), 4047 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle ); 4048 } 4049 else 4050 { 4051 for (SCTAB i=0; i<=MAXTAB; i++) 4052 if ( pTab[i] && rMark.GetTableSelect(i) ) 4053 pTab[i]->ApplySelectionStyle( rStyle, rMark ); 4054 } 4055 } 4056 4057 4058 void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark, 4059 const SvxBorderLine* pLine, sal_Bool bColorOnly ) 4060 { 4061 if ( bColorOnly && !pLine ) 4062 return; 4063 4064 for (SCTAB i=0; i<=MAXTAB; i++) 4065 if (pTab[i]) 4066 if (rMark.GetTableSelect(i)) 4067 pTab[i]->ApplySelectionLineStyle( rMark, pLine, bColorOnly ); 4068 } 4069 4070 4071 const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4072 { 4073 if ( VALIDTAB(nTab) && pTab[nTab] ) 4074 return pTab[nTab]->GetStyle(nCol, nRow); 4075 else 4076 return NULL; 4077 } 4078 4079 4080 const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const 4081 { 4082 sal_Bool bEqual = sal_True; 4083 sal_Bool bFound; 4084 4085 const ScStyleSheet* pStyle = NULL; 4086 const ScStyleSheet* pNewStyle; 4087 4088 if ( rMark.IsMultiMarked() ) 4089 for (SCTAB i=0; i<=MAXTAB && bEqual; i++) 4090 if (pTab[i] && rMark.GetTableSelect(i)) 4091 { 4092 pNewStyle = pTab[i]->GetSelectionStyle( rMark, bFound ); 4093 if (bFound) 4094 { 4095 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 4096 bEqual = sal_False; // unterschiedliche 4097 pStyle = pNewStyle; 4098 } 4099 } 4100 if ( rMark.IsMarked() ) 4101 { 4102 ScRange aRange; 4103 rMark.GetMarkArea( aRange ); 4104 for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual; i++) 4105 if (pTab[i] && rMark.GetTableSelect(i)) 4106 { 4107 pNewStyle = pTab[i]->GetAreaStyle( bFound, 4108 aRange.aStart.Col(), aRange.aStart.Row(), 4109 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4110 if (bFound) 4111 { 4112 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 4113 bEqual = sal_False; // unterschiedliche 4114 pStyle = pNewStyle; 4115 } 4116 } 4117 } 4118 4119 return bEqual ? pStyle : NULL; 4120 } 4121 4122 4123 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved, 4124 OutputDevice* pDev, 4125 double nPPTX, double nPPTY, 4126 const Fraction& rZoomX, const Fraction& rZoomY ) 4127 { 4128 for (SCTAB i=0; i <= MAXTAB; i++) 4129 if (pTab[i]) 4130 pTab[i]->StyleSheetChanged 4131 ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY ); 4132 4133 if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) ) 4134 { 4135 // update attributes for all note objects 4136 ScDetectiveFunc::UpdateAllComments( *this ); 4137 } 4138 } 4139 4140 4141 sal_Bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const 4142 { 4143 if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN ) 4144 { 4145 if ( bGatherAllStyles ) 4146 { 4147 SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(), 4148 SFX_STYLE_FAMILY_PARA ); 4149 for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle; 4150 pStyle = aIter.Next() ) 4151 { 4152 const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle ); 4153 if ( pScStyle ) 4154 pScStyle->SetUsage( ScStyleSheet::NOTUSED ); 4155 } 4156 } 4157 4158 sal_Bool bIsUsed = sal_False; 4159 4160 for ( SCTAB i=0; i<=MAXTAB; i++ ) 4161 { 4162 if ( pTab[i] ) 4163 { 4164 if ( pTab[i]->IsStyleSheetUsed( rStyle, bGatherAllStyles ) ) 4165 { 4166 if ( !bGatherAllStyles ) 4167 return sal_True; 4168 bIsUsed = sal_True; 4169 } 4170 } 4171 } 4172 4173 if ( bGatherAllStyles ) 4174 bStyleSheetUsageInvalid = sal_False; 4175 4176 return bIsUsed; 4177 } 4178 4179 return rStyle.GetUsage() == ScStyleSheet::USED; 4180 } 4181 4182 4183 sal_Bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow, 4184 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ) 4185 { 4186 if (VALIDTAB(nTab)) 4187 if (pTab[nTab]) 4188 return pTab[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); 4189 4190 DBG_ERROR("ApplyFlags: falsche Tabelle"); 4191 return sal_False; 4192 } 4193 4194 4195 sal_Bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow, 4196 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ) 4197 { 4198 if (VALIDTAB(nTab)) 4199 if (pTab[nTab]) 4200 return pTab[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); 4201 4202 DBG_ERROR("RemoveFlags: falsche Tabelle"); 4203 return sal_False; 4204 } 4205 4206 4207 void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr, 4208 sal_Bool bPutToPool ) 4209 { 4210 if (VALIDTAB(nTab)) 4211 if (pTab[nTab]) 4212 pTab[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool ); 4213 } 4214 4215 4216 void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr, 4217 sal_Bool bPutToPool ) 4218 { 4219 SCTAB nTab = rPos.Tab(); 4220 if (pTab[nTab]) 4221 pTab[nTab]->SetPattern( rPos, rAttr, bPutToPool ); 4222 } 4223 4224 4225 ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep ) 4226 { 4227 ScMergePatternState aState; 4228 4229 if ( rMark.IsMultiMarked() ) // multi selection 4230 { 4231 for (SCTAB i=0; i<=MAXTAB; i++) 4232 if (pTab[i] && rMark.GetTableSelect(i)) 4233 pTab[i]->MergeSelectionPattern( aState, rMark, bDeep ); 4234 } 4235 if ( rMark.IsMarked() ) // simle selection 4236 { 4237 ScRange aRange; 4238 rMark.GetMarkArea(aRange); 4239 for (SCTAB i=0; i<=MAXTAB; i++) 4240 if (pTab[i] && rMark.GetTableSelect(i)) 4241 pTab[i]->MergePatternArea( aState, 4242 aRange.aStart.Col(), aRange.aStart.Row(), 4243 aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep ); 4244 } 4245 4246 DBG_ASSERT( aState.pItemSet, "SelectionPattern Null" ); 4247 if (aState.pItemSet) 4248 return new ScPatternAttr( aState.pItemSet ); 4249 else 4250 return new ScPatternAttr( GetPool() ); // empty 4251 } 4252 4253 4254 const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep ) 4255 { 4256 delete pSelectionAttr; 4257 pSelectionAttr = CreateSelectionPattern( rMark, bDeep ); 4258 return pSelectionAttr; 4259 } 4260 4261 4262 void ScDocument::GetSelectionFrame( const ScMarkData& rMark, 4263 SvxBoxItem& rLineOuter, 4264 SvxBoxInfoItem& rLineInner ) 4265 { 4266 rLineOuter.SetLine(NULL, BOX_LINE_TOP); 4267 rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM); 4268 rLineOuter.SetLine(NULL, BOX_LINE_LEFT); 4269 rLineOuter.SetLine(NULL, BOX_LINE_RIGHT); 4270 rLineOuter.SetDistance(0); 4271 4272 rLineInner.SetLine(NULL, BOXINFO_LINE_HORI); 4273 rLineInner.SetLine(NULL, BOXINFO_LINE_VERT); 4274 rLineInner.SetTable(sal_True); 4275 rLineInner.SetDist(sal_True); 4276 rLineInner.SetMinDist(sal_False); 4277 4278 ScLineFlags aFlags; 4279 4280 if (rMark.IsMarked()) 4281 { 4282 ScRange aRange; 4283 rMark.GetMarkArea(aRange); 4284 rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() ); 4285 rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() ); 4286 for (SCTAB i=0; i<=MAXTAB; i++) 4287 if (pTab[i] && rMark.GetTableSelect(i)) 4288 pTab[i]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags, 4289 aRange.aStart.Col(), aRange.aStart.Row(), 4290 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4291 } 4292 4293 // Don't care Status auswerten 4294 4295 rLineInner.SetValid( VALID_LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) ); 4296 rLineInner.SetValid( VALID_RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) ); 4297 rLineInner.SetValid( VALID_TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) ); 4298 rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) ); 4299 rLineInner.SetValid( VALID_HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) ); 4300 rLineInner.SetValid( VALID_VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) ); 4301 } 4302 4303 4304 bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 4305 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask ) 4306 { 4307 if ( nMask & HASATTR_ROTATE ) 4308 { 4309 // Attribut im Dokument ueberhaupt verwendet? 4310 // (wie in fillinfo) 4311 4312 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 4313 4314 sal_Bool bAnyItem = sal_False; 4315 sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE ); 4316 for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++) 4317 { 4318 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem ); 4319 if ( pItem ) 4320 { 4321 // 90 or 270 degrees is former SvxOrientationItem - only look for other values 4322 // (see ScPatternAttr::GetCellOrientation) 4323 sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue(); 4324 if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 ) 4325 { 4326 bAnyItem = sal_True; 4327 break; 4328 } 4329 } 4330 } 4331 if (!bAnyItem) 4332 nMask &= ~HASATTR_ROTATE; 4333 } 4334 4335 if ( nMask & HASATTR_RTL ) 4336 { 4337 // first check if right-to left is in the pool at all 4338 // (the same item is used in cell and page format) 4339 4340 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 4341 4342 sal_Bool bHasRtl = sal_False; 4343 sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR ); 4344 for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++) 4345 { 4346 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem ); 4347 if ( pItem && ((const SvxFrameDirectionItem*)pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP ) 4348 { 4349 bHasRtl = sal_True; 4350 break; 4351 } 4352 } 4353 if (!bHasRtl) 4354 nMask &= ~HASATTR_RTL; 4355 } 4356 4357 if (!nMask) 4358 return false; 4359 4360 bool bFound = false; 4361 for (SCTAB i=nTab1; i<=nTab2 && !bFound; i++) 4362 if (pTab[i]) 4363 { 4364 if ( nMask & HASATTR_RTL ) 4365 { 4366 if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L ) // sheet default 4367 bFound = true; 4368 } 4369 if ( nMask & HASATTR_RIGHTORCENTER ) 4370 { 4371 // On a RTL sheet, don't start to look for the default left value 4372 // (which is then logically right), instead always assume sal_True. 4373 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets. 4374 4375 if ( IsLayoutRTL(i) ) 4376 bFound = true; 4377 } 4378 4379 if ( !bFound ) 4380 bFound = pTab[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask ); 4381 } 4382 4383 return bFound; 4384 } 4385 4386 bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask ) 4387 { 4388 return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(), 4389 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), 4390 nMask ); 4391 } 4392 4393 void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount, 4394 SCCOL nX1, SCCOL nX2 ) const 4395 { 4396 if ( ValidTab(nTab) && pTab[nTab] ) 4397 pTab[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 ); 4398 else 4399 { 4400 DBG_ERRORFILE("FindMaxRotCol: falsche Tabelle"); 4401 } 4402 } 4403 4404 void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab, 4405 const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop, 4406 const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const 4407 { 4408 //! Seitengrenzen fuer Druck beruecksichtigen !!!!! 4409 4410 const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER ); 4411 DBG_ASSERT(pThisAttr,"wo ist das Attribut?"); 4412 4413 const SvxBorderLine* pLeftLine = pThisAttr->GetLeft(); 4414 const SvxBorderLine* pTopLine = pThisAttr->GetTop(); 4415 const SvxBorderLine* pRightLine = pThisAttr->GetRight(); 4416 const SvxBorderLine* pBottomLine = pThisAttr->GetBottom(); 4417 4418 if ( nCol > 0 ) 4419 { 4420 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4421 GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight(); 4422 if ( ScHasPriority( pOther, pLeftLine ) ) 4423 pLeftLine = pOther; 4424 } 4425 if ( nRow > 0 ) 4426 { 4427 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4428 GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom(); 4429 if ( ScHasPriority( pOther, pTopLine ) ) 4430 pTopLine = pOther; 4431 } 4432 if ( nCol < MAXCOL ) 4433 { 4434 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4435 GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft(); 4436 if ( ScHasPriority( pOther, pRightLine ) ) 4437 pRightLine = pOther; 4438 } 4439 if ( nRow < MAXROW ) 4440 { 4441 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4442 GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop(); 4443 if ( ScHasPriority( pOther, pBottomLine ) ) 4444 pBottomLine = pOther; 4445 } 4446 4447 if (ppLeft) 4448 *ppLeft = pLeftLine; 4449 if (ppTop) 4450 *ppTop = pTopLine; 4451 if (ppRight) 4452 *ppRight = pRightLine; 4453 if (ppBottom) 4454 *ppBottom = pBottomLine; 4455 } 4456 4457 sal_Bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 4458 SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const 4459 { 4460 if (VALIDTAB(nTab)) 4461 if (pTab[nTab]) 4462 return pTab[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes ); 4463 4464 DBG_ERROR("Falsche Tabellennummer"); 4465 return sal_False; 4466 } 4467 4468 4469 void ScDocument::LockTable(SCTAB nTab) 4470 { 4471 if ( ValidTab(nTab) && pTab[nTab] ) 4472 pTab[nTab]->LockTable(); 4473 else 4474 { 4475 DBG_ERROR("Falsche Tabellennummer"); 4476 } 4477 } 4478 4479 4480 void ScDocument::UnlockTable(SCTAB nTab) 4481 { 4482 if ( ValidTab(nTab) && pTab[nTab] ) 4483 pTab[nTab]->UnlockTable(); 4484 else 4485 { 4486 DBG_ERROR("Falsche Tabellennummer"); 4487 } 4488 } 4489 4490 4491 sal_Bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 4492 SCCOL nEndCol, SCROW nEndRow, 4493 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 4494 { 4495 // import into read-only document is possible 4496 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() ) 4497 { 4498 if ( pOnlyNotBecauseOfMatrix ) 4499 *pOnlyNotBecauseOfMatrix = sal_False; 4500 return sal_False; 4501 } 4502 4503 if (VALIDTAB(nTab)) 4504 if (pTab[nTab]) 4505 return pTab[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol, 4506 nEndRow, pOnlyNotBecauseOfMatrix ); 4507 4508 DBG_ERROR("Falsche Tabellennummer"); 4509 if ( pOnlyNotBecauseOfMatrix ) 4510 *pOnlyNotBecauseOfMatrix = sal_False; 4511 return sal_False; 4512 } 4513 4514 4515 sal_Bool ScDocument::IsSelectionEditable( const ScMarkData& rMark, 4516 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 4517 { 4518 // import into read-only document is possible 4519 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() ) 4520 { 4521 if ( pOnlyNotBecauseOfMatrix ) 4522 *pOnlyNotBecauseOfMatrix = sal_False; 4523 return sal_False; 4524 } 4525 4526 ScRange aRange; 4527 rMark.GetMarkArea(aRange); 4528 4529 sal_Bool bOk = sal_True; 4530 sal_Bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL ); 4531 for ( SCTAB i=0; i<=MAXTAB && (bOk || bMatrix); i++ ) 4532 { 4533 if ( pTab[i] && rMark.GetTableSelect(i) ) 4534 { 4535 if (rMark.IsMarked()) 4536 { 4537 if ( !pTab[i]->IsBlockEditable( aRange.aStart.Col(), 4538 aRange.aStart.Row(), aRange.aEnd.Col(), 4539 aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) ) 4540 { 4541 bOk = sal_False; 4542 if ( pOnlyNotBecauseOfMatrix ) 4543 bMatrix = *pOnlyNotBecauseOfMatrix; 4544 } 4545 } 4546 if (rMark.IsMultiMarked()) 4547 { 4548 if ( !pTab[i]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) ) 4549 { 4550 bOk = sal_False; 4551 if ( pOnlyNotBecauseOfMatrix ) 4552 bMatrix = *pOnlyNotBecauseOfMatrix; 4553 } 4554 } 4555 } 4556 } 4557 4558 if ( pOnlyNotBecauseOfMatrix ) 4559 *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix ); 4560 4561 return bOk; 4562 } 4563 4564 4565 sal_Bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow, 4566 SCCOL nEndCol, SCROW nEndRow, 4567 const ScMarkData& rMark ) const 4568 { 4569 sal_Bool bOk = sal_True; 4570 for (SCTAB i=0; i<=MAXTAB && bOk; i++) 4571 if (pTab[i]) 4572 if (rMark.GetTableSelect(i)) 4573 if (pTab[i]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow )) 4574 bOk = sal_False; 4575 4576 return !bOk; 4577 } 4578 4579 4580 sal_Bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix ) 4581 { 4582 // if rCell is part of a matrix formula, return its complete range 4583 4584 sal_Bool bRet = sal_False; 4585 ScBaseCell* pCell = GetCell( rCellPos ); 4586 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) 4587 { 4588 ScAddress aOrigin = rCellPos; 4589 if ( ((ScFormulaCell*)pCell)->GetMatrixOrigin( aOrigin ) ) 4590 { 4591 if ( aOrigin != rCellPos ) 4592 pCell = GetCell( aOrigin ); 4593 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) 4594 { 4595 SCCOL nSizeX; 4596 SCROW nSizeY; 4597 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY); 4598 if ( !(nSizeX > 0 && nSizeY > 0) ) 4599 { 4600 // GetMatrixEdge computes also dimensions of the matrix 4601 // if not already done (may occur if document is loaded 4602 // from old file format). 4603 // Needs an "invalid" initialized address. 4604 aOrigin.SetInvalid(); 4605 ((ScFormulaCell*)pCell)->GetMatrixEdge(aOrigin); 4606 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY); 4607 } 4608 if ( nSizeX > 0 && nSizeY > 0 ) 4609 { 4610 ScAddress aEnd( aOrigin.Col() + nSizeX - 1, 4611 aOrigin.Row() + nSizeY - 1, 4612 aOrigin.Tab() ); 4613 4614 rMatrix.aStart = aOrigin; 4615 rMatrix.aEnd = aEnd; 4616 bRet = sal_True; 4617 } 4618 } 4619 } 4620 } 4621 return bRet; 4622 } 4623 4624 4625 sal_Bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow, 4626 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 4627 { 4628 sal_Bool bFound = sal_False; 4629 if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) ) 4630 { 4631 if (pTab[nTab]) 4632 { 4633 SCCOL nCol; 4634 SCCOL nOldCol = rStartCol; 4635 SCROW nOldRow = rStartRow; 4636 for (nCol=nOldCol; nCol<=nEndCol; nCol++) 4637 while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))-> 4638 IsVerOverlapped()) 4639 --rStartRow; 4640 4641 //! weiterreichen ? 4642 4643 ScAttrArray* pAttrArray = pTab[nTab]->aCol[nOldCol].pAttrArray; 4644 SCSIZE nIndex; 4645 pAttrArray->Search( nOldRow, nIndex ); 4646 SCROW nAttrPos = nOldRow; 4647 while (nAttrPos<=nEndRow) 4648 { 4649 DBG_ASSERT( nIndex < pAttrArray->nCount, "Falscher Index im AttrArray" ); 4650 4651 if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern-> 4652 GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped()) 4653 { 4654 SCROW nLoopEndRow = Min( nEndRow, pAttrArray->pData[nIndex].nRow ); 4655 for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++) 4656 { 4657 SCCOL nTempCol = nOldCol; 4658 do 4659 --nTempCol; 4660 while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG)) 4661 ->IsHorOverlapped()); 4662 if (nTempCol < rStartCol) 4663 rStartCol = nTempCol; 4664 } 4665 } 4666 nAttrPos = pAttrArray->pData[nIndex].nRow + 1; 4667 ++nIndex; 4668 } 4669 } 4670 } 4671 else 4672 { 4673 DBG_ERROR("ExtendOverlapped: falscher Bereich"); 4674 } 4675 4676 return bFound; 4677 } 4678 4679 4680 sal_Bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow, 4681 SCCOL& rEndCol, SCROW& rEndRow, 4682 const ScMarkData& rMark, sal_Bool bRefresh, sal_Bool bAttrs ) 4683 { 4684 // use all selected sheets from rMark 4685 4686 sal_Bool bFound = sal_False; 4687 SCCOL nOldEndCol = rEndCol; 4688 SCROW nOldEndRow = rEndRow; 4689 4690 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) 4691 if ( pTab[nTab] && rMark.GetTableSelect(nTab) ) 4692 { 4693 SCCOL nThisEndCol = nOldEndCol; 4694 SCROW nThisEndRow = nOldEndRow; 4695 if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, nTab, bRefresh, bAttrs ) ) 4696 bFound = sal_True; 4697 if ( nThisEndCol > rEndCol ) 4698 rEndCol = nThisEndCol; 4699 if ( nThisEndRow > rEndRow ) 4700 rEndRow = nThisEndRow; 4701 } 4702 4703 return bFound; 4704 } 4705 4706 4707 sal_Bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow, 4708 SCCOL& rEndCol, SCROW& rEndRow, 4709 SCTAB nTab, sal_Bool bRefresh, sal_Bool bAttrs ) 4710 { 4711 sal_Bool bFound = sal_False; 4712 if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) ) 4713 { 4714 if (pTab[nTab]) 4715 bFound = pTab[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh, bAttrs ); 4716 4717 if (bRefresh) 4718 RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab ); 4719 } 4720 else 4721 { 4722 DBG_ERROR("ExtendMerge: falscher Bereich"); 4723 } 4724 4725 return bFound; 4726 } 4727 4728 4729 sal_Bool ScDocument::ExtendMerge( ScRange& rRange, sal_Bool bRefresh, sal_Bool bAttrs ) 4730 { 4731 sal_Bool bFound = sal_False; 4732 SCTAB nStartTab = rRange.aStart.Tab(); 4733 SCTAB nEndTab = rRange.aEnd.Tab(); 4734 SCCOL nEndCol = rRange.aEnd.Col(); 4735 SCROW nEndRow = rRange.aEnd.Row(); 4736 4737 PutInOrder( nStartTab, nEndTab ); 4738 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ ) 4739 { 4740 SCCOL nExtendCol = rRange.aEnd.Col(); 4741 SCROW nExtendRow = rRange.aEnd.Row(); 4742 if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(), 4743 nExtendCol, nExtendRow, 4744 nTab, bRefresh, bAttrs ) ) 4745 { 4746 bFound = sal_True; 4747 if (nExtendCol > nEndCol) nEndCol = nExtendCol; 4748 if (nExtendRow > nEndRow) nEndRow = nExtendRow; 4749 } 4750 } 4751 4752 rRange.aEnd.SetCol(nEndCol); 4753 rRange.aEnd.SetRow(nEndRow); 4754 4755 return bFound; 4756 } 4757 4758 sal_Bool ScDocument::ExtendTotalMerge( ScRange& rRange ) 4759 { 4760 // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn 4761 // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden 4762 4763 sal_Bool bRet = sal_False; 4764 ScRange aExt = rRange; 4765 if (ExtendMerge(aExt)) 4766 { 4767 if ( aExt.aEnd.Row() > rRange.aEnd.Row() ) 4768 { 4769 ScRange aTest = aExt; 4770 aTest.aStart.SetRow( rRange.aEnd.Row() + 1 ); 4771 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) ) 4772 aExt.aEnd.SetRow(rRange.aEnd.Row()); 4773 } 4774 if ( aExt.aEnd.Col() > rRange.aEnd.Col() ) 4775 { 4776 ScRange aTest = aExt; 4777 aTest.aStart.SetCol( rRange.aEnd.Col() + 1 ); 4778 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) ) 4779 aExt.aEnd.SetCol(rRange.aEnd.Col()); 4780 } 4781 4782 bRet = ( aExt.aEnd != rRange.aEnd ); 4783 rRange = aExt; 4784 } 4785 return bRet; 4786 } 4787 4788 sal_Bool ScDocument::ExtendOverlapped( ScRange& rRange ) 4789 { 4790 sal_Bool bFound = sal_False; 4791 SCTAB nStartTab = rRange.aStart.Tab(); 4792 SCTAB nEndTab = rRange.aEnd.Tab(); 4793 SCCOL nStartCol = rRange.aStart.Col(); 4794 SCROW nStartRow = rRange.aStart.Row(); 4795 4796 PutInOrder( nStartTab, nEndTab ); 4797 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ ) 4798 { 4799 SCCOL nExtendCol = rRange.aStart.Col(); 4800 SCROW nExtendRow = rRange.aStart.Row(); 4801 ExtendOverlapped( nExtendCol, nExtendRow, 4802 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab ); 4803 if (nExtendCol < nStartCol) 4804 { 4805 nStartCol = nExtendCol; 4806 bFound = sal_True; 4807 } 4808 if (nExtendRow < nStartRow) 4809 { 4810 nStartRow = nExtendRow; 4811 bFound = sal_True; 4812 } 4813 } 4814 4815 rRange.aStart.SetCol(nStartCol); 4816 rRange.aStart.SetRow(nStartRow); 4817 4818 return bFound; 4819 } 4820 4821 sal_Bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow, 4822 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 4823 { 4824 sal_uInt16 nCount = pDBCollection->GetCount(); 4825 sal_uInt16 i; 4826 ScDBData* pData; 4827 SCTAB nDBTab; 4828 SCCOL nDBStartCol; 4829 SCROW nDBStartRow; 4830 SCCOL nDBEndCol; 4831 SCROW nDBEndRow; 4832 4833 // Autofilter loeschen 4834 4835 sal_Bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO ); 4836 4837 // Autofilter setzen 4838 4839 for (i=0; i<nCount; i++) 4840 { 4841 pData = (*pDBCollection)[i]; 4842 if (pData->HasAutoFilter()) 4843 { 4844 pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow ); 4845 if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow && 4846 nDBStartCol<=nEndCol && nDBEndCol>=nStartCol ) 4847 { 4848 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow, 4849 nDBTab, SC_MF_AUTO )) 4850 bChange = sal_True; 4851 } 4852 } 4853 } 4854 return bChange; 4855 } 4856 4857 4858 sal_Bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4859 { 4860 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*) 4861 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); 4862 if (pAttr) 4863 return pAttr->IsHorOverlapped(); 4864 else 4865 { 4866 DBG_ERROR("Overlapped: Attr==0"); 4867 return sal_False; 4868 } 4869 } 4870 4871 4872 sal_Bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4873 { 4874 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*) 4875 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); 4876 if (pAttr) 4877 return pAttr->IsVerOverlapped(); 4878 else 4879 { 4880 DBG_ERROR("Overlapped: Attr==0"); 4881 return sal_False; 4882 } 4883 } 4884 4885 4886 void ScDocument::ApplySelectionFrame( const ScMarkData& rMark, 4887 const SvxBoxItem* pLineOuter, 4888 const SvxBoxInfoItem* pLineInner ) 4889 { 4890 ScRangeList aRangeList; 4891 rMark.FillRangeListWithMarks( &aRangeList, sal_False ); 4892 sal_uLong nRangeCount = aRangeList.Count(); 4893 for (SCTAB i=0; i<=MAXTAB; i++) 4894 { 4895 if (pTab[i] && rMark.GetTableSelect(i)) 4896 { 4897 for (sal_uLong j=0; j<nRangeCount; j++) 4898 { 4899 ScRange aRange = *aRangeList.GetObject(j); 4900 pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner, 4901 aRange.aStart.Col(), aRange.aStart.Row(), 4902 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4903 } 4904 } 4905 } 4906 } 4907 4908 4909 void ScDocument::ApplyFrameAreaTab( const ScRange& rRange, 4910 const SvxBoxItem* pLineOuter, 4911 const SvxBoxInfoItem* pLineInner ) 4912 { 4913 SCTAB nStartTab = rRange.aStart.Tab(); 4914 SCTAB nEndTab = rRange.aStart.Tab(); 4915 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 4916 if (pTab[nTab]) 4917 pTab[nTab]->ApplyBlockFrame( pLineOuter, pLineInner, 4918 rRange.aStart.Col(), rRange.aStart.Row(), 4919 rRange.aEnd.Col(), rRange.aEnd.Row() ); 4920 } 4921 4922 4923 void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark ) 4924 { 4925 const SfxItemSet* pSet = &rAttr.GetItemSet(); 4926 sal_Bool bSet = sal_False; 4927 sal_uInt16 i; 4928 for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++) 4929 if (pSet->GetItemState(i) == SFX_ITEM_SET) 4930 bSet = sal_True; 4931 4932 if (bSet) 4933 { 4934 // ApplySelectionCache needs multi mark 4935 if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) 4936 { 4937 ScRange aRange; 4938 rMark.GetMarkArea( aRange ); 4939 ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(), 4940 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr ); 4941 } 4942 else 4943 { 4944 SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet ); 4945 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++) 4946 if (pTab[nTab]) 4947 if (rMark.GetTableSelect(nTab)) 4948 pTab[nTab]->ApplySelectionCache( &aCache, rMark ); 4949 } 4950 } 4951 } 4952 4953 4954 void ScDocument::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark ) 4955 { 4956 for (SCTAB i=0; i<=MAXTAB; i++) 4957 if (pTab[i] && rMark.GetTableSelect(i)) 4958 pTab[i]->ChangeSelectionIndent( bIncrement, rMark ); 4959 } 4960 4961 4962 void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark ) 4963 { 4964 for (SCTAB i=0; i<=MAXTAB; i++) 4965 if (pTab[i] && rMark.GetTableSelect(i)) 4966 pTab[i]->ClearSelectionItems( pWhich, rMark ); 4967 } 4968 4969 4970 void ScDocument::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark ) 4971 { 4972 for (SCTAB i=0; i<=MAXTAB; i++) 4973 if (pTab[i] && rMark.GetTableSelect(i)) 4974 pTab[i]->DeleteSelection( nDelFlag, rMark ); 4975 } 4976 4977 4978 void ScDocument::DeleteSelectionTab( SCTAB nTab, sal_uInt16 nDelFlag, const ScMarkData& rMark ) 4979 { 4980 if (ValidTab(nTab) && pTab[nTab]) 4981 pTab[nTab]->DeleteSelection( nDelFlag, rMark ); 4982 else 4983 { 4984 DBG_ERROR("Falsche Tabelle"); 4985 } 4986 } 4987 4988 4989 ScPatternAttr* ScDocument::GetDefPattern() const 4990 { 4991 return (ScPatternAttr*) &xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN); 4992 } 4993 4994 4995 ScDocumentPool* ScDocument::GetPool() 4996 { 4997 return xPoolHelper->GetDocPool(); 4998 } 4999 5000 5001 5002 ScStyleSheetPool* ScDocument::GetStyleSheetPool() const 5003 { 5004 return xPoolHelper->GetStylePool(); 5005 } 5006 5007 5008 SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, 5009 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir ) 5010 { 5011 PutInOrder(nStartCol, nEndCol); 5012 PutInOrder(nStartRow, nEndRow); 5013 PutInOrder(nStartTab, nEndTab); 5014 if (VALIDTAB(nStartTab)) 5015 { 5016 if (pTab[nStartTab]) 5017 return pTab[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir); 5018 else 5019 return 0; 5020 } 5021 else 5022 return 0; 5023 } 5024 5025 5026 void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY ) 5027 { 5028 if (ValidTab(nTab) && pTab[nTab]) 5029 pTab[nTab]->FindAreaPos( rCol, rRow, nMovX, nMovY ); 5030 } 5031 5032 5033 void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY, 5034 sal_Bool bMarked, sal_Bool bUnprotected, const ScMarkData& rMark ) 5035 { 5036 DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" ); 5037 5038 ScMarkData aCopyMark = rMark; 5039 aCopyMark.SetMarking(sal_False); 5040 aCopyMark.MarkToMulti(); 5041 5042 if (ValidTab(nTab) && pTab[nTab]) 5043 pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark ); 5044 } 5045 5046 // 5047 // Datei-Operationen 5048 // 5049 5050 5051 void ScDocument::UpdStlShtPtrsFrmNms() 5052 { 5053 ScPatternAttr::pDoc = this; 5054 5055 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 5056 5057 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN); 5058 ScPatternAttr* pPattern; 5059 for (sal_uInt32 i=0; i<nCount; i++) 5060 { 5061 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i); 5062 if (pPattern) 5063 pPattern->UpdateStyleSheet(); 5064 } 5065 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet(); 5066 } 5067 5068 5069 void ScDocument::StylesToNames() 5070 { 5071 ScPatternAttr::pDoc = this; 5072 5073 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 5074 5075 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN); 5076 ScPatternAttr* pPattern; 5077 for (sal_uInt32 i=0; i<nCount; i++) 5078 { 5079 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i); 5080 if (pPattern) 5081 pPattern->StyleToName(); 5082 } 5083 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName(); 5084 } 5085 5086 5087 sal_uLong ScDocument::GetCellCount() const 5088 { 5089 sal_uLong nCellCount = 0L; 5090 5091 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5092 if ( pTab[nTab] ) 5093 nCellCount += pTab[nTab]->GetCellCount(); 5094 5095 return nCellCount; 5096 } 5097 5098 SCSIZE ScDocument::GetCellCount(SCTAB nTab, SCCOL nCol) const 5099 { 5100 if (!ValidTab(nTab) || !pTab[nTab]) 5101 return 0; 5102 5103 return pTab[nTab]->GetCellCount(nCol); 5104 } 5105 5106 sal_uLong ScDocument::GetCodeCount() const 5107 { 5108 sal_uLong nCodeCount = 0; 5109 5110 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5111 if ( pTab[nTab] ) 5112 nCodeCount += pTab[nTab]->GetCodeCount(); 5113 5114 return nCodeCount; 5115 } 5116 5117 5118 sal_uLong ScDocument::GetWeightedCount() const 5119 { 5120 sal_uLong nCellCount = 0L; 5121 5122 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5123 if ( pTab[nTab] ) 5124 nCellCount += pTab[nTab]->GetWeightedCount(); 5125 5126 return nCellCount; 5127 } 5128 5129 5130 void ScDocument::PageStyleModified( SCTAB nTab, const String& rNewName ) 5131 { 5132 if ( ValidTab(nTab) && pTab[nTab] ) 5133 pTab[nTab]->PageStyleModified( rNewName ); 5134 } 5135 5136 5137 void ScDocument::SetPageStyle( SCTAB nTab, const String& rName ) 5138 { 5139 if ( ValidTab(nTab) && pTab[nTab] ) 5140 pTab[nTab]->SetPageStyle( rName ); 5141 } 5142 5143 5144 const String& ScDocument::GetPageStyle( SCTAB nTab ) const 5145 { 5146 if ( ValidTab(nTab) && pTab[nTab] ) 5147 return pTab[nTab]->GetPageStyle(); 5148 5149 return EMPTY_STRING; 5150 } 5151 5152 5153 void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize ) 5154 { 5155 if ( ValidTab(nTab) && pTab[nTab] ) 5156 pTab[nTab]->SetPageSize( rSize ); 5157 } 5158 5159 Size ScDocument::GetPageSize( SCTAB nTab ) const 5160 { 5161 if ( ValidTab(nTab) && pTab[nTab] ) 5162 return pTab[nTab]->GetPageSize(); 5163 5164 DBG_ERROR("falsche Tab"); 5165 return Size(); 5166 } 5167 5168 5169 void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ) 5170 { 5171 if ( ValidTab(nTab) && pTab[nTab] ) 5172 pTab[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow ); 5173 } 5174 5175 void ScDocument::InvalidatePageBreaks(SCTAB nTab) 5176 { 5177 if (ValidTab(nTab) && pTab[nTab]) 5178 pTab[nTab]->InvalidatePageBreaks(); 5179 } 5180 5181 void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea ) 5182 { 5183 if ( ValidTab(nTab) && pTab[nTab] ) 5184 pTab[nTab]->UpdatePageBreaks( pUserArea ); 5185 } 5186 5187 void ScDocument::RemoveManualBreaks( SCTAB nTab ) 5188 { 5189 if ( ValidTab(nTab) && pTab[nTab] ) 5190 pTab[nTab]->RemoveManualBreaks(); 5191 } 5192 5193 sal_Bool ScDocument::HasManualBreaks( SCTAB nTab ) const 5194 { 5195 if ( ValidTab(nTab) && pTab[nTab] ) 5196 return pTab[nTab]->HasManualBreaks(); 5197 5198 DBG_ERROR("falsche Tab"); 5199 return sal_False; 5200 } 5201 5202 5203 void ScDocument::GetDocStat( ScDocStat& rDocStat ) 5204 { 5205 rDocStat.nTableCount = GetTableCount(); 5206 rDocStat.aDocName = aDocName; 5207 rDocStat.nCellCount = GetCellCount(); 5208 } 5209 5210 5211 sal_Bool ScDocument::HasPrintRange() 5212 { 5213 sal_Bool bResult = sal_False; 5214 5215 for ( SCTAB i=0; !bResult && i<nMaxTableNumber; i++ ) 5216 if ( pTab[i] ) 5217 bResult = pTab[i]->IsPrintEntireSheet() || (pTab[i]->GetPrintRangeCount() > 0); 5218 5219 return bResult; 5220 } 5221 5222 5223 sal_Bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const 5224 { 5225 return (ValidTab(nTab) ) && pTab[nTab] && pTab[nTab]->IsPrintEntireSheet(); 5226 } 5227 5228 5229 sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab ) 5230 { 5231 if (ValidTab(nTab) && pTab[nTab]) 5232 return pTab[nTab]->GetPrintRangeCount(); 5233 5234 return 0; 5235 } 5236 5237 5238 const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos ) 5239 { 5240 if (ValidTab(nTab) && pTab[nTab]) 5241 return pTab[nTab]->GetPrintRange(nPos); 5242 5243 return NULL; 5244 } 5245 5246 5247 const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab ) 5248 { 5249 if (ValidTab(nTab) && pTab[nTab]) 5250 return pTab[nTab]->GetRepeatColRange(); 5251 5252 return NULL; 5253 } 5254 5255 5256 const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab ) 5257 { 5258 if (ValidTab(nTab) && pTab[nTab]) 5259 return pTab[nTab]->GetRepeatRowRange(); 5260 5261 return NULL; 5262 } 5263 5264 5265 void ScDocument::ClearPrintRanges( SCTAB nTab ) 5266 { 5267 if (ValidTab(nTab) && pTab[nTab]) 5268 pTab[nTab]->ClearPrintRanges(); 5269 } 5270 5271 5272 void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew ) 5273 { 5274 if (ValidTab(nTab) && pTab[nTab]) 5275 pTab[nTab]->AddPrintRange( rNew ); 5276 } 5277 5278 5279 //UNUSED2009-05 void ScDocument::SetPrintRange( SCTAB nTab, const ScRange& rNew ) 5280 //UNUSED2009-05 { 5281 //UNUSED2009-05 if (ValidTab(nTab) && pTab[nTab]) 5282 //UNUSED2009-05 pTab[nTab]->SetPrintRange( rNew ); 5283 //UNUSED2009-05 } 5284 5285 5286 void ScDocument::SetPrintEntireSheet( SCTAB nTab ) 5287 { 5288 if (ValidTab(nTab) && pTab[nTab]) 5289 pTab[nTab]->SetPrintEntireSheet(); 5290 } 5291 5292 5293 void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew ) 5294 { 5295 if (ValidTab(nTab) && pTab[nTab]) 5296 pTab[nTab]->SetRepeatColRange( pNew ); 5297 } 5298 5299 5300 void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew ) 5301 { 5302 if (ValidTab(nTab) && pTab[nTab]) 5303 pTab[nTab]->SetRepeatRowRange( pNew ); 5304 } 5305 5306 5307 ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const 5308 { 5309 SCTAB nCount = GetTableCount(); 5310 ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount ); 5311 for (SCTAB i=0; i<nCount; i++) 5312 if (pTab[i]) 5313 pTab[i]->FillPrintSaver( pNew->GetTabData(i) ); 5314 return pNew; 5315 } 5316 5317 5318 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver ) 5319 { 5320 SCTAB nCount = rSaver.GetTabCount(); 5321 for (SCTAB i=0; i<nCount; i++) 5322 if (pTab[i]) 5323 pTab[i]->RestorePrintRanges( rSaver.GetTabData(i) ); 5324 } 5325 5326 5327 sal_Bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const 5328 { 5329 // Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine 5330 // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen) 5331 // und eine Seitennummer angegeben ist (nicht 0) 5332 5333 if ( nTab < MAXTAB && pTab[nTab] && pTab[nTab+1] ) 5334 { 5335 String aNew = pTab[nTab+1]->GetPageStyle(); 5336 if ( aNew != pTab[nTab]->GetPageStyle() ) 5337 { 5338 SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE ); 5339 if ( pStyle ) 5340 { 5341 const SfxItemSet& rSet = pStyle->GetItemSet(); 5342 sal_uInt16 nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue(); 5343 if ( nFirst != 0 ) 5344 return sal_True; // Seitennummer in neuer Vorlage angegeben 5345 } 5346 } 5347 } 5348 5349 return sal_False; // sonst nicht 5350 } 5351 5352 SfxUndoManager* ScDocument::GetUndoManager() 5353 { 5354 if (!mpUndoManager) 5355 { 5356 // to support enhanced text edit for draw objects, use an SdrUndoManager 5357 mpUndoManager = new SdrUndoManager; 5358 } 5359 5360 return mpUndoManager; 5361 } 5362 5363 ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const 5364 { 5365 if (ValidTab(nTab) && pTab[nTab]) 5366 return new ScRowBreakIterator(pTab[nTab]->maRowPageBreaks); 5367 return NULL; 5368 } 5369 5370 void ScDocument::EnableUndo( bool bVal ) 5371 { 5372 GetUndoManager()->EnableUndo(bVal); 5373 if( pDrawLayer ) pDrawLayer->EnableUndo(bVal); 5374 mbUndoEnabled = bVal; 5375 } 5376 5377 bool ScDocument::IsInVBAMode() const 5378 { 5379 bool bResult = false; 5380 if ( pShell ) 5381 { 5382 com::sun::star::uno::Reference< com::sun::star::script::vba::XVBACompatibility > xVBA( pShell->GetBasicContainer(), com::sun::star::uno::UNO_QUERY ); 5383 bResult = xVBA.is() && xVBA->getVBACompatibilityMode(); 5384 } 5385 return bResult; 5386 } 5387