re-enabled user-defined numeric fields for dBase export
[LibreOffice.git] / sc / source / core / data / documen3.cxx
blob1b64286481a8dd7ba3c90679ea69c34220722e22
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
21 #include "scitems.hxx"
22 #include <editeng/langitem.hxx>
23 #include <svl/srchitem.hxx>
24 #include <sfx2/linkmgr.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/objsh.hxx>
27 #include <svl/zforlist.hxx>
28 #include <svl/PasswordHelper.hxx>
29 #include <vcl/svapp.hxx>
30 #include "document.hxx"
31 #include "attrib.hxx"
32 #include "cell.hxx"
33 #include "table.hxx"
34 #include "rangenam.hxx"
35 #include "dbdata.hxx"
36 #include "pivot.hxx"
37 #include "docpool.hxx"
38 #include "poolhelp.hxx"
39 #include "autoform.hxx"
40 #include "rangelst.hxx"
41 #include "chartarr.hxx"
42 #include "chartlock.hxx"
43 #include "refupdat.hxx"
44 #include "docoptio.hxx"
45 #include "viewopti.hxx"
46 #include "scextopt.hxx"
47 #include "brdcst.hxx"
48 #include "bcaslot.hxx"
49 #include "tablink.hxx"
50 #include "externalrefmgr.hxx"
51 #include "markdata.hxx"
52 #include "validat.hxx"
53 #include "dociter.hxx"
54 #include "detdata.hxx"
55 #include "detfunc.hxx"
56 #include "inputopt.hxx" // GetExpandRefs
57 #include "chartlis.hxx"
58 #include "sc.hrc" // SID_LINK
59 #include "hints.hxx"
60 #include "dpobject.hxx"
61 #include "drwlayer.hxx"
62 #include "unoreflist.hxx"
63 #include "listenercalls.hxx"
64 #include "dpshttab.hxx"
65 #include "dpcache.hxx"
66 #include "tabprotection.hxx"
67 #include "formulaparserpool.hxx"
68 #include "clipparam.hxx"
69 #include "sheetevents.hxx"
70 #include "colorscale.hxx"
71 #include "queryentry.hxx"
72 #include "formulacell.hxx"
74 #include "globalnames.hxx"
75 #include <memory>
77 using namespace com::sun::star;
79 namespace {
81 void sortAndRemoveDuplicates(std::vector<ScTypedStrData>& rStrings, bool bCaseSens)
83 if (bCaseSens)
85 std::sort(rStrings.begin(), rStrings.end(), ScTypedStrData::LessCaseSensitive());
86 std::vector<ScTypedStrData>::iterator it =
87 std::unique(rStrings.begin(), rStrings.end(), ScTypedStrData::EqualCaseSensitive());
88 rStrings.erase(it, rStrings.end());
90 else
92 std::sort(rStrings.begin(), rStrings.end(), ScTypedStrData::LessCaseInsensitive());
93 std::vector<ScTypedStrData>::iterator it =
94 std::unique(rStrings.begin(), rStrings.end(), ScTypedStrData::EqualCaseInsensitive());
95 rStrings.erase(it, rStrings.end());
101 void ScDocument::GetAllTabRangeNames(ScRangeName::TabNameCopyMap& rNames) const
103 ScRangeName::TabNameCopyMap aNames;
104 for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i)
106 if (!maTabs[i])
107 // no more tables to iterate through.
108 break;
110 const ScRangeName* p = maTabs[i]->GetRangeName();
111 if (!p || p->empty())
112 // ignore empty ones.
113 continue;
115 aNames.insert(ScRangeName::TabNameCopyMap::value_type(i, p));
117 rNames.swap(aNames);
120 void ScDocument::SetAllRangeNames( const boost::ptr_map<OUString, ScRangeName>& rRangeMap)
122 OUString aGlobalStr(STR_GLOBAL_RANGE_NAME);
123 boost::ptr_map<OUString,ScRangeName>::const_iterator itr = rRangeMap.begin(), itrEnd = rRangeMap.end();
124 for (; itr!=itrEnd; ++itr)
126 if (itr->first == aGlobalStr)
128 delete pRangeName;
129 const ScRangeName* pName = itr->second;
130 if (pName->empty())
131 pRangeName = NULL;
132 else
133 pRangeName = new ScRangeName( *pName );
135 else
137 const ScRangeName* pName = itr->second;
138 SCTAB nTab;
139 GetTable(itr->first, nTab);
140 if (pName->empty())
141 SetRangeName( nTab, NULL );
142 else
143 SetRangeName( nTab, new ScRangeName( *pName ) );
148 void ScDocument::GetTabRangeNameMap(std::map<OUString, ScRangeName*>& aRangeNameMap)
150 for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i)
152 if (!maTabs[i])
153 continue;
154 ScRangeName* p = maTabs[i]->GetRangeName();
155 if (!p )
157 p = new ScRangeName();
158 SetRangeName(i, p);
160 OUString aTableName;
161 maTabs[i]->GetName(aTableName);
162 aRangeNameMap.insert(std::pair<OUString, ScRangeName*>(aTableName,p));
166 void ScDocument::GetRangeNameMap(std::map<OUString, ScRangeName*>& aRangeNameMap)
168 GetTabRangeNameMap(aRangeNameMap);
169 if (!pRangeName)
171 pRangeName = new ScRangeName();
173 OUString aGlobal(STR_GLOBAL_RANGE_NAME);
174 aRangeNameMap.insert(std::pair<OUString, ScRangeName*>(aGlobal, pRangeName));
177 ScRangeName* ScDocument::GetRangeName(SCTAB nTab) const
179 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
180 return NULL;
182 return maTabs[nTab]->GetRangeName();
185 ScRangeName* ScDocument::GetRangeName() const
187 if (!pRangeName)
188 pRangeName = new ScRangeName;
189 return pRangeName;
192 void ScDocument::SetRangeName(SCTAB nTab, ScRangeName* pNew)
194 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
195 return;
197 return maTabs[nTab]->SetRangeName(pNew);
200 void ScDocument::SetRangeName( ScRangeName* pNewRangeName )
202 delete pRangeName;
203 pRangeName = pNewRangeName;
207 const ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, OUString* pName ) const
209 const ScRangeData* pData = NULL;
210 if ( pRangeName )
212 pData = pRangeName->findByRange( rBlock );
213 if (pData && pName)
214 *pName = pData->GetName();
216 return pData;
219 ScDBCollection* ScDocument::GetDBCollection() const
221 return pDBCollection;
224 void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, bool bRemoveAutoFilter )
226 if (pDBCollection && bRemoveAutoFilter)
228 // remove auto filter attribute if new db data don't contain auto filter flag
229 // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo!
231 ScDBCollection::NamedDBs& rNamedDBs = pDBCollection->getNamedDBs();
232 ScDBCollection::NamedDBs::const_iterator itr = rNamedDBs.begin(), itrEnd = rNamedDBs.end();
233 for (; itr != itrEnd; ++itr)
235 const ScDBData& rOldData = *itr;
236 if (!rOldData.HasAutoFilter())
237 continue;
239 ScRange aOldRange;
240 rOldData.GetArea(aOldRange);
242 bool bFound = false;
243 if (pNewDBCollection)
245 ScDBData* pNewData = pNewDBCollection->getNamedDBs().findByUpperName(rOldData.GetUpperName());
246 if (pNewData)
248 if (pNewData->HasAutoFilter())
250 ScRange aNewRange;
251 pNewData->GetArea(aNewRange);
252 if (aOldRange.aStart == aNewRange.aStart)
253 bFound = true;
258 if (!bFound)
260 aOldRange.aEnd.SetRow(aOldRange.aStart.Row());
261 RemoveFlagsTab( aOldRange.aStart.Col(), aOldRange.aStart.Row(),
262 aOldRange.aEnd.Col(), aOldRange.aEnd.Row(),
263 aOldRange.aStart.Tab(), SC_MF_AUTO );
264 RepaintRange( aOldRange );
269 delete pDBCollection;
271 pDBCollection = pNewDBCollection;
274 const ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
276 if (pDBCollection)
277 return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
278 else
279 return NULL;
282 ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly)
284 if (pDBCollection)
285 return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
286 else
287 return NULL;
290 const ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
292 if (pDBCollection)
293 return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
294 else
295 return NULL;
298 ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
300 if (pDBCollection)
301 return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
302 else
303 return NULL;
306 bool ScDocument::HasPivotTable() const
308 return pDPCollection && pDPCollection->GetCount();
311 ScDPCollection* ScDocument::GetDPCollection()
313 if (!pDPCollection)
314 pDPCollection = new ScDPCollection(this);
315 return pDPCollection;
318 const ScDPCollection* ScDocument::GetDPCollection() const
320 return pDPCollection;
323 ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
325 if (!pDPCollection)
326 return NULL;
328 sal_uInt16 nCount = pDPCollection->GetCount();
329 ScAddress aPos( nCol, nRow, nTab );
330 for (sal_uInt16 i=0; i<nCount; i++)
331 if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) )
332 return (*pDPCollection)[i];
334 return NULL;
337 ScDPObject* ScDocument::GetDPAtBlock( const ScRange & rBlock ) const
339 if (!pDPCollection)
340 return NULL;
342 /* Walk the collection in reverse order to get something of an
343 * approximation of MS Excels 'most recent' effect. */
344 sal_uInt16 i = pDPCollection->GetCount();
345 while ( i-- > 0 )
346 if ( (*pDPCollection)[i]->GetOutRange().In( rBlock ) )
347 return (*pDPCollection)[i];
349 return NULL;
352 ScChartCollection* ScDocument::GetChartCollection() const
354 return pChartCollection;
357 void ScDocument::StopTemporaryChartLock()
359 if( apTemporaryChartLock.get() )
360 apTemporaryChartLock->StopLocking();
363 ScChartListenerCollection* ScDocument::GetChartListenerCollection() const
365 return pChartListenerCollection;
368 void ScDocument::SetChartListenerCollection(
369 ScChartListenerCollection* pNewChartListenerCollection,
370 bool bSetChartRangeLists )
372 ScChartListenerCollection* pOld = pChartListenerCollection;
373 pChartListenerCollection = pNewChartListenerCollection;
374 if ( pChartListenerCollection )
376 if ( pOld )
377 pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists );
378 pChartListenerCollection->StartAllListeners();
380 delete pOld;
383 void ScDocument::SetScenario( SCTAB nTab, bool bFlag )
385 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
386 maTabs[nTab]->SetScenario(bFlag);
389 bool ScDocument::IsScenario( SCTAB nTab ) const
391 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] &&maTabs[nTab]->IsScenario();
394 void ScDocument::SetScenarioData( SCTAB nTab, const OUString& rComment,
395 const Color& rColor, sal_uInt16 nFlags )
397 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
399 maTabs[nTab]->SetScenarioComment( rComment );
400 maTabs[nTab]->SetScenarioColor( rColor );
401 maTabs[nTab]->SetScenarioFlags( nFlags );
405 Color ScDocument::GetTabBgColor( SCTAB nTab ) const
407 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
408 return maTabs[nTab]->GetTabBgColor();
409 return Color(COL_AUTO);
412 void ScDocument::SetTabBgColor( SCTAB nTab, const Color& rColor )
414 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
415 maTabs[nTab]->SetTabBgColor(rColor);
418 bool ScDocument::IsDefaultTabBgColor( SCTAB nTab ) const
420 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
421 return maTabs[nTab]->GetTabBgColor() == COL_AUTO;
422 return true;
425 void ScDocument::GetScenarioData( SCTAB nTab, OUString& rComment,
426 Color& rColor, sal_uInt16& rFlags ) const
428 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
430 maTabs[nTab]->GetScenarioComment( rComment );
431 rColor = maTabs[nTab]->GetScenarioColor();
432 rFlags = maTabs[nTab]->GetScenarioFlags();
436 void ScDocument::GetScenarioFlags( SCTAB nTab, sal_uInt16& rFlags ) const
438 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
439 rFlags = maTabs[nTab]->GetScenarioFlags();
442 bool ScDocument::IsLinked( SCTAB nTab ) const
444 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsLinked();
445 // euqivalent to
446 //if (ValidTab(nTab) && pTab[nTab])
447 // return pTab[nTab]->IsLinked();
448 //return false;
451 formula::FormulaGrammar::AddressConvention ScDocument::GetAddressConvention() const
453 return formula::FormulaGrammar::extractRefConvention(eGrammar);
456 formula::FormulaGrammar::Grammar ScDocument::GetGrammar() const
458 return eGrammar;
461 void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram )
463 eGrammar = eGram;
466 sal_uInt8 ScDocument::GetLinkMode( SCTAB nTab ) const
468 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
469 return maTabs[nTab]->GetLinkMode();
470 return SC_LINK_NONE;
473 const OUString ScDocument::GetLinkDoc( SCTAB nTab ) const
475 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
476 return maTabs[nTab]->GetLinkDoc();
477 return OUString();
480 const OUString ScDocument::GetLinkFlt( SCTAB nTab ) const
482 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
483 return maTabs[nTab]->GetLinkFlt();
484 return OUString();
487 const OUString ScDocument::GetLinkOpt( SCTAB nTab ) const
489 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
490 return maTabs[nTab]->GetLinkOpt();
491 return OUString();
494 const OUString ScDocument::GetLinkTab( SCTAB nTab ) const
496 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
497 return maTabs[nTab]->GetLinkTab();
498 return OUString();
501 sal_uLong ScDocument::GetLinkRefreshDelay( SCTAB nTab ) const
503 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
504 return maTabs[nTab]->GetLinkRefreshDelay();
505 return 0;
508 void ScDocument::SetLink( SCTAB nTab, sal_uInt8 nMode, const OUString& rDoc,
509 const OUString& rFilter, const OUString& rOptions,
510 const OUString& rTabName, sal_uLong nRefreshDelay )
512 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
513 maTabs[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName, nRefreshDelay );
516 bool ScDocument::HasLink( const OUString& rDoc,
517 const OUString& rFilter, const OUString& rOptions ) const
519 SCTAB nCount = static_cast<SCTAB>(maTabs.size());
520 for (SCTAB i=0; i<nCount; i++)
521 if (maTabs[i]->IsLinked()
522 && maTabs[i]->GetLinkDoc() == rDoc
523 && maTabs[i]->GetLinkFlt() == rFilter
524 && maTabs[i]->GetLinkOpt() == rOptions)
525 return true;
527 return false;
530 bool ScDocument::LinkExternalTab( SCTAB& rTab, const OUString& aDocTab,
531 const OUString& aFileName, const OUString& aTabName )
533 if ( IsClipboard() )
535 OSL_FAIL( "LinkExternalTab in Clipboard" );
536 return false;
538 rTab = 0;
539 OUString aFilterName; // wird vom Loader gefuellt
540 OUString aOptions; // Filter-Optionen
541 sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0;
542 ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 );
543 if ( aLoader.IsError() )
544 return false;
545 ScDocument* pSrcDoc = aLoader.GetDocument();
547 // Tabelle kopieren
548 SCTAB nSrcTab;
549 if ( pSrcDoc->GetTable( aTabName, nSrcTab ) )
551 if ( !InsertTab( SC_TAB_APPEND, aDocTab, true ) )
553 OSL_FAIL("can't insert external document table");
554 return false;
556 rTab = GetTableCount() - 1;
557 // nicht neu einfuegen, nur Ergebnisse
558 TransferTab( pSrcDoc, nSrcTab, rTab, false, true );
560 else
561 return false;
563 sal_uLong nRefreshDelay = 0;
565 bool bWasThere = HasLink( aFileName, aFilterName, aOptions );
566 SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName, nRefreshDelay );
567 if ( !bWasThere ) // Link pro Quelldokument nur einmal eintragen
569 ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions, nRefreshDelay );
570 pLink->SetInCreate( true );
571 String aFilName = aFilterName;
572 GetLinkManager()->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, OUString(aFileName),
573 &aFilName );
574 pLink->Update();
575 pLink->SetInCreate( false );
576 SfxBindings* pBindings = GetViewBindings();
577 if (pBindings)
578 pBindings->Invalidate( SID_LINKS );
580 return true;
583 ScExternalRefManager* ScDocument::GetExternalRefManager() const
585 ScDocument* pThis = const_cast<ScDocument*>(this);
586 if (!pExternalRefMgr.get())
587 pThis->pExternalRefMgr.reset( new ScExternalRefManager( pThis));
589 return pExternalRefMgr.get();
592 bool ScDocument::IsInExternalReferenceMarking() const
594 return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking();
597 void ScDocument::MarkUsedExternalReferences()
599 if (!pExternalRefMgr.get())
600 return;
601 if (!pExternalRefMgr->hasExternalData())
602 return;
603 // Charts.
604 pExternalRefMgr->markUsedByLinkListeners();
605 // Formula cells.
606 pExternalRefMgr->markUsedExternalRefCells();
608 /* NOTE: Conditional formats and validation objects are marked when
609 * collecting them during export. */
612 ScFormulaParserPool& ScDocument::GetFormulaParserPool() const
614 if( !mxFormulaParserPool.get() )
615 mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) );
616 return *mxFormulaParserPool;
619 const ScSheetEvents* ScDocument::GetSheetEvents( SCTAB nTab ) const
621 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
622 return maTabs[nTab]->GetSheetEvents();
623 return NULL;
626 void ScDocument::SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew )
628 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
629 maTabs[nTab]->SetSheetEvents( pNew );
632 bool ScDocument::HasSheetEventScript( SCTAB nTab, sal_Int32 nEvent, bool bWithVbaEvents ) const
634 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
636 // check if any event handler script has been configured
637 const ScSheetEvents* pEvents = maTabs[nTab]->GetSheetEvents();
638 if ( pEvents && pEvents->GetScript( nEvent ) )
639 return true;
640 // check if VBA event handlers exist
641 if (bWithVbaEvents && mxVbaEvents.is()) try
643 uno::Sequence< uno::Any > aArgs( 1 );
644 aArgs[ 0 ] <<= nTab;
645 if (mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs ) ||
646 mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaDocumentEventId( nEvent ), uno::Sequence< uno::Any >() ))
647 return true;
649 catch( uno::Exception& )
653 return false;
656 bool ScDocument::HasAnySheetEventScript( sal_Int32 nEvent, bool bWithVbaEvents ) const
658 SCTAB nSize = static_cast<SCTAB>(maTabs.size());
659 for (SCTAB nTab = 0; nTab < nSize; nTab++)
660 if (HasSheetEventScript( nTab, nEvent, bWithVbaEvents ))
661 return true;
662 return false;
665 bool ScDocument::HasAnyCalcNotification() const
667 SCTAB nSize = static_cast<SCTAB>(maTabs.size());
668 for (SCTAB nTab = 0; nTab < nSize; nTab++)
669 if (maTabs[nTab] && maTabs[nTab]->GetCalcNotification())
670 return true;
671 return false;
674 bool ScDocument::HasCalcNotification( SCTAB nTab ) const
676 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
677 return maTabs[nTab]->GetCalcNotification();
678 return false;
681 void ScDocument::SetCalcNotification( SCTAB nTab )
683 // set only if not set before
684 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && !maTabs[nTab]->GetCalcNotification())
685 maTabs[nTab]->SetCalcNotification(true);
688 void ScDocument::ResetCalcNotifications()
690 SCTAB nSize = static_cast<SCTAB>(maTabs.size());
691 for (SCTAB nTab = 0; nTab < nSize; nTab++)
692 if (maTabs[nTab] && maTabs[nTab]->GetCalcNotification())
693 maTabs[nTab]->SetCalcNotification(false);
696 ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, bool bCreate )
698 ScOutlineTable* pVal = NULL;
700 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
701 if (maTabs[nTab])
703 pVal = maTabs[nTab]->GetOutlineTable();
704 if (!pVal)
705 if (bCreate)
707 maTabs[nTab]->StartOutlineTable();
708 pVal = maTabs[nTab]->GetOutlineTable();
712 return pVal;
715 bool ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline )
717 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->SetOutlineTable(pNewOutline);
720 void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow,
721 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
723 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
724 maTabs[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
727 bool ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam )
729 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->TestRemoveSubTotals( rParam );
732 void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
734 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
735 maTabs[nTab]->RemoveSubTotals( rParam );
738 bool ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
740 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->DoSubTotals( rParam );
743 bool ScDocument::HasSubTotalCells( const ScRange& rRange )
745 ScCellIterator aIter( this, rRange );
746 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
748 if (aIter.getType() != CELLTYPE_FORMULA)
749 continue;
751 if (aIter.getFormulaCell()->IsSubTotal())
752 return true;
754 return false; // none found
757 // kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc
758 // auch Zellen stehen, nach pDestDoc
760 void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
762 SCTAB nCount = static_cast<SCTAB>(maTabs.size());
763 for (SCTAB nTab=0; nTab<nCount; nTab++)
764 if (maTabs[nTab] && pPosDoc->maTabs[nTab] && pDestDoc->maTabs[nTab])
765 maTabs[nTab]->CopyUpdated( pPosDoc->maTabs[nTab], pDestDoc->maTabs[nTab] );
768 void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, bool bNewScenario )
770 if (ValidTab(nSrcTab) && ValidTab(nDestTab) && nSrcTab < static_cast<SCTAB>(maTabs.size())
771 && nDestTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab] && maTabs[nDestTab])
773 // Flags fuer aktive Szenarios richtig setzen
774 // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben
776 ScRangeList aRanges = *maTabs[nSrcTab]->GetScenarioRanges();
778 // nDestTab ist die Zieltabelle
779 for ( SCTAB nTab = nDestTab+1;
780 nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario();
781 nTab++ )
783 if ( maTabs[nTab]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist
785 bool bTouched = false;
786 for ( size_t nR=0, nRangeCount = aRanges.size(); nR < nRangeCount && !bTouched; nR++ )
788 const ScRange* pRange = aRanges[ nR ];
789 if ( maTabs[nTab]->HasScenarioRange( *pRange ) )
790 bTouched = true;
792 if (bTouched)
794 maTabs[nTab]->SetActiveScenario(false);
795 if ( maTabs[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
796 maTabs[nTab]->CopyScenarioFrom( maTabs[nDestTab] );
801 maTabs[nSrcTab]->SetActiveScenario(true); // da kommt's her...
802 if (!bNewScenario) // Daten aus dem ausgewaehlten Szenario kopieren
804 bool bOldAutoCalc = GetAutoCalc();
805 SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
806 maTabs[nSrcTab]->CopyScenarioTo( maTabs[nDestTab] );
807 SetDirty();
808 SetAutoCalc( bOldAutoCalc );
813 void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark,
814 bool bResetMark, sal_uInt16 nNeededBits ) const
816 if (bResetMark)
817 rDestMark.ResetMark();
819 if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
820 maTabs[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
822 rDestMark.SetAreaTab( nDestTab );
825 bool ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const
827 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->HasScenarioRange( rRange );
830 const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const
832 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
833 return maTabs[nTab]->GetScenarioRanges();
835 return NULL;
838 bool ScDocument::IsActiveScenario( SCTAB nTab ) const
840 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsActiveScenario( );
843 void ScDocument::SetActiveScenario( SCTAB nTab, bool bActive )
845 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
846 maTabs[nTab]->SetActiveScenario( bActive );
849 bool ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const
851 if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size())
852 && nDestTab < static_cast<SCTAB>(maTabs.size())&& ValidTab(nDestTab))
853 return maTabs[nSrcTab]->TestCopyScenarioTo( maTabs[nDestTab] );
855 OSL_FAIL("wrong table at TestCopyScenario");
856 return false;
859 void ScDocument::AddUnoObject( SfxListener& rObject )
861 if (!pUnoBroadcaster)
862 pUnoBroadcaster = new SfxBroadcaster;
864 rObject.StartListening( *pUnoBroadcaster );
867 void ScDocument::RemoveUnoObject( SfxListener& rObject )
869 if (pUnoBroadcaster)
871 rObject.EndListening( *pUnoBroadcaster );
873 if ( bInUnoBroadcast )
875 // Broadcasts from ScDocument::BroadcastUno are the only way that
876 // uno object methods are called without holding a reference.
878 // If RemoveUnoObject is called from an object dtor in the finalizer thread
879 // while the main thread is calling BroadcastUno, the dtor thread must wait
880 // (or the object's Notify might try to access a deleted object).
881 // The SolarMutex can't be locked here because if a component is called from
882 // a VCL event, the main thread has the SolarMutex locked all the time.
884 // This check is done after calling EndListening, so a later BroadcastUno call
885 // won't touch this object.
887 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
888 if ( rSolarMutex.tryToAcquire() )
890 // BroadcastUno is always called with the SolarMutex locked, so if it
891 // can be acquired, this is within the same thread (should not happen)
892 OSL_FAIL( "RemoveUnoObject called from BroadcastUno" );
893 rSolarMutex.release();
895 else
897 // let the thread that called BroadcastUno continue
898 while ( bInUnoBroadcast )
900 osl::Thread::yield();
905 else
907 OSL_FAIL("No Uno broadcaster");
911 void ScDocument::BroadcastUno( const SfxHint &rHint )
913 if (pUnoBroadcaster)
915 bInUnoBroadcast = true;
916 pUnoBroadcaster->Broadcast( rHint );
917 bInUnoBroadcast = false;
919 // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
920 // The listener calls must be processed after completing the broadcast,
921 // because they can add or remove objects from pUnoBroadcaster.
923 if ( pUnoListenerCalls && rHint.ISA( SfxSimpleHint ) &&
924 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DATACHANGED &&
925 !bInUnoListenerCall )
927 // Listener calls may lead to BroadcastUno calls again. The listener calls
928 // are not nested, instead the calls are collected in the list, and the
929 // outermost call executes them all.
931 ScChartLockGuard aChartLockGuard(this);
932 bInUnoListenerCall = true;
933 pUnoListenerCalls->ExecuteAndClear();
934 bInUnoListenerCall = false;
939 void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener,
940 const lang::EventObject& rEvent )
942 OSL_ENSURE( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
944 if ( !pUnoListenerCalls )
945 pUnoListenerCalls = new ScUnoListenerCalls;
946 pUnoListenerCalls->Add( rListener, rEvent );
949 void ScDocument::BeginUnoRefUndo()
951 OSL_ENSURE( !pUnoRefUndoList, "BeginUnoRefUndo twice" );
952 delete pUnoRefUndoList;
954 pUnoRefUndoList = new ScUnoRefList;
957 ScUnoRefList* ScDocument::EndUnoRefUndo()
959 ScUnoRefList* pRet = pUnoRefUndoList;
960 pUnoRefUndoList = NULL;
961 return pRet; // must be deleted by caller!
964 void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
966 if ( pUnoRefUndoList )
967 pUnoRefUndoList->Add( nId, rOldRanges );
970 sal_Int64 ScDocument::GetNewUnoId()
972 return ++nUnoObjectId;
975 void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
976 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
977 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
978 SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
979 ScDocument* pUndoDoc, bool bIncludeDraw,
980 bool bUpdateNoteCaptionPos )
982 PutInOrder( nCol1, nCol2 );
983 PutInOrder( nRow1, nRow2 );
984 PutInOrder( nTab1, nTab2 );
985 if (ValidTab(nTab1) && ValidTab(nTab2))
987 bool bExpandRefsOld = IsExpandRefs();
988 if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
989 SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
990 SCTAB i;
991 SCTAB iMax;
992 if ( eUpdateRefMode == URM_COPY )
994 i = nTab1;
995 iMax = nTab2;
997 else
999 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1000 xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
1001 xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
1002 pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
1003 if (pRangeName)
1004 pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
1005 if ( pDPCollection )
1006 pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
1007 UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
1008 UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz );
1009 if ( pValidationList )
1010 pValidationList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
1011 if ( pDetOpList )
1012 pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
1013 if ( pUnoBroadcaster )
1014 pUnoBroadcaster->Broadcast( ScUpdateRefHint(
1015 eUpdateRefMode, aRange, nDx, nDy, nDz ) );
1016 i = 0;
1017 iMax = static_cast<SCTAB>(maTabs.size())-1;
1019 for ( ; i<=iMax && i < static_cast<SCTAB>(maTabs.size()); i++)
1020 if (maTabs[i])
1021 maTabs[i]->UpdateReference(
1022 eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
1023 nDx, nDy, nDz, pUndoDoc, bIncludeDraw, bUpdateNoteCaptionPos );
1025 if ( bIsEmbedded )
1027 SCCOL theCol1;
1028 SCROW theRow1;
1029 SCTAB theTab1;
1030 SCCOL theCol2;
1031 SCROW theRow2;
1032 SCTAB theTab2;
1033 theCol1 = aEmbedRange.aStart.Col();
1034 theRow1 = aEmbedRange.aStart.Row();
1035 theTab1 = aEmbedRange.aStart.Tab();
1036 theCol2 = aEmbedRange.aEnd.Col();
1037 theRow2 = aEmbedRange.aEnd.Row();
1038 theTab2 = aEmbedRange.aEnd.Tab();
1039 if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
1040 nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
1042 aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
1045 SetExpandRefs( bExpandRefsOld );
1047 // after moving, no clipboard move ref-updates are possible
1048 if ( eUpdateRefMode != URM_COPY && IsClipboardSource() )
1050 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
1051 if (pClipDoc)
1052 pClipDoc->GetClipParam().mbCutMode = false;
1057 void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
1058 const ScMarkData& rMark, ScDocument* pUndoDoc )
1060 OSL_ENSURE(pClipDoc->bIsClip, "UpdateTranspose: No Clip");
1062 ScRange aSource;
1063 ScClipParam& rClipParam = GetClipParam();
1064 if (!rClipParam.maRanges.empty())
1065 aSource = *rClipParam.maRanges.front();
1066 ScAddress aDest = rDestPos;
1068 SCTAB nClipTab = 0;
1069 for (SCTAB nDestTab=0; nDestTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nDestTab]; nDestTab++)
1070 if (rMark.GetTableSelect(nDestTab))
1072 while (!pClipDoc->maTabs[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
1073 aSource.aStart.SetTab( nClipTab );
1074 aSource.aEnd.SetTab( nClipTab );
1075 aDest.SetTab( nDestTab );
1077 // wie UpdateReference
1078 if (pRangeName)
1079 pRangeName->UpdateTranspose( aSource, aDest ); // vor den Zellen!
1080 for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
1081 if (maTabs[i])
1082 maTabs[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
1084 nClipTab = (nClipTab+1) % (MAXTAB+1);
1088 void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1090 //! pDBCollection
1091 //! pPivotCollection
1092 //! UpdateChartRef
1094 if (pRangeName)
1095 pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
1097 for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()) && maTabs[i]; i++)
1098 maTabs[i]->UpdateGrow( rArea, nGrowX, nGrowY );
1101 void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScProgress* pProgress, const ScMarkData& rMark,
1102 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1103 double nStepValue, double nMaxValue)
1105 PutInOrder( nCol1, nCol2 );
1106 PutInOrder( nRow1, nRow2 );
1107 SCTAB nMax = maTabs.size();
1108 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1109 for (; itr != itrEnd && *itr < nMax; ++itr)
1110 if (maTabs[*itr])
1111 maTabs[*itr]->Fill(nCol1, nRow1, nCol2, nRow2,
1112 nFillCount, eFillDir, eFillCmd, eFillDateCmd,
1113 nStepValue, nMaxValue, pProgress);
1116 OUString ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
1118 SCTAB nTab = rSource.aStart.Tab();
1119 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1120 return maTabs[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
1122 return OUString();
1125 void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1126 sal_uInt16 nFormatNo, const ScMarkData& rMark )
1128 PutInOrder( nStartCol, nEndCol );
1129 PutInOrder( nStartRow, nEndRow );
1130 SCTAB nMax = maTabs.size();
1131 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1132 for (; itr != itrEnd && *itr < nMax; ++itr)
1133 if (maTabs[*itr])
1134 maTabs[*itr]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
1137 void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1138 ScAutoFormatData& rData)
1140 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
1142 if (maTabs[nTab])
1144 PutInOrder(nStartCol, nEndCol);
1145 PutInOrder(nStartRow, nEndRow);
1146 maTabs[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
1151 void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
1152 SCCOL& rCol, SCROW& rRow )
1154 sal_uInt16 nCommand = rSearchItem.GetCommand();
1155 bool bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE ||
1156 nCommand == SVX_SEARCHCMD_REPLACE_ALL );
1157 if ( rSearchItem.GetBackward() )
1159 if ( rSearchItem.GetRowDirection() )
1161 if ( rSearchItem.GetPattern() )
1163 rCol = MAXCOL;
1164 rRow = MAXROW+1;
1166 else if ( bReplace )
1168 rCol = MAXCOL;
1169 rRow = MAXROW;
1171 else
1173 rCol = MAXCOL+1;
1174 rRow = MAXROW;
1177 else
1179 if ( rSearchItem.GetPattern() )
1181 rCol = MAXCOL+1;
1182 rRow = MAXROW;
1184 else if ( bReplace )
1186 rCol = MAXCOL;
1187 rRow = MAXROW;
1189 else
1191 rCol = MAXCOL;
1192 rRow = MAXROW+1;
1196 else
1198 if ( rSearchItem.GetRowDirection() )
1200 if ( rSearchItem.GetPattern() )
1202 rCol = 0;
1203 rRow = (SCROW) -1;
1205 else if ( bReplace )
1207 rCol = 0;
1208 rRow = 0;
1210 else
1212 rCol = (SCCOL) -1;
1213 rRow = 0;
1216 else
1218 if ( rSearchItem.GetPattern() )
1220 rCol = (SCCOL) -1;
1221 rRow = 0;
1223 else if ( bReplace )
1225 rCol = 0;
1226 rRow = 0;
1228 else
1230 rCol = 0;
1231 rRow = (SCROW) -1;
1237 bool ScDocument::SearchAndReplace(
1238 const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
1239 const ScMarkData& rMark, ScRangeList& rMatchedRanges,
1240 OUString& rUndoStr, ScDocument* pUndoDoc)
1242 //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!!
1244 bool bFound = false;
1245 if (rTab >= static_cast<SCTAB>(maTabs.size()))
1246 OSL_FAIL("table out of range");
1247 if (ValidTab(rTab))
1249 SCCOL nCol;
1250 SCROW nRow;
1251 SCTAB nTab;
1252 sal_uInt16 nCommand = rSearchItem.GetCommand();
1253 if ( nCommand == SVX_SEARCHCMD_FIND_ALL ||
1254 nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1256 SCTAB nMax = maTabs.size();
1257 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1258 for (; itr != itrEnd && *itr < nMax; ++itr)
1259 if (maTabs[*itr])
1261 nCol = 0;
1262 nRow = 0;
1263 bFound |= maTabs[*itr]->SearchAndReplace(
1264 rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1267 // Markierung wird innen schon komplett gesetzt
1269 else
1271 nCol = rCol;
1272 nRow = rRow;
1273 if (rSearchItem.GetBackward())
1275 for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--)
1276 if (maTabs[nTab])
1278 if (rMark.GetTableSelect(nTab))
1280 bFound = maTabs[nTab]->SearchAndReplace(
1281 rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1282 if (bFound)
1284 rCol = nCol;
1285 rRow = nRow;
1286 rTab = nTab;
1288 else
1289 ScDocument::GetSearchAndReplaceStart(
1290 rSearchItem, nCol, nRow );
1294 else
1296 for (nTab = rTab; (nTab < static_cast<SCTAB>(maTabs.size())) && !bFound; nTab++)
1297 if (maTabs[nTab])
1299 if (rMark.GetTableSelect(nTab))
1301 bFound = maTabs[nTab]->SearchAndReplace(
1302 rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1303 if (bFound)
1305 rCol = nCol;
1306 rRow = nRow;
1307 rTab = nTab;
1309 else
1310 ScDocument::GetSearchAndReplaceStart(
1311 rSearchItem, nCol, nRow );
1317 return bFound;
1320 // Outline anpassen
1322 bool ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bShow )
1324 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1325 return maTabs[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
1327 OSL_FAIL("missing tab");
1328 return false;
1331 bool ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bShow )
1333 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1334 return maTabs[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
1336 OSL_FAIL("missing tab");
1337 return false;
1340 void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress)
1342 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1344 bool bOldEnableIdle = IsIdleEnabled();
1345 EnableIdle(false);
1346 maTabs[nTab]->Sort(rSortParam, bKeepQuery, pProgress);
1347 EnableIdle(bOldEnableIdle);
1351 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, bool bKeepSub)
1353 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1354 return maTabs[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
1356 OSL_FAIL("missing tab");
1357 return 0;
1361 void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rStr)
1363 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1364 maTabs[nTab]->GetUpperCellString( nCol, nRow, rStr );
1365 else
1366 rStr = OUString();
1369 bool ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
1371 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1372 return maTabs[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1374 OSL_FAIL("missing tab");
1375 return false;
1378 bool ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
1380 const ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
1381 bool bHasAutoFilter = (pDBData != NULL);
1383 if ( pDBData )
1385 if ( pDBData->HasHeader() )
1387 SCCOL nCol;
1388 SCROW nRow;
1389 sal_Int16 nFlag;
1391 ScQueryParam aParam;
1392 pDBData->GetQueryParam( aParam );
1393 nRow = aParam.nRow1;
1395 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
1397 nFlag = ((ScMergeFlagAttr*)
1398 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
1399 GetValue();
1401 if ( (nFlag & SC_MF_AUTO) == 0 )
1402 bHasAutoFilter = false;
1405 else
1406 bHasAutoFilter = false;
1409 return bHasAutoFilter;
1412 bool ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1413 SCTAB nTab )
1415 return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1418 bool ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1419 SCTAB nTab )
1421 return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1425 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox
1428 bool ScDocument::GetFilterEntries(
1429 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, std::vector<ScTypedStrData>& rStrings, bool& rHasDates)
1431 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && pDBCollection )
1433 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, false); //!??
1434 if (pDBData)
1436 pDBData->ExtendDataArea(this);
1437 SCTAB nAreaTab;
1438 SCCOL nStartCol;
1439 SCROW nStartRow;
1440 SCCOL nEndCol;
1441 SCROW nEndRow;
1442 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1444 if (pDBData->HasHeader())
1445 ++nStartRow;
1447 ScQueryParam aParam;
1448 pDBData->GetQueryParam( aParam );
1450 // return all filter entries, if a filter condition is connected with a boolean OR
1451 if ( bFilter )
1453 SCSIZE nEntryCount = aParam.GetEntryCount();
1454 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1456 ScQueryEntry& rEntry = aParam.GetEntry(i);
1457 if ( rEntry.eConnect != SC_AND )
1459 bFilter = false;
1460 break;
1465 if ( bFilter )
1467 maTabs[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
1469 else
1471 maTabs[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1474 sortAndRemoveDuplicates(rStrings, aParam.bCaseSens);
1475 return true;
1479 return false;
1483 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog
1486 bool ScDocument::GetFilterEntriesArea(
1487 SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bCaseSens,
1488 std::vector<ScTypedStrData>& rStrings, bool& rHasDates)
1490 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1492 maTabs[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1493 sortAndRemoveDuplicates(rStrings, bCaseSens);
1494 return true;
1497 return false;
1501 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
1504 bool ScDocument::GetDataEntries(
1505 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bCaseSens,
1506 std::vector<ScTypedStrData>& rStrings, bool bLimit )
1508 if( !bLimit )
1510 /* Try to generate the list from list validation. This part is skipped,
1511 if bLimit==true, because in that case this function is called to get
1512 cell values for auto completion on input. */
1513 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
1514 if( nValidation )
1516 const ScValidationData* pData = GetValidationEntry( nValidation );
1517 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
1519 if (pData->GetListType() == ValidListType::SORTEDASCENDING)
1520 sortAndRemoveDuplicates(rStrings, bCaseSens);
1522 return true;
1527 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()))
1528 return false;
1530 if (!maTabs[nTab])
1531 return false;
1533 std::set<ScTypedStrData> aStrings;
1534 bool bRet = maTabs[nTab]->GetDataEntries(nCol, nRow, aStrings, bLimit);
1535 rStrings.insert(rStrings.end(), aStrings.begin(), aStrings.end());
1536 sortAndRemoveDuplicates(rStrings, bCaseSens);
1538 return bRet;
1542 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
1545 bool ScDocument::GetFormulaEntries( ScTypedCaseStrSet& rStrings )
1548 // Bereichsnamen
1551 if ( pRangeName )
1553 ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
1554 for (; itr != itrEnd; ++itr)
1555 rStrings.insert(ScTypedStrData(itr->second->GetName(), 0.0, ScTypedStrData::Name));
1559 // Datenbank-Bereiche
1562 if ( pDBCollection )
1564 const ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs();
1565 ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
1566 for (; itr != itrEnd; ++itr)
1567 rStrings.insert(ScTypedStrData(itr->GetName(), 0.0, ScTypedStrData::DbName));
1571 // Inhalte von Beschriftungsbereichen
1574 ScRangePairList* pLists[2];
1575 pLists[0] = GetColNameRanges();
1576 pLists[1] = GetRowNameRanges();
1577 for (sal_uInt16 nListNo=0; nListNo<2; nListNo++)
1579 ScRangePairList* pList = pLists[ nListNo ];
1580 if (!pList)
1581 continue;
1583 for ( size_t i = 0, nPairs = pList->size(); i < nPairs; ++i )
1585 ScRangePair* pPair = (*pList)[i];
1586 ScRange aRange = pPair->GetRange(0);
1587 ScCellIterator aIter( this, aRange );
1588 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
1590 if (!aIter.hasString())
1591 continue;
1593 OUString aStr = aIter.getString();
1594 rStrings.insert(ScTypedStrData(aStr, 0.0, ScTypedStrData::Header));
1599 return true;
1603 bool ScDocument::IsEmbedded() const
1605 return bIsEmbedded;
1608 void ScDocument::GetEmbedded( ScRange& rRange ) const
1610 rRange = aEmbedRange;
1613 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
1615 Rectangle aRect;
1616 ScTable* pTable = NULL;
1617 if ( aEmbedRange.aStart.Tab() < static_cast<SCTAB>(maTabs.size()) )
1618 pTable = maTabs[aEmbedRange.aStart.Tab()];
1619 else
1620 OSL_FAIL("table out of range");
1621 if (!pTable)
1623 OSL_FAIL("GetEmbeddedRect without a table");
1625 else
1627 SCCOL i;
1629 for (i=0; i<aEmbedRange.aStart.Col(); i++)
1630 aRect.Left() += pTable->GetColWidth(i);
1631 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
1632 aRect.Right() = aRect.Left();
1633 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
1634 aRect.Right() += pTable->GetColWidth(i);
1635 aRect.Bottom() = aRect.Top();
1636 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
1638 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
1639 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
1640 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
1641 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
1643 return aRect;
1646 void ScDocument::SetEmbedded( const ScRange& rRange )
1648 bIsEmbedded = true;
1649 aEmbedRange = rRange;
1652 void ScDocument::ResetEmbedded()
1654 bIsEmbedded = false;
1655 aEmbedRange = ScRange();
1659 /** Similar to ScViewData::AddPixelsWhile(), but add height twips and only
1660 while result is less than nStopTwips.
1661 @return true if advanced at least one row.
1663 static bool lcl_AddTwipsWhile( long & rTwips, long nStopTwips, SCROW & rPosY, SCROW nEndRow, const ScTable * pTable, bool bHiddenAsZero = true )
1665 SCROW nRow = rPosY;
1666 bool bAdded = false;
1667 bool bStop = false;
1668 while (rTwips < nStopTwips && nRow <= nEndRow && !bStop)
1670 SCROW nHeightEndRow;
1671 sal_uInt16 nHeight = pTable->GetRowHeight( nRow, NULL, &nHeightEndRow, bHiddenAsZero );
1672 if (nHeightEndRow > nEndRow)
1673 nHeightEndRow = nEndRow;
1674 if (!nHeight)
1675 nRow = nHeightEndRow + 1;
1676 else
1678 SCROW nRows = nHeightEndRow - nRow + 1;
1679 sal_Int64 nAdd = static_cast<sal_Int64>(nHeight) * nRows;
1680 if (nAdd + rTwips >= nStopTwips)
1682 sal_Int64 nDiff = nAdd + rTwips - nStopTwips;
1683 nRows -= static_cast<SCROW>(nDiff / nHeight);
1684 nAdd = static_cast<sal_Int64>(nHeight) * nRows;
1685 // We're looking for a value that satisfies loop condition.
1686 if (nAdd + rTwips >= nStopTwips)
1688 --nRows;
1689 nAdd -= nHeight;
1691 bStop = true;
1693 rTwips += static_cast<long>(nAdd);
1694 nRow += nRows;
1697 if (nRow > rPosY)
1699 --nRow;
1700 bAdded = true;
1702 rPosY = nRow;
1703 return bAdded;
1706 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect, bool bHiddenAsZero ) const
1708 ScTable* pTable = NULL;
1709 if (nTab < static_cast<SCTAB>(maTabs.size()))
1710 pTable = maTabs[nTab];
1711 else
1712 OSL_FAIL("table out of range");
1713 if (!pTable)
1715 OSL_FAIL("GetRange without a table");
1716 return ScRange();
1719 Rectangle aPosRect = rMMRect;
1720 if ( IsNegativePage( nTab ) )
1721 ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values
1723 long nSize;
1724 long nTwips;
1725 long nAdd;
1726 bool bEnd;
1728 nSize = 0;
1729 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
1731 SCCOL nX1 = 0;
1732 bEnd = false;
1733 while (!bEnd)
1735 nAdd = (long) pTable->GetColWidth(nX1, bHiddenAsZero);
1736 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
1738 nSize += nAdd;
1739 ++nX1;
1741 else
1742 bEnd = true;
1745 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
1747 SCCOL nX2 = nX1;
1748 bEnd = false;
1749 while (!bEnd)
1751 nAdd = (long) pTable->GetColWidth(nX2, bHiddenAsZero);
1752 if (nSize+nAdd < nTwips && nX2<MAXCOL)
1754 nSize += nAdd;
1755 ++nX2;
1757 else
1758 bEnd = true;
1762 nSize = 0;
1763 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
1765 SCROW nY1 = 0;
1766 // Was if(nSize+nAdd<=nTwips+1) inside loop => if(nSize+nAdd<nTwips+2)
1767 if (lcl_AddTwipsWhile( nSize, nTwips+2, nY1, MAXROW, pTable, bHiddenAsZero) && nY1 < MAXROW)
1768 ++nY1; // original loop ended on last matched +1 unless that was MAXROW
1770 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
1772 SCROW nY2 = nY1;
1773 // Was if(nSize+nAdd<nTwips) inside loop => if(nSize+nAdd<nTwips)
1774 if (lcl_AddTwipsWhile( nSize, nTwips, nY2, MAXROW, pTable, bHiddenAsZero) && nY2 < MAXROW)
1775 ++nY2; // original loop ended on last matched +1 unless that was MAXROW
1777 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
1780 void ScDocument::SetEmbedded( SCTAB nTab, const Rectangle& rRect ) // aus VisArea (1/100 mm)
1782 bIsEmbedded = true;
1783 aEmbedRange = GetRange( nTab, rRect );
1786 ScDocProtection* ScDocument::GetDocProtection() const
1788 return pDocProtection.get();
1791 void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
1793 if (pProtect)
1794 pDocProtection.reset(new ScDocProtection(*pProtect));
1795 else
1796 pDocProtection.reset(NULL);
1799 bool ScDocument::IsDocProtected() const
1801 return pDocProtection.get() && pDocProtection->isProtected();
1804 bool ScDocument::IsDocEditable() const
1806 // import into read-only document is possible
1807 return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
1810 bool ScDocument::IsTabProtected( SCTAB nTab ) const
1812 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1813 return maTabs[nTab]->IsProtected();
1815 OSL_FAIL("Wrong table number");
1816 return false;
1819 ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
1821 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1822 return maTabs[nTab]->GetProtection();
1824 return NULL;
1827 void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
1829 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()))
1830 return;
1832 maTabs[nTab]->SetProtection(pProtect);
1835 void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
1837 if (!ValidTab(nTabSrc) || nTabSrc >= static_cast<SCTAB>(maTabs.size()) || nTabDest >= static_cast<SCTAB>(maTabs.size()) || !ValidTab(nTabDest))
1838 return;
1840 maTabs[nTabDest]->SetProtection( maTabs[nTabSrc]->GetProtection() );
1843 const ScDocOptions& ScDocument::GetDocOptions() const
1845 OSL_ENSURE( pDocOptions, "No DocOptions! :-(" );
1846 return *pDocOptions;
1849 void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
1851 OSL_ENSURE( pDocOptions, "No DocOptions! :-(" );
1853 *pDocOptions = rOpt;
1854 xPoolHelper->SetFormTableOpt(rOpt);
1857 const ScViewOptions& ScDocument::GetViewOptions() const
1859 OSL_ENSURE( pViewOptions, "No ViewOptions! :-(" );
1860 return *pViewOptions;
1863 void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
1865 OSL_ENSURE( pViewOptions, "No ViewOptions! :-(" );
1866 *pViewOptions = rOpt;
1869 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
1871 rLatin = eLanguage;
1872 rCjk = eCjkLanguage;
1873 rCtl = eCtlLanguage;
1876 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
1878 eLanguage = eLatin;
1879 eCjkLanguage = eCjk;
1880 eCtlLanguage = eCtl;
1881 if ( xPoolHelper.is() )
1883 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
1884 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
1885 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
1886 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
1889 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool
1892 void ScDocument::SetDrawDefaults()
1894 bSetDrawDefaults = true;
1895 UpdateDrawDefaults();
1898 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero ) const
1900 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
1902 OSL_FAIL("GetMMRect: wrong table");
1903 return Rectangle(0,0,0,0);
1906 SCCOL i;
1907 Rectangle aRect;
1909 for (i=0; i<nStartCol; i++)
1910 aRect.Left() += GetColWidth(i,nTab, bHiddenAsZero );
1911 aRect.Top() += GetRowHeight( 0, nStartRow-1, nTab, bHiddenAsZero );
1913 aRect.Right() = aRect.Left();
1914 aRect.Bottom() = aRect.Top();
1916 for (i=nStartCol; i<=nEndCol; i++)
1917 aRect.Right() += GetColWidth(i,nTab, bHiddenAsZero);
1918 aRect.Bottom() += GetRowHeight( nStartRow, nEndRow, nTab, bHiddenAsZero );
1920 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
1921 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
1922 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
1923 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
1925 if ( IsNegativePage( nTab ) )
1926 ScDrawLayer::MirrorRectRTL( aRect );
1928 return aRect;
1931 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
1933 delete pExtDocOptions;
1934 pExtDocOptions = pNewOptions;
1937 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1938 SCCOL nEndCol, SCROW nEndRow )
1940 OUString aEmpty;
1941 OUStringBuffer aTotal;
1942 OUString aCellStr;
1943 SCCOL nCol;
1944 SCROW nRow;
1945 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
1946 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1948 aCellStr = GetString(nCol, nRow, nTab);
1949 if (!aCellStr.isEmpty())
1951 if (aTotal.getLength())
1952 aTotal.append(' ');
1953 aTotal.append(aCellStr);
1955 if (nCol != nStartCol || nRow != nStartRow)
1956 SetString(nCol,nRow,nTab,aEmpty);
1959 SetString(nStartCol,nStartRow,nTab,aTotal.makeStringAndClear());
1962 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1963 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
1965 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
1966 ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
1968 if ( nEndCol > nStartCol )
1969 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
1970 if ( nEndRow > nStartRow )
1971 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
1972 if ( nEndCol > nStartCol && nEndRow > nStartRow )
1973 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1975 // remove all covered notes (removed captions are collected by drawing undo if active)
1976 sal_uInt16 nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS);
1977 if( nStartCol < nEndCol )
1978 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
1979 if( nStartRow < nEndRow )
1980 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
1983 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
1985 const ScMergeAttr* pAttr = (const ScMergeAttr*)
1986 GetAttr( nCol, nRow, nTab, ATTR_MERGE );
1988 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
1989 return;
1991 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
1992 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
1994 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1996 const ScMergeAttr* pDefAttr = (const ScMergeAttr*)
1997 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE );
1998 ApplyAttr( nCol, nRow, nTab, *pDefAttr );
2001 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
2002 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow ) const
2004 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2005 maTabs[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
2008 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */