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