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