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