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