1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2011 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 // INCLUDE --------------------------------------------------------------- 32 33 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp> 34 #include "scitems.hxx" 35 #include <editeng/langitem.hxx> 36 #include <svl/srchitem.hxx> 37 #include <sfx2/linkmgr.hxx> 38 #include <sfx2/bindings.hxx> 39 #include <sfx2/objsh.hxx> 40 #include <svl/zforlist.hxx> 41 #include <svl/PasswordHelper.hxx> 42 #include <vcl/svapp.hxx> 43 #include "document.hxx" 44 #include "attrib.hxx" 45 #include "cell.hxx" 46 #include "table.hxx" 47 #include "rangenam.hxx" 48 #include "dbcolect.hxx" 49 #include "pivot.hxx" 50 #include "docpool.hxx" 51 #include "poolhelp.hxx" 52 #include "autoform.hxx" 53 #include "rangelst.hxx" 54 #include "chartarr.hxx" 55 #include "chartlock.hxx" 56 #include "refupdat.hxx" 57 #include "docoptio.hxx" 58 #include "viewopti.hxx" 59 #include "scextopt.hxx" 60 #include "brdcst.hxx" 61 #include "bcaslot.hxx" 62 #include "tablink.hxx" 63 #include "externalrefmgr.hxx" 64 #include "markdata.hxx" 65 #include "validat.hxx" 66 #include "dociter.hxx" 67 #include "detdata.hxx" 68 #include "detfunc.hxx" 69 #include "scmod.hxx" // SC_MOD 70 #include "inputopt.hxx" // GetExpandRefs 71 #include "chartlis.hxx" 72 #include "sc.hrc" // SID_LINK 73 #include "hints.hxx" 74 #include "dpobject.hxx" 75 #include "unoguard.hxx" 76 #include "drwlayer.hxx" 77 #include "unoreflist.hxx" 78 #include "listenercalls.hxx" 79 // Wang Xu Ming -- 2009-8-17 80 // DataPilot Migration - Cache&&Performance 81 #include "dpshttab.hxx" 82 #include "dptablecache.hxx" 83 // End Comments 84 #include "tabprotection.hxx" 85 #include "formulaparserpool.hxx" 86 #include "clipparam.hxx" 87 #include "sheetevents.hxx" 88 89 #include <memory> 90 91 using namespace com::sun::star; 92 93 //------------------------------------------------------------------------ 94 95 ScRangeName* ScDocument::GetRangeName() 96 { 97 return pRangeName; 98 } 99 100 void ScDocument::SetRangeName( ScRangeName* pNewRangeName ) 101 { 102 if (pRangeName) 103 delete pRangeName; 104 pRangeName = pNewRangeName; 105 } 106 107 //UNUSED2008-05 ScRangeData* ScDocument::GetRangeAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, 108 //UNUSED2008-05 sal_Bool bStartOnly) const 109 //UNUSED2008-05 { 110 //UNUSED2008-05 if ( pRangeName ) 111 //UNUSED2008-05 return pRangeName->GetRangeAtCursor( ScAddress( nCol, nRow, nTab ), bStartOnly ); 112 //UNUSED2008-05 else 113 //UNUSED2008-05 return NULL; 114 //UNUSED2008-05 } 115 116 ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, String* pName ) const 117 { 118 ScRangeData* pData = NULL; 119 if ( pRangeName ) 120 { 121 pData = pRangeName->GetRangeAtBlock( rBlock ); 122 if (pData && pName) 123 *pName = pData->GetName(); 124 } 125 return pData; 126 } 127 128 ScDBCollection* ScDocument::GetDBCollection() const 129 { 130 return pDBCollection; 131 } 132 133 void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, sal_Bool bRemoveAutoFilter ) 134 { 135 if ( bRemoveAutoFilter ) 136 { 137 // remove auto filter attribute if new db data don't contain auto filter flag 138 // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo! 139 140 if ( pDBCollection ) 141 { 142 sal_uInt16 nOldCount = pDBCollection->GetCount(); 143 for (sal_uInt16 nOld=0; nOld<nOldCount; nOld++) 144 { 145 ScDBData* pOldData = (*pDBCollection)[nOld]; 146 if ( pOldData->HasAutoFilter() ) 147 { 148 ScRange aOldRange; 149 pOldData->GetArea( aOldRange ); 150 151 sal_Bool bFound = sal_False; 152 sal_uInt16 nNewIndex = 0; 153 if ( pNewDBCollection && 154 pNewDBCollection->SearchName( pOldData->GetName(), nNewIndex ) ) 155 { 156 ScDBData* pNewData = (*pNewDBCollection)[nNewIndex]; 157 if ( pNewData->HasAutoFilter() ) 158 { 159 ScRange aNewRange; 160 pNewData->GetArea( aNewRange ); 161 if ( aOldRange.aStart == aNewRange.aStart ) 162 bFound = sal_True; 163 } 164 } 165 166 if ( !bFound ) 167 { 168 aOldRange.aEnd.SetRow( aOldRange.aStart.Row() ); 169 RemoveFlagsTab( aOldRange.aStart.Col(), aOldRange.aStart.Row(), 170 aOldRange.aEnd.Col(), aOldRange.aEnd.Row(), 171 aOldRange.aStart.Tab(), SC_MF_AUTO ); 172 RepaintRange( aOldRange ); 173 } 174 } 175 } 176 } 177 } 178 179 if (pDBCollection) 180 delete pDBCollection; 181 pDBCollection = pNewDBCollection; 182 } 183 184 ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly) const 185 { 186 if (pDBCollection) 187 return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly); 188 else 189 return NULL; 190 } 191 192 ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const 193 { 194 if (pDBCollection) 195 return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2); 196 else 197 return NULL; 198 } 199 200 ScDBData* ScDocument::GetFilterDBAtTable(SCTAB nTab) const 201 { 202 if (pDBCollection) 203 return pDBCollection->GetFilterDBAtTable(nTab); 204 else 205 return NULL; 206 } 207 208 ScDPCollection* ScDocument::GetDPCollection() 209 { 210 if (!pDPCollection) 211 pDPCollection = new ScDPCollection(this); 212 return pDPCollection; 213 } 214 215 ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const 216 { 217 if (!pDPCollection) 218 return NULL; 219 220 sal_uInt16 nCount = pDPCollection->GetCount(); 221 ScAddress aPos( nCol, nRow, nTab ); 222 for (sal_uInt16 i=0; i<nCount; i++) 223 if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) ) 224 return (*pDPCollection)[i]; 225 226 return NULL; 227 } 228 229 ScDPObject* ScDocument::GetDPAtBlock( const ScRange & rBlock ) const 230 { 231 if (!pDPCollection) 232 return NULL; 233 234 /* Walk the collection in reverse order to get something of an 235 * approximation of MS Excels 'most recent' effect. */ 236 sal_uInt16 i = pDPCollection->GetCount(); 237 while ( i-- > 0 ) 238 if ( (*pDPCollection)[i]->GetOutRange().In( rBlock ) ) 239 return (*pDPCollection)[i]; 240 241 return NULL; 242 } 243 244 ScChartCollection* ScDocument::GetChartCollection() const 245 { 246 return pChartCollection; 247 } 248 249 void ScDocument::StopTemporaryChartLock() 250 { 251 if( apTemporaryChartLock.get() ) 252 apTemporaryChartLock->StopLocking(); 253 } 254 255 void ScDocument::SetChartListenerCollection( 256 ScChartListenerCollection* pNewChartListenerCollection, 257 sal_Bool bSetChartRangeLists ) 258 { 259 ScChartListenerCollection* pOld = pChartListenerCollection; 260 pChartListenerCollection = pNewChartListenerCollection; 261 if ( pChartListenerCollection ) 262 { 263 if ( pOld ) 264 pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists ); 265 pChartListenerCollection->StartAllListeners(); 266 } 267 delete pOld; 268 } 269 270 void ScDocument::SetScenario( SCTAB nTab, sal_Bool bFlag ) 271 { 272 if (ValidTab(nTab) && pTab[nTab]) 273 pTab[nTab]->SetScenario(bFlag); 274 } 275 276 sal_Bool ScDocument::IsScenario( SCTAB nTab ) const 277 { 278 return ValidTab(nTab) && pTab[nTab] &&pTab[nTab]->IsScenario(); 279 //if (ValidTab(nTab) && pTab[nTab]) 280 // return pTab[nTab]->IsScenario(); 281 282 //return sal_False; 283 } 284 285 void ScDocument::SetScenarioData( SCTAB nTab, const String& rComment, 286 const Color& rColor, sal_uInt16 nFlags ) 287 { 288 if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario()) 289 { 290 pTab[nTab]->SetScenarioComment( rComment ); 291 pTab[nTab]->SetScenarioColor( rColor ); 292 pTab[nTab]->SetScenarioFlags( nFlags ); 293 } 294 } 295 296 Color ScDocument::GetTabBgColor( SCTAB nTab ) const 297 { 298 if (ValidTab(nTab) && pTab[nTab]) 299 return pTab[nTab]->GetTabBgColor(); 300 return Color(COL_AUTO); 301 } 302 303 void ScDocument::SetTabBgColor( SCTAB nTab, const Color& rColor ) 304 { 305 if (ValidTab(nTab) && pTab[nTab]) 306 pTab[nTab]->SetTabBgColor(rColor); 307 } 308 309 bool ScDocument::IsDefaultTabBgColor( SCTAB nTab ) const 310 { 311 if (ValidTab(nTab) && pTab[nTab]) 312 return pTab[nTab]->GetTabBgColor() == COL_AUTO; 313 return true; 314 } 315 316 void ScDocument::GetScenarioData( SCTAB nTab, String& rComment, 317 Color& rColor, sal_uInt16& rFlags ) const 318 { 319 if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario()) 320 { 321 pTab[nTab]->GetScenarioComment( rComment ); 322 rColor = pTab[nTab]->GetScenarioColor(); 323 rFlags = pTab[nTab]->GetScenarioFlags(); 324 } 325 } 326 327 void ScDocument::GetScenarioFlags( SCTAB nTab, sal_uInt16& rFlags ) const 328 { 329 if (VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->IsScenario()) 330 rFlags = pTab[nTab]->GetScenarioFlags(); 331 } 332 333 sal_Bool ScDocument::IsLinked( SCTAB nTab ) const 334 { 335 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsLinked(); 336 // euqivalent to 337 //if (ValidTab(nTab) && pTab[nTab]) 338 // return pTab[nTab]->IsLinked(); 339 //return sal_False; 340 } 341 342 formula::FormulaGrammar::AddressConvention ScDocument::GetAddressConvention() const 343 { 344 return formula::FormulaGrammar::extractRefConvention(eGrammar); 345 } 346 347 formula::FormulaGrammar::Grammar ScDocument::GetGrammar() const 348 { 349 return eGrammar; 350 } 351 352 void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram ) 353 { 354 eGrammar = eGram; 355 } 356 357 sal_Bool ScDocument::GetLinkMode( SCTAB nTab ) const 358 { 359 if (ValidTab(nTab) && pTab[nTab]) 360 return pTab[nTab]->GetLinkMode(); 361 return SC_LINK_NONE; 362 } 363 364 const String& ScDocument::GetLinkDoc( SCTAB nTab ) const 365 { 366 if (ValidTab(nTab) && pTab[nTab]) 367 return pTab[nTab]->GetLinkDoc(); 368 return EMPTY_STRING; 369 } 370 371 const String& ScDocument::GetLinkFlt( SCTAB nTab ) const 372 { 373 if (ValidTab(nTab) && pTab[nTab]) 374 return pTab[nTab]->GetLinkFlt(); 375 return EMPTY_STRING; 376 } 377 378 const String& ScDocument::GetLinkOpt( SCTAB nTab ) const 379 { 380 if (ValidTab(nTab) && pTab[nTab]) 381 return pTab[nTab]->GetLinkOpt(); 382 return EMPTY_STRING; 383 } 384 385 const String& ScDocument::GetLinkTab( SCTAB nTab ) const 386 { 387 if (ValidTab(nTab) && pTab[nTab]) 388 return pTab[nTab]->GetLinkTab(); 389 return EMPTY_STRING; 390 } 391 392 sal_uLong ScDocument::GetLinkRefreshDelay( SCTAB nTab ) const 393 { 394 if (ValidTab(nTab) && pTab[nTab]) 395 return pTab[nTab]->GetLinkRefreshDelay(); 396 return 0; 397 } 398 399 void ScDocument::SetLink( SCTAB nTab, sal_uInt8 nMode, const String& rDoc, 400 const String& rFilter, const String& rOptions, 401 const String& rTabName, sal_uLong nRefreshDelay ) 402 { 403 if (ValidTab(nTab) && pTab[nTab]) 404 pTab[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName, nRefreshDelay ); 405 } 406 407 sal_Bool ScDocument::HasLink( const String& rDoc, 408 const String& rFilter, const String& rOptions ) const 409 { 410 SCTAB nCount = GetTableCount(); 411 for (SCTAB i=0; i<nCount; i++) 412 if (pTab[i]->IsLinked() 413 && pTab[i]->GetLinkDoc() == rDoc 414 && pTab[i]->GetLinkFlt() == rFilter 415 && pTab[i]->GetLinkOpt() == rOptions) 416 return sal_True; 417 418 return sal_False; 419 } 420 421 sal_Bool ScDocument::LinkExternalTab( SCTAB& rTab, const String& aDocTab, 422 const String& aFileName, const String& aTabName ) 423 { 424 if ( IsClipboard() ) 425 { 426 DBG_ERRORFILE( "LinkExternalTab in Clipboard" ); 427 return sal_False; 428 } 429 rTab = 0; 430 String aFilterName; // wird vom Loader gefuellt 431 String aOptions; // Filter-Optionen 432 sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0; 433 ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 ); 434 if ( aLoader.IsError() ) 435 return sal_False; 436 ScDocument* pSrcDoc = aLoader.GetDocument(); 437 438 // Tabelle kopieren 439 SCTAB nSrcTab; 440 if ( pSrcDoc->GetTable( aTabName, nSrcTab ) ) 441 { 442 if ( !InsertTab( SC_TAB_APPEND, aDocTab, sal_True ) ) 443 { 444 DBG_ERRORFILE("can't insert external document table"); 445 return sal_False; 446 } 447 rTab = GetTableCount() - 1; 448 // nicht neu einfuegen, nur Ergebnisse 449 TransferTab( pSrcDoc, nSrcTab, rTab, sal_False, sal_True ); 450 } 451 else 452 return sal_False; 453 454 sal_uLong nRefreshDelay = 0; 455 456 sal_Bool bWasThere = HasLink( aFileName, aFilterName, aOptions ); 457 SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName, nRefreshDelay ); 458 if ( !bWasThere ) // Link pro Quelldokument nur einmal eintragen 459 { 460 ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions, nRefreshDelay ); 461 pLink->SetInCreate( sal_True ); 462 GetLinkManager()->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, 463 &aFilterName ); 464 pLink->Update(); 465 pLink->SetInCreate( sal_False ); 466 SfxBindings* pBindings = GetViewBindings(); 467 if (pBindings) 468 pBindings->Invalidate( SID_LINKS ); 469 } 470 return sal_True; 471 } 472 473 ScExternalRefManager* ScDocument::GetExternalRefManager() const 474 { 475 ScDocument* pThis = const_cast<ScDocument*>(this); 476 if (!pExternalRefMgr.get()) 477 pThis->pExternalRefMgr.reset( new ScExternalRefManager( pThis)); 478 479 return pExternalRefMgr.get(); 480 } 481 482 bool ScDocument::IsInExternalReferenceMarking() const 483 { 484 return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking(); 485 } 486 487 void ScDocument::MarkUsedExternalReferences() 488 { 489 if (!pExternalRefMgr.get()) 490 return; 491 if (!pExternalRefMgr->hasExternalData()) 492 return; 493 // Charts. 494 bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners(); 495 // Formula cells. 496 bAllMarked = pExternalRefMgr->markUsedExternalRefCells(); 497 498 /* NOTE: Conditional formats and validation objects are marked when 499 * collecting them during export. */ 500 } 501 502 ScFormulaParserPool& ScDocument::GetFormulaParserPool() const 503 { 504 if( !mxFormulaParserPool.get() ) 505 mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) ); 506 return *mxFormulaParserPool; 507 } 508 509 const ScSheetEvents* ScDocument::GetSheetEvents( SCTAB nTab ) const 510 { 511 if (VALIDTAB(nTab) && pTab[nTab]) 512 return pTab[nTab]->GetSheetEvents(); 513 return NULL; 514 } 515 516 void ScDocument::SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew ) 517 { 518 if (VALIDTAB(nTab) && pTab[nTab]) 519 pTab[nTab]->SetSheetEvents( pNew ); 520 } 521 522 bool ScDocument::HasSheetEventScript( SCTAB nTab, sal_Int32 nEvent, bool bWithVbaEvents ) const 523 { 524 if (pTab[nTab]) 525 { 526 // check if any event handler script has been configured 527 const ScSheetEvents* pEvents = pTab[nTab]->GetSheetEvents(); 528 if ( pEvents && pEvents->GetScript( nEvent ) ) 529 return true; 530 // check if VBA event handlers exist 531 if (bWithVbaEvents && mxVbaEvents.is()) try 532 { 533 uno::Sequence< uno::Any > aArgs( 1 ); 534 aArgs[ 0 ] <<= nTab; 535 if (mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs ) || 536 mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaDocumentEventId( nEvent ), uno::Sequence< uno::Any >() )) 537 return true; 538 } 539 catch( uno::Exception& ) 540 { 541 } 542 } 543 return false; 544 } 545 546 bool ScDocument::HasAnySheetEventScript( sal_Int32 nEvent, bool bWithVbaEvents ) const 547 { 548 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) 549 if (HasSheetEventScript( nTab, nEvent, bWithVbaEvents )) 550 return true; 551 return false; 552 } 553 554 bool ScDocument::HasAnyCalcNotification() const 555 { 556 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) 557 if (pTab[nTab] && pTab[nTab]->GetCalcNotification()) 558 return true; 559 return false; 560 } 561 562 sal_Bool ScDocument::HasCalcNotification( SCTAB nTab ) const 563 { 564 if (VALIDTAB(nTab) && pTab[nTab]) 565 return pTab[nTab]->GetCalcNotification(); 566 return sal_False; 567 } 568 569 void ScDocument::SetCalcNotification( SCTAB nTab ) 570 { 571 // set only if not set before 572 if (VALIDTAB(nTab) && pTab[nTab] && !pTab[nTab]->GetCalcNotification()) 573 pTab[nTab]->SetCalcNotification(sal_True); 574 } 575 576 void ScDocument::ResetCalcNotifications() 577 { 578 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) 579 if (pTab[nTab] && pTab[nTab]->GetCalcNotification()) 580 pTab[nTab]->SetCalcNotification(sal_False); 581 } 582 583 ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, sal_Bool bCreate ) 584 { 585 ScOutlineTable* pVal = NULL; 586 587 if (VALIDTAB(nTab)) 588 if (pTab[nTab]) 589 { 590 pVal = pTab[nTab]->GetOutlineTable(); 591 if (!pVal) 592 if (bCreate) 593 { 594 pTab[nTab]->StartOutlineTable(); 595 pVal = pTab[nTab]->GetOutlineTable(); 596 } 597 } 598 599 return pVal; 600 } 601 602 sal_Bool ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline ) 603 { 604 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->SetOutlineTable(pNewOutline); 605 //if (VALIDTAB(nTab)) 606 // if (pTab[nTab]) 607 // return pTab[nTab]->SetOutlineTable(pNewOutline); 608 609 //return sal_False; 610 } 611 612 void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, 613 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 614 { 615 if (VALIDTAB(nTab) && pTab[nTab]) 616 pTab[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow ); 617 } 618 619 sal_Bool ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam ) 620 { 621 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->TestRemoveSubTotals( rParam ); 622 //if (VALIDTAB(nTab) && pTab[nTab] ) 623 // return pTab[nTab]->TestRemoveSubTotals( rParam ); 624 625 //return sal_False; 626 } 627 628 void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam ) 629 { 630 if ( VALIDTAB(nTab) && pTab[nTab] ) 631 pTab[nTab]->RemoveSubTotals( rParam ); 632 } 633 634 sal_Bool ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam ) 635 { 636 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->DoSubTotals( rParam ); 637 //if (VALIDTAB(nTab)) 638 // if (pTab[nTab]) 639 // return pTab[nTab]->DoSubTotals( rParam ); 640 641 //return sal_False; 642 } 643 644 sal_Bool ScDocument::HasSubTotalCells( const ScRange& rRange ) 645 { 646 ScCellIterator aIter( this, rRange ); 647 ScBaseCell* pCell = aIter.GetFirst(); 648 while (pCell) 649 { 650 if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->IsSubTotal() ) 651 return sal_True; 652 653 pCell = aIter.GetNext(); 654 } 655 return sal_False; // none found 656 } 657 658 // kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc 659 // auch Zellen stehen, nach pDestDoc 660 661 void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc ) 662 { 663 SCTAB nCount = GetTableCount(); 664 for (SCTAB nTab=0; nTab<nCount; nTab++) 665 if (pTab[nTab] && pPosDoc->pTab[nTab] && pDestDoc->pTab[nTab]) 666 pTab[nTab]->CopyUpdated( pPosDoc->pTab[nTab], pDestDoc->pTab[nTab] ); 667 } 668 669 void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, sal_Bool bNewScenario ) 670 { 671 if (ValidTab(nSrcTab) && ValidTab(nDestTab) && pTab[nSrcTab] && pTab[nDestTab]) 672 { 673 // Flags fuer aktive Szenarios richtig setzen 674 // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben 675 676 ScRangeList aRanges = *pTab[nSrcTab]->GetScenarioRanges(); 677 const sal_uLong nRangeCount = aRanges.Count(); 678 679 // nDestTab ist die Zieltabelle 680 for ( SCTAB nTab = nDestTab+1; 681 nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario(); 682 nTab++ ) 683 { 684 if ( pTab[nTab]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist 685 { 686 sal_Bool bTouched = sal_False; 687 for ( sal_uLong nR=0; nR<nRangeCount && !bTouched; nR++) 688 { 689 const ScRange* pRange = aRanges.GetObject(nR); 690 if ( pTab[nTab]->HasScenarioRange( *pRange ) ) 691 bTouched = sal_True; 692 } 693 if (bTouched) 694 { 695 pTab[nTab]->SetActiveScenario(sal_False); 696 if ( pTab[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY ) 697 pTab[nTab]->CopyScenarioFrom( pTab[nDestTab] ); 698 } 699 } 700 } 701 702 pTab[nSrcTab]->SetActiveScenario(sal_True); // da kommt's her... 703 if (!bNewScenario) // Daten aus dem ausgewaehlten Szenario kopieren 704 { 705 sal_Bool bOldAutoCalc = GetAutoCalc(); 706 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden 707 pTab[nSrcTab]->CopyScenarioTo( pTab[nDestTab] ); 708 SetDirty(); 709 SetAutoCalc( bOldAutoCalc ); 710 } 711 } 712 } 713 714 void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark, 715 sal_Bool bResetMark, sal_uInt16 nNeededBits ) const 716 { 717 if (bResetMark) 718 rDestMark.ResetMark(); 719 720 if (ValidTab(nSrcTab) && pTab[nSrcTab]) 721 pTab[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits ); 722 723 rDestMark.SetAreaTab( nDestTab ); 724 } 725 726 sal_Bool ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const 727 { 728 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->HasScenarioRange( rRange ); 729 //if (ValidTab(nTab) && pTab[nTab]) 730 // return pTab[nTab]->HasScenarioRange( rRange ); 731 732 //return sal_False; 733 } 734 735 const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const 736 { 737 if (ValidTab(nTab) && pTab[nTab]) 738 return pTab[nTab]->GetScenarioRanges(); 739 740 return NULL; 741 } 742 743 sal_Bool ScDocument::IsActiveScenario( SCTAB nTab ) const 744 { 745 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsActiveScenario( ); 746 //if (ValidTab(nTab) && pTab[nTab]) 747 // return pTab[nTab]->IsActiveScenario(); 748 749 //return sal_False; 750 } 751 752 void ScDocument::SetActiveScenario( SCTAB nTab, sal_Bool bActive ) 753 { 754 if (ValidTab(nTab) && pTab[nTab]) 755 pTab[nTab]->SetActiveScenario( bActive ); 756 } 757 758 sal_Bool ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const 759 { 760 if (ValidTab(nSrcTab) && ValidTab(nDestTab)) 761 return pTab[nSrcTab]->TestCopyScenarioTo( pTab[nDestTab] ); 762 763 DBG_ERROR("falsche Tabelle bei TestCopyScenario"); 764 return sal_False; 765 } 766 767 void ScDocument::AddUnoObject( SfxListener& rObject ) 768 { 769 if (!pUnoBroadcaster) 770 pUnoBroadcaster = new SfxBroadcaster; 771 772 rObject.StartListening( *pUnoBroadcaster ); 773 } 774 775 void ScDocument::RemoveUnoObject( SfxListener& rObject ) 776 { 777 if (pUnoBroadcaster) 778 { 779 rObject.EndListening( *pUnoBroadcaster ); 780 781 if ( bInUnoBroadcast ) 782 { 783 // #107294# Broadcasts from ScDocument::BroadcastUno are the only way that 784 // uno object methods are called without holding a reference. 785 // 786 // If RemoveUnoObject is called from an object dtor in the finalizer thread 787 // while the main thread is calling BroadcastUno, the dtor thread must wait 788 // (or the object's Notify might try to access a deleted object). 789 // The SolarMutex can't be locked here because if a component is called from 790 // a VCL event, the main thread has the SolarMutex locked all the time. 791 // 792 // This check is done after calling EndListening, so a later BroadcastUno call 793 // won't touch this object. 794 795 vos::IMutex& rSolarMutex = Application::GetSolarMutex(); 796 if ( rSolarMutex.tryToAcquire() ) 797 { 798 // BroadcastUno is always called with the SolarMutex locked, so if it 799 // can be acquired, this is within the same thread (should not happen) 800 DBG_ERRORFILE( "RemoveUnoObject called from BroadcastUno" ); 801 rSolarMutex.release(); 802 } 803 else 804 { 805 // let the thread that called BroadcastUno continue 806 while ( bInUnoBroadcast ) 807 { 808 vos::OThread::yield(); 809 } 810 } 811 } 812 } 813 else 814 { 815 DBG_ERROR("No Uno broadcaster"); 816 } 817 } 818 819 void ScDocument::BroadcastUno( const SfxHint &rHint ) 820 { 821 if (pUnoBroadcaster) 822 { 823 bInUnoBroadcast = sal_True; 824 pUnoBroadcaster->Broadcast( rHint ); 825 bInUnoBroadcast = sal_False; 826 827 // During Broadcast notification, Uno objects can add to pUnoListenerCalls. 828 // The listener calls must be processed after completing the broadcast, 829 // because they can add or remove objects from pUnoBroadcaster. 830 831 if ( pUnoListenerCalls && rHint.ISA( SfxSimpleHint ) && 832 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DATACHANGED && 833 !bInUnoListenerCall ) 834 { 835 // Listener calls may lead to BroadcastUno calls again. The listener calls 836 // are not nested, instead the calls are collected in the list, and the 837 // outermost call executes them all. 838 839 ScChartLockGuard aChartLockGuard(this); 840 bInUnoListenerCall = sal_True; 841 pUnoListenerCalls->ExecuteAndClear(); 842 bInUnoListenerCall = sal_False; 843 } 844 } 845 } 846 847 void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener, 848 const lang::EventObject& rEvent ) 849 { 850 DBG_ASSERT( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" ); 851 852 if ( !pUnoListenerCalls ) 853 pUnoListenerCalls = new ScUnoListenerCalls; 854 pUnoListenerCalls->Add( rListener, rEvent ); 855 } 856 857 void ScDocument::BeginUnoRefUndo() 858 { 859 DBG_ASSERT( !pUnoRefUndoList, "BeginUnoRefUndo twice" ); 860 delete pUnoRefUndoList; 861 862 pUnoRefUndoList = new ScUnoRefList; 863 } 864 865 ScUnoRefList* ScDocument::EndUnoRefUndo() 866 { 867 ScUnoRefList* pRet = pUnoRefUndoList; 868 pUnoRefUndoList = NULL; 869 return pRet; // must be deleted by caller! 870 } 871 872 void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges ) 873 { 874 if ( pUnoRefUndoList ) 875 pUnoRefUndoList->Add( nId, rOldRanges ); 876 } 877 878 sal_Int64 ScDocument::GetNewUnoId() 879 { 880 return ++nUnoObjectId; 881 } 882 883 void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode, 884 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, 885 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, 886 SCsCOL nDx, SCsROW nDy, SCsTAB nDz, 887 ScDocument* pUndoDoc, sal_Bool bIncludeDraw, 888 bool bUpdateNoteCaptionPos ) 889 { 890 PutInOrder( nCol1, nCol2 ); 891 PutInOrder( nRow1, nRow2 ); 892 PutInOrder( nTab1, nTab2 ); 893 if (VALIDTAB(nTab1) && VALIDTAB(nTab2)) 894 { 895 sal_Bool bExpandRefsOld = IsExpandRefs(); 896 if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) ) 897 SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() ); 898 SCTAB i; 899 SCTAB iMax; 900 if ( eUpdateRefMode == URM_COPY ) 901 { 902 i = nTab1; 903 iMax = nTab2; 904 } 905 else 906 { 907 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 908 xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz ); 909 xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz ); 910 pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz ); 911 pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz ); 912 if ( pDPCollection ) 913 pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz ); 914 UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz ); 915 UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz ); 916 if ( pCondFormList ) 917 pCondFormList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz ); 918 if ( pValidationList ) 919 pValidationList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz ); 920 if ( pDetOpList ) 921 pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz ); 922 if ( pUnoBroadcaster ) 923 pUnoBroadcaster->Broadcast( ScUpdateRefHint( 924 eUpdateRefMode, aRange, nDx, nDy, nDz ) ); 925 i = 0; 926 iMax = MAXTAB; 927 } 928 for ( ; i<=iMax; i++) 929 if (pTab[i]) 930 pTab[i]->UpdateReference( 931 eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, 932 nDx, nDy, nDz, pUndoDoc, bIncludeDraw, bUpdateNoteCaptionPos ); 933 934 if ( bIsEmbedded ) 935 { 936 SCCOL theCol1; 937 SCROW theRow1; 938 SCTAB theTab1; 939 SCCOL theCol2; 940 SCROW theRow2; 941 SCTAB theTab2; 942 theCol1 = aEmbedRange.aStart.Col(); 943 theRow1 = aEmbedRange.aStart.Row(); 944 theTab1 = aEmbedRange.aStart.Tab(); 945 theCol2 = aEmbedRange.aEnd.Col(); 946 theRow2 = aEmbedRange.aEnd.Row(); 947 theTab2 = aEmbedRange.aEnd.Tab(); 948 if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2, 949 nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) ) 950 { 951 aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ); 952 } 953 } 954 SetExpandRefs( bExpandRefsOld ); 955 956 // #30428# after moving, no clipboard move ref-updates are possible 957 if ( eUpdateRefMode != URM_COPY && IsClipboardSource() ) 958 { 959 ScDocument* pClipDoc = SC_MOD()->GetClipDoc(); 960 if (pClipDoc) 961 pClipDoc->GetClipParam().mbCutMode = false; 962 } 963 } 964 } 965 966 void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc, 967 const ScMarkData& rMark, ScDocument* pUndoDoc ) 968 { 969 DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip"); 970 971 ScRange aSource; 972 ScClipParam& rClipParam = GetClipParam(); 973 if (rClipParam.maRanges.Count()) 974 aSource = *rClipParam.maRanges.First(); 975 ScAddress aDest = rDestPos; 976 977 SCTAB nClipTab = 0; 978 for (SCTAB nDestTab=0; nDestTab<=MAXTAB && pTab[nDestTab]; nDestTab++) 979 if (rMark.GetTableSelect(nDestTab)) 980 { 981 while (!pClipDoc->pTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1); 982 aSource.aStart.SetTab( nClipTab ); 983 aSource.aEnd.SetTab( nClipTab ); 984 aDest.SetTab( nDestTab ); 985 986 // wie UpdateReference 987 988 pRangeName->UpdateTranspose( aSource, aDest ); // vor den Zellen! 989 for (SCTAB i=0; i<=MAXTAB; i++) 990 if (pTab[i]) 991 pTab[i]->UpdateTranspose( aSource, aDest, pUndoDoc ); 992 993 nClipTab = (nClipTab+1) % (MAXTAB+1); 994 } 995 } 996 997 void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY ) 998 { 999 //! pDBCollection 1000 //! pPivotCollection 1001 //! UpdateChartRef 1002 1003 pRangeName->UpdateGrow( rArea, nGrowX, nGrowY ); 1004 1005 for (SCTAB i=0; i<=MAXTAB && pTab[i]; i++) 1006 pTab[i]->UpdateGrow( rArea, nGrowX, nGrowY ); 1007 } 1008 1009 void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, 1010 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd, 1011 double nStepValue, double nMaxValue) 1012 { 1013 PutInOrder( nCol1, nCol2 ); 1014 PutInOrder( nRow1, nRow2 ); 1015 for (SCTAB i=0; i <= MAXTAB; i++) 1016 if (pTab[i]) 1017 if (rMark.GetTableSelect(i)) 1018 pTab[i]->Fill(nCol1, nRow1, nCol2, nRow2, 1019 nFillCount, eFillDir, eFillCmd, eFillDateCmd, 1020 nStepValue, nMaxValue); 1021 } 1022 1023 String ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY ) 1024 { 1025 SCTAB nTab = rSource.aStart.Tab(); 1026 if (pTab[nTab]) 1027 return pTab[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY ); 1028 1029 return EMPTY_STRING; 1030 } 1031 1032 void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1033 sal_uInt16 nFormatNo, const ScMarkData& rMark ) 1034 { 1035 PutInOrder( nStartCol, nEndCol ); 1036 PutInOrder( nStartRow, nEndRow ); 1037 for (SCTAB i=0; i <= MAXTAB; i++) 1038 if (pTab[i]) 1039 if (rMark.GetTableSelect(i)) 1040 pTab[i]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo ); 1041 } 1042 1043 void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1044 ScAutoFormatData& rData) 1045 { 1046 if (VALIDTAB(nTab)) 1047 { 1048 if (pTab[nTab]) 1049 { 1050 PutInOrder(nStartCol, nEndCol); 1051 PutInOrder(nStartRow, nEndRow); 1052 pTab[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData); 1053 } 1054 } 1055 } 1056 1057 // static 1058 void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem, 1059 SCCOL& rCol, SCROW& rRow ) 1060 { 1061 sal_uInt16 nCommand = rSearchItem.GetCommand(); 1062 sal_Bool bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE || 1063 nCommand == SVX_SEARCHCMD_REPLACE_ALL ); 1064 if ( rSearchItem.GetBackward() ) 1065 { 1066 if ( rSearchItem.GetRowDirection() ) 1067 { 1068 if ( rSearchItem.GetPattern() ) 1069 { 1070 rCol = MAXCOL; 1071 rRow = MAXROW+1; 1072 } 1073 else if ( bReplace ) 1074 { 1075 rCol = MAXCOL; 1076 rRow = MAXROW; 1077 } 1078 else 1079 { 1080 rCol = MAXCOL+1; 1081 rRow = MAXROW; 1082 } 1083 } 1084 else 1085 { 1086 if ( rSearchItem.GetPattern() ) 1087 { 1088 rCol = MAXCOL+1; 1089 rRow = MAXROW; 1090 } 1091 else if ( bReplace ) 1092 { 1093 rCol = MAXCOL; 1094 rRow = MAXROW; 1095 } 1096 else 1097 { 1098 rCol = MAXCOL; 1099 rRow = MAXROW+1; 1100 } 1101 } 1102 } 1103 else 1104 { 1105 if ( rSearchItem.GetRowDirection() ) 1106 { 1107 if ( rSearchItem.GetPattern() ) 1108 { 1109 rCol = 0; 1110 rRow = (SCROW) -1; 1111 } 1112 else if ( bReplace ) 1113 { 1114 rCol = 0; 1115 rRow = 0; 1116 } 1117 else 1118 { 1119 rCol = (SCCOL) -1; 1120 rRow = 0; 1121 } 1122 } 1123 else 1124 { 1125 if ( rSearchItem.GetPattern() ) 1126 { 1127 rCol = (SCCOL) -1; 1128 rRow = 0; 1129 } 1130 else if ( bReplace ) 1131 { 1132 rCol = 0; 1133 rRow = 0; 1134 } 1135 else 1136 { 1137 rCol = 0; 1138 rRow = (SCROW) -1; 1139 } 1140 } 1141 } 1142 } 1143 1144 sal_Bool ScDocument::SearchAndReplace(const SvxSearchItem& rSearchItem, 1145 SCCOL& rCol, SCROW& rRow, SCTAB& rTab, 1146 ScMarkData& rMark, 1147 String& rUndoStr, ScDocument* pUndoDoc) 1148 { 1149 //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!! 1150 1151 rMark.MarkToMulti(); 1152 1153 sal_Bool bFound = sal_False; 1154 if (VALIDTAB(rTab)) 1155 { 1156 SCCOL nCol; 1157 SCROW nRow; 1158 SCTAB nTab; 1159 sal_uInt16 nCommand = rSearchItem.GetCommand(); 1160 if ( nCommand == SVX_SEARCHCMD_FIND_ALL || 1161 nCommand == SVX_SEARCHCMD_REPLACE_ALL ) 1162 { 1163 for (nTab = 0; nTab <= MAXTAB; nTab++) 1164 if (pTab[nTab]) 1165 { 1166 if (rMark.GetTableSelect(nTab)) 1167 { 1168 nCol = 0; 1169 nRow = 0; 1170 bFound |= pTab[nTab]->SearchAndReplace( 1171 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc ); 1172 } 1173 } 1174 1175 // Markierung wird innen schon komplett gesetzt 1176 } 1177 else 1178 { 1179 nCol = rCol; 1180 nRow = rRow; 1181 if (rSearchItem.GetBackward()) 1182 { 1183 for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--) 1184 if (pTab[nTab]) 1185 { 1186 if (rMark.GetTableSelect(nTab)) 1187 { 1188 bFound = pTab[nTab]->SearchAndReplace( 1189 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc ); 1190 if (bFound) 1191 { 1192 rCol = nCol; 1193 rRow = nRow; 1194 rTab = nTab; 1195 } 1196 else 1197 ScDocument::GetSearchAndReplaceStart( 1198 rSearchItem, nCol, nRow ); 1199 } 1200 } 1201 } 1202 else 1203 { 1204 for (nTab = rTab; (nTab <= MAXTAB) && !bFound; nTab++) 1205 if (pTab[nTab]) 1206 { 1207 if (rMark.GetTableSelect(nTab)) 1208 { 1209 bFound = pTab[nTab]->SearchAndReplace( 1210 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc ); 1211 if (bFound) 1212 { 1213 rCol = nCol; 1214 rRow = nRow; 1215 rTab = nTab; 1216 } 1217 else 1218 ScDocument::GetSearchAndReplaceStart( 1219 rSearchItem, nCol, nRow ); 1220 } 1221 } 1222 } 1223 } 1224 } 1225 return bFound; 1226 } 1227 1228 // Outline anpassen 1229 1230 sal_Bool ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, sal_Bool bShow ) 1231 { 1232 if ( ValidTab(nTab) && pTab[nTab] ) 1233 return pTab[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow ); 1234 1235 DBG_ERROR("missing tab"); 1236 return sal_False; 1237 } 1238 1239 sal_Bool ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_Bool bShow ) 1240 { 1241 if ( ValidTab(nTab) && pTab[nTab] ) 1242 return pTab[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow ); 1243 1244 DBG_ERROR("missing tab"); 1245 return sal_False; 1246 } 1247 1248 void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, sal_Bool bKeepQuery) 1249 { 1250 if ( ValidTab(nTab) && pTab[nTab] ) 1251 { 1252 sal_Bool bOldDisableIdle = IsIdleDisabled(); 1253 DisableIdle( sal_True ); 1254 pTab[nTab]->Sort(rSortParam, bKeepQuery); 1255 DisableIdle( bOldDisableIdle ); 1256 } 1257 } 1258 1259 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, sal_Bool bKeepSub) 1260 { 1261 if ( ValidTab(nTab) && pTab[nTab] ) 1262 return pTab[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub); 1263 1264 DBG_ERROR("missing tab"); 1265 return 0; 1266 } 1267 1268 1269 sal_Bool ScDocument::ValidQuery( SCROW nRow, SCTAB nTab, const ScQueryParam& rQueryParam, sal_Bool* pSpecial ) 1270 { 1271 if ( ValidTab(nTab) && pTab[nTab] ) 1272 return pTab[nTab]->ValidQuery( nRow, rQueryParam, pSpecial ); 1273 1274 DBG_ERROR("missing tab"); 1275 return sal_False; 1276 } 1277 1278 1279 void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr) 1280 { 1281 if ( ValidTab(nTab) && pTab[nTab] ) 1282 pTab[nTab]->GetUpperCellString( nCol, nRow, rStr ); 1283 else 1284 rStr.Erase(); 1285 } 1286 1287 sal_Bool ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam) 1288 { 1289 if ( ValidTab(nTab) && pTab[nTab] ) 1290 return pTab[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam); 1291 1292 DBG_ERROR("missing tab"); 1293 return sal_False; 1294 } 1295 1296 sal_Bool ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab ) 1297 { 1298 ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab ); 1299 sal_Bool bHasAutoFilter = ( pDBData != NULL ); 1300 1301 if ( pDBData ) 1302 { 1303 if ( pDBData->HasHeader() ) 1304 { 1305 SCCOL nCol; 1306 SCROW nRow; 1307 sal_Int16 nFlag; 1308 1309 ScQueryParam aParam; 1310 pDBData->GetQueryParam( aParam ); 1311 nRow = aParam.nRow1; 1312 1313 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ ) 1314 { 1315 nFlag = ((ScMergeFlagAttr*) 1316 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))-> 1317 GetValue(); 1318 1319 if ( (nFlag & SC_MF_AUTO) == 0 ) 1320 bHasAutoFilter = sal_False; 1321 } 1322 } 1323 else 1324 bHasAutoFilter = sal_False; 1325 } 1326 1327 return bHasAutoFilter; 1328 } 1329 1330 sal_Bool ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1331 SCTAB nTab ) 1332 { 1333 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1334 //if (VALIDTAB(nTab)) 1335 // if (pTab[nTab]) 1336 // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1337 1338 //return sal_False; 1339 } 1340 1341 sal_Bool ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1342 SCTAB nTab ) 1343 { 1344 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1345 //if (VALIDTAB(nTab)) 1346 // if (pTab[nTab]) 1347 // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1348 1349 //return sal_False; 1350 } 1351 1352 // 1353 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox 1354 // 1355 1356 sal_Bool ScDocument::GetFilterEntries( 1357 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates) 1358 { 1359 if ( ValidTab(nTab) && pTab[nTab] && pDBCollection ) 1360 { 1361 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, sal_False); //!?? 1362 if (pDBData) 1363 { 1364 SCTAB nAreaTab; 1365 SCCOL nStartCol; 1366 SCROW nStartRow; 1367 SCCOL nEndCol; 1368 SCROW nEndRow; 1369 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); 1370 1371 //Add for i85305 1372 SCCOL nTmpStartCol = nCol; 1373 SCROW nTmpStartRow = nRow; 1374 SCCOL nTmpEndCol = nCol; 1375 SCROW nTmpEndRow = nRow; 1376 GetDataArea( nTab, nTmpStartCol, nTmpStartRow, nTmpEndCol, nTmpEndRow, sal_False, false); 1377 if (nTmpEndRow > nEndRow) 1378 { 1379 nEndRow = nTmpEndRow; 1380 pDBData->SetArea(nAreaTab, nStartCol,nStartRow, nEndCol,nEndRow); 1381 } 1382 //End of i85305 1383 1384 if (pDBData->HasHeader()) 1385 ++nStartRow; 1386 1387 ScQueryParam aParam; 1388 pDBData->GetQueryParam( aParam ); 1389 rStrings.SetCaseSensitive( aParam.bCaseSens ); 1390 1391 // return all filter entries, if a filter condition is connected with a boolean OR 1392 if ( bFilter ) 1393 { 1394 SCSIZE nEntryCount = aParam.GetEntryCount(); 1395 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i ) 1396 { 1397 ScQueryEntry& rEntry = aParam.GetEntry(i); 1398 if ( rEntry.eConnect != SC_AND ) 1399 { 1400 bFilter = false; 1401 break; 1402 } 1403 } 1404 } 1405 1406 if ( bFilter ) 1407 { 1408 pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates ); 1409 } 1410 else 1411 { 1412 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates ); 1413 } 1414 1415 return sal_True; 1416 } 1417 } 1418 1419 return sal_False; 1420 } 1421 1422 // 1423 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog 1424 // 1425 1426 sal_Bool ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, 1427 SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates ) 1428 { 1429 if ( ValidTab(nTab) && pTab[nTab] ) 1430 { 1431 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates ); 1432 return sal_True; 1433 } 1434 1435 return sal_False; 1436 } 1437 1438 // 1439 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln) 1440 // 1441 1442 sal_Bool ScDocument::GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, 1443 TypedScStrCollection& rStrings, sal_Bool bLimit ) 1444 { 1445 if( !bLimit ) 1446 { 1447 /* Try to generate the list from list validation. This part is skipped, 1448 if bLimit==sal_True, because in that case this function is called to get 1449 cell values for auto completion on input. */ 1450 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue(); 1451 if( nValidation ) 1452 { 1453 const ScValidationData* pData = GetValidationEntry( nValidation ); 1454 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) ) 1455 return sal_True; 1456 } 1457 } 1458 1459 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit ); 1460 //if (ValidTab(nTab) && pTab[nTab]) 1461 // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit ); 1462 1463 //return sal_False; 1464 } 1465 1466 // 1467 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe 1468 // 1469 1470 // Funktionen werden als 1 schon vom InputHandler eingefuegt 1471 #define SC_STRTYPE_NAMES 2 1472 #define SC_STRTYPE_DBNAMES 3 1473 #define SC_STRTYPE_HEADERS 4 1474 1475 sal_Bool ScDocument::GetFormulaEntries( TypedScStrCollection& rStrings ) 1476 { 1477 sal_uInt16 i; 1478 1479 // 1480 // Bereichsnamen 1481 // 1482 1483 if ( pRangeName ) 1484 { 1485 sal_uInt16 nRangeCount = pRangeName->GetCount(); 1486 for ( i=0; i<nRangeCount; i++ ) 1487 { 1488 ScRangeData* pData = (*pRangeName)[i]; 1489 if (pData) 1490 { 1491 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES ); 1492 if ( !rStrings.Insert(pNew) ) 1493 delete pNew; 1494 } 1495 } 1496 } 1497 1498 // 1499 // Datenbank-Bereiche 1500 // 1501 1502 if ( pDBCollection ) 1503 { 1504 sal_uInt16 nDBCount = pDBCollection->GetCount(); 1505 for ( i=0; i<nDBCount; i++ ) 1506 { 1507 ScDBData* pData = (*pDBCollection)[i]; 1508 if (pData) 1509 { 1510 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES ); 1511 if ( !rStrings.Insert(pNew) ) 1512 delete pNew; 1513 } 1514 } 1515 } 1516 1517 // 1518 // Inhalte von Beschriftungsbereichen 1519 // 1520 1521 ScRangePairList* pLists[2]; 1522 pLists[0] = GetColNameRanges(); 1523 pLists[1] = GetRowNameRanges(); 1524 for (sal_uInt16 nListNo=0; nListNo<2; nListNo++) 1525 { 1526 ScRangePairList* pList = pLists[nListNo]; 1527 if (pList) 1528 for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() ) 1529 { 1530 ScRange aRange = pPair->GetRange(0); 1531 ScCellIterator aIter( this, aRange ); 1532 for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() ) 1533 if ( pCell->HasStringData() ) 1534 { 1535 String aStr = pCell->GetStringData(); 1536 TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS ); 1537 if ( !rStrings.Insert(pNew) ) 1538 delete pNew; 1539 } 1540 } 1541 } 1542 1543 return sal_True; 1544 } 1545 1546 1547 sal_Bool ScDocument::IsEmbedded() const 1548 { 1549 return bIsEmbedded; 1550 } 1551 1552 void ScDocument::GetEmbedded( ScRange& rRange ) const 1553 { 1554 rRange = aEmbedRange; 1555 } 1556 1557 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm 1558 { 1559 Rectangle aRect; 1560 ScTable* pTable = pTab[aEmbedRange.aStart.Tab()]; 1561 if (!pTable) 1562 { 1563 DBG_ERROR("GetEmbeddedRect ohne Tabelle"); 1564 } 1565 else 1566 { 1567 SCCOL i; 1568 1569 for (i=0; i<aEmbedRange.aStart.Col(); i++) 1570 aRect.Left() += pTable->GetColWidth(i); 1571 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1); 1572 aRect.Right() = aRect.Left(); 1573 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++) 1574 aRect.Right() += pTable->GetColWidth(i); 1575 aRect.Bottom() = aRect.Top(); 1576 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row()); 1577 1578 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS ); 1579 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS ); 1580 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS ); 1581 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS ); 1582 } 1583 return aRect; 1584 } 1585 1586 void ScDocument::SetEmbedded( const ScRange& rRange ) 1587 { 1588 bIsEmbedded = sal_True; 1589 aEmbedRange = rRange; 1590 } 1591 1592 void ScDocument::ResetEmbedded() 1593 { 1594 bIsEmbedded = sal_False; 1595 aEmbedRange = ScRange(); 1596 } 1597 1598 1599 /** Similar to ScViewData::AddPixelsWhile(), but add height twips and only 1600 while result is less than nStopTwips. 1601 @return sal_True if advanced at least one row. 1602 */ 1603 bool lcl_AddTwipsWhile( long & rTwips, long nStopTwips, SCROW & rPosY, SCROW nEndRow, const ScTable * pTable ) 1604 { 1605 SCROW nRow = rPosY; 1606 bool bAdded = false; 1607 bool bStop = false; 1608 while (rTwips < nStopTwips && nRow <= nEndRow && !bStop) 1609 { 1610 SCROW nHeightEndRow; 1611 sal_uInt16 nHeight = pTable->GetRowHeight( nRow, NULL, &nHeightEndRow); 1612 if (nHeightEndRow > nEndRow) 1613 nHeightEndRow = nEndRow; 1614 if (!nHeight) 1615 nRow = nHeightEndRow + 1; 1616 else 1617 { 1618 SCROW nRows = nHeightEndRow - nRow + 1; 1619 sal_Int64 nAdd = static_cast<sal_Int64>(nHeight) * nRows; 1620 if (nAdd + rTwips >= nStopTwips) 1621 { 1622 sal_Int64 nDiff = nAdd + rTwips - nStopTwips; 1623 nRows -= static_cast<SCROW>(nDiff / nHeight); 1624 nAdd = nHeight * nRows; 1625 // We're looking for a value that satisfies loop condition. 1626 if (nAdd + rTwips >= nStopTwips) 1627 { 1628 --nRows; 1629 nAdd -= nHeight; 1630 } 1631 bStop = true; 1632 } 1633 rTwips += static_cast<long>(nAdd); 1634 nRow += nRows; 1635 } 1636 } 1637 if (nRow > rPosY) 1638 { 1639 --nRow; 1640 bAdded = true; 1641 } 1642 rPosY = nRow; 1643 return bAdded; 1644 } 1645 1646 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect ) 1647 { 1648 ScTable* pTable = pTab[nTab]; 1649 if (!pTable) 1650 { 1651 DBG_ERROR("GetRange ohne Tabelle"); 1652 return ScRange(); 1653 } 1654 1655 Rectangle aPosRect = rMMRect; 1656 if ( IsNegativePage( nTab ) ) 1657 ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values 1658 1659 long nSize; 1660 long nTwips; 1661 long nAdd; 1662 sal_Bool bEnd; 1663 1664 nSize = 0; 1665 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS); 1666 1667 SCCOL nX1 = 0; 1668 bEnd = sal_False; 1669 while (!bEnd) 1670 { 1671 nAdd = (long) pTable->GetColWidth(nX1); 1672 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL) 1673 { 1674 nSize += nAdd; 1675 ++nX1; 1676 } 1677 else 1678 bEnd = sal_True; 1679 } 1680 1681 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS); 1682 1683 SCCOL nX2 = nX1; 1684 bEnd = sal_False; 1685 while (!bEnd) 1686 { 1687 nAdd = (long) pTable->GetColWidth(nX2); 1688 if (nSize+nAdd < nTwips && nX2<MAXCOL) 1689 { 1690 nSize += nAdd; 1691 ++nX2; 1692 } 1693 else 1694 bEnd = sal_True; 1695 } 1696 1697 1698 nSize = 0; 1699 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS); 1700 1701 SCROW nY1 = 0; 1702 // Was if(nSize+nAdd<=nTwips+1) inside loop => if(nSize+nAdd<nTwips+2) 1703 if (lcl_AddTwipsWhile( nSize, nTwips+2, nY1, MAXROW, pTable) && nY1 < MAXROW) 1704 ++nY1; // original loop ended on last matched +1 unless that was MAXROW 1705 1706 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS); 1707 1708 SCROW nY2 = nY1; 1709 // Was if(nSize+nAdd<nTwips) inside loop => if(nSize+nAdd<nTwips) 1710 if (lcl_AddTwipsWhile( nSize, nTwips, nY2, MAXROW, pTable) && nY2 < MAXROW) 1711 ++nY2; // original loop ended on last matched +1 unless that was MAXROW 1712 1713 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab ); 1714 } 1715 1716 void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm) 1717 { 1718 bIsEmbedded = sal_True; 1719 aEmbedRange = GetRange( nVisibleTab, rRect ); 1720 } 1721 1722 // VisArea auf Zellgrenzen anpassen 1723 1724 void lcl_SnapHor( ScTable* pTable, long& rVal, SCCOL& rStartCol ) 1725 { 1726 SCCOL nCol = 0; 1727 long nTwips = (long) (rVal / HMM_PER_TWIPS); 1728 long nSnap = 0; 1729 while ( nCol<MAXCOL ) 1730 { 1731 long nAdd = pTable->GetColWidth(nCol); 1732 if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol ) 1733 { 1734 nSnap += nAdd; 1735 ++nCol; 1736 } 1737 else 1738 break; 1739 } 1740 rVal = (long) ( nSnap * HMM_PER_TWIPS ); 1741 rStartCol = nCol; 1742 } 1743 1744 void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow ) 1745 { 1746 SCROW nRow = 0; 1747 long nTwips = (long) (rVal / HMM_PER_TWIPS); 1748 long nSnap = 0; 1749 1750 bool bFound = false; 1751 for (SCROW i = nRow; i <= MAXROW; ++i) 1752 { 1753 SCROW nLastRow; 1754 if (pTable->RowHidden(i, NULL, &nLastRow)) 1755 { 1756 i = nLastRow; 1757 continue; 1758 } 1759 1760 nRow = i; 1761 long nAdd = pTable->GetRowHeight(i); 1762 if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow ) 1763 { 1764 nSnap += nAdd; 1765 ++nRow; 1766 } 1767 else 1768 { 1769 bFound = true; 1770 break; 1771 } 1772 } 1773 if (!bFound) 1774 nRow = MAXROW; // all hidden down to the bottom 1775 1776 rVal = (long) ( nSnap * HMM_PER_TWIPS ); 1777 rStartRow = nRow; 1778 } 1779 1780 void ScDocument::SnapVisArea( Rectangle& rRect ) const 1781 { 1782 ScTable* pTable = pTab[nVisibleTab]; 1783 if (!pTable) 1784 { 1785 DBG_ERROR("SetEmbedded ohne Tabelle"); 1786 return; 1787 } 1788 1789 sal_Bool bNegativePage = IsNegativePage( nVisibleTab ); 1790 if ( bNegativePage ) 1791 ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values 1792 1793 SCCOL nCol = 0; 1794 lcl_SnapHor( pTable, rRect.Left(), nCol ); 1795 ++nCol; // mindestens eine Spalte 1796 lcl_SnapHor( pTable, rRect.Right(), nCol ); 1797 1798 SCROW nRow = 0; 1799 lcl_SnapVer( pTable, rRect.Top(), nRow ); 1800 ++nRow; // mindestens eine Zeile 1801 lcl_SnapVer( pTable, rRect.Bottom(), nRow ); 1802 1803 if ( bNegativePage ) 1804 ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle 1805 } 1806 1807 ScDocProtection* ScDocument::GetDocProtection() const 1808 { 1809 return pDocProtection.get(); 1810 } 1811 1812 void ScDocument::SetDocProtection(const ScDocProtection* pProtect) 1813 { 1814 if (pProtect) 1815 pDocProtection.reset(new ScDocProtection(*pProtect)); 1816 else 1817 pDocProtection.reset(NULL); 1818 } 1819 1820 sal_Bool ScDocument::IsDocProtected() const 1821 { 1822 return pDocProtection.get() && pDocProtection->isProtected(); 1823 } 1824 1825 sal_Bool ScDocument::IsDocEditable() const 1826 { 1827 // import into read-only document is possible 1828 return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() ); 1829 } 1830 1831 sal_Bool ScDocument::IsTabProtected( SCTAB nTab ) const 1832 { 1833 if (VALIDTAB(nTab) && pTab[nTab]) 1834 return pTab[nTab]->IsProtected(); 1835 1836 DBG_ERROR("Falsche Tabellennummer"); 1837 return sal_False; 1838 } 1839 1840 ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const 1841 { 1842 if (VALIDTAB(nTab) && pTab[nTab]) 1843 return pTab[nTab]->GetProtection(); 1844 1845 return NULL; 1846 } 1847 1848 void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect) 1849 { 1850 if (!ValidTab(nTab)) 1851 return; 1852 1853 pTab[nTab]->SetProtection(pProtect); 1854 } 1855 1856 void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest) 1857 { 1858 if (!ValidTab(nTabSrc) || !ValidTab(nTabDest)) 1859 return; 1860 1861 pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() ); 1862 } 1863 1864 const ScDocOptions& ScDocument::GetDocOptions() const 1865 { 1866 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" ); 1867 return *pDocOptions; 1868 } 1869 1870 void ScDocument::SetDocOptions( const ScDocOptions& rOpt ) 1871 { 1872 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" ); 1873 *pDocOptions = rOpt; 1874 1875 xPoolHelper->SetFormTableOpt(rOpt); 1876 } 1877 1878 const ScViewOptions& ScDocument::GetViewOptions() const 1879 { 1880 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" ); 1881 return *pViewOptions; 1882 } 1883 1884 void ScDocument::SetViewOptions( const ScViewOptions& rOpt ) 1885 { 1886 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" ); 1887 *pViewOptions = rOpt; 1888 } 1889 1890 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const 1891 { 1892 rLatin = eLanguage; 1893 rCjk = eCjkLanguage; 1894 rCtl = eCtlLanguage; 1895 } 1896 1897 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl ) 1898 { 1899 eLanguage = eLatin; 1900 eCjkLanguage = eCjk; 1901 eCtlLanguage = eCtl; 1902 if ( xPoolHelper.isValid() ) 1903 { 1904 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 1905 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) ); 1906 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) ); 1907 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) ); 1908 } 1909 1910 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool 1911 } 1912 1913 void ScDocument::SetDrawDefaults() 1914 { 1915 bSetDrawDefaults = sal_True; 1916 UpdateDrawDefaults(); 1917 } 1918 1919 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow, 1920 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 1921 { 1922 if (!ValidTab(nTab) || !pTab[nTab]) 1923 { 1924 DBG_ERROR("GetMMRect: falsche Tabelle"); 1925 return Rectangle(0,0,0,0); 1926 } 1927 1928 SCCOL i; 1929 Rectangle aRect; 1930 1931 for (i=0; i<nStartCol; i++) 1932 aRect.Left() += GetColWidth(i,nTab); 1933 aRect.Top() += GetRowHeight( 0, nStartRow-1, nTab); 1934 1935 aRect.Right() = aRect.Left(); 1936 aRect.Bottom() = aRect.Top(); 1937 1938 for (i=nStartCol; i<=nEndCol; i++) 1939 aRect.Right() += GetColWidth(i,nTab); 1940 aRect.Bottom() += GetRowHeight( nStartRow, nEndRow, nTab); 1941 1942 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS); 1943 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS); 1944 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS); 1945 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS); 1946 1947 if ( IsNegativePage( nTab ) ) 1948 ScDrawLayer::MirrorRectRTL( aRect ); 1949 1950 return aRect; 1951 } 1952 1953 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions ) 1954 { 1955 delete pExtDocOptions; 1956 pExtDocOptions = pNewOptions; 1957 } 1958 1959 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 1960 SCCOL nEndCol, SCROW nEndRow ) 1961 { 1962 String aEmpty; 1963 String aTotal; 1964 String aCellStr; 1965 SCCOL nCol; 1966 SCROW nRow; 1967 for (nRow=nStartRow; nRow<=nEndRow; nRow++) 1968 for (nCol=nStartCol; nCol<=nEndCol; nCol++) 1969 { 1970 GetString(nCol,nRow,nTab,aCellStr); 1971 if (aCellStr.Len()) 1972 { 1973 if (aTotal.Len()) 1974 aTotal += ' '; 1975 aTotal += aCellStr; 1976 } 1977 if (nCol != nStartCol || nRow != nStartRow) 1978 SetString(nCol,nRow,nTab,aEmpty); 1979 } 1980 1981 SetString(nStartCol,nStartRow,nTab,aTotal); 1982 } 1983 1984 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 1985 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions ) 1986 { 1987 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 ); 1988 ApplyAttr( nStartCol, nStartRow, nTab, aAttr ); 1989 1990 if ( nEndCol > nStartCol ) 1991 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR ); 1992 if ( nEndRow > nStartRow ) 1993 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER ); 1994 if ( nEndCol > nStartCol && nEndRow > nStartRow ) 1995 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER ); 1996 1997 // remove all covered notes (removed captions are collected by drawing undo if active) 1998 sal_uInt16 nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS); 1999 if( nStartCol < nEndCol ) 2000 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag ); 2001 if( nStartRow < nEndRow ) 2002 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag ); 2003 } 2004 2005 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab ) 2006 { 2007 const ScMergeAttr* pAttr = (const ScMergeAttr*) 2008 GetAttr( nCol, nRow, nTab, ATTR_MERGE ); 2009 2010 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 ) 2011 return; 2012 2013 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1; 2014 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1; 2015 2016 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER ); 2017 2018 const ScMergeAttr* pDefAttr = (const ScMergeAttr*) 2019 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE ); 2020 ApplyAttr( nCol, nRow, nTab, *pDefAttr ); 2021 } 2022 2023 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab, 2024 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow ) 2025 { 2026 if ( ValidTab(nTab) && pTab[nTab] ) 2027 pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow ); 2028 } 2029 2030 void ScDocument::IncSizeRecalcLevel( SCTAB nTab ) 2031 { 2032 if ( ValidTab(nTab) && pTab[nTab] ) 2033 pTab[nTab]->IncRecalcLevel(); 2034 } 2035 2036 void ScDocument::DecSizeRecalcLevel( SCTAB nTab, bool bUpdateNoteCaptionPos ) 2037 { 2038 if ( ValidTab(nTab) && pTab[nTab] ) 2039 pTab[nTab]->DecRecalcLevel( bUpdateNoteCaptionPos ); 2040 } 2041 2042 // Wang Xu Ming -- 2009-8-17 2043 // DataPilot Migration - Cache&&Performance 2044 ScDPTableDataCache* ScDocument::GetDPObjectCache( long nID ) 2045 { 2046 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2047 { // 2048 if ( nID == (*iter)->GetId() ) 2049 return *iter; 2050 } 2051 return NULL; 2052 } 2053 2054 ScDPTableDataCache* ScDocument::GetUsedDPObjectCache ( ScRange rRange ) 2055 { 2056 ScDPTableDataCache* pCache = NULL; 2057 sal_uInt16 nCount = GetDPCollection()->GetCount(); 2058 for ( short i=nCount-1; i>=0 ; i--) 2059 { 2060 if ( const ScSheetSourceDesc* pUsedSheetDesc = (*pDPCollection)[i]->GetSheetDesc() ) 2061 if ( rRange == pUsedSheetDesc->aSourceRange ) 2062 { 2063 long nID = (*pDPCollection)[i]->GetCacheId(); 2064 if ( nID >= 0 ) 2065 pCache= GetDPObjectCache( nID ); 2066 if ( pCache ) 2067 return pCache; 2068 } 2069 } 2070 return pCache; 2071 } 2072 2073 long ScDocument::AddDPObjectCache( ScDPTableDataCache* pData ) 2074 { 2075 if ( pData->GetId() < 0 ) 2076 { //create a id for it 2077 pData->SetId( GetNewDPObjectCacheId() ); 2078 } 2079 m_listDPObjectsCaches.push_back( pData ); 2080 return pData->GetId(); 2081 } 2082 2083 long ScDocument::GetNewDPObjectCacheId() 2084 { 2085 long nID = 0; 2086 2087 bool bFound = false; 2088 std::list<ScDPTableDataCache*>::iterator iter; 2089 do { 2090 for ( iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2091 { //Get a new Id 2092 if ( nID == (*iter)->GetId() ) 2093 { 2094 nID++; 2095 bFound = true; 2096 break; 2097 } 2098 } 2099 if ( iter == m_listDPObjectsCaches.end() ) 2100 bFound = false; 2101 } while ( bFound ); 2102 2103 return nID; 2104 } 2105 2106 void ScDocument::RemoveDPObjectCache( long nID ) 2107 { 2108 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2109 { 2110 if ( nID == (*iter)->GetId() ) 2111 { 2112 ScDPTableDataCache* pCache = *iter; 2113 m_listDPObjectsCaches.erase( iter ); 2114 delete pCache; 2115 break; 2116 } 2117 } 2118 2119 } 2120 2121 void ScDocument::RemoveUnusedDPObjectCaches() 2122 { 2123 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); ) 2124 { 2125 long nID = (*iter)->GetId(); 2126 sal_uInt16 nCount = GetDPCollection()->GetCount(); 2127 sal_uInt16 i ; 2128 for ( i=0; i<nCount; i++) 2129 { 2130 if ( nID == (*pDPCollection)[i]->GetCacheId() ) 2131 break; 2132 } 2133 if ( i == nCount ) 2134 { 2135 ScDPTableDataCache* pCache = *iter; 2136 iter = m_listDPObjectsCaches.erase( iter ); 2137 delete pCache; 2138 continue; 2139 } 2140 ++iter; 2141 } 2142 } 2143 2144 void ScDocument::GetUsedDPObjectCache( std::list<ScDPTableDataCache*>& usedlist ) 2145 { 2146 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2147 { 2148 long nID = (*iter)->GetId(); 2149 sal_uInt16 nCount = GetDPCollection()->GetCount(); 2150 sal_uInt16 i=0; 2151 for ( i=0; i<nCount; i++) 2152 if ( nID == (*pDPCollection)[i]->GetCacheId() ) 2153 break; 2154 if ( i != nCount ) 2155 usedlist.push_back( *iter ); 2156 } 2157 } 2158 // End Comments 2159