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