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( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab ) 1293 { 1294 ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab ); 1295 sal_Bool bHasAutoFilter = ( pDBData != NULL ); 1296 1297 if ( pDBData ) 1298 { 1299 if ( pDBData->HasHeader() ) 1300 { 1301 SCCOL nCol; 1302 SCROW nRow; 1303 sal_Int16 nFlag; 1304 1305 ScQueryParam aParam; 1306 pDBData->GetQueryParam( aParam ); 1307 nRow = aParam.nRow1; 1308 1309 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ ) 1310 { 1311 nFlag = ((ScMergeFlagAttr*) 1312 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))-> 1313 GetValue(); 1314 1315 if ( (nFlag & SC_MF_AUTO) == 0 ) 1316 bHasAutoFilter = sal_False; 1317 } 1318 } 1319 else 1320 bHasAutoFilter = sal_False; 1321 } 1322 1323 return bHasAutoFilter; 1324 } 1325 1326 sal_Bool ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1327 SCTAB nTab ) 1328 { 1329 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1330 //if (VALIDTAB(nTab)) 1331 // if (pTab[nTab]) 1332 // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1333 1334 //return sal_False; 1335 } 1336 1337 sal_Bool ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1338 SCTAB nTab ) 1339 { 1340 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1341 //if (VALIDTAB(nTab)) 1342 // if (pTab[nTab]) 1343 // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow ); 1344 1345 //return sal_False; 1346 } 1347 1348 // 1349 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox 1350 // 1351 1352 sal_Bool ScDocument::GetFilterEntries( 1353 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates) 1354 { 1355 if ( ValidTab(nTab) && pTab[nTab] && pDBCollection ) 1356 { 1357 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, sal_False); //!?? 1358 if (pDBData) 1359 { 1360 SCTAB nAreaTab; 1361 SCCOL nStartCol; 1362 SCROW nStartRow; 1363 SCCOL nEndCol; 1364 SCROW nEndRow; 1365 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); 1366 1367 //Add for i85305 1368 SCCOL nTmpStartCol = nCol; 1369 SCROW nTmpStartRow = nRow; 1370 SCCOL nTmpEndCol = nCol; 1371 SCROW nTmpEndRow = nRow; 1372 GetDataArea( nTab, nTmpStartCol, nTmpStartRow, nTmpEndCol, nTmpEndRow, sal_False, false); 1373 if (nTmpEndRow > nEndRow) 1374 { 1375 nEndRow = nTmpEndRow; 1376 pDBData->SetArea(nAreaTab, nStartCol,nStartRow, nEndCol,nEndRow); 1377 } 1378 //End of i85305 1379 1380 if (pDBData->HasHeader()) 1381 ++nStartRow; 1382 1383 ScQueryParam aParam; 1384 pDBData->GetQueryParam( aParam ); 1385 rStrings.SetCaseSensitive( aParam.bCaseSens ); 1386 1387 // return all filter entries, if a filter condition is connected with a boolean OR 1388 if ( bFilter ) 1389 { 1390 SCSIZE nEntryCount = aParam.GetEntryCount(); 1391 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i ) 1392 { 1393 ScQueryEntry& rEntry = aParam.GetEntry(i); 1394 if ( rEntry.eConnect != SC_AND ) 1395 { 1396 bFilter = false; 1397 break; 1398 } 1399 } 1400 } 1401 1402 if ( bFilter ) 1403 { 1404 pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates ); 1405 } 1406 else 1407 { 1408 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates ); 1409 } 1410 1411 return sal_True; 1412 } 1413 } 1414 1415 return sal_False; 1416 } 1417 1418 // 1419 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog 1420 // 1421 1422 sal_Bool ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, 1423 SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates ) 1424 { 1425 if ( ValidTab(nTab) && pTab[nTab] ) 1426 { 1427 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates ); 1428 return sal_True; 1429 } 1430 1431 return sal_False; 1432 } 1433 1434 // 1435 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln) 1436 // 1437 1438 sal_Bool ScDocument::GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, 1439 TypedScStrCollection& rStrings, sal_Bool bLimit ) 1440 { 1441 if( !bLimit ) 1442 { 1443 /* Try to generate the list from list validation. This part is skipped, 1444 if bLimit==sal_True, because in that case this function is called to get 1445 cell values for auto completion on input. */ 1446 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue(); 1447 if( nValidation ) 1448 { 1449 const ScValidationData* pData = GetValidationEntry( nValidation ); 1450 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) ) 1451 return sal_True; 1452 } 1453 } 1454 1455 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit ); 1456 //if (ValidTab(nTab) && pTab[nTab]) 1457 // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit ); 1458 1459 //return sal_False; 1460 } 1461 1462 // 1463 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe 1464 // 1465 1466 // Funktionen werden als 1 schon vom InputHandler eingefuegt 1467 #define SC_STRTYPE_NAMES 2 1468 #define SC_STRTYPE_DBNAMES 3 1469 #define SC_STRTYPE_HEADERS 4 1470 1471 sal_Bool ScDocument::GetFormulaEntries( TypedScStrCollection& rStrings ) 1472 { 1473 sal_uInt16 i; 1474 1475 // 1476 // Bereichsnamen 1477 // 1478 1479 if ( pRangeName ) 1480 { 1481 sal_uInt16 nRangeCount = pRangeName->GetCount(); 1482 for ( i=0; i<nRangeCount; i++ ) 1483 { 1484 ScRangeData* pData = (*pRangeName)[i]; 1485 if (pData) 1486 { 1487 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES ); 1488 if ( !rStrings.Insert(pNew) ) 1489 delete pNew; 1490 } 1491 } 1492 } 1493 1494 // 1495 // Datenbank-Bereiche 1496 // 1497 1498 if ( pDBCollection ) 1499 { 1500 sal_uInt16 nDBCount = pDBCollection->GetCount(); 1501 for ( i=0; i<nDBCount; i++ ) 1502 { 1503 ScDBData* pData = (*pDBCollection)[i]; 1504 if (pData) 1505 { 1506 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES ); 1507 if ( !rStrings.Insert(pNew) ) 1508 delete pNew; 1509 } 1510 } 1511 } 1512 1513 // 1514 // Inhalte von Beschriftungsbereichen 1515 // 1516 1517 ScRangePairList* pLists[2]; 1518 pLists[0] = GetColNameRanges(); 1519 pLists[1] = GetRowNameRanges(); 1520 for (sal_uInt16 nListNo=0; nListNo<2; nListNo++) 1521 { 1522 ScRangePairList* pList = pLists[nListNo]; 1523 if (pList) 1524 for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() ) 1525 { 1526 ScRange aRange = pPair->GetRange(0); 1527 ScCellIterator aIter( this, aRange ); 1528 for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() ) 1529 if ( pCell->HasStringData() ) 1530 { 1531 String aStr = pCell->GetStringData(); 1532 TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS ); 1533 if ( !rStrings.Insert(pNew) ) 1534 delete pNew; 1535 } 1536 } 1537 } 1538 1539 return sal_True; 1540 } 1541 1542 1543 sal_Bool ScDocument::IsEmbedded() const 1544 { 1545 return bIsEmbedded; 1546 } 1547 1548 void ScDocument::GetEmbedded( ScRange& rRange ) const 1549 { 1550 rRange = aEmbedRange; 1551 } 1552 1553 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm 1554 { 1555 Rectangle aRect; 1556 ScTable* pTable = pTab[aEmbedRange.aStart.Tab()]; 1557 if (!pTable) 1558 { 1559 DBG_ERROR("GetEmbeddedRect ohne Tabelle"); 1560 } 1561 else 1562 { 1563 SCCOL i; 1564 1565 for (i=0; i<aEmbedRange.aStart.Col(); i++) 1566 aRect.Left() += pTable->GetColWidth(i); 1567 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1); 1568 aRect.Right() = aRect.Left(); 1569 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++) 1570 aRect.Right() += pTable->GetColWidth(i); 1571 aRect.Bottom() = aRect.Top(); 1572 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row()); 1573 1574 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS ); 1575 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS ); 1576 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS ); 1577 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS ); 1578 } 1579 return aRect; 1580 } 1581 1582 void ScDocument::SetEmbedded( const ScRange& rRange ) 1583 { 1584 bIsEmbedded = sal_True; 1585 aEmbedRange = rRange; 1586 } 1587 1588 void ScDocument::ResetEmbedded() 1589 { 1590 bIsEmbedded = sal_False; 1591 aEmbedRange = ScRange(); 1592 } 1593 1594 1595 /** Similar to ScViewData::AddPixelsWhile(), but add height twips and only 1596 while result is less than nStopTwips. 1597 @return sal_True if advanced at least one row. 1598 */ 1599 bool lcl_AddTwipsWhile( long & rTwips, long nStopTwips, SCROW & rPosY, SCROW nEndRow, const ScTable * pTable ) 1600 { 1601 SCROW nRow = rPosY; 1602 bool bAdded = false; 1603 bool bStop = false; 1604 while (rTwips < nStopTwips && nRow <= nEndRow && !bStop) 1605 { 1606 SCROW nHeightEndRow; 1607 sal_uInt16 nHeight = pTable->GetRowHeight( nRow, NULL, &nHeightEndRow); 1608 if (nHeightEndRow > nEndRow) 1609 nHeightEndRow = nEndRow; 1610 if (!nHeight) 1611 nRow = nHeightEndRow + 1; 1612 else 1613 { 1614 SCROW nRows = nHeightEndRow - nRow + 1; 1615 sal_Int64 nAdd = static_cast<sal_Int64>(nHeight) * nRows; 1616 if (nAdd + rTwips >= nStopTwips) 1617 { 1618 sal_Int64 nDiff = nAdd + rTwips - nStopTwips; 1619 nRows -= static_cast<SCROW>(nDiff / nHeight); 1620 nAdd = nHeight * nRows; 1621 // We're looking for a value that satisfies loop condition. 1622 if (nAdd + rTwips >= nStopTwips) 1623 { 1624 --nRows; 1625 nAdd -= nHeight; 1626 } 1627 bStop = true; 1628 } 1629 rTwips += static_cast<long>(nAdd); 1630 nRow += nRows; 1631 } 1632 } 1633 if (nRow > rPosY) 1634 { 1635 --nRow; 1636 bAdded = true; 1637 } 1638 rPosY = nRow; 1639 return bAdded; 1640 } 1641 1642 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect ) 1643 { 1644 ScTable* pTable = pTab[nTab]; 1645 if (!pTable) 1646 { 1647 DBG_ERROR("GetRange ohne Tabelle"); 1648 return ScRange(); 1649 } 1650 1651 Rectangle aPosRect = rMMRect; 1652 if ( IsNegativePage( nTab ) ) 1653 ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values 1654 1655 long nSize; 1656 long nTwips; 1657 long nAdd; 1658 sal_Bool bEnd; 1659 1660 nSize = 0; 1661 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS); 1662 1663 SCCOL nX1 = 0; 1664 bEnd = sal_False; 1665 while (!bEnd) 1666 { 1667 nAdd = (long) pTable->GetColWidth(nX1); 1668 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL) 1669 { 1670 nSize += nAdd; 1671 ++nX1; 1672 } 1673 else 1674 bEnd = sal_True; 1675 } 1676 1677 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS); 1678 1679 SCCOL nX2 = nX1; 1680 bEnd = sal_False; 1681 while (!bEnd) 1682 { 1683 nAdd = (long) pTable->GetColWidth(nX2); 1684 if (nSize+nAdd < nTwips && nX2<MAXCOL) 1685 { 1686 nSize += nAdd; 1687 ++nX2; 1688 } 1689 else 1690 bEnd = sal_True; 1691 } 1692 1693 1694 nSize = 0; 1695 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS); 1696 1697 SCROW nY1 = 0; 1698 // Was if(nSize+nAdd<=nTwips+1) inside loop => if(nSize+nAdd<nTwips+2) 1699 if (lcl_AddTwipsWhile( nSize, nTwips+2, nY1, MAXROW, pTable) && nY1 < MAXROW) 1700 ++nY1; // original loop ended on last matched +1 unless that was MAXROW 1701 1702 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS); 1703 1704 SCROW nY2 = nY1; 1705 // Was if(nSize+nAdd<nTwips) inside loop => if(nSize+nAdd<nTwips) 1706 if (lcl_AddTwipsWhile( nSize, nTwips, nY2, MAXROW, pTable) && nY2 < MAXROW) 1707 ++nY2; // original loop ended on last matched +1 unless that was MAXROW 1708 1709 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab ); 1710 } 1711 1712 void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm) 1713 { 1714 bIsEmbedded = sal_True; 1715 aEmbedRange = GetRange( nVisibleTab, rRect ); 1716 } 1717 1718 // VisArea auf Zellgrenzen anpassen 1719 1720 void lcl_SnapHor( ScTable* pTable, long& rVal, SCCOL& rStartCol ) 1721 { 1722 SCCOL nCol = 0; 1723 long nTwips = (long) (rVal / HMM_PER_TWIPS); 1724 long nSnap = 0; 1725 while ( nCol<MAXCOL ) 1726 { 1727 long nAdd = pTable->GetColWidth(nCol); 1728 if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol ) 1729 { 1730 nSnap += nAdd; 1731 ++nCol; 1732 } 1733 else 1734 break; 1735 } 1736 rVal = (long) ( nSnap * HMM_PER_TWIPS ); 1737 rStartCol = nCol; 1738 } 1739 1740 void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow ) 1741 { 1742 SCROW nRow = 0; 1743 long nTwips = (long) (rVal / HMM_PER_TWIPS); 1744 long nSnap = 0; 1745 1746 bool bFound = false; 1747 for (SCROW i = nRow; i <= MAXROW; ++i) 1748 { 1749 SCROW nLastRow; 1750 if (pTable->RowHidden(i, NULL, &nLastRow)) 1751 { 1752 i = nLastRow; 1753 continue; 1754 } 1755 1756 nRow = i; 1757 long nAdd = pTable->GetRowHeight(i); 1758 if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow ) 1759 { 1760 nSnap += nAdd; 1761 ++nRow; 1762 } 1763 else 1764 { 1765 bFound = true; 1766 break; 1767 } 1768 } 1769 if (!bFound) 1770 nRow = MAXROW; // all hidden down to the bottom 1771 1772 rVal = (long) ( nSnap * HMM_PER_TWIPS ); 1773 rStartRow = nRow; 1774 } 1775 1776 void ScDocument::SnapVisArea( Rectangle& rRect ) const 1777 { 1778 ScTable* pTable = pTab[nVisibleTab]; 1779 if (!pTable) 1780 { 1781 DBG_ERROR("SetEmbedded ohne Tabelle"); 1782 return; 1783 } 1784 1785 sal_Bool bNegativePage = IsNegativePage( nVisibleTab ); 1786 if ( bNegativePage ) 1787 ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values 1788 1789 SCCOL nCol = 0; 1790 lcl_SnapHor( pTable, rRect.Left(), nCol ); 1791 ++nCol; // mindestens eine Spalte 1792 lcl_SnapHor( pTable, rRect.Right(), nCol ); 1793 1794 SCROW nRow = 0; 1795 lcl_SnapVer( pTable, rRect.Top(), nRow ); 1796 ++nRow; // mindestens eine Zeile 1797 lcl_SnapVer( pTable, rRect.Bottom(), nRow ); 1798 1799 if ( bNegativePage ) 1800 ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle 1801 } 1802 1803 ScDocProtection* ScDocument::GetDocProtection() const 1804 { 1805 return pDocProtection.get(); 1806 } 1807 1808 void ScDocument::SetDocProtection(const ScDocProtection* pProtect) 1809 { 1810 if (pProtect) 1811 pDocProtection.reset(new ScDocProtection(*pProtect)); 1812 else 1813 pDocProtection.reset(NULL); 1814 } 1815 1816 sal_Bool ScDocument::IsDocProtected() const 1817 { 1818 return pDocProtection.get() && pDocProtection->isProtected(); 1819 } 1820 1821 sal_Bool ScDocument::IsDocEditable() const 1822 { 1823 // import into read-only document is possible 1824 return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() ); 1825 } 1826 1827 sal_Bool ScDocument::IsTabProtected( SCTAB nTab ) const 1828 { 1829 if (VALIDTAB(nTab) && pTab[nTab]) 1830 return pTab[nTab]->IsProtected(); 1831 1832 DBG_ERROR("Falsche Tabellennummer"); 1833 return sal_False; 1834 } 1835 1836 ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const 1837 { 1838 if (VALIDTAB(nTab) && pTab[nTab]) 1839 return pTab[nTab]->GetProtection(); 1840 1841 return NULL; 1842 } 1843 1844 void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect) 1845 { 1846 if (!ValidTab(nTab)) 1847 return; 1848 1849 pTab[nTab]->SetProtection(pProtect); 1850 } 1851 1852 void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest) 1853 { 1854 if (!ValidTab(nTabSrc) || !ValidTab(nTabDest)) 1855 return; 1856 1857 pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() ); 1858 } 1859 1860 const ScDocOptions& ScDocument::GetDocOptions() const 1861 { 1862 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" ); 1863 return *pDocOptions; 1864 } 1865 1866 void ScDocument::SetDocOptions( const ScDocOptions& rOpt ) 1867 { 1868 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" ); 1869 *pDocOptions = rOpt; 1870 1871 xPoolHelper->SetFormTableOpt(rOpt); 1872 } 1873 1874 const ScViewOptions& ScDocument::GetViewOptions() const 1875 { 1876 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" ); 1877 return *pViewOptions; 1878 } 1879 1880 void ScDocument::SetViewOptions( const ScViewOptions& rOpt ) 1881 { 1882 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" ); 1883 *pViewOptions = rOpt; 1884 } 1885 1886 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const 1887 { 1888 rLatin = eLanguage; 1889 rCjk = eCjkLanguage; 1890 rCtl = eCtlLanguage; 1891 } 1892 1893 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl ) 1894 { 1895 eLanguage = eLatin; 1896 eCjkLanguage = eCjk; 1897 eCtlLanguage = eCtl; 1898 if ( xPoolHelper.isValid() ) 1899 { 1900 ScDocumentPool* pPool = xPoolHelper->GetDocPool(); 1901 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) ); 1902 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) ); 1903 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) ); 1904 } 1905 1906 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool 1907 } 1908 1909 void ScDocument::SetDrawDefaults() 1910 { 1911 bSetDrawDefaults = sal_True; 1912 UpdateDrawDefaults(); 1913 } 1914 1915 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow, 1916 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) 1917 { 1918 if (!ValidTab(nTab) || !pTab[nTab]) 1919 { 1920 DBG_ERROR("GetMMRect: falsche Tabelle"); 1921 return Rectangle(0,0,0,0); 1922 } 1923 1924 SCCOL i; 1925 Rectangle aRect; 1926 1927 for (i=0; i<nStartCol; i++) 1928 aRect.Left() += GetColWidth(i,nTab); 1929 aRect.Top() += GetRowHeight( 0, nStartRow-1, nTab); 1930 1931 aRect.Right() = aRect.Left(); 1932 aRect.Bottom() = aRect.Top(); 1933 1934 for (i=nStartCol; i<=nEndCol; i++) 1935 aRect.Right() += GetColWidth(i,nTab); 1936 aRect.Bottom() += GetRowHeight( nStartRow, nEndRow, nTab); 1937 1938 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS); 1939 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS); 1940 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS); 1941 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS); 1942 1943 if ( IsNegativePage( nTab ) ) 1944 ScDrawLayer::MirrorRectRTL( aRect ); 1945 1946 return aRect; 1947 } 1948 1949 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions ) 1950 { 1951 delete pExtDocOptions; 1952 pExtDocOptions = pNewOptions; 1953 } 1954 1955 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 1956 SCCOL nEndCol, SCROW nEndRow ) 1957 { 1958 String aEmpty; 1959 String aTotal; 1960 String aCellStr; 1961 SCCOL nCol; 1962 SCROW nRow; 1963 for (nRow=nStartRow; nRow<=nEndRow; nRow++) 1964 for (nCol=nStartCol; nCol<=nEndCol; nCol++) 1965 { 1966 GetString(nCol,nRow,nTab,aCellStr); 1967 if (aCellStr.Len()) 1968 { 1969 if (aTotal.Len()) 1970 aTotal += ' '; 1971 aTotal += aCellStr; 1972 } 1973 if (nCol != nStartCol || nRow != nStartRow) 1974 SetString(nCol,nRow,nTab,aEmpty); 1975 } 1976 1977 SetString(nStartCol,nStartRow,nTab,aTotal); 1978 } 1979 1980 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, 1981 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions ) 1982 { 1983 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 ); 1984 ApplyAttr( nStartCol, nStartRow, nTab, aAttr ); 1985 1986 if ( nEndCol > nStartCol ) 1987 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR ); 1988 if ( nEndRow > nStartRow ) 1989 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER ); 1990 if ( nEndCol > nStartCol && nEndRow > nStartRow ) 1991 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER ); 1992 1993 // remove all covered notes (removed captions are collected by drawing undo if active) 1994 sal_uInt16 nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS); 1995 if( nStartCol < nEndCol ) 1996 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag ); 1997 if( nStartRow < nEndRow ) 1998 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag ); 1999 } 2000 2001 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab ) 2002 { 2003 const ScMergeAttr* pAttr = (const ScMergeAttr*) 2004 GetAttr( nCol, nRow, nTab, ATTR_MERGE ); 2005 2006 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 ) 2007 return; 2008 2009 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1; 2010 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1; 2011 2012 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER ); 2013 2014 const ScMergeAttr* pDefAttr = (const ScMergeAttr*) 2015 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE ); 2016 ApplyAttr( nCol, nRow, nTab, *pDefAttr ); 2017 } 2018 2019 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab, 2020 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow ) 2021 { 2022 if ( ValidTab(nTab) && pTab[nTab] ) 2023 pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow ); 2024 } 2025 2026 void ScDocument::IncSizeRecalcLevel( SCTAB nTab ) 2027 { 2028 if ( ValidTab(nTab) && pTab[nTab] ) 2029 pTab[nTab]->IncRecalcLevel(); 2030 } 2031 2032 void ScDocument::DecSizeRecalcLevel( SCTAB nTab, bool bUpdateNoteCaptionPos ) 2033 { 2034 if ( ValidTab(nTab) && pTab[nTab] ) 2035 pTab[nTab]->DecRecalcLevel( bUpdateNoteCaptionPos ); 2036 } 2037 2038 // Wang Xu Ming -- 2009-8-17 2039 // DataPilot Migration - Cache&&Performance 2040 ScDPTableDataCache* ScDocument::GetDPObjectCache( long nID ) 2041 { 2042 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2043 { // 2044 if ( nID == (*iter)->GetId() ) 2045 return *iter; 2046 } 2047 return NULL; 2048 } 2049 2050 ScDPTableDataCache* ScDocument::GetUsedDPObjectCache ( ScRange rRange ) 2051 { 2052 ScDPTableDataCache* pCache = NULL; 2053 sal_uInt16 nCount = GetDPCollection()->GetCount(); 2054 for ( short i=nCount-1; i>=0 ; i--) 2055 { 2056 if ( const ScSheetSourceDesc* pUsedSheetDesc = (*pDPCollection)[i]->GetSheetDesc() ) 2057 if ( rRange == pUsedSheetDesc->aSourceRange ) 2058 { 2059 long nID = (*pDPCollection)[i]->GetCacheId(); 2060 if ( nID >= 0 ) 2061 pCache= GetDPObjectCache( nID ); 2062 if ( pCache ) 2063 return pCache; 2064 } 2065 } 2066 return pCache; 2067 } 2068 2069 long ScDocument::AddDPObjectCache( ScDPTableDataCache* pData ) 2070 { 2071 if ( pData->GetId() < 0 ) 2072 { //create a id for it 2073 pData->SetId( GetNewDPObjectCacheId() ); 2074 } 2075 m_listDPObjectsCaches.push_back( pData ); 2076 return pData->GetId(); 2077 } 2078 2079 long ScDocument::GetNewDPObjectCacheId() 2080 { 2081 long nID = 0; 2082 2083 bool bFound = false; 2084 std::list<ScDPTableDataCache*>::iterator iter; 2085 do { 2086 for ( iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2087 { //Get a new Id 2088 if ( nID == (*iter)->GetId() ) 2089 { 2090 nID++; 2091 bFound = true; 2092 break; 2093 } 2094 } 2095 if ( iter == m_listDPObjectsCaches.end() ) 2096 bFound = false; 2097 } while ( bFound ); 2098 2099 return nID; 2100 } 2101 2102 void ScDocument::RemoveDPObjectCache( long nID ) 2103 { 2104 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2105 { 2106 if ( nID == (*iter)->GetId() ) 2107 { 2108 ScDPTableDataCache* pCache = *iter; 2109 m_listDPObjectsCaches.erase( iter ); 2110 delete pCache; 2111 break; 2112 } 2113 } 2114 2115 } 2116 2117 void ScDocument::RemoveUnusedDPObjectCaches() 2118 { 2119 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); ) 2120 { 2121 long nID = (*iter)->GetId(); 2122 sal_uInt16 nCount = GetDPCollection()->GetCount(); 2123 sal_uInt16 i ; 2124 for ( i=0; i<nCount; i++) 2125 { 2126 if ( nID == (*pDPCollection)[i]->GetCacheId() ) 2127 break; 2128 } 2129 if ( i == nCount ) 2130 { 2131 ScDPTableDataCache* pCache = *iter; 2132 iter = m_listDPObjectsCaches.erase( iter ); 2133 delete pCache; 2134 continue; 2135 } 2136 ++iter; 2137 } 2138 } 2139 2140 void ScDocument::GetUsedDPObjectCache( std::list<ScDPTableDataCache*>& usedlist ) 2141 { 2142 for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) 2143 { 2144 long nID = (*iter)->GetId(); 2145 sal_uInt16 nCount = GetDPCollection()->GetCount(); 2146 sal_uInt16 i=0; 2147 for ( i=0; i<nCount; i++) 2148 if ( nID == (*pDPCollection)[i]->GetCacheId() ) 2149 break; 2150 if ( i != nCount ) 2151 usedlist.push_back( *iter ); 2152 } 2153 } 2154 // End Comments 2155