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 void ScDocument::FillDPCache( ScDPTableDataCache * pCache, SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ) 2687 { 2688 if ( VALIDTAB(nTab) && pTab[nTab] ) 2689 pTab[nTab]->FillDPCache( pCache, nStartCol, nEndCol, nStartRow, nEndRow ); 2690 } 2691 2692 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString ) 2693 { 2694 if ( VALIDTAB(nTab) && pTab[nTab] ) 2695 pTab[nTab]->GetInputString( nCol, nRow, rString ); 2696 else 2697 rString.Erase(); 2698 } 2699 2700 2701 sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, rtl::OUString& rString ) 2702 { 2703 // Used in formulas (add-in parameters etc), so it must use the same semantics as 2704 // ScInterpreter::GetCellString: always format values as numbers. 2705 // The return value is the error code. 2706 2707 sal_uInt16 nErr = 0; 2708 String aStr; 2709 ScBaseCell* pCell = GetCell( rPos ); 2710 if (pCell) 2711 { 2712 SvNumberFormatter* pFormatter = GetFormatTable(); 2713 switch (pCell->GetCellType()) 2714 { 2715 case CELLTYPE_STRING: 2716 static_cast<ScStringCell*>(pCell)->GetString(aStr); 2717 break; 2718 case CELLTYPE_EDIT: 2719 static_cast<ScEditCell*>(pCell)->GetString(aStr); 2720 break; 2721 case CELLTYPE_FORMULA: 2722 { 2723 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); 2724 nErr = pFCell->GetErrCode(); 2725 if (pFCell->IsValue()) 2726 { 2727 double fVal = pFCell->GetValue(); 2728 sal_uInt32 nIndex = pFormatter->GetStandardFormat( 2729 NUMBERFORMAT_NUMBER, 2730 ScGlobal::eLnge); 2731 pFormatter->GetInputLineString(fVal, nIndex, aStr); 2732 } 2733 else 2734 pFCell->GetString(aStr); 2735 } 2736 break; 2737 case CELLTYPE_VALUE: 2738 { 2739 double fVal = static_cast<ScValueCell*>(pCell)->GetValue(); 2740 sal_uInt32 nIndex = pFormatter->GetStandardFormat( 2741 NUMBERFORMAT_NUMBER, 2742 ScGlobal::eLnge); 2743 pFormatter->GetInputLineString(fVal, nIndex, aStr); 2744 } 2745 break; 2746 default: 2747 ; 2748 } 2749 } 2750 rString = aStr; 2751 return nErr; 2752 } 2753 2754 2755 void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue ) 2756 { 2757 if ( VALIDTAB(nTab) && pTab[nTab] ) 2758 rValue = pTab[nTab]->GetValue( nCol, nRow ); 2759 else 2760 rValue = 0.0; 2761 } 2762 2763 2764 double ScDocument::GetValue( const ScAddress& rPos ) 2765 { 2766 SCTAB nTab = rPos.Tab(); 2767 if ( pTab[nTab] ) 2768 return pTab[nTab]->GetValue( rPos ); 2769 return 0.0; 2770 } 2771 2772 2773 void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab, 2774 sal_uInt32& rFormat ) 2775 { 2776 if (VALIDTAB(nTab)) 2777 if (pTab[nTab]) 2778 { 2779 rFormat = pTab[nTab]->GetNumberFormat( nCol, nRow ); 2780 return ; 2781 } 2782 rFormat = 0; 2783 } 2784 2785 2786 sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const 2787 { 2788 SCTAB nTab = rPos.Tab(); 2789 if ( pTab[nTab] ) 2790 return pTab[nTab]->GetNumberFormat( rPos ); 2791 return 0; 2792 } 2793 2794 2795 void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex, 2796 const ScAddress& rPos, const ScBaseCell* pCell ) const 2797 { 2798 SCTAB nTab = rPos.Tab(); 2799 if ( pTab[nTab] ) 2800 { 2801 nIndex = pTab[nTab]->GetNumberFormat( rPos ); 2802 if ( (nIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && pCell && 2803 pCell->GetCellType() == CELLTYPE_FORMULA ) 2804 static_cast<const ScFormulaCell*>(pCell)->GetFormatInfo( nType, nIndex ); 2805 else 2806 nType = GetFormatTable()->GetType( nIndex ); 2807 } 2808 else 2809 { 2810 nType = NUMBERFORMAT_UNDEFINED; 2811 nIndex = 0; 2812 } 2813 } 2814 2815 2816 void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rFormula, 2817 sal_Bool bAsciiExport ) const 2818 { 2819 if ( VALIDTAB(nTab) && pTab[nTab] ) 2820 pTab[nTab]->GetFormula( nCol, nRow, rFormula, bAsciiExport ); 2821 else 2822 rFormula.Erase(); 2823 } 2824 2825 2826 CellType ScDocument::GetCellType( const ScAddress& rPos ) const 2827 { 2828 SCTAB nTab = rPos.Tab(); 2829 if ( pTab[nTab] ) 2830 return pTab[nTab]->GetCellType( rPos ); 2831 return CELLTYPE_NONE; 2832 } 2833 2834 2835 void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab, 2836 CellType& rCellType ) const 2837 { 2838 if (ValidTab(nTab) && pTab[nTab]) 2839 rCellType = pTab[nTab]->GetCellType( nCol, nRow ); 2840 else 2841 rCellType = CELLTYPE_NONE; 2842 } 2843 2844 2845 void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab, 2846 ScBaseCell*& rpCell ) const 2847 { 2848 if (ValidTab(nTab) && pTab[nTab]) 2849 rpCell = pTab[nTab]->GetCell( nCol, nRow ); 2850 else 2851 { 2852 DBG_ERROR("GetCell ohne Tabelle"); 2853 rpCell = NULL; 2854 } 2855 } 2856 2857 2858 ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const 2859 { 2860 SCTAB nTab = rPos.Tab(); 2861 if (ValidTab(nTab) && pTab[nTab]) 2862 return pTab[nTab]->GetCell( rPos ); 2863 2864 DBG_ERROR("GetCell ohne Tabelle"); 2865 return NULL; 2866 } 2867 2868 2869 sal_Bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2870 { 2871 if ( VALIDTAB(nTab) && pTab[nTab] ) 2872 return pTab[nTab]->HasStringData( nCol, nRow ); 2873 else 2874 return sal_False; 2875 } 2876 2877 2878 sal_Bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2879 { 2880 if ( VALIDTAB(nTab) && pTab[nTab] ) 2881 return pTab[nTab]->HasValueData( nCol, nRow ); 2882 else 2883 return sal_False; 2884 } 2885 2886 2887 sal_Bool ScDocument::HasStringCells( const ScRange& rRange ) const 2888 { 2889 // sal_True, wenn String- oder Editzellen im Bereich 2890 2891 SCCOL nStartCol = rRange.aStart.Col(); 2892 SCROW nStartRow = rRange.aStart.Row(); 2893 SCTAB nStartTab = rRange.aStart.Tab(); 2894 SCCOL nEndCol = rRange.aEnd.Col(); 2895 SCROW nEndRow = rRange.aEnd.Row(); 2896 SCTAB nEndTab = rRange.aEnd.Tab(); 2897 2898 for ( SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++ ) 2899 if ( pTab[nTab] && pTab[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) ) 2900 return sal_True; 2901 2902 return sal_False; 2903 } 2904 2905 2906 sal_Bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 2907 { 2908 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue(); 2909 if( nValidation ) 2910 { 2911 const ScValidationData* pData = GetValidationEntry( nValidation ); 2912 if( pData && pData->HasSelectionList() ) 2913 return sal_True; 2914 } 2915 return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) ); 2916 } 2917 2918 2919 ScPostIt* ScDocument::GetNote( const ScAddress& rPos ) 2920 { 2921 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0; 2922 return pTable ? pTable->GetNote( rPos.Col(), rPos.Row() ) : 0; 2923 } 2924 2925 2926 void ScDocument::TakeNote( const ScAddress& rPos, ScPostIt*& rpNote ) 2927 { 2928 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] ) 2929 pTab[ rPos.Tab() ]->TakeNote( rPos.Col(), rPos.Row(), rpNote ); 2930 else 2931 DELETEZ( rpNote ); 2932 } 2933 2934 2935 ScPostIt* ScDocument::ReleaseNote( const ScAddress& rPos ) 2936 { 2937 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0; 2938 return pTable ? pTable->ReleaseNote( rPos.Col(), rPos.Row() ) : 0; 2939 } 2940 2941 2942 ScPostIt* ScDocument::GetOrCreateNote( const ScAddress& rPos ) 2943 { 2944 ScPostIt* pNote = GetNote( rPos ); 2945 if( !pNote ) 2946 { 2947 pNote = new ScPostIt( *this, rPos, false ); 2948 TakeNote( rPos, pNote ); 2949 } 2950 return pNote; 2951 } 2952 2953 2954 void ScDocument::DeleteNote( const ScAddress& rPos ) 2955 { 2956 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] ) 2957 pTab[ rPos.Tab() ]->DeleteNote( rPos.Col(), rPos.Row() ); 2958 } 2959 2960 2961 void ScDocument::InitializeNoteCaptions( SCTAB nTab, bool bForced ) 2962 { 2963 if( ValidTab( nTab ) && pTab[ nTab ] ) 2964 pTab[ nTab ]->InitializeNoteCaptions( bForced ); 2965 } 2966 2967 void ScDocument::InitializeAllNoteCaptions( bool bForced ) 2968 { 2969 for( SCTAB nTab = 0; nTab < GetTableCount(); ++nTab ) 2970 InitializeNoteCaptions( nTab, bForced ); 2971 } 2972 2973 void ScDocument::SetDirty() 2974 { 2975 sal_Bool bOldAutoCalc = GetAutoCalc(); 2976 bAutoCalc = sal_False; // keine Mehrfachberechnung 2977 { // scope for bulk broadcast 2978 ScBulkBroadcast aBulkBroadcast( GetBASM()); 2979 for (SCTAB i=0; i<=MAXTAB; i++) 2980 if (pTab[i]) pTab[i]->SetDirty(); 2981 } 2982 2983 // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt, 2984 // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt 2985 // (#45205#) - darum alle Charts nochmal explizit 2986 if (pChartListenerCollection) 2987 pChartListenerCollection->SetDirty(); 2988 2989 SetAutoCalc( bOldAutoCalc ); 2990 } 2991 2992 2993 void ScDocument::SetDirty( const ScRange& rRange ) 2994 { 2995 sal_Bool bOldAutoCalc = GetAutoCalc(); 2996 bAutoCalc = sal_False; // keine Mehrfachberechnung 2997 { // scope for bulk broadcast 2998 ScBulkBroadcast aBulkBroadcast( GetBASM()); 2999 SCTAB nTab2 = rRange.aEnd.Tab(); 3000 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++) 3001 if (pTab[i]) pTab[i]->SetDirty( rRange ); 3002 } 3003 SetAutoCalc( bOldAutoCalc ); 3004 } 3005 3006 3007 void ScDocument::SetTableOpDirty( const ScRange& rRange ) 3008 { 3009 sal_Bool bOldAutoCalc = GetAutoCalc(); 3010 bAutoCalc = sal_False; // no multiple recalculation 3011 SCTAB nTab2 = rRange.aEnd.Tab(); 3012 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++) 3013 if (pTab[i]) pTab[i]->SetTableOpDirty( rRange ); 3014 SetAutoCalc( bOldAutoCalc ); 3015 } 3016 3017 3018 void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges ) 3019 { 3020 sal_uLong nRangeCount = rRanges.Count(); 3021 for (sal_uLong nPos=0; nPos<nRangeCount; nPos++) 3022 { 3023 ScCellIterator aIter( this, *rRanges.GetObject(nPos) ); 3024 ScBaseCell* pCell = aIter.GetFirst(); 3025 while (pCell) 3026 { 3027 if (pCell->GetCellType() == CELLTYPE_FORMULA) 3028 { 3029 if ( static_cast<ScFormulaCell*>(pCell)->GetDirty() && GetAutoCalc() ) 3030 static_cast<ScFormulaCell*>(pCell)->Interpret(); 3031 } 3032 pCell = aIter.GetNext(); 3033 } 3034 } 3035 } 3036 3037 3038 void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell ) 3039 { 3040 ScInterpreterTableOpParams* p = aTableOpList.Last(); 3041 if ( p && p->bCollectNotifications ) 3042 { 3043 if ( p->bRefresh ) 3044 { // refresh pointers only 3045 p->aNotifiedFormulaCells.push_back( pCell ); 3046 } 3047 else 3048 { // init both, address and pointer 3049 p->aNotifiedFormulaCells.push_back( pCell ); 3050 p->aNotifiedFormulaPos.push_back( pCell->aPos ); 3051 } 3052 } 3053 } 3054 3055 3056 void ScDocument::CalcAll() 3057 { 3058 ClearLookupCaches(); // Ensure we don't deliver zombie data. 3059 sal_Bool bOldAutoCalc = GetAutoCalc(); 3060 SetAutoCalc( sal_True ); 3061 SCTAB i; 3062 for (i=0; i<=MAXTAB; i++) 3063 if (pTab[i]) pTab[i]->SetDirtyVar(); 3064 for (i=0; i<=MAXTAB; i++) 3065 if (pTab[i]) pTab[i]->CalcAll(); 3066 ClearFormulaTree(); 3067 SetAutoCalc( bOldAutoCalc ); 3068 } 3069 3070 3071 void ScDocument::CompileAll() 3072 { 3073 if ( pCondFormList ) 3074 pCondFormList->CompileAll(); 3075 3076 for (SCTAB i=0; i<=MAXTAB; i++) 3077 if (pTab[i]) pTab[i]->CompileAll(); 3078 SetDirty(); 3079 } 3080 3081 3082 void ScDocument::CompileXML() 3083 { 3084 sal_Bool bOldAutoCalc = GetAutoCalc(); 3085 SetAutoCalc( sal_False ); 3086 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString( 3087 STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() ); 3088 3089 // #b6355215# set AutoNameCache to speed up automatic name lookup 3090 DBG_ASSERT( !pAutoNameCache, "AutoNameCache already set" ); 3091 pAutoNameCache = new ScAutoNameCache( this ); 3092 3093 for (SCTAB i=0; i<=MAXTAB; i++) 3094 if (pTab[i]) pTab[i]->CompileXML( aProgress ); 3095 3096 DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change 3097 3098 if ( pCondFormList ) 3099 pCondFormList->CompileXML(); 3100 if ( pValidationList ) 3101 pValidationList->CompileXML(); 3102 3103 SetDirty(); 3104 SetAutoCalc( bOldAutoCalc ); 3105 } 3106 3107 3108 void ScDocument::CalcAfterLoad() 3109 { 3110 SCTAB i; 3111 3112 if (bIsClip) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen 3113 return; // dann wird erst beim Einfuegen in das richtige Doc berechnet 3114 3115 bCalcingAfterLoad = sal_True; 3116 for ( i = 0; i <= MAXTAB; i++) 3117 if (pTab[i]) pTab[i]->CalcAfterLoad(); 3118 for (i=0; i<=MAXTAB; i++) 3119 if (pTab[i]) pTab[i]->SetDirtyAfterLoad(); 3120 bCalcingAfterLoad = sal_False; 3121 3122 SetDetectiveDirty(sal_False); // noch keine wirklichen Aenderungen 3123 3124 // #i112436# If formula cells are already dirty, they don't broadcast further changes. 3125 // So the source ranges of charts must be interpreted even if they are not visible, 3126 // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899). 3127 if (pChartListenerCollection) 3128 { 3129 sal_uInt16 nChartCount = pChartListenerCollection->GetCount(); 3130 for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ ) 3131 { 3132 ScChartListener* pChartListener = static_cast<ScChartListener*>(pChartListenerCollection->At(nIndex)); 3133 InterpretDirtyCells(*pChartListener->GetRangeList()); 3134 } 3135 } 3136 } 3137 3138 3139 sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const 3140 { 3141 SCTAB nTab = rPos.Tab(); 3142 if ( pTab[nTab] ) 3143 return pTab[nTab]->GetErrCode( rPos ); 3144 return 0; 3145 } 3146 3147 3148 void ScDocument::ResetChanged( const ScRange& rRange ) 3149 { 3150 SCTAB nStartTab = rRange.aStart.Tab(); 3151 SCTAB nEndTab = rRange.aEnd.Tab(); 3152 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 3153 if (pTab[nTab]) 3154 pTab[nTab]->ResetChanged( rRange ); 3155 } 3156 3157 // 3158 // Spaltenbreiten / Zeilenhoehen -------------------------------------- 3159 // 3160 3161 3162 void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth ) 3163 { 3164 if ( ValidTab(nTab) && pTab[nTab] ) 3165 pTab[nTab]->SetColWidth( nCol, nNewWidth ); 3166 } 3167 3168 3169 void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3170 { 3171 if ( ValidTab(nTab) && pTab[nTab] ) 3172 pTab[nTab]->SetRowHeight( nRow, nNewHeight ); 3173 } 3174 3175 3176 void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3177 { 3178 if ( ValidTab(nTab) && pTab[nTab] ) 3179 pTab[nTab]->SetRowHeightRange 3180 ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 ); 3181 } 3182 3183 void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) 3184 { 3185 if ( ValidTab(nTab) && pTab[nTab] ) 3186 pTab[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight ); 3187 } 3188 3189 void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_Bool bManual ) 3190 { 3191 if ( ValidTab(nTab) && pTab[nTab] ) 3192 pTab[nTab]->SetManualHeight( nStartRow, nEndRow, bManual ); 3193 } 3194 3195 3196 sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab ) const 3197 { 3198 if ( ValidTab(nTab) && pTab[nTab] ) 3199 return pTab[nTab]->GetColWidth( nCol ); 3200 DBG_ERROR("Falsche Tabellennummer"); 3201 return 0; 3202 } 3203 3204 3205 sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const 3206 { 3207 if ( ValidTab(nTab) && pTab[nTab] ) 3208 return pTab[nTab]->GetOriginalWidth( nCol ); 3209 DBG_ERROR("Falsche Tabellennummer"); 3210 return 0; 3211 } 3212 3213 3214 sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const 3215 { 3216 if ( ValidTab(nTab) && pTab[nTab] ) 3217 return pTab[nTab]->GetCommonWidth( nEndCol ); 3218 DBG_ERROR("Wrong table number"); 3219 return 0; 3220 } 3221 3222 3223 sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const 3224 { 3225 if ( ValidTab(nTab) && pTab[nTab] ) 3226 return pTab[nTab]->GetOriginalHeight( nRow ); 3227 DBG_ERROR("Wrong table number"); 3228 return 0; 3229 } 3230 3231 3232 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const 3233 { 3234 if ( ValidTab(nTab) && pTab[nTab] ) 3235 return pTab[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero ); 3236 DBG_ERROR("Wrong sheet number"); 3237 return 0; 3238 } 3239 3240 3241 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const 3242 { 3243 if ( ValidTab(nTab) && pTab[nTab] ) 3244 return pTab[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero ); 3245 DBG_ERROR("Wrong sheet number"); 3246 return 0; 3247 } 3248 3249 3250 sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const 3251 { 3252 if (nStartRow == nEndRow) 3253 return GetRowHeight( nStartRow, nTab); // faster for a single row 3254 3255 // check bounds because this method replaces former for(i=start;i<=end;++i) loops 3256 if (nStartRow > nEndRow) 3257 return 0; 3258 3259 if ( ValidTab(nTab) && pTab[nTab] ) 3260 return pTab[nTab]->GetRowHeight( nStartRow, nEndRow); 3261 3262 DBG_ERROR("wrong sheet number"); 3263 return 0; 3264 } 3265 3266 SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const 3267 { 3268 return pTab[nTab]->GetRowForHeight(nHeight); 3269 } 3270 3271 sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, 3272 SCTAB nTab, double fScale ) const 3273 { 3274 // faster for a single row 3275 if (nStartRow == nEndRow) 3276 return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale); 3277 3278 // check bounds because this method replaces former for(i=start;i<=end;++i) loops 3279 if (nStartRow > nEndRow) 3280 return 0; 3281 3282 if ( ValidTab(nTab) && pTab[nTab] ) 3283 return pTab[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale); 3284 3285 DBG_ERROR("wrong sheet number"); 3286 return 0; 3287 } 3288 3289 SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const 3290 { 3291 if ( ValidTab(nTab) && pTab[nTab] ) 3292 return pTab[nTab]->GetHiddenRowCount( nRow ); 3293 DBG_ERROR("Falsche Tabellennummer"); 3294 return 0; 3295 } 3296 3297 3298 sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab ) const 3299 { 3300 if ( ValidTab(nTab) && pTab[nTab] ) 3301 return pTab[nTab]->GetColOffset( nCol ); 3302 DBG_ERROR("Falsche Tabellennummer"); 3303 return 0; 3304 } 3305 3306 3307 sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab ) const 3308 { 3309 if ( ValidTab(nTab) && pTab[nTab] ) 3310 return pTab[nTab]->GetRowOffset( nRow ); 3311 DBG_ERROR("Falsche Tabellennummer"); 3312 return 0; 3313 } 3314 3315 3316 sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev, 3317 double nPPTX, double nPPTY, 3318 const Fraction& rZoomX, const Fraction& rZoomY, 3319 sal_Bool bFormula, const ScMarkData* pMarkData, 3320 sal_Bool bSimpleTextImport ) 3321 { 3322 if ( ValidTab(nTab) && pTab[nTab] ) 3323 return pTab[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY, 3324 rZoomX, rZoomY, bFormula, pMarkData, bSimpleTextImport ); 3325 DBG_ERROR("Falsche Tabellennummer"); 3326 return 0; 3327 } 3328 3329 3330 long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab, 3331 OutputDevice* pDev, 3332 double nPPTX, double nPPTY, 3333 const Fraction& rZoomX, const Fraction& rZoomY, 3334 sal_Bool bWidth, sal_Bool bTotalSize ) 3335 { 3336 if ( ValidTab(nTab) && pTab[nTab] ) 3337 return pTab[nTab]->GetNeededSize 3338 ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize ); 3339 DBG_ERROR("Falsche Tabellennummer"); 3340 return 0; 3341 } 3342 3343 3344 sal_Bool ScDocument::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nExtra, 3345 OutputDevice* pDev, 3346 double nPPTX, double nPPTY, 3347 const Fraction& rZoomX, const Fraction& rZoomY, 3348 sal_Bool bShrink ) 3349 { 3350 //! MarkToMulti(); 3351 if ( ValidTab(nTab) && pTab[nTab] ) 3352 return pTab[nTab]->SetOptimalHeight( nStartRow, nEndRow, nExtra, 3353 pDev, nPPTX, nPPTY, rZoomX, rZoomY, bShrink ); 3354 DBG_ERROR("Falsche Tabellennummer"); 3355 return sal_False; 3356 } 3357 3358 3359 void ScDocument::UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY, 3360 const Fraction& rZoomX, const Fraction& rZoomY, const ScMarkData* pTabMark ) 3361 { 3362 // one progress across all (selected) sheets 3363 3364 sal_uLong nCellCount = 0; 3365 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 3366 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) 3367 nCellCount += pTab[nTab]->GetWeightedCount(); 3368 3369 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount ); 3370 3371 sal_uLong nProgressStart = 0; 3372 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 3373 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) 3374 { 3375 pTab[nTab]->SetOptimalHeight( 0, MAXROW, 0, 3376 pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False, &aProgress, nProgressStart ); 3377 nProgressStart += pTab[nTab]->GetWeightedCount(); 3378 } 3379 } 3380 3381 3382 // 3383 // Spalten-/Zeilen-Flags ---------------------------------------------- 3384 // 3385 3386 void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, sal_Bool bShow) 3387 { 3388 if ( ValidTab(nTab) && pTab[nTab] ) 3389 pTab[nTab]->ShowCol( nCol, bShow ); 3390 } 3391 3392 3393 void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, sal_Bool bShow) 3394 { 3395 if ( ValidTab(nTab) && pTab[nTab] ) 3396 pTab[nTab]->ShowRow( nRow, bShow ); 3397 } 3398 3399 3400 void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, sal_Bool bShow) 3401 { 3402 if ( ValidTab(nTab) && pTab[nTab] ) 3403 pTab[nTab]->ShowRows( nRow1, nRow2, bShow ); 3404 } 3405 3406 3407 void ScDocument::SetColFlags( SCCOL nCol, SCTAB nTab, sal_uInt8 nNewFlags ) 3408 { 3409 if ( ValidTab(nTab) && pTab[nTab] ) 3410 pTab[nTab]->SetColFlags( nCol, nNewFlags ); 3411 } 3412 3413 3414 void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags ) 3415 { 3416 if ( ValidTab(nTab) && pTab[nTab] ) 3417 pTab[nTab]->SetRowFlags( nRow, nNewFlags ); 3418 } 3419 3420 3421 void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags ) 3422 { 3423 if ( ValidTab(nTab) && pTab[nTab] ) 3424 pTab[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags ); 3425 } 3426 3427 3428 sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const 3429 { 3430 if ( ValidTab(nTab) && pTab[nTab] ) 3431 return pTab[nTab]->GetColFlags( nCol ); 3432 DBG_ERROR("Falsche Tabellennummer"); 3433 return 0; 3434 } 3435 3436 sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const 3437 { 3438 if ( ValidTab(nTab) && pTab[nTab] ) 3439 return pTab[nTab]->GetRowFlags( nRow ); 3440 DBG_ERROR("Falsche Tabellennummer"); 3441 return 0; 3442 } 3443 3444 ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArrayModifiable( 3445 SCTAB nTab ) 3446 { 3447 return const_cast< ScBitMaskCompressedArray< SCROW, sal_uInt8> & >( 3448 GetRowFlagsArray( nTab)); 3449 } 3450 3451 const ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArray( 3452 SCTAB nTab ) const 3453 { 3454 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pFlags; 3455 if ( ValidTab(nTab) && pTab[nTab] ) 3456 pFlags = pTab[nTab]->GetRowFlagsArray(); 3457 else 3458 { 3459 DBG_ERROR("wrong sheet number"); 3460 pFlags = 0; 3461 } 3462 if (!pFlags) 3463 { 3464 DBG_ERROR("no row flags at sheet"); 3465 static ScBitMaskCompressedArray< SCROW, sal_uInt8> aDummy( MAXROW, 0); 3466 pFlags = &aDummy; 3467 } 3468 return *pFlags; 3469 } 3470 3471 void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const 3472 { 3473 if (!ValidTab(nTab) || !pTab[nTab]) 3474 return; 3475 3476 pTab[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual); 3477 } 3478 3479 void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const 3480 { 3481 if (!ValidTab(nTab) || !pTab[nTab]) 3482 return; 3483 3484 pTab[nTab]->GetAllColBreaks(rBreaks, bPage, bManual); 3485 } 3486 3487 ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const 3488 { 3489 ScBreakType nType = BREAK_NONE; 3490 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3491 return nType; 3492 3493 if (pTab[nTab]->HasRowPageBreak(nRow)) 3494 nType |= BREAK_PAGE; 3495 3496 if (pTab[nTab]->HasRowManualBreak(nRow)) 3497 nType |= BREAK_MANUAL; 3498 3499 return nType; 3500 } 3501 3502 ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const 3503 { 3504 ScBreakType nType = BREAK_NONE; 3505 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3506 return nType; 3507 3508 if (pTab[nTab]->HasColPageBreak(nCol)) 3509 nType |= BREAK_PAGE; 3510 3511 if (pTab[nTab]->HasColManualBreak(nCol)) 3512 nType |= BREAK_MANUAL; 3513 3514 return nType; 3515 } 3516 3517 void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) 3518 { 3519 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3520 return; 3521 3522 pTab[nTab]->SetRowBreak(nRow, bPage, bManual); 3523 } 3524 3525 void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) 3526 { 3527 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3528 return; 3529 3530 pTab[nTab]->SetColBreak(nCol, bPage, bManual); 3531 } 3532 3533 void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) 3534 { 3535 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow)) 3536 return; 3537 3538 pTab[nTab]->RemoveRowBreak(nRow, bPage, bManual); 3539 } 3540 3541 void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) 3542 { 3543 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol)) 3544 return; 3545 3546 pTab[nTab]->RemoveColBreak(nCol, bPage, bManual); 3547 } 3548 3549 Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const 3550 { 3551 if (!ValidTab(nTab) || !pTab[nTab]) 3552 return Sequence<TablePageBreakData>(); 3553 3554 return pTab[nTab]->GetRowBreakData(); 3555 } 3556 3557 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) 3558 { 3559 if (!ValidTab(nTab) || !pTab[nTab]) 3560 return false; 3561 3562 return pTab[nTab]->RowHidden(nRow, pFirstRow, pLastRow); 3563 } 3564 3565 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastRow) 3566 { 3567 if (!ValidTab(nTab) || !pTab[nTab]) 3568 { 3569 rLastRow = nRow; 3570 return false; 3571 } 3572 3573 return pTab[nTab]->RowHidden(nRow, rLastRow); 3574 } 3575 3576 3577 bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3578 { 3579 if (!ValidTab(nTab) || !pTab[nTab]) 3580 return false; 3581 3582 return pTab[nTab]->HasHiddenRows(nStartRow, nEndRow); 3583 } 3584 3585 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL& rLastCol) 3586 { 3587 if (!ValidTab(nTab) || !pTab[nTab]) 3588 { 3589 rLastCol = nCol; 3590 return false; 3591 } 3592 3593 return pTab[nTab]->ColHidden(nCol, rLastCol); 3594 } 3595 3596 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) 3597 { 3598 if (!ValidTab(nTab) || !pTab[nTab]) 3599 { 3600 if (pFirstCol) 3601 *pFirstCol = nCol; 3602 if (pLastCol) 3603 *pLastCol = nCol; 3604 return false; 3605 } 3606 3607 return pTab[nTab]->ColHidden(nCol, pFirstCol, pLastCol); 3608 } 3609 3610 void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden) 3611 { 3612 if (!ValidTab(nTab) || !pTab[nTab]) 3613 return; 3614 3615 pTab[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden); 3616 } 3617 3618 void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden) 3619 { 3620 if (!ValidTab(nTab) || !pTab[nTab]) 3621 return; 3622 3623 pTab[nTab]->SetColHidden(nStartCol, nEndCol, bHidden); 3624 } 3625 3626 SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3627 { 3628 if (!ValidTab(nTab) || !pTab[nTab]) 3629 return ::std::numeric_limits<SCROW>::max();; 3630 3631 return pTab[nTab]->FirstVisibleRow(nStartRow, nEndRow); 3632 } 3633 3634 SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3635 { 3636 if (!ValidTab(nTab) || !pTab[nTab]) 3637 return ::std::numeric_limits<SCROW>::max();; 3638 3639 return pTab[nTab]->LastVisibleRow(nStartRow, nEndRow); 3640 } 3641 3642 SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3643 { 3644 if (!ValidTab(nTab) || !pTab[nTab]) 3645 return 0; 3646 3647 return pTab[nTab]->CountVisibleRows(nStartRow, nEndRow); 3648 } 3649 3650 bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) 3651 { 3652 if (!ValidTab(nTab) || !pTab[nTab]) 3653 return false; 3654 3655 return pTab[nTab]->RowFiltered(nRow, pFirstRow, pLastRow); 3656 } 3657 3658 bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3659 { 3660 if (!ValidTab(nTab) || !pTab[nTab]) 3661 return false; 3662 3663 return pTab[nTab]->HasFilteredRows(nStartRow, nEndRow); 3664 } 3665 3666 bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) 3667 { 3668 if (!ValidTab(nTab) || !pTab[nTab]) 3669 return false; 3670 3671 return pTab[nTab]->ColFiltered(nCol, pFirstCol, pLastCol); 3672 } 3673 3674 void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered) 3675 { 3676 if (!ValidTab(nTab) || !pTab[nTab]) 3677 return; 3678 3679 pTab[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered); 3680 } 3681 3682 void ScDocument::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bFiltered) 3683 { 3684 if (!ValidTab(nTab) || !pTab[nTab]) 3685 return; 3686 3687 pTab[nTab]->SetColFiltered(nStartCol, nEndCol, bFiltered); 3688 } 3689 3690 SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3691 { 3692 if (!ValidTab(nTab) || !pTab[nTab]) 3693 return ::std::numeric_limits<SCROW>::max();; 3694 3695 return pTab[nTab]->FirstNonFilteredRow(nStartRow, nEndRow); 3696 } 3697 3698 SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3699 { 3700 if (!ValidTab(nTab) || !pTab[nTab]) 3701 return ::std::numeric_limits<SCROW>::max();; 3702 3703 return pTab[nTab]->LastNonFilteredRow(nStartRow, nEndRow); 3704 } 3705 3706 SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) 3707 { 3708 if (!ValidTab(nTab) || !pTab[nTab]) 3709 return 0; 3710 3711 return pTab[nTab]->CountNonFilteredRows(nStartRow, nEndRow); 3712 } 3713 3714 void ScDocument::SyncColRowFlags() 3715 { 3716 for (SCTAB i = 0; i <= nMaxTableNumber; ++i) 3717 { 3718 if (!ValidTab(i) || !pTab[i]) 3719 continue; 3720 3721 pTab[i]->SyncColRowFlags(); 3722 } 3723 } 3724 3725 SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const 3726 { 3727 if ( ValidTab(nTab) && pTab[nTab] ) 3728 return pTab[nTab]->GetLastFlaggedRow(); 3729 return 0; 3730 } 3731 3732 3733 SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const 3734 { 3735 if ( ValidTab(nTab) && pTab[nTab] ) 3736 return pTab[nTab]->GetLastChangedCol(); 3737 return 0; 3738 } 3739 3740 SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const 3741 { 3742 if ( ValidTab(nTab) && pTab[nTab] ) 3743 return pTab[nTab]->GetLastChangedRow(); 3744 return 0; 3745 } 3746 3747 3748 SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const 3749 { 3750 if ( ValidTab(nTab) && pTab[nTab] ) 3751 { 3752 sal_uInt8 nStartFlags = pTab[nTab]->GetColFlags(nStart); 3753 sal_uInt16 nStartWidth = pTab[nTab]->GetOriginalWidth(nStart); 3754 for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++) 3755 { 3756 if (((nStartFlags & CR_MANUALBREAK) != (pTab[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) || 3757 (nStartWidth != pTab[nTab]->GetOriginalWidth(nCol)) || 3758 ((nStartFlags & CR_HIDDEN) != (pTab[nTab]->GetColFlags(nCol) & CR_HIDDEN)) ) 3759 return nCol; 3760 } 3761 return MAXCOL+1; 3762 } 3763 return 0; 3764 } 3765 3766 SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const 3767 { 3768 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pRowFlagsArray; 3769 if ( ValidTab(nTab) && pTab[nTab] && ((pRowFlagsArray = pTab[nTab]->GetRowFlagsArray()) != NULL) && 3770 pTab[nTab]->mpRowHeights && pTab[nTab]->mpHiddenRows ) 3771 { 3772 size_t nIndex; // ignored 3773 SCROW nFlagsEndRow; 3774 SCROW nHiddenEndRow; 3775 SCROW nHeightEndRow; 3776 sal_uInt8 nFlags; 3777 bool bHidden; 3778 sal_uInt16 nHeight; 3779 sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow); 3780 bool bStartHidden = bHidden = pTab[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow); 3781 sal_uInt16 nStartHeight = nHeight = pTab[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false); 3782 SCROW nRow; 3783 while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW) 3784 { 3785 if (nFlagsEndRow < nRow) 3786 nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow); 3787 if (nHiddenEndRow < nRow) 3788 bHidden = pTab[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow); 3789 if (nHeightEndRow < nRow) 3790 nHeight = pTab[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false); 3791 if ( ((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) || 3792 ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) || 3793 (bStartHidden != bHidden) || 3794 (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) || 3795 (!bCareManualSize && ((nStartHeight != nHeight)))) 3796 return nRow; 3797 } 3798 return MAXROW+1; 3799 } 3800 return 0; 3801 } 3802 3803 sal_Bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault) 3804 { 3805 sal_Bool bRet(sal_False); 3806 nDefault = 0; 3807 ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow); 3808 SCCOL nColumn; 3809 SCROW nStartRow; 3810 SCROW nEndRow; 3811 const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); 3812 if (nEndRow < nLastRow) 3813 { 3814 ScDefaultAttrSet aSet; 3815 ScDefaultAttrSet::iterator aItr = aSet.end(); 3816 while (pAttr) 3817 { 3818 ScDefaultAttr aAttr(pAttr); 3819 aItr = aSet.find(aAttr); 3820 if (aItr == aSet.end()) 3821 { 3822 aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1); 3823 aAttr.nFirst = nStartRow; 3824 aSet.insert(aAttr); 3825 } 3826 else 3827 { 3828 aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1); 3829 aAttr.nFirst = aItr->nFirst; 3830 aSet.erase(aItr); 3831 aSet.insert(aAttr); 3832 } 3833 pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); 3834 } 3835 ScDefaultAttrSet::iterator aDefaultItr = aSet.begin(); 3836 aItr = aDefaultItr; 3837 aItr++; 3838 while (aItr != aSet.end()) 3839 { 3840 // for entries with equal count, use the one with the lowest start row, 3841 // don't use the random order of pointer comparisons 3842 if ( aItr->nCount > aDefaultItr->nCount || 3843 ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) ) 3844 aDefaultItr = aItr; 3845 aItr++; 3846 } 3847 nDefault = aDefaultItr->nFirst; 3848 bRet = sal_True; 3849 } 3850 else 3851 bRet = sal_True; 3852 return bRet; 3853 } 3854 3855 sal_Bool ScDocument::GetRowDefault( SCTAB /* nTab */, SCROW /* nRow */, SCCOL /* nLastCol */, SCCOL& /* nDefault */ ) 3856 { 3857 sal_Bool bRet(sal_False); 3858 return bRet; 3859 } 3860 3861 void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) 3862 { 3863 if ( ValidTab(nTab) && pTab[nTab] ) 3864 pTab[nTab]->StripHidden( rX1, rY1, rX2, rY2 ); 3865 } 3866 3867 3868 void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) 3869 { 3870 if ( ValidTab(nTab) && pTab[nTab] ) 3871 pTab[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 ); 3872 } 3873 3874 // 3875 // Attribute ---------------------------------------------------------- 3876 // 3877 3878 const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const 3879 { 3880 if ( ValidTab(nTab) && pTab[nTab] ) 3881 { 3882 const SfxPoolItem* pTemp = pTab[nTab]->GetAttr( nCol, nRow, nWhich ); 3883 if (pTemp) 3884 return pTemp; 3885 else 3886 { 3887 DBG_ERROR( "Attribut Null" ); 3888 } 3889 } 3890 return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich ); 3891 } 3892 3893 3894 const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 3895 { 3896 if ( ValidTab(nTab) && pTab[nTab] ) 3897 return pTab[nTab]->GetPattern( nCol, nRow ); 3898 return NULL; 3899 } 3900 3901 3902 const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const 3903 { 3904 if ( ValidTab(nTab) && pTab[nTab] ) 3905 return pTab[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow ); 3906 return NULL; 3907 } 3908 3909 3910 void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr ) 3911 { 3912 if ( ValidTab(nTab) && pTab[nTab] ) 3913 pTab[nTab]->ApplyAttr( nCol, nRow, rAttr ); 3914 } 3915 3916 3917 void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr ) 3918 { 3919 if ( ValidTab(nTab) && pTab[nTab] ) 3920 pTab[nTab]->ApplyPattern( nCol, nRow, rAttr ); 3921 } 3922 3923 3924 void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, 3925 SCCOL nEndCol, SCROW nEndRow, 3926 const ScMarkData& rMark, 3927 const ScPatternAttr& rAttr ) 3928 { 3929 for (SCTAB i=0; i <= MAXTAB; i++) 3930 if (pTab[i]) 3931 if (rMark.GetTableSelect(i)) 3932 pTab[i]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr ); 3933 } 3934 3935 3936 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow, 3937 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr ) 3938 { 3939 if (VALIDTAB(nTab)) 3940 if (pTab[nTab]) 3941 pTab[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr ); 3942 } 3943 3944 void ScDocument::ApplyPooledPatternAreaTab( SCCOL nStartCol, SCROW nStartRow, 3945 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rPooledAttr, const ScPatternAttr& rAttr ) 3946 { 3947 if (VALIDTAB(nTab)) 3948 if (pTab[nTab]) 3949 pTab[nTab]->ApplyPooledPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rPooledAttr, rAttr ); 3950 } 3951 3952 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange, 3953 const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType ) 3954 { 3955 for (SCTAB i=0; i <= MAXTAB; i++) 3956 if (pTab[i]) 3957 if (rMark.GetTableSelect(i)) 3958 pTab[i]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType ); 3959 } 3960 3961 3962 void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle) 3963 { 3964 if (VALIDTAB(nTab)) 3965 if (pTab[nTab]) 3966 pTab[nTab]->ApplyStyle( nCol, nRow, rStyle ); 3967 } 3968 3969 3970 void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, 3971 SCCOL nEndCol, SCROW nEndRow, 3972 const ScMarkData& rMark, 3973 const ScStyleSheet& rStyle) 3974 { 3975 for (SCTAB i=0; i <= MAXTAB; i++) 3976 if (pTab[i]) 3977 if (rMark.GetTableSelect(i)) 3978 pTab[i]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); 3979 } 3980 3981 3982 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow, 3983 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle) 3984 { 3985 if (VALIDTAB(nTab)) 3986 if (pTab[nTab]) 3987 pTab[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); 3988 } 3989 3990 3991 void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark) 3992 { 3993 // ApplySelectionStyle needs multi mark 3994 if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) 3995 { 3996 ScRange aRange; 3997 rMark.GetMarkArea( aRange ); 3998 ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(), 3999 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle ); 4000 } 4001 else 4002 { 4003 for (SCTAB i=0; i<=MAXTAB; i++) 4004 if ( pTab[i] && rMark.GetTableSelect(i) ) 4005 pTab[i]->ApplySelectionStyle( rStyle, rMark ); 4006 } 4007 } 4008 4009 4010 void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark, 4011 const SvxBorderLine* pLine, sal_Bool bColorOnly ) 4012 { 4013 if ( bColorOnly && !pLine ) 4014 return; 4015 4016 for (SCTAB i=0; i<=MAXTAB; i++) 4017 if (pTab[i]) 4018 if (rMark.GetTableSelect(i)) 4019 pTab[i]->ApplySelectionLineStyle( rMark, pLine, bColorOnly ); 4020 } 4021 4022 4023 const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4024 { 4025 if ( VALIDTAB(nTab) && pTab[nTab] ) 4026 return pTab[nTab]->GetStyle(nCol, nRow); 4027 else 4028 return NULL; 4029 } 4030 4031 4032 const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const 4033 { 4034 sal_Bool bEqual = sal_True; 4035 sal_Bool bFound; 4036 4037 const ScStyleSheet* pStyle = NULL; 4038 const ScStyleSheet* pNewStyle; 4039 4040 if ( rMark.IsMultiMarked() ) 4041 for (SCTAB i=0; i<=MAXTAB && bEqual; i++) 4042 if (pTab[i] && rMark.GetTableSelect(i)) 4043 { 4044 pNewStyle = pTab[i]->GetSelectionStyle( rMark, bFound ); 4045 if (bFound) 4046 { 4047 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 4048 bEqual = sal_False; // unterschiedliche 4049 pStyle = pNewStyle; 4050 } 4051 } 4052 if ( rMark.IsMarked() ) 4053 { 4054 ScRange aRange; 4055 rMark.GetMarkArea( aRange ); 4056 for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual; i++) 4057 if (pTab[i] && rMark.GetTableSelect(i)) 4058 { 4059 pNewStyle = pTab[i]->GetAreaStyle( bFound, 4060 aRange.aStart.Col(), aRange.aStart.Row(), 4061 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4062 if (bFound) 4063 { 4064 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) 4065 bEqual = sal_False; // unterschiedliche 4066 pStyle = pNewStyle; 4067 } 4068 } 4069 } 4070 4071 return bEqual ? pStyle : NULL; 4072 } 4073 4074 4075 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved, 4076 OutputDevice* pDev, 4077 double nPPTX, double nPPTY, 4078 const Fraction& rZoomX, const Fraction& rZoomY ) 4079 { 4080 for (SCTAB i=0; i <= MAXTAB; i++) 4081 if (pTab[i]) 4082 pTab[i]->StyleSheetChanged 4083 ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY ); 4084 4085 if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) ) 4086 { 4087 // update attributes for all note objects 4088 ScDetectiveFunc::UpdateAllComments( *this ); 4089 } 4090 } 4091 4092 4093 sal_Bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const 4094 { 4095 if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN ) 4096 { 4097 if ( bGatherAllStyles ) 4098 { 4099 SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(), 4100 SFX_STYLE_FAMILY_PARA ); 4101 for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle; 4102 pStyle = aIter.Next() ) 4103 { 4104 const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle ); 4105 if ( pScStyle ) 4106 pScStyle->SetUsage( ScStyleSheet::NOTUSED ); 4107 } 4108 } 4109 4110 sal_Bool bIsUsed = sal_False; 4111 4112 for ( SCTAB i=0; i<=MAXTAB; i++ ) 4113 { 4114 if ( pTab[i] ) 4115 { 4116 if ( pTab[i]->IsStyleSheetUsed( rStyle, bGatherAllStyles ) ) 4117 { 4118 if ( !bGatherAllStyles ) 4119 return sal_True; 4120 bIsUsed = sal_True; 4121 } 4122 } 4123 } 4124 4125 if ( bGatherAllStyles ) 4126 bStyleSheetUsageInvalid = sal_False; 4127 4128 return bIsUsed; 4129 } 4130 4131 return rStyle.GetUsage() == ScStyleSheet::USED; 4132 } 4133 4134 4135 sal_Bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow, 4136 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ) 4137 { 4138 if (VALIDTAB(nTab)) 4139 if (pTab[nTab]) 4140 return pTab[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); 4141 4142 DBG_ERROR("ApplyFlags: falsche Tabelle"); 4143 return sal_False; 4144 } 4145 4146 4147 sal_Bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow, 4148 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ) 4149 { 4150 if (VALIDTAB(nTab)) 4151 if (pTab[nTab]) 4152 return pTab[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); 4153 4154 DBG_ERROR("RemoveFlags: falsche Tabelle"); 4155 return sal_False; 4156 } 4157 4158 4159 void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr, 4160 sal_Bool bPutToPool ) 4161 { 4162 if (VALIDTAB(nTab)) 4163 if (pTab[nTab]) 4164 pTab[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool ); 4165 } 4166 4167 4168 void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr, 4169 sal_Bool bPutToPool ) 4170 { 4171 SCTAB nTab = rPos.Tab(); 4172 if (pTab[nTab]) 4173 pTab[nTab]->SetPattern( rPos, rAttr, bPutToPool ); 4174 } 4175 4176 4177 ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep ) 4178 { 4179 ScMergePatternState aState; 4180 4181 if ( rMark.IsMultiMarked() ) // multi selection 4182 { 4183 for (SCTAB i=0; i<=MAXTAB; i++) 4184 if (pTab[i] && rMark.GetTableSelect(i)) 4185 pTab[i]->MergeSelectionPattern( aState, rMark, bDeep ); 4186 } 4187 if ( rMark.IsMarked() ) // simle selection 4188 { 4189 ScRange aRange; 4190 rMark.GetMarkArea(aRange); 4191 for (SCTAB i=0; i<=MAXTAB; i++) 4192 if (pTab[i] && rMark.GetTableSelect(i)) 4193 pTab[i]->MergePatternArea( aState, 4194 aRange.aStart.Col(), aRange.aStart.Row(), 4195 aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep ); 4196 } 4197 4198 DBG_ASSERT( aState.pItemSet, "SelectionPattern Null" ); 4199 if (aState.pItemSet) 4200 return new ScPatternAttr( aState.pItemSet ); 4201 else 4202 return new ScPatternAttr( GetPool() ); // empty 4203 } 4204 4205 4206 const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep ) 4207 { 4208 delete pSelectionAttr; 4209 pSelectionAttr = CreateSelectionPattern( rMark, bDeep ); 4210 return pSelectionAttr; 4211 } 4212 4213 4214 void ScDocument::GetSelectionFrame( const ScMarkData& rMark, 4215 SvxBoxItem& rLineOuter, 4216 SvxBoxInfoItem& rLineInner ) 4217 { 4218 rLineOuter.SetLine(NULL, BOX_LINE_TOP); 4219 rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM); 4220 rLineOuter.SetLine(NULL, BOX_LINE_LEFT); 4221 rLineOuter.SetLine(NULL, BOX_LINE_RIGHT); 4222 rLineOuter.SetDistance(0); 4223 4224 rLineInner.SetLine(NULL, BOXINFO_LINE_HORI); 4225 rLineInner.SetLine(NULL, BOXINFO_LINE_VERT); 4226 rLineInner.SetTable(sal_True); 4227 rLineInner.SetDist(sal_True); 4228 rLineInner.SetMinDist(sal_False); 4229 4230 ScLineFlags aFlags; 4231 4232 if (rMark.IsMarked()) 4233 { 4234 ScRange aRange; 4235 rMark.GetMarkArea(aRange); 4236 rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() ); 4237 rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() ); 4238 for (SCTAB i=0; i<=MAXTAB; i++) 4239 if (pTab[i] && rMark.GetTableSelect(i)) 4240 pTab[i]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags, 4241 aRange.aStart.Col(), aRange.aStart.Row(), 4242 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4243 } 4244 4245 // Don't care Status auswerten 4246 4247 rLineInner.SetValid( VALID_LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) ); 4248 rLineInner.SetValid( VALID_RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) ); 4249 rLineInner.SetValid( VALID_TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) ); 4250 rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) ); 4251 rLineInner.SetValid( VALID_HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) ); 4252 rLineInner.SetValid( VALID_VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) ); 4253 } 4254 4255 4256 bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 4257 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask ) 4258 { 4259 if ( nMask & HASATTR_ROTATE ) 4260 { 4261 // Attribut im Dokument ueberhaupt verwendet? 4262 // (wie in fillinfo) 4263 4264 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 4265 4266 sal_Bool bAnyItem = sal_False; 4267 sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE ); 4268 for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++) 4269 { 4270 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem ); 4271 if ( pItem ) 4272 { 4273 // 90 or 270 degrees is former SvxOrientationItem - only look for other values 4274 // (see ScPatternAttr::GetCellOrientation) 4275 sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue(); 4276 if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 ) 4277 { 4278 bAnyItem = sal_True; 4279 break; 4280 } 4281 } 4282 } 4283 if (!bAnyItem) 4284 nMask &= ~HASATTR_ROTATE; 4285 } 4286 4287 if ( nMask & HASATTR_RTL ) 4288 { 4289 // first check if right-to left is in the pool at all 4290 // (the same item is used in cell and page format) 4291 4292 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 4293 4294 sal_Bool bHasRtl = sal_False; 4295 sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR ); 4296 for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++) 4297 { 4298 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem ); 4299 if ( pItem && ((const SvxFrameDirectionItem*)pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP ) 4300 { 4301 bHasRtl = sal_True; 4302 break; 4303 } 4304 } 4305 if (!bHasRtl) 4306 nMask &= ~HASATTR_RTL; 4307 } 4308 4309 if (!nMask) 4310 return false; 4311 4312 bool bFound = false; 4313 for (SCTAB i=nTab1; i<=nTab2 && !bFound; i++) 4314 if (pTab[i]) 4315 { 4316 if ( nMask & HASATTR_RTL ) 4317 { 4318 if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L ) // sheet default 4319 bFound = true; 4320 } 4321 if ( nMask & HASATTR_RIGHTORCENTER ) 4322 { 4323 // On a RTL sheet, don't start to look for the default left value 4324 // (which is then logically right), instead always assume sal_True. 4325 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets. 4326 4327 if ( IsLayoutRTL(i) ) 4328 bFound = true; 4329 } 4330 4331 if ( !bFound ) 4332 bFound = pTab[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask ); 4333 } 4334 4335 return bFound; 4336 } 4337 4338 bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask ) 4339 { 4340 return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(), 4341 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), 4342 nMask ); 4343 } 4344 4345 void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount, 4346 SCCOL nX1, SCCOL nX2 ) const 4347 { 4348 if ( ValidTab(nTab) && pTab[nTab] ) 4349 pTab[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 ); 4350 else 4351 { 4352 DBG_ERRORFILE("FindMaxRotCol: falsche Tabelle"); 4353 } 4354 } 4355 4356 void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab, 4357 const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop, 4358 const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const 4359 { 4360 //! Seitengrenzen fuer Druck beruecksichtigen !!!!! 4361 4362 const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER ); 4363 DBG_ASSERT(pThisAttr,"wo ist das Attribut?"); 4364 4365 const SvxBorderLine* pLeftLine = pThisAttr->GetLeft(); 4366 const SvxBorderLine* pTopLine = pThisAttr->GetTop(); 4367 const SvxBorderLine* pRightLine = pThisAttr->GetRight(); 4368 const SvxBorderLine* pBottomLine = pThisAttr->GetBottom(); 4369 4370 if ( nCol > 0 ) 4371 { 4372 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4373 GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight(); 4374 if ( ScHasPriority( pOther, pLeftLine ) ) 4375 pLeftLine = pOther; 4376 } 4377 if ( nRow > 0 ) 4378 { 4379 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4380 GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom(); 4381 if ( ScHasPriority( pOther, pTopLine ) ) 4382 pTopLine = pOther; 4383 } 4384 if ( nCol < MAXCOL ) 4385 { 4386 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4387 GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft(); 4388 if ( ScHasPriority( pOther, pRightLine ) ) 4389 pRightLine = pOther; 4390 } 4391 if ( nRow < MAXROW ) 4392 { 4393 const SvxBorderLine* pOther = ((const SvxBoxItem*) 4394 GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop(); 4395 if ( ScHasPriority( pOther, pBottomLine ) ) 4396 pBottomLine = pOther; 4397 } 4398 4399 if (ppLeft) 4400 *ppLeft = pLeftLine; 4401 if (ppTop) 4402 *ppTop = pTopLine; 4403 if (ppRight) 4404 *ppRight = pRightLine; 4405 if (ppBottom) 4406 *ppBottom = pBottomLine; 4407 } 4408 4409 sal_Bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 4410 SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const 4411 { 4412 if (VALIDTAB(nTab)) 4413 if (pTab[nTab]) 4414 return pTab[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes ); 4415 4416 DBG_ERROR("Falsche Tabellennummer"); 4417 return sal_False; 4418 } 4419 4420 4421 void ScDocument::LockTable(SCTAB nTab) 4422 { 4423 if ( ValidTab(nTab) && pTab[nTab] ) 4424 pTab[nTab]->LockTable(); 4425 else 4426 { 4427 DBG_ERROR("Falsche Tabellennummer"); 4428 } 4429 } 4430 4431 4432 void ScDocument::UnlockTable(SCTAB nTab) 4433 { 4434 if ( ValidTab(nTab) && pTab[nTab] ) 4435 pTab[nTab]->UnlockTable(); 4436 else 4437 { 4438 DBG_ERROR("Falsche Tabellennummer"); 4439 } 4440 } 4441 4442 4443 sal_Bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 4444 SCCOL nEndCol, SCROW nEndRow, 4445 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 4446 { 4447 // import into read-only document is possible 4448 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() ) 4449 { 4450 if ( pOnlyNotBecauseOfMatrix ) 4451 *pOnlyNotBecauseOfMatrix = sal_False; 4452 return sal_False; 4453 } 4454 4455 if (VALIDTAB(nTab)) 4456 if (pTab[nTab]) 4457 return pTab[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol, 4458 nEndRow, pOnlyNotBecauseOfMatrix ); 4459 4460 DBG_ERROR("Falsche Tabellennummer"); 4461 if ( pOnlyNotBecauseOfMatrix ) 4462 *pOnlyNotBecauseOfMatrix = sal_False; 4463 return sal_False; 4464 } 4465 4466 4467 sal_Bool ScDocument::IsSelectionEditable( const ScMarkData& rMark, 4468 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const 4469 { 4470 // import into read-only document is possible 4471 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() ) 4472 { 4473 if ( pOnlyNotBecauseOfMatrix ) 4474 *pOnlyNotBecauseOfMatrix = sal_False; 4475 return sal_False; 4476 } 4477 4478 ScRange aRange; 4479 rMark.GetMarkArea(aRange); 4480 4481 sal_Bool bOk = sal_True; 4482 sal_Bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL ); 4483 for ( SCTAB i=0; i<=MAXTAB && (bOk || bMatrix); i++ ) 4484 { 4485 if ( pTab[i] && rMark.GetTableSelect(i) ) 4486 { 4487 if (rMark.IsMarked()) 4488 { 4489 if ( !pTab[i]->IsBlockEditable( aRange.aStart.Col(), 4490 aRange.aStart.Row(), aRange.aEnd.Col(), 4491 aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) ) 4492 { 4493 bOk = sal_False; 4494 if ( pOnlyNotBecauseOfMatrix ) 4495 bMatrix = *pOnlyNotBecauseOfMatrix; 4496 } 4497 } 4498 if (rMark.IsMultiMarked()) 4499 { 4500 if ( !pTab[i]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) ) 4501 { 4502 bOk = sal_False; 4503 if ( pOnlyNotBecauseOfMatrix ) 4504 bMatrix = *pOnlyNotBecauseOfMatrix; 4505 } 4506 } 4507 } 4508 } 4509 4510 if ( pOnlyNotBecauseOfMatrix ) 4511 *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix ); 4512 4513 return bOk; 4514 } 4515 4516 4517 sal_Bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow, 4518 SCCOL nEndCol, SCROW nEndRow, 4519 const ScMarkData& rMark ) const 4520 { 4521 sal_Bool bOk = sal_True; 4522 for (SCTAB i=0; i<=MAXTAB && bOk; i++) 4523 if (pTab[i]) 4524 if (rMark.GetTableSelect(i)) 4525 if (pTab[i]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow )) 4526 bOk = sal_False; 4527 4528 return !bOk; 4529 } 4530 4531 4532 sal_Bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix ) 4533 { 4534 // if rCell is part of a matrix formula, return its complete range 4535 4536 sal_Bool bRet = sal_False; 4537 ScBaseCell* pCell = GetCell( rCellPos ); 4538 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) 4539 { 4540 ScAddress aOrigin = rCellPos; 4541 if ( ((ScFormulaCell*)pCell)->GetMatrixOrigin( aOrigin ) ) 4542 { 4543 if ( aOrigin != rCellPos ) 4544 pCell = GetCell( aOrigin ); 4545 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) 4546 { 4547 SCCOL nSizeX; 4548 SCROW nSizeY; 4549 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY); 4550 if ( !(nSizeX > 0 && nSizeY > 0) ) 4551 { 4552 // GetMatrixEdge computes also dimensions of the matrix 4553 // if not already done (may occur if document is loaded 4554 // from old file format). 4555 // Needs an "invalid" initialized address. 4556 aOrigin.SetInvalid(); 4557 ((ScFormulaCell*)pCell)->GetMatrixEdge(aOrigin); 4558 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY); 4559 } 4560 if ( nSizeX > 0 && nSizeY > 0 ) 4561 { 4562 ScAddress aEnd( aOrigin.Col() + nSizeX - 1, 4563 aOrigin.Row() + nSizeY - 1, 4564 aOrigin.Tab() ); 4565 4566 rMatrix.aStart = aOrigin; 4567 rMatrix.aEnd = aEnd; 4568 bRet = sal_True; 4569 } 4570 } 4571 } 4572 } 4573 return bRet; 4574 } 4575 4576 4577 sal_Bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow, 4578 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 4579 { 4580 sal_Bool bFound = sal_False; 4581 if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) ) 4582 { 4583 if (pTab[nTab]) 4584 { 4585 SCCOL nCol; 4586 SCCOL nOldCol = rStartCol; 4587 SCROW nOldRow = rStartRow; 4588 for (nCol=nOldCol; nCol<=nEndCol; nCol++) 4589 while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))-> 4590 IsVerOverlapped()) 4591 --rStartRow; 4592 4593 //! weiterreichen ? 4594 4595 ScAttrArray* pAttrArray = pTab[nTab]->aCol[nOldCol].pAttrArray; 4596 SCSIZE nIndex; 4597 pAttrArray->Search( nOldRow, nIndex ); 4598 SCROW nAttrPos = nOldRow; 4599 while (nAttrPos<=nEndRow) 4600 { 4601 DBG_ASSERT( nIndex < pAttrArray->nCount, "Falscher Index im AttrArray" ); 4602 4603 if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern-> 4604 GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped()) 4605 { 4606 SCROW nLoopEndRow = Min( nEndRow, pAttrArray->pData[nIndex].nRow ); 4607 for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++) 4608 { 4609 SCCOL nTempCol = nOldCol; 4610 do 4611 --nTempCol; 4612 while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG)) 4613 ->IsHorOverlapped()); 4614 if (nTempCol < rStartCol) 4615 rStartCol = nTempCol; 4616 } 4617 } 4618 nAttrPos = pAttrArray->pData[nIndex].nRow + 1; 4619 ++nIndex; 4620 } 4621 } 4622 } 4623 else 4624 { 4625 DBG_ERROR("ExtendOverlapped: falscher Bereich"); 4626 } 4627 4628 return bFound; 4629 } 4630 4631 4632 sal_Bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow, 4633 SCCOL& rEndCol, SCROW& rEndRow, 4634 const ScMarkData& rMark, sal_Bool bRefresh, sal_Bool bAttrs ) 4635 { 4636 // use all selected sheets from rMark 4637 4638 sal_Bool bFound = sal_False; 4639 SCCOL nOldEndCol = rEndCol; 4640 SCROW nOldEndRow = rEndRow; 4641 4642 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) 4643 if ( pTab[nTab] && rMark.GetTableSelect(nTab) ) 4644 { 4645 SCCOL nThisEndCol = nOldEndCol; 4646 SCROW nThisEndRow = nOldEndRow; 4647 if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, nTab, bRefresh, bAttrs ) ) 4648 bFound = sal_True; 4649 if ( nThisEndCol > rEndCol ) 4650 rEndCol = nThisEndCol; 4651 if ( nThisEndRow > rEndRow ) 4652 rEndRow = nThisEndRow; 4653 } 4654 4655 return bFound; 4656 } 4657 4658 4659 sal_Bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow, 4660 SCCOL& rEndCol, SCROW& rEndRow, 4661 SCTAB nTab, sal_Bool bRefresh, sal_Bool bAttrs ) 4662 { 4663 sal_Bool bFound = sal_False; 4664 if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) ) 4665 { 4666 if (pTab[nTab]) 4667 bFound = pTab[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh, bAttrs ); 4668 4669 if (bRefresh) 4670 RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab ); 4671 } 4672 else 4673 { 4674 DBG_ERROR("ExtendMerge: falscher Bereich"); 4675 } 4676 4677 return bFound; 4678 } 4679 4680 4681 sal_Bool ScDocument::ExtendMerge( ScRange& rRange, sal_Bool bRefresh, sal_Bool bAttrs ) 4682 { 4683 sal_Bool bFound = sal_False; 4684 SCTAB nStartTab = rRange.aStart.Tab(); 4685 SCTAB nEndTab = rRange.aEnd.Tab(); 4686 SCCOL nEndCol = rRange.aEnd.Col(); 4687 SCROW nEndRow = rRange.aEnd.Row(); 4688 4689 PutInOrder( nStartTab, nEndTab ); 4690 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ ) 4691 { 4692 SCCOL nExtendCol = rRange.aEnd.Col(); 4693 SCROW nExtendRow = rRange.aEnd.Row(); 4694 if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(), 4695 nExtendCol, nExtendRow, 4696 nTab, bRefresh, bAttrs ) ) 4697 { 4698 bFound = sal_True; 4699 if (nExtendCol > nEndCol) nEndCol = nExtendCol; 4700 if (nExtendRow > nEndRow) nEndRow = nExtendRow; 4701 } 4702 } 4703 4704 rRange.aEnd.SetCol(nEndCol); 4705 rRange.aEnd.SetRow(nEndRow); 4706 4707 return bFound; 4708 } 4709 4710 sal_Bool ScDocument::ExtendTotalMerge( ScRange& rRange ) 4711 { 4712 // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn 4713 // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden 4714 4715 sal_Bool bRet = sal_False; 4716 ScRange aExt = rRange; 4717 if (ExtendMerge(aExt)) 4718 { 4719 if ( aExt.aEnd.Row() > rRange.aEnd.Row() ) 4720 { 4721 ScRange aTest = aExt; 4722 aTest.aStart.SetRow( rRange.aEnd.Row() + 1 ); 4723 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) ) 4724 aExt.aEnd.SetRow(rRange.aEnd.Row()); 4725 } 4726 if ( aExt.aEnd.Col() > rRange.aEnd.Col() ) 4727 { 4728 ScRange aTest = aExt; 4729 aTest.aStart.SetCol( rRange.aEnd.Col() + 1 ); 4730 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) ) 4731 aExt.aEnd.SetCol(rRange.aEnd.Col()); 4732 } 4733 4734 bRet = ( aExt.aEnd != rRange.aEnd ); 4735 rRange = aExt; 4736 } 4737 return bRet; 4738 } 4739 4740 sal_Bool ScDocument::ExtendOverlapped( ScRange& rRange ) 4741 { 4742 sal_Bool bFound = sal_False; 4743 SCTAB nStartTab = rRange.aStart.Tab(); 4744 SCTAB nEndTab = rRange.aEnd.Tab(); 4745 SCCOL nStartCol = rRange.aStart.Col(); 4746 SCROW nStartRow = rRange.aStart.Row(); 4747 4748 PutInOrder( nStartTab, nEndTab ); 4749 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ ) 4750 { 4751 SCCOL nExtendCol = rRange.aStart.Col(); 4752 SCROW nExtendRow = rRange.aStart.Row(); 4753 ExtendOverlapped( nExtendCol, nExtendRow, 4754 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab ); 4755 if (nExtendCol < nStartCol) 4756 { 4757 nStartCol = nExtendCol; 4758 bFound = sal_True; 4759 } 4760 if (nExtendRow < nStartRow) 4761 { 4762 nStartRow = nExtendRow; 4763 bFound = sal_True; 4764 } 4765 } 4766 4767 rRange.aStart.SetCol(nStartCol); 4768 rRange.aStart.SetRow(nStartRow); 4769 4770 return bFound; 4771 } 4772 4773 sal_Bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow, 4774 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 4775 { 4776 sal_uInt16 nCount = pDBCollection->GetCount(); 4777 sal_uInt16 i; 4778 ScDBData* pData; 4779 SCTAB nDBTab; 4780 SCCOL nDBStartCol; 4781 SCROW nDBStartRow; 4782 SCCOL nDBEndCol; 4783 SCROW nDBEndRow; 4784 4785 // Autofilter loeschen 4786 4787 sal_Bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO ); 4788 4789 // Autofilter setzen 4790 4791 for (i=0; i<nCount; i++) 4792 { 4793 pData = (*pDBCollection)[i]; 4794 if (pData->HasAutoFilter()) 4795 { 4796 pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow ); 4797 if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow && 4798 nDBStartCol<=nEndCol && nDBEndCol>=nStartCol ) 4799 { 4800 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow, 4801 nDBTab, SC_MF_AUTO )) 4802 bChange = sal_True; 4803 } 4804 } 4805 } 4806 return bChange; 4807 } 4808 4809 4810 sal_Bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4811 { 4812 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*) 4813 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); 4814 if (pAttr) 4815 return pAttr->IsHorOverlapped(); 4816 else 4817 { 4818 DBG_ERROR("Overlapped: Attr==0"); 4819 return sal_False; 4820 } 4821 } 4822 4823 4824 sal_Bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const 4825 { 4826 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*) 4827 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); 4828 if (pAttr) 4829 return pAttr->IsVerOverlapped(); 4830 else 4831 { 4832 DBG_ERROR("Overlapped: Attr==0"); 4833 return sal_False; 4834 } 4835 } 4836 4837 4838 void ScDocument::ApplySelectionFrame( const ScMarkData& rMark, 4839 const SvxBoxItem* pLineOuter, 4840 const SvxBoxInfoItem* pLineInner ) 4841 { 4842 ScRangeList aRangeList; 4843 rMark.FillRangeListWithMarks( &aRangeList, sal_False ); 4844 sal_uLong nRangeCount = aRangeList.Count(); 4845 for (SCTAB i=0; i<=MAXTAB; i++) 4846 { 4847 if (pTab[i] && rMark.GetTableSelect(i)) 4848 { 4849 for (sal_uLong j=0; j<nRangeCount; j++) 4850 { 4851 ScRange aRange = *aRangeList.GetObject(j); 4852 pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner, 4853 aRange.aStart.Col(), aRange.aStart.Row(), 4854 aRange.aEnd.Col(), aRange.aEnd.Row() ); 4855 } 4856 } 4857 } 4858 } 4859 4860 4861 void ScDocument::ApplyFrameAreaTab( const ScRange& rRange, 4862 const SvxBoxItem* pLineOuter, 4863 const SvxBoxInfoItem* pLineInner ) 4864 { 4865 SCTAB nStartTab = rRange.aStart.Tab(); 4866 SCTAB nEndTab = rRange.aStart.Tab(); 4867 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) 4868 if (pTab[nTab]) 4869 pTab[nTab]->ApplyBlockFrame( pLineOuter, pLineInner, 4870 rRange.aStart.Col(), rRange.aStart.Row(), 4871 rRange.aEnd.Col(), rRange.aEnd.Row() ); 4872 } 4873 4874 4875 void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark ) 4876 { 4877 const SfxItemSet* pSet = &rAttr.GetItemSet(); 4878 sal_Bool bSet = sal_False; 4879 sal_uInt16 i; 4880 for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++) 4881 if (pSet->GetItemState(i) == SFX_ITEM_SET) 4882 bSet = sal_True; 4883 4884 if (bSet) 4885 { 4886 // ApplySelectionCache needs multi mark 4887 if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) 4888 { 4889 ScRange aRange; 4890 rMark.GetMarkArea( aRange ); 4891 ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(), 4892 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr ); 4893 } 4894 else 4895 { 4896 SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet ); 4897 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++) 4898 if (pTab[nTab]) 4899 if (rMark.GetTableSelect(nTab)) 4900 pTab[nTab]->ApplySelectionCache( &aCache, rMark ); 4901 } 4902 } 4903 } 4904 4905 4906 void ScDocument::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark ) 4907 { 4908 for (SCTAB i=0; i<=MAXTAB; i++) 4909 if (pTab[i] && rMark.GetTableSelect(i)) 4910 pTab[i]->ChangeSelectionIndent( bIncrement, rMark ); 4911 } 4912 4913 4914 void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark ) 4915 { 4916 for (SCTAB i=0; i<=MAXTAB; i++) 4917 if (pTab[i] && rMark.GetTableSelect(i)) 4918 pTab[i]->ClearSelectionItems( pWhich, rMark ); 4919 } 4920 4921 4922 void ScDocument::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark ) 4923 { 4924 for (SCTAB i=0; i<=MAXTAB; i++) 4925 if (pTab[i] && rMark.GetTableSelect(i)) 4926 pTab[i]->DeleteSelection( nDelFlag, rMark ); 4927 } 4928 4929 4930 void ScDocument::DeleteSelectionTab( SCTAB nTab, sal_uInt16 nDelFlag, const ScMarkData& rMark ) 4931 { 4932 if (ValidTab(nTab) && pTab[nTab]) 4933 pTab[nTab]->DeleteSelection( nDelFlag, rMark ); 4934 else 4935 { 4936 DBG_ERROR("Falsche Tabelle"); 4937 } 4938 } 4939 4940 4941 ScPatternAttr* ScDocument::GetDefPattern() const 4942 { 4943 return (ScPatternAttr*) &xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN); 4944 } 4945 4946 4947 ScDocumentPool* ScDocument::GetPool() 4948 { 4949 return xPoolHelper->GetDocPool(); 4950 } 4951 4952 4953 4954 ScStyleSheetPool* ScDocument::GetStyleSheetPool() const 4955 { 4956 return xPoolHelper->GetStylePool(); 4957 } 4958 4959 4960 SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, 4961 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir ) 4962 { 4963 PutInOrder(nStartCol, nEndCol); 4964 PutInOrder(nStartRow, nEndRow); 4965 PutInOrder(nStartTab, nEndTab); 4966 if (VALIDTAB(nStartTab)) 4967 { 4968 if (pTab[nStartTab]) 4969 return pTab[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir); 4970 else 4971 return 0; 4972 } 4973 else 4974 return 0; 4975 } 4976 4977 4978 void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY ) 4979 { 4980 if (ValidTab(nTab) && pTab[nTab]) 4981 pTab[nTab]->FindAreaPos( rCol, rRow, nMovX, nMovY ); 4982 } 4983 4984 4985 void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY, 4986 sal_Bool bMarked, sal_Bool bUnprotected, const ScMarkData& rMark ) 4987 { 4988 DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" ); 4989 4990 ScMarkData aCopyMark = rMark; 4991 aCopyMark.SetMarking(sal_False); 4992 aCopyMark.MarkToMulti(); 4993 4994 if (ValidTab(nTab) && pTab[nTab]) 4995 pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark ); 4996 } 4997 4998 // 4999 // Datei-Operationen 5000 // 5001 5002 5003 void ScDocument::UpdStlShtPtrsFrmNms() 5004 { 5005 ScPatternAttr::pDoc = this; 5006 5007 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 5008 5009 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN); 5010 ScPatternAttr* pPattern; 5011 for (sal_uInt32 i=0; i<nCount; i++) 5012 { 5013 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i); 5014 if (pPattern) 5015 pPattern->UpdateStyleSheet(); 5016 } 5017 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet(); 5018 } 5019 5020 5021 void ScDocument::StylesToNames() 5022 { 5023 ScPatternAttr::pDoc = this; 5024 5025 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 5026 5027 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN); 5028 ScPatternAttr* pPattern; 5029 for (sal_uInt32 i=0; i<nCount; i++) 5030 { 5031 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i); 5032 if (pPattern) 5033 pPattern->StyleToName(); 5034 } 5035 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName(); 5036 } 5037 5038 5039 sal_uLong ScDocument::GetCellCount() const 5040 { 5041 sal_uLong nCellCount = 0L; 5042 5043 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5044 if ( pTab[nTab] ) 5045 nCellCount += pTab[nTab]->GetCellCount(); 5046 5047 return nCellCount; 5048 } 5049 5050 SCSIZE ScDocument::GetCellCount(SCTAB nTab, SCCOL nCol) const 5051 { 5052 if (!ValidTab(nTab) || !pTab[nTab]) 5053 return 0; 5054 5055 return pTab[nTab]->GetCellCount(nCol); 5056 } 5057 5058 sal_uLong ScDocument::GetCodeCount() const 5059 { 5060 sal_uLong nCodeCount = 0; 5061 5062 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5063 if ( pTab[nTab] ) 5064 nCodeCount += pTab[nTab]->GetCodeCount(); 5065 5066 return nCodeCount; 5067 } 5068 5069 5070 sal_uLong ScDocument::GetWeightedCount() const 5071 { 5072 sal_uLong nCellCount = 0L; 5073 5074 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) 5075 if ( pTab[nTab] ) 5076 nCellCount += pTab[nTab]->GetWeightedCount(); 5077 5078 return nCellCount; 5079 } 5080 5081 5082 void ScDocument::PageStyleModified( SCTAB nTab, const String& rNewName ) 5083 { 5084 if ( ValidTab(nTab) && pTab[nTab] ) 5085 pTab[nTab]->PageStyleModified( rNewName ); 5086 } 5087 5088 5089 void ScDocument::SetPageStyle( SCTAB nTab, const String& rName ) 5090 { 5091 if ( ValidTab(nTab) && pTab[nTab] ) 5092 pTab[nTab]->SetPageStyle( rName ); 5093 } 5094 5095 5096 const String& ScDocument::GetPageStyle( SCTAB nTab ) const 5097 { 5098 if ( ValidTab(nTab) && pTab[nTab] ) 5099 return pTab[nTab]->GetPageStyle(); 5100 5101 return EMPTY_STRING; 5102 } 5103 5104 5105 void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize ) 5106 { 5107 if ( ValidTab(nTab) && pTab[nTab] ) 5108 pTab[nTab]->SetPageSize( rSize ); 5109 } 5110 5111 Size ScDocument::GetPageSize( SCTAB nTab ) const 5112 { 5113 if ( ValidTab(nTab) && pTab[nTab] ) 5114 return pTab[nTab]->GetPageSize(); 5115 5116 DBG_ERROR("falsche Tab"); 5117 return Size(); 5118 } 5119 5120 5121 void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ) 5122 { 5123 if ( ValidTab(nTab) && pTab[nTab] ) 5124 pTab[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow ); 5125 } 5126 5127 void ScDocument::InvalidatePageBreaks(SCTAB nTab) 5128 { 5129 if (ValidTab(nTab) && pTab[nTab]) 5130 pTab[nTab]->InvalidatePageBreaks(); 5131 } 5132 5133 void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea ) 5134 { 5135 if ( ValidTab(nTab) && pTab[nTab] ) 5136 pTab[nTab]->UpdatePageBreaks( pUserArea ); 5137 } 5138 5139 void ScDocument::RemoveManualBreaks( SCTAB nTab ) 5140 { 5141 if ( ValidTab(nTab) && pTab[nTab] ) 5142 pTab[nTab]->RemoveManualBreaks(); 5143 } 5144 5145 sal_Bool ScDocument::HasManualBreaks( SCTAB nTab ) const 5146 { 5147 if ( ValidTab(nTab) && pTab[nTab] ) 5148 return pTab[nTab]->HasManualBreaks(); 5149 5150 DBG_ERROR("falsche Tab"); 5151 return sal_False; 5152 } 5153 5154 5155 void ScDocument::GetDocStat( ScDocStat& rDocStat ) 5156 { 5157 rDocStat.nTableCount = GetTableCount(); 5158 rDocStat.aDocName = aDocName; 5159 rDocStat.nCellCount = GetCellCount(); 5160 } 5161 5162 5163 sal_Bool ScDocument::HasPrintRange() 5164 { 5165 sal_Bool bResult = sal_False; 5166 5167 for ( SCTAB i=0; !bResult && i<nMaxTableNumber; i++ ) 5168 if ( pTab[i] ) 5169 bResult = pTab[i]->IsPrintEntireSheet() || (pTab[i]->GetPrintRangeCount() > 0); 5170 5171 return bResult; 5172 } 5173 5174 5175 sal_Bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const 5176 { 5177 return (ValidTab(nTab) ) && pTab[nTab] && pTab[nTab]->IsPrintEntireSheet(); 5178 } 5179 5180 5181 sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab ) 5182 { 5183 if (ValidTab(nTab) && pTab[nTab]) 5184 return pTab[nTab]->GetPrintRangeCount(); 5185 5186 return 0; 5187 } 5188 5189 5190 const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos ) 5191 { 5192 if (ValidTab(nTab) && pTab[nTab]) 5193 return pTab[nTab]->GetPrintRange(nPos); 5194 5195 return NULL; 5196 } 5197 5198 5199 const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab ) 5200 { 5201 if (ValidTab(nTab) && pTab[nTab]) 5202 return pTab[nTab]->GetRepeatColRange(); 5203 5204 return NULL; 5205 } 5206 5207 5208 const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab ) 5209 { 5210 if (ValidTab(nTab) && pTab[nTab]) 5211 return pTab[nTab]->GetRepeatRowRange(); 5212 5213 return NULL; 5214 } 5215 5216 5217 void ScDocument::ClearPrintRanges( SCTAB nTab ) 5218 { 5219 if (ValidTab(nTab) && pTab[nTab]) 5220 pTab[nTab]->ClearPrintRanges(); 5221 } 5222 5223 5224 void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew ) 5225 { 5226 if (ValidTab(nTab) && pTab[nTab]) 5227 pTab[nTab]->AddPrintRange( rNew ); 5228 } 5229 5230 5231 //UNUSED2009-05 void ScDocument::SetPrintRange( SCTAB nTab, const ScRange& rNew ) 5232 //UNUSED2009-05 { 5233 //UNUSED2009-05 if (ValidTab(nTab) && pTab[nTab]) 5234 //UNUSED2009-05 pTab[nTab]->SetPrintRange( rNew ); 5235 //UNUSED2009-05 } 5236 5237 5238 void ScDocument::SetPrintEntireSheet( SCTAB nTab ) 5239 { 5240 if (ValidTab(nTab) && pTab[nTab]) 5241 pTab[nTab]->SetPrintEntireSheet(); 5242 } 5243 5244 5245 void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew ) 5246 { 5247 if (ValidTab(nTab) && pTab[nTab]) 5248 pTab[nTab]->SetRepeatColRange( pNew ); 5249 } 5250 5251 5252 void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew ) 5253 { 5254 if (ValidTab(nTab) && pTab[nTab]) 5255 pTab[nTab]->SetRepeatRowRange( pNew ); 5256 } 5257 5258 5259 ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const 5260 { 5261 SCTAB nCount = GetTableCount(); 5262 ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount ); 5263 for (SCTAB i=0; i<nCount; i++) 5264 if (pTab[i]) 5265 pTab[i]->FillPrintSaver( pNew->GetTabData(i) ); 5266 return pNew; 5267 } 5268 5269 5270 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver ) 5271 { 5272 SCTAB nCount = rSaver.GetTabCount(); 5273 for (SCTAB i=0; i<nCount; i++) 5274 if (pTab[i]) 5275 pTab[i]->RestorePrintRanges( rSaver.GetTabData(i) ); 5276 } 5277 5278 5279 sal_Bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const 5280 { 5281 // Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine 5282 // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen) 5283 // und eine Seitennummer angegeben ist (nicht 0) 5284 5285 if ( nTab < MAXTAB && pTab[nTab] && pTab[nTab+1] ) 5286 { 5287 String aNew = pTab[nTab+1]->GetPageStyle(); 5288 if ( aNew != pTab[nTab]->GetPageStyle() ) 5289 { 5290 SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE ); 5291 if ( pStyle ) 5292 { 5293 const SfxItemSet& rSet = pStyle->GetItemSet(); 5294 sal_uInt16 nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue(); 5295 if ( nFirst != 0 ) 5296 return sal_True; // Seitennummer in neuer Vorlage angegeben 5297 } 5298 } 5299 } 5300 5301 return sal_False; // sonst nicht 5302 } 5303 5304 SfxUndoManager* ScDocument::GetUndoManager() 5305 { 5306 if (!mpUndoManager) 5307 { 5308 // to support enhanced text edit for draw objects, use an SdrUndoManager 5309 mpUndoManager = new SdrUndoManager; 5310 } 5311 5312 return mpUndoManager; 5313 } 5314 5315 ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const 5316 { 5317 if (ValidTab(nTab) && pTab[nTab]) 5318 return new ScRowBreakIterator(pTab[nTab]->maRowPageBreaks); 5319 return NULL; 5320 } 5321 5322 void ScDocument::EnableUndo( bool bVal ) 5323 { 5324 GetUndoManager()->EnableUndo(bVal); 5325 if( pDrawLayer ) pDrawLayer->EnableUndo(bVal); 5326 mbUndoEnabled = bVal; 5327 } 5328 5329 bool ScDocument::IsInVBAMode() const 5330 { 5331 bool bResult = false; 5332 if ( pShell ) 5333 { 5334 com::sun::star::uno::Reference< com::sun::star::script::vba::XVBACompatibility > xVBA( pShell->GetBasicContainer(), com::sun::star::uno::UNO_QUERY ); 5335 bResult = xVBA.is() && xVBA->getVBACompatibilityMode(); 5336 } 5337 return bResult; 5338 } 5339