Update to m13
[ooovba.git] / sc / source / core / data / documen3.cxx
blobd276f255d998eb20dc4657d5678ba376a403392b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: documen3.cxx,v $
10 * $Revision: 1.42.100.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include "scitems.hxx"
37 #include <svx/langitem.hxx>
38 #include <svx/srchitem.hxx>
39 #include <svx/linkmgr.hxx>
40 #include <sfx2/bindings.hxx>
41 #include <sfx2/objsh.hxx>
42 #include <svtools/zforlist.hxx>
43 #include <vcl/svapp.hxx>
44 #include "document.hxx"
45 #include "attrib.hxx"
46 #include "cell.hxx"
47 #include "table.hxx"
48 #include "rangenam.hxx"
49 #include "dbcolect.hxx"
50 #include "pivot.hxx"
51 #include "docpool.hxx"
52 #include "poolhelp.hxx"
53 #include "autoform.hxx"
54 #include "rangelst.hxx"
55 #include "chartarr.hxx"
56 #include "chartlock.hxx"
57 #include "compiler.hxx"
58 #include "refupdat.hxx"
59 #include "docoptio.hxx"
60 #include "viewopti.hxx"
61 #include "scextopt.hxx"
62 #include "brdcst.hxx"
63 #include "bcaslot.hxx"
64 #include "tablink.hxx"
65 #include "externalrefmgr.hxx"
66 #include "markdata.hxx"
67 #include "validat.hxx"
68 #include "dociter.hxx"
69 #include "detdata.hxx"
70 #include "detfunc.hxx"
71 #include "scmod.hxx" // SC_MOD
72 #include "inputopt.hxx" // GetExpandRefs
73 #include "chartlis.hxx"
74 #include "sc.hrc" // SID_LINK
75 #include "hints.hxx"
76 #include "dpobject.hxx"
77 #include "unoguard.hxx"
78 #include "drwlayer.hxx"
79 #include "unoreflist.hxx"
80 #include "listenercalls.hxx"
81 #include "svtools/PasswordHelper.hxx"
82 #include "tabprotection.hxx"
83 #include "clipparam.hxx"
85 #include <memory>
87 using namespace com::sun::star;
88 using ::std::auto_ptr;
90 //------------------------------------------------------------------------
92 ScRangeName* ScDocument::GetRangeName()
94 return pRangeName;
97 void ScDocument::SetRangeName( ScRangeName* pNewRangeName )
99 if (pRangeName)
100 delete pRangeName;
101 pRangeName = pNewRangeName;
104 //UNUSED2008-05 ScRangeData* ScDocument::GetRangeAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab,
105 //UNUSED2008-05 BOOL bStartOnly) const
106 //UNUSED2008-05 {
107 //UNUSED2008-05 if ( pRangeName )
108 //UNUSED2008-05 return pRangeName->GetRangeAtCursor( ScAddress( nCol, nRow, nTab ), bStartOnly );
109 //UNUSED2008-05 else
110 //UNUSED2008-05 return NULL;
111 //UNUSED2008-05 }
113 ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, String* pName ) const
115 ScRangeData* pData = NULL;
116 if ( pRangeName )
118 pData = pRangeName->GetRangeAtBlock( rBlock );
119 if (pData && pName)
120 *pName = pData->GetName();
122 return pData;
125 ScDBCollection* ScDocument::GetDBCollection() const
127 return pDBCollection;
130 void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, BOOL bRemoveAutoFilter )
132 if ( bRemoveAutoFilter )
134 // remove auto filter attribute if new db data don't contain auto filter flag
135 // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo!
137 if ( pDBCollection )
139 USHORT nOldCount = pDBCollection->GetCount();
140 for (USHORT nOld=0; nOld<nOldCount; nOld++)
142 ScDBData* pOldData = (*pDBCollection)[nOld];
143 if ( pOldData->HasAutoFilter() )
145 ScRange aOldRange;
146 pOldData->GetArea( aOldRange );
148 BOOL bFound = FALSE;
149 USHORT nNewIndex = 0;
150 if ( pNewDBCollection &&
151 pNewDBCollection->SearchName( pOldData->GetName(), nNewIndex ) )
153 ScDBData* pNewData = (*pNewDBCollection)[nNewIndex];
154 if ( pNewData->HasAutoFilter() )
156 ScRange aNewRange;
157 pNewData->GetArea( aNewRange );
158 if ( aOldRange.aStart == aNewRange.aStart )
159 bFound = TRUE;
163 if ( !bFound )
165 aOldRange.aEnd.SetRow( aOldRange.aStart.Row() );
166 RemoveFlagsTab( aOldRange.aStart.Col(), aOldRange.aStart.Row(),
167 aOldRange.aEnd.Col(), aOldRange.aEnd.Row(),
168 aOldRange.aStart.Tab(), SC_MF_AUTO );
169 if (pShell)
170 pShell->Broadcast( ScPaintHint( aOldRange, PAINT_GRID ) );
177 if (pDBCollection)
178 delete pDBCollection;
179 pDBCollection = pNewDBCollection;
182 ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, BOOL bStartOnly) const
184 if (pDBCollection)
185 return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
186 else
187 return NULL;
190 ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
192 if (pDBCollection)
193 return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
194 else
195 return NULL;
198 ScDPCollection* ScDocument::GetDPCollection()
200 if (!pDPCollection)
201 pDPCollection = new ScDPCollection(this);
202 return pDPCollection;
205 ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
207 if (!pDPCollection)
208 return NULL;
210 USHORT nCount = pDPCollection->GetCount();
211 ScAddress aPos( nCol, nRow, nTab );
212 for (USHORT i=0; i<nCount; i++)
213 if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) )
214 return (*pDPCollection)[i];
216 return NULL;
219 ScDPObject* ScDocument::GetDPAtBlock( const ScRange & rBlock ) const
221 if (!pDPCollection)
222 return NULL;
224 /* Walk the collection in reverse order to get something of an
225 * approximation of MS Excels 'most recent' effect. */
226 USHORT i = pDPCollection->GetCount();
227 while ( i-- > 0 )
228 if ( (*pDPCollection)[i]->GetOutRange().In( rBlock ) )
229 return (*pDPCollection)[i];
231 return NULL;
234 #if OLD_PIVOT_IMPLEMENTATION
235 ScPivotCollection* ScDocument::GetPivotCollection() const
237 return pPivotCollection;
240 void ScDocument::SetPivotCollection(ScPivotCollection* pNewPivotCollection)
242 if ( pPivotCollection && pNewPivotCollection &&
243 *pPivotCollection == *pNewPivotCollection )
245 delete pNewPivotCollection;
246 return;
249 if (pPivotCollection)
250 delete pPivotCollection;
251 pPivotCollection = pNewPivotCollection;
253 if (pPivotCollection)
255 USHORT nCount = pPivotCollection->GetCount();
256 for (USHORT i=0; i<nCount; i++)
258 ScPivot* pPivot = (*pPivotCollection)[i];
259 if (pPivot->CreateData())
260 pPivot->ReleaseData();
265 ScPivot* ScDocument::GetPivotAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
267 if (pPivotCollection)
268 return pPivotCollection->GetPivotAtCursor(nCol, nRow, nTab);
269 else
270 return NULL;
272 #endif
274 ScChartCollection* ScDocument::GetChartCollection() const
276 return pChartCollection;
279 void ScDocument::StopTemporaryChartLock()
281 if( apTemporaryChartLock.get() )
282 apTemporaryChartLock->StopLocking();
285 void ScDocument::SetChartListenerCollection(
286 ScChartListenerCollection* pNewChartListenerCollection,
287 BOOL bSetChartRangeLists )
289 ScChartListenerCollection* pOld = pChartListenerCollection;
290 pChartListenerCollection = pNewChartListenerCollection;
291 if ( pChartListenerCollection )
293 if ( pOld )
294 pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists );
295 pChartListenerCollection->StartAllListeners();
297 delete pOld;
300 void ScDocument::SetScenario( SCTAB nTab, BOOL bFlag )
302 if (ValidTab(nTab) && pTab[nTab])
303 pTab[nTab]->SetScenario(bFlag);
306 BOOL ScDocument::IsScenario( SCTAB nTab ) const
308 return ValidTab(nTab) && pTab[nTab] &&pTab[nTab]->IsScenario();
309 //if (ValidTab(nTab) && pTab[nTab])
310 // return pTab[nTab]->IsScenario();
312 //return FALSE;
315 void ScDocument::SetScenarioData( SCTAB nTab, const String& rComment,
316 const Color& rColor, USHORT nFlags )
318 if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
320 pTab[nTab]->SetScenarioComment( rComment );
321 pTab[nTab]->SetScenarioColor( rColor );
322 pTab[nTab]->SetScenarioFlags( nFlags );
326 void ScDocument::GetScenarioData( SCTAB nTab, String& rComment,
327 Color& rColor, USHORT& rFlags ) const
329 if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
331 pTab[nTab]->GetScenarioComment( rComment );
332 rColor = pTab[nTab]->GetScenarioColor();
333 rFlags = pTab[nTab]->GetScenarioFlags();
337 void ScDocument::GetScenarioFlags( SCTAB nTab, USHORT& rFlags ) const
339 if (VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
340 rFlags = pTab[nTab]->GetScenarioFlags();
343 BOOL ScDocument::IsLinked( SCTAB nTab ) const
345 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsLinked();
346 // euqivalent to
347 //if (ValidTab(nTab) && pTab[nTab])
348 // return pTab[nTab]->IsLinked();
349 //return FALSE;
352 formula::FormulaGrammar::AddressConvention ScDocument::GetAddressConvention() const
354 return formula::FormulaGrammar::extractRefConvention(eGrammar);
357 formula::FormulaGrammar::Grammar ScDocument::GetGrammar() const
359 return eGrammar;
362 void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram )
364 eGrammar = eGram;
367 BOOL ScDocument::GetLinkMode( SCTAB nTab ) const
369 if (ValidTab(nTab) && pTab[nTab])
370 return pTab[nTab]->GetLinkMode();
371 return SC_LINK_NONE;
374 const String& ScDocument::GetLinkDoc( SCTAB nTab ) const
376 if (ValidTab(nTab) && pTab[nTab])
377 return pTab[nTab]->GetLinkDoc();
378 return EMPTY_STRING;
381 const String& ScDocument::GetLinkFlt( SCTAB nTab ) const
383 if (ValidTab(nTab) && pTab[nTab])
384 return pTab[nTab]->GetLinkFlt();
385 return EMPTY_STRING;
388 const String& ScDocument::GetLinkOpt( SCTAB nTab ) const
390 if (ValidTab(nTab) && pTab[nTab])
391 return pTab[nTab]->GetLinkOpt();
392 return EMPTY_STRING;
395 const String& ScDocument::GetLinkTab( SCTAB nTab ) const
397 if (ValidTab(nTab) && pTab[nTab])
398 return pTab[nTab]->GetLinkTab();
399 return EMPTY_STRING;
402 ULONG ScDocument::GetLinkRefreshDelay( SCTAB nTab ) const
404 if (ValidTab(nTab) && pTab[nTab])
405 return pTab[nTab]->GetLinkRefreshDelay();
406 return 0;
409 void ScDocument::SetLink( SCTAB nTab, BYTE nMode, const String& rDoc,
410 const String& rFilter, const String& rOptions,
411 const String& rTabName, ULONG nRefreshDelay )
413 if (ValidTab(nTab) && pTab[nTab])
414 pTab[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName, nRefreshDelay );
417 BOOL ScDocument::HasLink( const String& rDoc,
418 const String& rFilter, const String& rOptions ) const
420 SCTAB nCount = GetTableCount();
421 for (SCTAB i=0; i<nCount; i++)
422 if (pTab[i]->IsLinked()
423 && pTab[i]->GetLinkDoc() == rDoc
424 && pTab[i]->GetLinkFlt() == rFilter
425 && pTab[i]->GetLinkOpt() == rOptions)
426 return TRUE;
428 return FALSE;
431 BOOL ScDocument::LinkExternalTab( SCTAB& rTab, const String& aDocTab,
432 const String& aFileName, const String& aTabName )
434 if ( IsClipboard() )
436 DBG_ERRORFILE( "LinkExternalTab in Clipboard" );
437 return FALSE;
439 rTab = 0;
440 String aFilterName; // wird vom Loader gefuellt
441 String aOptions; // Filter-Optionen
442 sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0;
443 ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 );
444 if ( aLoader.IsError() )
445 return FALSE;
446 ScDocument* pSrcDoc = aLoader.GetDocument();
448 // Tabelle kopieren
449 SCTAB nSrcTab;
450 if ( pSrcDoc->GetTable( aTabName, nSrcTab ) )
452 if ( !InsertTab( SC_TAB_APPEND, aDocTab, TRUE ) )
454 DBG_ERRORFILE("can't insert external document table");
455 return FALSE;
457 rTab = GetTableCount() - 1;
458 // nicht neu einfuegen, nur Ergebnisse
459 TransferTab( pSrcDoc, nSrcTab, rTab, FALSE, TRUE );
461 else
462 return FALSE;
464 ULONG nRefreshDelay = 0;
466 BOOL bWasThere = HasLink( aFileName, aFilterName, aOptions );
467 SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName, nRefreshDelay );
468 if ( !bWasThere ) // Link pro Quelldokument nur einmal eintragen
470 ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions, nRefreshDelay );
471 pLink->SetInCreate( TRUE );
472 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName,
473 &aFilterName );
474 pLink->Update();
475 pLink->SetInCreate( FALSE );
476 SfxBindings* pBindings = GetViewBindings();
477 if (pBindings)
478 pBindings->Invalidate( SID_LINKS );
480 return TRUE;
483 ScExternalRefManager* ScDocument::GetExternalRefManager()
485 if (!pExternalRefMgr.get())
486 pExternalRefMgr.reset(new ScExternalRefManager(this));
488 return pExternalRefMgr.get();
491 bool ScDocument::IsInExternalReferenceMarking() const
493 return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking();
496 void ScDocument::MarkUsedExternalReferences()
498 if (!pExternalRefMgr.get())
499 return;
500 if (!pExternalRefMgr->hasExternalData())
501 return;
502 // Charts.
503 bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners();
504 // Formula cells.
505 for (SCTAB nTab = 0; !bAllMarked && nTab < nMaxTableNumber; ++nTab)
507 if (pTab[nTab])
508 bAllMarked = pTab[nTab]->MarkUsedExternalReferences();
510 /* NOTE: Conditional formats and validation objects are marked when
511 * collecting them during export. */
514 ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate )
516 ScOutlineTable* pVal = NULL;
518 if (VALIDTAB(nTab))
519 if (pTab[nTab])
521 pVal = pTab[nTab]->GetOutlineTable();
522 if (!pVal)
523 if (bCreate)
525 pTab[nTab]->StartOutlineTable();
526 pVal = pTab[nTab]->GetOutlineTable();
530 return pVal;
533 BOOL ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline )
535 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->SetOutlineTable(pNewOutline);
536 //if (VALIDTAB(nTab))
537 // if (pTab[nTab])
538 // return pTab[nTab]->SetOutlineTable(pNewOutline);
540 //return FALSE;
543 void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow,
544 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
546 if (VALIDTAB(nTab) && pTab[nTab])
547 pTab[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
550 BOOL ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam )
552 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->TestRemoveSubTotals( rParam );
553 //if (VALIDTAB(nTab) && pTab[nTab] )
554 // return pTab[nTab]->TestRemoveSubTotals( rParam );
556 //return FALSE;
559 void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
561 if ( VALIDTAB(nTab) && pTab[nTab] )
562 pTab[nTab]->RemoveSubTotals( rParam );
565 BOOL ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
567 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->DoSubTotals( rParam );
568 //if (VALIDTAB(nTab))
569 // if (pTab[nTab])
570 // return pTab[nTab]->DoSubTotals( rParam );
572 //return FALSE;
575 BOOL ScDocument::HasSubTotalCells( const ScRange& rRange )
577 ScCellIterator aIter( this, rRange );
578 ScBaseCell* pCell = aIter.GetFirst();
579 while (pCell)
581 if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->IsSubTotal() )
582 return TRUE;
584 pCell = aIter.GetNext();
586 return FALSE; // none found
589 // kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc
590 // auch Zellen stehen, nach pDestDoc
592 void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
594 SCTAB nCount = GetTableCount();
595 for (SCTAB nTab=0; nTab<nCount; nTab++)
596 if (pTab[nTab] && pPosDoc->pTab[nTab] && pDestDoc->pTab[nTab])
597 pTab[nTab]->CopyUpdated( pPosDoc->pTab[nTab], pDestDoc->pTab[nTab] );
600 void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, BOOL bNewScenario )
602 if (ValidTab(nSrcTab) && ValidTab(nDestTab) && pTab[nSrcTab] && pTab[nDestTab])
604 // Flags fuer aktive Szenarios richtig setzen
605 // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben
607 ScRangeList aRanges = *pTab[nSrcTab]->GetScenarioRanges();
608 const ULONG nRangeCount = aRanges.Count();
610 // nDestTab ist die Zieltabelle
611 for ( SCTAB nTab = nDestTab+1;
612 nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario();
613 nTab++ )
615 if ( pTab[nTab]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist
617 BOOL bTouched = FALSE;
618 for ( ULONG nR=0; nR<nRangeCount && !bTouched; nR++)
620 const ScRange* pRange = aRanges.GetObject(nR);
621 if ( pTab[nTab]->HasScenarioRange( *pRange ) )
622 bTouched = TRUE;
624 if (bTouched)
626 pTab[nTab]->SetActiveScenario(FALSE);
627 if ( pTab[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
628 pTab[nTab]->CopyScenarioFrom( pTab[nDestTab] );
633 pTab[nSrcTab]->SetActiveScenario(TRUE); // da kommt's her...
634 if (!bNewScenario) // Daten aus dem ausgewaehlten Szenario kopieren
636 BOOL bOldAutoCalc = GetAutoCalc();
637 SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
638 pTab[nSrcTab]->CopyScenarioTo( pTab[nDestTab] );
639 SetDirty();
640 SetAutoCalc( bOldAutoCalc );
645 void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark,
646 BOOL bResetMark, USHORT nNeededBits ) const
648 if (bResetMark)
649 rDestMark.ResetMark();
651 if (ValidTab(nSrcTab) && pTab[nSrcTab])
652 pTab[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
654 rDestMark.SetAreaTab( nDestTab );
657 BOOL ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const
659 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->HasScenarioRange( rRange );
660 //if (ValidTab(nTab) && pTab[nTab])
661 // return pTab[nTab]->HasScenarioRange( rRange );
663 //return FALSE;
666 const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const
668 if (ValidTab(nTab) && pTab[nTab])
669 return pTab[nTab]->GetScenarioRanges();
671 return NULL;
674 BOOL ScDocument::IsActiveScenario( SCTAB nTab ) const
676 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsActiveScenario( );
677 //if (ValidTab(nTab) && pTab[nTab])
678 // return pTab[nTab]->IsActiveScenario();
680 //return FALSE;
683 void ScDocument::SetActiveScenario( SCTAB nTab, BOOL bActive )
685 if (ValidTab(nTab) && pTab[nTab])
686 pTab[nTab]->SetActiveScenario( bActive );
689 BOOL ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const
691 if (ValidTab(nSrcTab) && ValidTab(nDestTab))
692 return pTab[nSrcTab]->TestCopyScenarioTo( pTab[nDestTab] );
694 DBG_ERROR("falsche Tabelle bei TestCopyScenario");
695 return FALSE;
698 void ScDocument::AddUnoObject( SfxListener& rObject )
700 if (!pUnoBroadcaster)
701 pUnoBroadcaster = new SfxBroadcaster;
703 rObject.StartListening( *pUnoBroadcaster );
706 void ScDocument::RemoveUnoObject( SfxListener& rObject )
708 if (pUnoBroadcaster)
710 rObject.EndListening( *pUnoBroadcaster );
712 if ( bInUnoBroadcast )
714 // #107294# Broadcasts from ScDocument::BroadcastUno are the only way that
715 // uno object methods are called without holding a reference.
717 // If RemoveUnoObject is called from an object dtor in the finalizer thread
718 // while the main thread is calling BroadcastUno, the dtor thread must wait
719 // (or the object's Notify might try to access a deleted object).
720 // The SolarMutex can't be locked here because if a component is called from
721 // a VCL event, the main thread has the SolarMutex locked all the time.
723 // This check is done after calling EndListening, so a later BroadcastUno call
724 // won't touch this object.
726 vos::IMutex& rSolarMutex = Application::GetSolarMutex();
727 if ( rSolarMutex.tryToAcquire() )
729 // BroadcastUno is always called with the SolarMutex locked, so if it
730 // can be acquired, this is within the same thread (should not happen)
731 DBG_ERRORFILE( "RemoveUnoObject called from BroadcastUno" );
732 rSolarMutex.release();
734 else
736 // let the thread that called BroadcastUno continue
737 while ( bInUnoBroadcast )
739 vos::OThread::yield();
744 else
746 DBG_ERROR("No Uno broadcaster");
750 void ScDocument::BroadcastUno( const SfxHint &rHint )
752 if (pUnoBroadcaster)
754 bInUnoBroadcast = TRUE;
755 pUnoBroadcaster->Broadcast( rHint );
756 bInUnoBroadcast = FALSE;
758 // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
759 // The listener calls must be processed after completing the broadcast,
760 // because they can add or remove objects from pUnoBroadcaster.
762 if ( pUnoListenerCalls && rHint.ISA( SfxSimpleHint ) &&
763 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DATACHANGED &&
764 !bInUnoListenerCall )
766 // Listener calls may lead to BroadcastUno calls again. The listener calls
767 // are not nested, instead the calls are collected in the list, and the
768 // outermost call executes them all.
770 ScChartLockGuard aChartLockGuard(this);
771 bInUnoListenerCall = TRUE;
772 pUnoListenerCalls->ExecuteAndClear();
773 bInUnoListenerCall = FALSE;
778 void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener,
779 const lang::EventObject& rEvent )
781 DBG_ASSERT( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
783 if ( !pUnoListenerCalls )
784 pUnoListenerCalls = new ScUnoListenerCalls;
785 pUnoListenerCalls->Add( rListener, rEvent );
788 void ScDocument::BeginUnoRefUndo()
790 DBG_ASSERT( !pUnoRefUndoList, "BeginUnoRefUndo twice" );
791 delete pUnoRefUndoList;
793 pUnoRefUndoList = new ScUnoRefList;
796 ScUnoRefList* ScDocument::EndUnoRefUndo()
798 ScUnoRefList* pRet = pUnoRefUndoList;
799 pUnoRefUndoList = NULL;
800 return pRet; // must be deleted by caller!
803 void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
805 if ( pUnoRefUndoList )
806 pUnoRefUndoList->Add( nId, rOldRanges );
809 sal_Int64 ScDocument::GetNewUnoId()
811 return ++nUnoObjectId;
814 void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
815 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
816 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
817 SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
818 ScDocument* pUndoDoc, BOOL bIncludeDraw )
820 PutInOrder( nCol1, nCol2 );
821 PutInOrder( nRow1, nRow2 );
822 PutInOrder( nTab1, nTab2 );
823 if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
825 BOOL bExpandRefsOld = IsExpandRefs();
826 if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
827 SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
828 SCTAB i;
829 SCTAB iMax;
830 if ( eUpdateRefMode == URM_COPY )
832 i = nTab1;
833 iMax = nTab2;
835 else
837 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
838 xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
839 xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
840 pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
841 pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
842 #if OLD_PIVOT_IMPLEMENTATION
843 if (pPivotCollection)
844 pPivotCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
845 #endif
846 if ( pDPCollection )
847 pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
848 UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
849 UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz );
850 if ( pCondFormList )
851 pCondFormList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
852 if ( pValidationList )
853 pValidationList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
854 if ( pDetOpList )
855 pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
856 if ( pUnoBroadcaster )
857 pUnoBroadcaster->Broadcast( ScUpdateRefHint(
858 eUpdateRefMode, aRange, nDx, nDy, nDz ) );
859 i = 0;
860 iMax = MAXTAB;
862 for ( ; i<=iMax; i++)
863 if (pTab[i])
864 pTab[i]->UpdateReference(
865 eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
866 nDx, nDy, nDz, pUndoDoc, bIncludeDraw );
868 if ( bIsEmbedded )
870 SCCOL theCol1;
871 SCROW theRow1;
872 SCTAB theTab1;
873 SCCOL theCol2;
874 SCROW theRow2;
875 SCTAB theTab2;
876 theCol1 = aEmbedRange.aStart.Col();
877 theRow1 = aEmbedRange.aStart.Row();
878 theTab1 = aEmbedRange.aStart.Tab();
879 theCol2 = aEmbedRange.aEnd.Col();
880 theRow2 = aEmbedRange.aEnd.Row();
881 theTab2 = aEmbedRange.aEnd.Tab();
882 if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
883 nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
885 aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
888 SetExpandRefs( bExpandRefsOld );
890 // #30428# after moving, no clipboard move ref-updates are possible
891 if ( eUpdateRefMode != URM_COPY && IsClipboardSource() )
893 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
894 if (pClipDoc)
895 pClipDoc->GetClipParam().mbCutMode = false;
900 void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
901 const ScMarkData& rMark, ScDocument* pUndoDoc )
903 DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
905 ScRange aSource;
906 ScClipParam& rClipParam = GetClipParam();
907 if (rClipParam.maRanges.Count())
908 aSource = *rClipParam.maRanges.First();
909 ScAddress aDest = rDestPos;
911 SCTAB nClipTab = 0;
912 for (SCTAB nDestTab=0; nDestTab<=MAXTAB && pTab[nDestTab]; nDestTab++)
913 if (rMark.GetTableSelect(nDestTab))
915 while (!pClipDoc->pTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
916 aSource.aStart.SetTab( nClipTab );
917 aSource.aEnd.SetTab( nClipTab );
918 aDest.SetTab( nDestTab );
920 // wie UpdateReference
922 pRangeName->UpdateTranspose( aSource, aDest ); // vor den Zellen!
923 for (SCTAB i=0; i<=MAXTAB; i++)
924 if (pTab[i])
925 pTab[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
927 nClipTab = (nClipTab+1) % (MAXTAB+1);
931 void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
933 //! pDBCollection
934 //! pPivotCollection
935 //! UpdateChartRef
937 pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
938 #if OLD_PIVOT_IMPLEMENTATION
939 pPivotCollection->UpdateGrow( rArea, nGrowX, nGrowY );
940 #endif
942 for (SCTAB i=0; i<=MAXTAB && pTab[i]; i++)
943 pTab[i]->UpdateGrow( rArea, nGrowX, nGrowY );
946 void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
947 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
948 double nStepValue, double nMaxValue)
950 PutInOrder( nCol1, nCol2 );
951 PutInOrder( nRow1, nRow2 );
952 for (SCTAB i=0; i <= MAXTAB; i++)
953 if (pTab[i])
954 if (rMark.GetTableSelect(i))
955 pTab[i]->Fill(nCol1, nRow1, nCol2, nRow2,
956 nFillCount, eFillDir, eFillCmd, eFillDateCmd,
957 nStepValue, nMaxValue);
960 String ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
962 SCTAB nTab = rSource.aStart.Tab();
963 if (pTab[nTab])
964 return pTab[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
966 return EMPTY_STRING;
969 void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
970 USHORT nFormatNo, const ScMarkData& rMark )
972 PutInOrder( nStartCol, nEndCol );
973 PutInOrder( nStartRow, nEndRow );
974 for (SCTAB i=0; i <= MAXTAB; i++)
975 if (pTab[i])
976 if (rMark.GetTableSelect(i))
977 pTab[i]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
980 void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
981 ScAutoFormatData& rData)
983 if (VALIDTAB(nTab))
985 if (pTab[nTab])
987 PutInOrder(nStartCol, nEndCol);
988 PutInOrder(nStartRow, nEndRow);
989 pTab[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
994 // static
995 void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
996 SCCOL& rCol, SCROW& rRow )
998 USHORT nCommand = rSearchItem.GetCommand();
999 BOOL bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE ||
1000 nCommand == SVX_SEARCHCMD_REPLACE_ALL );
1001 if ( rSearchItem.GetBackward() )
1003 if ( rSearchItem.GetRowDirection() )
1005 if ( rSearchItem.GetPattern() )
1007 rCol = MAXCOL;
1008 rRow = MAXROW+1;
1010 else if ( bReplace )
1012 rCol = MAXCOL;
1013 rRow = MAXROW;
1015 else
1017 rCol = MAXCOL+1;
1018 rRow = MAXROW;
1021 else
1023 if ( rSearchItem.GetPattern() )
1025 rCol = MAXCOL+1;
1026 rRow = MAXROW;
1028 else if ( bReplace )
1030 rCol = MAXCOL;
1031 rRow = MAXROW;
1033 else
1035 rCol = MAXCOL;
1036 rRow = MAXROW+1;
1040 else
1042 if ( rSearchItem.GetRowDirection() )
1044 if ( rSearchItem.GetPattern() )
1046 rCol = 0;
1047 rRow = (SCROW) -1;
1049 else if ( bReplace )
1051 rCol = 0;
1052 rRow = 0;
1054 else
1056 rCol = (SCCOL) -1;
1057 rRow = 0;
1060 else
1062 if ( rSearchItem.GetPattern() )
1064 rCol = (SCCOL) -1;
1065 rRow = 0;
1067 else if ( bReplace )
1069 rCol = 0;
1070 rRow = 0;
1072 else
1074 rCol = 0;
1075 rRow = (SCROW) -1;
1081 BOOL ScDocument::SearchAndReplace(const SvxSearchItem& rSearchItem,
1082 SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
1083 ScMarkData& rMark,
1084 String& rUndoStr, ScDocument* pUndoDoc)
1086 //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!!
1088 rMark.MarkToMulti();
1090 BOOL bFound = FALSE;
1091 if (VALIDTAB(rTab))
1093 SCCOL nCol;
1094 SCROW nRow;
1095 SCTAB nTab;
1096 USHORT nCommand = rSearchItem.GetCommand();
1097 if ( nCommand == SVX_SEARCHCMD_FIND_ALL ||
1098 nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1100 for (nTab = 0; nTab <= MAXTAB; nTab++)
1101 if (pTab[nTab])
1103 if (rMark.GetTableSelect(nTab))
1105 nCol = 0;
1106 nRow = 0;
1107 bFound |= pTab[nTab]->SearchAndReplace(
1108 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1112 // Markierung wird innen schon komplett gesetzt
1114 else
1116 nCol = rCol;
1117 nRow = rRow;
1118 if (rSearchItem.GetBackward())
1120 for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--)
1121 if (pTab[nTab])
1123 if (rMark.GetTableSelect(nTab))
1125 bFound = pTab[nTab]->SearchAndReplace(
1126 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1127 if (bFound)
1129 rCol = nCol;
1130 rRow = nRow;
1131 rTab = nTab;
1133 else
1134 ScDocument::GetSearchAndReplaceStart(
1135 rSearchItem, nCol, nRow );
1139 else
1141 for (nTab = rTab; (nTab <= MAXTAB) && !bFound; nTab++)
1142 if (pTab[nTab])
1144 if (rMark.GetTableSelect(nTab))
1146 bFound = pTab[nTab]->SearchAndReplace(
1147 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1148 if (bFound)
1150 rCol = nCol;
1151 rRow = nRow;
1152 rTab = nTab;
1154 else
1155 ScDocument::GetSearchAndReplaceStart(
1156 rSearchItem, nCol, nRow );
1162 return bFound;
1165 // Outline anpassen
1167 BOOL ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, BOOL bShow )
1169 if ( ValidTab(nTab) && pTab[nTab] )
1170 return pTab[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
1172 DBG_ERROR("missing tab");
1173 return FALSE;
1176 BOOL ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bShow )
1178 if ( ValidTab(nTab) && pTab[nTab] )
1179 return pTab[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
1181 DBG_ERROR("missing tab");
1182 return FALSE;
1185 void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, BOOL bKeepQuery)
1187 if ( ValidTab(nTab) && pTab[nTab] )
1189 BOOL bOldDisableIdle = IsIdleDisabled();
1190 DisableIdle( TRUE );
1191 pTab[nTab]->Sort(rSortParam, bKeepQuery);
1192 DisableIdle( bOldDisableIdle );
1196 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, BOOL bKeepSub)
1198 if ( ValidTab(nTab) && pTab[nTab] )
1199 return pTab[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
1201 DBG_ERROR("missing tab");
1202 return 0;
1206 BOOL ScDocument::ValidQuery( SCROW nRow, SCTAB nTab, const ScQueryParam& rQueryParam, BOOL* pSpecial )
1208 if ( ValidTab(nTab) && pTab[nTab] )
1209 return pTab[nTab]->ValidQuery( nRow, rQueryParam, pSpecial );
1211 DBG_ERROR("missing tab");
1212 return FALSE;
1216 void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr)
1218 if ( ValidTab(nTab) && pTab[nTab] )
1219 pTab[nTab]->GetUpperCellString( nCol, nRow, rStr );
1220 else
1221 rStr.Erase();
1224 BOOL ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
1226 if ( ValidTab(nTab) && pTab[nTab] )
1227 return pTab[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1229 DBG_ERROR("missing tab");
1230 return FALSE;
1233 BOOL ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
1235 ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
1236 BOOL bHasAutoFilter = ( pDBData != NULL );
1238 if ( pDBData )
1240 if ( pDBData->HasHeader() )
1242 SCCOL nCol;
1243 SCROW nRow;
1244 INT16 nFlag;
1246 ScQueryParam aParam;
1247 pDBData->GetQueryParam( aParam );
1248 nRow = aParam.nRow1;
1250 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
1252 nFlag = ((ScMergeFlagAttr*)
1253 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
1254 GetValue();
1256 if ( (nFlag & SC_MF_AUTO) == 0 )
1257 bHasAutoFilter = FALSE;
1260 else
1261 bHasAutoFilter = FALSE;
1264 return bHasAutoFilter;
1267 BOOL ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1268 SCTAB nTab )
1270 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1271 //if (VALIDTAB(nTab))
1272 // if (pTab[nTab])
1273 // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1275 //return FALSE;
1278 BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1279 SCTAB nTab )
1281 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1282 //if (VALIDTAB(nTab))
1283 // if (pTab[nTab])
1284 // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1286 //return FALSE;
1289 void ScDocument::UpdateDynamicEndRow(ScDBData& rDBData) const
1291 SCCOL nCol1, nCol2;
1292 SCROW nRow1, nRow2;
1293 SCTAB nTab;
1294 rDBData.GetArea(nTab, nCol1, nRow1, nCol2, nRow2);
1295 SCCOL nCol1a = nCol1, nCol2a = nCol2;
1296 SCROW nRow1a = nRow1, nRow2a = nRow2;
1297 GetDataArea(nTab, nCol1a, nRow1a, nCol2a, nRow2a, false);
1298 rDBData.SetDynamicEndRow(nRow2a);
1302 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox
1305 BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScStrCollection& rStrings, bool bFilter )
1307 if ( ValidTab(nTab) && pTab[nTab] && pDBCollection )
1309 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE); //!??
1310 if (pDBData)
1312 UpdateDynamicEndRow(*pDBData);
1313 SCTAB nAreaTab;
1314 SCCOL nStartCol;
1315 SCROW nStartRow;
1316 SCCOL nEndCol;
1317 SCROW nEndRow;
1318 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1319 if (pDBData->HasHeader())
1320 ++nStartRow;
1322 ScQueryParam aParam;
1323 pDBData->GetQueryParam( aParam );
1324 nEndRow = aParam.nDynamicEndRow;
1325 rStrings.SetCaseSensitive( aParam.bCaseSens );
1327 // return all filter entries, if a filter condition is connected with a boolean OR
1328 if ( bFilter )
1330 SCSIZE nEntryCount = aParam.GetEntryCount();
1331 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1333 ScQueryEntry& rEntry = aParam.GetEntry(i);
1334 if ( rEntry.eConnect != SC_AND )
1336 bFilter = false;
1337 break;
1342 if ( bFilter )
1344 pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings );
1346 else
1348 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
1351 return TRUE;
1355 return FALSE;
1359 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog
1362 BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
1363 SCTAB nTab, TypedScStrCollection& rStrings )
1365 if ( ValidTab(nTab) && pTab[nTab] )
1367 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
1368 return TRUE;
1371 return FALSE;
1375 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
1378 BOOL ScDocument::GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
1379 TypedScStrCollection& rStrings, BOOL bLimit )
1381 if( !bLimit )
1383 /* Try to generate the list from list validation. This part is skipped,
1384 if bLimit==TRUE, because in that case this function is called to get
1385 cell values for auto completion on input. */
1386 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
1387 if( nValidation )
1389 const ScValidationData* pData = GetValidationEntry( nValidation );
1390 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
1391 return TRUE;
1395 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1396 //if (ValidTab(nTab) && pTab[nTab])
1397 // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1399 //return FALSE;
1403 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
1406 // Funktionen werden als 1 schon vom InputHandler eingefuegt
1407 #define SC_STRTYPE_NAMES 2
1408 #define SC_STRTYPE_DBNAMES 3
1409 #define SC_STRTYPE_HEADERS 4
1411 BOOL ScDocument::GetFormulaEntries( TypedScStrCollection& rStrings )
1413 USHORT i;
1416 // Bereichsnamen
1419 if ( pRangeName )
1421 USHORT nRangeCount = pRangeName->GetCount();
1422 for ( i=0; i<nRangeCount; i++ )
1424 ScRangeData* pData = (*pRangeName)[i];
1425 if (pData)
1427 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES );
1428 if ( !rStrings.Insert(pNew) )
1429 delete pNew;
1435 // Datenbank-Bereiche
1438 if ( pDBCollection )
1440 USHORT nDBCount = pDBCollection->GetCount();
1441 for ( i=0; i<nDBCount; i++ )
1443 ScDBData* pData = (*pDBCollection)[i];
1444 if (pData)
1446 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES );
1447 if ( !rStrings.Insert(pNew) )
1448 delete pNew;
1454 // Inhalte von Beschriftungsbereichen
1457 ScRangePairList* pLists[2];
1458 pLists[0] = GetColNameRanges();
1459 pLists[1] = GetRowNameRanges();
1460 for (USHORT nListNo=0; nListNo<2; nListNo++)
1462 ScRangePairList* pList = pLists[nListNo];
1463 if (pList)
1464 for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() )
1466 ScRange aRange = pPair->GetRange(0);
1467 ScCellIterator aIter( this, aRange );
1468 for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
1469 if ( pCell->HasStringData() )
1471 String aStr = pCell->GetStringData();
1472 TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS );
1473 if ( !rStrings.Insert(pNew) )
1474 delete pNew;
1479 return TRUE;
1483 BOOL ScDocument::IsEmbedded() const
1485 return bIsEmbedded;
1488 void ScDocument::GetEmbedded( ScRange& rRange ) const
1490 rRange = aEmbedRange;
1493 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
1495 Rectangle aRect;
1496 ScTable* pTable = pTab[aEmbedRange.aStart.Tab()];
1497 if (!pTable)
1499 DBG_ERROR("GetEmbeddedRect ohne Tabelle");
1501 else
1503 SCCOL i;
1505 for (i=0; i<aEmbedRange.aStart.Col(); i++)
1506 aRect.Left() += pTable->GetColWidth(i);
1507 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
1508 aRect.Right() = aRect.Left();
1509 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
1510 aRect.Right() += pTable->GetColWidth(i);
1511 aRect.Bottom() = aRect.Top();
1512 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
1514 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
1515 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
1516 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
1517 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
1519 return aRect;
1522 void ScDocument::SetEmbedded( const ScRange& rRange )
1524 bIsEmbedded = TRUE;
1525 aEmbedRange = rRange;
1528 void ScDocument::ResetEmbedded()
1530 bIsEmbedded = FALSE;
1531 aEmbedRange = ScRange();
1534 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect )
1536 ScTable* pTable = pTab[nTab];
1537 if (!pTable)
1539 DBG_ERROR("GetRange ohne Tabelle");
1540 return ScRange();
1543 Rectangle aPosRect = rMMRect;
1544 if ( IsNegativePage( nTab ) )
1545 ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values
1547 long nSize;
1548 long nTwips;
1549 long nAdd;
1550 BOOL bEnd;
1552 nSize = 0;
1553 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
1555 SCCOL nX1 = 0;
1556 bEnd = FALSE;
1557 while (!bEnd)
1559 nAdd = (long) pTable->GetColWidth(nX1);
1560 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
1562 nSize += nAdd;
1563 ++nX1;
1565 else
1566 bEnd = TRUE;
1569 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
1571 SCCOL nX2 = nX1;
1572 bEnd = FALSE;
1573 while (!bEnd)
1575 nAdd = (long) pTable->GetColWidth(nX2);
1576 if (nSize+nAdd < nTwips && nX2<MAXCOL)
1578 nSize += nAdd;
1579 ++nX2;
1581 else
1582 bEnd = TRUE;
1586 nSize = 0;
1587 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
1589 SCROW nY1 = 0;
1590 bEnd = FALSE;
1591 for (SCROW i = nY1; i <= MAXROW && !bEnd; ++i)
1593 if (pTable->RowHidden(i))
1594 continue;
1596 nY1 = i;
1597 nAdd = static_cast<long>(pTable->GetRowHeight(i));
1598 if (nSize+nAdd <= nTwips+1 && nY1<MAXROW)
1600 nSize += nAdd;
1601 ++nY1;
1603 else
1604 bEnd = TRUE;
1606 if (!bEnd)
1607 nY1 = MAXROW; // all hidden down to the bottom
1609 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
1611 SCROW nY2 = nY1;
1612 bEnd = FALSE;
1613 for (SCROW i = nY2; i <= MAXROW && !bEnd; ++i)
1615 nY2 = i;
1616 nAdd = static_cast<long>(pTable->GetRowHeight(i));
1617 if (nSize+nAdd < nTwips && nY2<MAXROW)
1619 nSize += nAdd;
1620 ++nY2;
1622 else
1623 bEnd = TRUE;
1625 if (!bEnd)
1626 nY2 = MAXROW; // all hidden down to the bottom
1628 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
1631 void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm)
1633 bIsEmbedded = TRUE;
1634 aEmbedRange = GetRange( nVisibleTab, rRect );
1637 // VisArea auf Zellgrenzen anpassen
1639 void lcl_SnapHor( ScTable* pTable, long& rVal, SCCOL& rStartCol )
1641 SCCOL nCol = 0;
1642 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1643 long nSnap = 0;
1644 while ( nCol<MAXCOL )
1646 long nAdd = pTable->GetColWidth(nCol);
1647 if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
1649 nSnap += nAdd;
1650 ++nCol;
1652 else
1653 break;
1655 rVal = (long) ( nSnap * HMM_PER_TWIPS );
1656 rStartCol = nCol;
1659 void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow )
1661 SCROW nRow = 0;
1662 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1663 long nSnap = 0;
1665 bool bFound = false;
1666 for (SCROW i = nRow; i <= MAXROW; ++i)
1668 SCROW nLastRow;
1669 if (pTable->RowHidden(i, NULL, &nLastRow))
1671 i = nLastRow;
1672 continue;
1675 nRow = i;
1676 long nAdd = pTable->GetRowHeight(i);
1677 if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
1679 nSnap += nAdd;
1680 ++nRow;
1682 else
1684 bFound = true;
1685 break;
1688 if (!bFound)
1689 nRow = MAXROW; // all hidden down to the bottom
1691 rVal = (long) ( nSnap * HMM_PER_TWIPS );
1692 rStartRow = nRow;
1695 void ScDocument::SnapVisArea( Rectangle& rRect ) const
1697 ScTable* pTable = pTab[nVisibleTab];
1698 if (!pTable)
1700 DBG_ERROR("SetEmbedded ohne Tabelle");
1701 return;
1704 BOOL bNegativePage = IsNegativePage( nVisibleTab );
1705 if ( bNegativePage )
1706 ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values
1708 SCCOL nCol = 0;
1709 lcl_SnapHor( pTable, rRect.Left(), nCol );
1710 ++nCol; // mindestens eine Spalte
1711 lcl_SnapHor( pTable, rRect.Right(), nCol );
1713 SCROW nRow = 0;
1714 lcl_SnapVer( pTable, rRect.Top(), nRow );
1715 ++nRow; // mindestens eine Zeile
1716 lcl_SnapVer( pTable, rRect.Bottom(), nRow );
1718 if ( bNegativePage )
1719 ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
1722 ScDocProtection* ScDocument::GetDocProtection() const
1724 return pDocProtection.get();
1727 void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
1729 if (pProtect)
1730 pDocProtection.reset(new ScDocProtection(*pProtect));
1731 else
1732 pDocProtection.reset(NULL);
1735 BOOL ScDocument::IsDocProtected() const
1737 return pDocProtection.get() && pDocProtection->isProtected();
1740 BOOL ScDocument::IsDocEditable() const
1742 // import into read-only document is possible
1743 return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
1746 BOOL ScDocument::IsTabProtected( SCTAB nTab ) const
1748 if (VALIDTAB(nTab) && pTab[nTab])
1749 return pTab[nTab]->IsProtected();
1751 DBG_ERROR("Falsche Tabellennummer");
1752 return FALSE;
1755 ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
1757 if (VALIDTAB(nTab) && pTab[nTab])
1758 return pTab[nTab]->GetProtection();
1760 return NULL;
1763 void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
1765 if (!ValidTab(nTab))
1766 return;
1768 pTab[nTab]->SetProtection(pProtect);
1771 void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
1773 if (!ValidTab(nTabSrc) || !ValidTab(nTabDest))
1774 return;
1776 pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() );
1779 const ScDocOptions& ScDocument::GetDocOptions() const
1781 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
1782 return *pDocOptions;
1785 void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
1787 USHORT d,m,y;
1789 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
1790 *pDocOptions = rOpt;
1791 rOpt.GetDate( d,m,y );
1793 SvNumberFormatter* pFormatter = xPoolHelper->GetFormTable();
1794 pFormatter->ChangeNullDate( d,m,y );
1795 pFormatter->ChangeStandardPrec( (USHORT)rOpt.GetStdPrecision() );
1796 pFormatter->SetYear2000( rOpt.GetYear2000() );
1797 SetGrammar( rOpt.GetFormulaSyntax() );
1799 // Update the separators.
1800 ScCompiler::UpdateSeparatorsNative(
1801 rOpt.GetFormulaSepArg(), rOpt.GetFormulaSepArrayCol(), rOpt.GetFormulaSepArrayRow());
1804 const ScViewOptions& ScDocument::GetViewOptions() const
1806 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1807 return *pViewOptions;
1810 void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
1812 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1813 *pViewOptions = rOpt;
1816 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
1818 rLatin = eLanguage;
1819 rCjk = eCjkLanguage;
1820 rCtl = eCtlLanguage;
1823 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
1825 eLanguage = eLatin;
1826 eCjkLanguage = eCjk;
1827 eCtlLanguage = eCtl;
1828 if ( xPoolHelper.isValid() )
1830 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
1831 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
1832 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
1833 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
1836 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool
1839 void ScDocument::SetDrawDefaults()
1841 bSetDrawDefaults = TRUE;
1842 UpdateDrawDefaults();
1845 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow,
1846 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
1848 if (!ValidTab(nTab) || !pTab[nTab])
1850 DBG_ERROR("GetMMRect: falsche Tabelle");
1851 return Rectangle(0,0,0,0);
1854 SCCOL i;
1855 Rectangle aRect;
1857 for (i=0; i<nStartCol; i++)
1858 aRect.Left() += GetColWidth(i,nTab);
1859 aRect.Top() += FastGetRowHeight( 0, nStartRow-1, nTab);
1861 aRect.Right() = aRect.Left();
1862 aRect.Bottom() = aRect.Top();
1864 for (i=nStartCol; i<=nEndCol; i++)
1865 aRect.Right() += GetColWidth(i,nTab);
1866 aRect.Bottom() += FastGetRowHeight( nStartRow, nEndRow, nTab);
1868 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
1869 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
1870 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
1871 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
1873 if ( IsNegativePage( nTab ) )
1874 ScDrawLayer::MirrorRectRTL( aRect );
1876 return aRect;
1879 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
1881 delete pExtDocOptions;
1882 pExtDocOptions = pNewOptions;
1885 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1886 SCCOL nEndCol, SCROW nEndRow )
1888 String aEmpty;
1889 String aTotal;
1890 String aCellStr;
1891 SCCOL nCol;
1892 SCROW nRow;
1893 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
1894 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1896 GetString(nCol,nRow,nTab,aCellStr);
1897 if (aCellStr.Len())
1899 if (aTotal.Len())
1900 aTotal += ' ';
1901 aTotal += aCellStr;
1903 if (nCol != nStartCol || nRow != nStartRow)
1904 SetString(nCol,nRow,nTab,aEmpty);
1907 SetString(nStartCol,nStartRow,nTab,aTotal);
1910 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1911 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
1913 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
1914 ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
1916 if ( nEndCol > nStartCol )
1917 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
1918 if ( nEndRow > nStartRow )
1919 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
1920 if ( nEndCol > nStartCol && nEndRow > nStartRow )
1921 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1923 // remove all covered notes (removed captions are collected by drawing undo if active)
1924 USHORT nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS);
1925 if( nStartCol < nEndCol )
1926 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
1927 if( nStartRow < nEndRow )
1928 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
1931 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
1933 const ScMergeAttr* pAttr = (const ScMergeAttr*)
1934 GetAttr( nCol, nRow, nTab, ATTR_MERGE );
1936 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
1937 return;
1939 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
1940 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
1942 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1944 const ScMergeAttr* pDefAttr = (const ScMergeAttr*)
1945 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE );
1946 ApplyAttr( nCol, nRow, nTab, *pDefAttr );
1949 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
1950 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1952 if ( ValidTab(nTab) && pTab[nTab] )
1953 pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
1956 void ScDocument::IncSizeRecalcLevel( SCTAB nTab )
1958 if ( ValidTab(nTab) && pTab[nTab] )
1959 pTab[nTab]->IncRecalcLevel();
1962 void ScDocument::DecSizeRecalcLevel( SCTAB nTab )
1964 if ( ValidTab(nTab) && pTab[nTab] )
1965 pTab[nTab]->DecRecalcLevel();