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