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