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