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