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