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