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