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