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 #define _ZFORLIST_DECLARE_TABLE
30 #include "scitems.hxx"
31 #include <editeng/eeitem.hxx>
32
33 #include <editeng/boxitem.hxx>
34 #include <editeng/frmdiritem.hxx>
35 #include <svx/pageitem.hxx>
36 #include <editeng/editeng.hxx>
37 #include <svx/svditer.hxx>
38 #include <svx/svdpage.hxx>
39 #include <svx/svdocapt.hxx>
40 #include <sfx2/app.hxx>
41 #include <sfx2/objsh.hxx>
42 #include <svl/poolcach.hxx>
43 #include <unotools/saveopt.hxx>
44 #include <svl/zforlist.hxx>
45 #include <unotools/charclass.hxx>
46 #include <unotools/transliterationwrapper.hxx>
47 #include <tools/tenccvt.hxx>
48 #include <svx/sdrundomanager.hxx>
49
50 #include <com/sun/star/text/WritingMode2.hpp>
51 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
52 #include <com/sun/star/sheet/TablePageBreakData.hpp>
53
54 #include "document.hxx"
55 #include "table.hxx"
56 #include "attrib.hxx"
57 #include "attarray.hxx"
58 #include "markarr.hxx"
59 #include "patattr.hxx"
60 #include "rangenam.hxx"
61 #include "poolhelp.hxx"
62 #include "docpool.hxx"
63 #include "stlpool.hxx"
64 #include "stlsheet.hxx"
65 #include "globstr.hrc"
66 #include "rechead.hxx"
67 #include "dbcolect.hxx"
68 #include "pivot.hxx"
69 #include "chartlis.hxx"
70 #include "rangelst.hxx"
71 #include "markdata.hxx"
72 #include "drwlayer.hxx"
73 #include "conditio.hxx"
74 #include "validat.hxx"
75 #include "prnsave.hxx"
76 #include "chgtrack.hxx"
77 #include "sc.hrc"
78 #include "scresid.hxx"
79 #include "hints.hxx"
80 #include "detdata.hxx"
81 #include "cell.hxx"
82 #include "dpobject.hxx"
83 #include "detfunc.hxx" // for UpdateAllComments
84 #include "scmod.hxx"
85 #include "dociter.hxx"
86 #include "progress.hxx"
87 #include "autonamecache.hxx"
88 #include "bcaslot.hxx"
89 #include "postit.hxx"
90 #include "externalrefmgr.hxx"
91 #include "tabprotection.hxx"
92 #include "clipparam.hxx"
93
94 #include <map>
95 #include <limits>
96
97 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
98 using ::com::sun::star::uno::Sequence;
99 using ::com::sun::star::sheet::TablePageBreakData;
100 using ::std::set;
101
102 struct ScDefaultAttr
103 {
104 const ScPatternAttr* pAttr;
105 SCROW nFirst;
106 SCSIZE nCount;
ScDefaultAttrScDefaultAttr107 ScDefaultAttr(const ScPatternAttr* pPatAttr) : pAttr(pPatAttr), nFirst(0), nCount(0) {}
108 };
109
110 struct ScLessDefaultAttr
111 {
operator ()ScLessDefaultAttr112 sal_Bool operator() (const ScDefaultAttr& rValue1, const ScDefaultAttr& rValue2) const
113 {
114 return rValue1.pAttr < rValue2.pAttr;
115 }
116 };
117
118 typedef std::set<ScDefaultAttr, ScLessDefaultAttr> ScDefaultAttrSet;
119
MakeTable(SCTAB nTab,bool _bNeedsNameCheck)120 void ScDocument::MakeTable( SCTAB nTab,bool _bNeedsNameCheck )
121 {
122 if ( ValidTab(nTab) && !pTab[nTab] )
123 {
124 String aString = ScGlobal::GetRscString(STR_TABLE_DEF); //"Tabelle"
125 aString += String::CreateFromInt32(nTab+1);
126 if ( _bNeedsNameCheck )
127 CreateValidTabName( aString ); // keine doppelten
128
129 pTab[nTab] = new ScTable(this, nTab, aString);
130 pTab[nTab]->SetLoadingMedium(bLoadingMedium);
131 ++nMaxTableNumber;
132 }
133 }
134
135
HasTable(SCTAB nTab) const136 sal_Bool ScDocument::HasTable( SCTAB nTab ) const
137 {
138 if (VALIDTAB(nTab))
139 if (pTab[nTab])
140 return sal_True;
141
142 return sal_False;
143 }
144
145
GetName(SCTAB nTab,String & rName) const146 sal_Bool ScDocument::GetName( SCTAB nTab, String& rName ) const
147 {
148 if (VALIDTAB(nTab))
149 if (pTab[nTab])
150 {
151 pTab[nTab]->GetName( rName );
152 return sal_True;
153 }
154 rName.Erase();
155 return sal_False;
156 }
157
SetCodeName(SCTAB nTab,const String & rName)158 sal_Bool ScDocument::SetCodeName( SCTAB nTab, const String& rName )
159 {
160 if (VALIDTAB(nTab))
161 {
162 if (pTab[nTab])
163 {
164 pTab[nTab]->SetCodeName( rName );
165 return sal_True;
166 }
167 }
168 OSL_TRACE( "**** can't set code name %s", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() );
169 return sal_False;
170 }
171
GetCodeName(SCTAB nTab,String & rName) const172 sal_Bool ScDocument::GetCodeName( SCTAB nTab, String& rName ) const
173 {
174 if (VALIDTAB(nTab))
175 if (pTab[nTab])
176 {
177 pTab[nTab]->GetCodeName( rName );
178 return sal_True;
179 }
180 rName.Erase();
181 return sal_False;
182 }
183
184
GetTable(const String & rName,SCTAB & rTab) const185 sal_Bool ScDocument::GetTable( const String& rName, SCTAB& rTab ) const
186 {
187 String aUpperName = rName;
188 ScGlobal::pCharClass->toUpper(aUpperName);
189
190 for (SCTAB i=0; i<=MAXTAB; i++)
191 if (pTab[i])
192 {
193 if ( pTab[i]->GetUpperName() == aUpperName )
194 {
195 rTab = i;
196 return sal_True;
197 }
198 }
199 rTab = 0;
200 return sal_False;
201 }
202
GetTableByIndex(sal_Int32 nIndex)203 ScTable* ScDocument::GetTableByIndex(sal_Int32 nIndex)
204 {
205 if ( nIndex <= MAXTAB && nIndex >= 0)
206 return pTab[nIndex];
207
208 return NULL;
209 }
210
ValidTabName(const String & rName) const211 sal_Bool ScDocument::ValidTabName( const String& rName ) const
212 {
213 xub_StrLen nLen = rName.Len();
214 if (!nLen)
215 return false;
216
217 #if 1
218 // Restrict sheet names to what Excel accepts.
219 /* TODO: We may want to remove this restriction for full ODFF compliance.
220 * Merely loading and calculating ODF documents using these characters in
221 * sheet names is not affected by this, but all sheet name editing and
222 * copying functionality is, maybe falling back to "Sheet4" or similar. */
223 for (xub_StrLen i = 0; i < nLen; ++i)
224 {
225 const sal_Unicode c = rName.GetChar(i);
226 switch (c)
227 {
228 case ':':
229 case '\\':
230 case '/':
231 case '?':
232 case '*':
233 case '[':
234 case ']':
235 // these characters are not allowed to match XL's convention.
236 return false;
237 case '\'':
238 if (i == 0 || i == nLen - 1)
239 // single quote is not allowed at the first or last
240 // character position.
241 return false;
242 break;
243 }
244 }
245 #endif
246
247 return true;
248 }
249
250
ValidNewTabName(const String & rName) const251 sal_Bool ScDocument::ValidNewTabName( const String& rName ) const
252 {
253 sal_Bool bValid = ValidTabName(rName);
254 for (SCTAB i=0; (i<=MAXTAB) && bValid; i++)
255 if (pTab[i])
256 {
257 String aOldName;
258 pTab[i]->GetName(aOldName);
259 bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
260 }
261 return bValid;
262 }
263
264
CreateValidTabName(String & rName) const265 void ScDocument::CreateValidTabName(String& rName) const
266 {
267 if ( !ValidTabName(rName) )
268 {
269 // neu erzeugen
270
271 const String aStrTable( ScResId(SCSTR_TABLE) );
272 sal_Bool bOk = sal_False;
273
274 // vorneweg testen, ob der Prefix als gueltig erkannt wird
275 // wenn nicht, nur doppelte vermeiden
276 sal_Bool bPrefix = ValidTabName( aStrTable );
277 DBG_ASSERT(bPrefix, "ungueltiger Tabellenname");
278 SCTAB nDummy;
279
280 SCTAB nLoops = 0; // "zur Sicherheit"
281 for ( SCTAB i = nMaxTableNumber+1; !bOk && nLoops <= MAXTAB; i++ )
282 {
283 rName = aStrTable;
284 rName += String::CreateFromInt32(i);
285 if (bPrefix)
286 bOk = ValidNewTabName( rName );
287 else
288 bOk = !GetTable( rName, nDummy );
289 ++nLoops;
290 }
291
292 DBG_ASSERT(bOk, "kein gueltiger Tabellenname gefunden");
293 if ( !bOk )
294 rName = aStrTable;
295 }
296 else
297 {
298 // uebergebenen Namen ueberpruefen
299
300 if ( !ValidNewTabName(rName) )
301 {
302 SCTAB i = 1;
303 String aName;
304 do
305 {
306 i++;
307 aName = rName;
308 aName += '_';
309 aName += String::CreateFromInt32(static_cast<sal_Int32>(i));
310 }
311 while (!ValidNewTabName(aName) && (i < MAXTAB+1));
312 rName = aName;
313 }
314 }
315 }
316
317
InsertTab(SCTAB nPos,const String & rName,sal_Bool bExternalDocument)318 sal_Bool ScDocument::InsertTab( SCTAB nPos, const String& rName,
319 sal_Bool bExternalDocument )
320 {
321 SCTAB nTabCount = GetTableCount();
322 sal_Bool bValid = ValidTab(nTabCount);
323 if ( !bExternalDocument ) // sonst rName == "'Doc'!Tab", vorher pruefen
324 bValid = (bValid && ValidNewTabName(rName));
325 if (bValid)
326 {
327 if (nPos == SC_TAB_APPEND || nPos == nTabCount)
328 {
329 pTab[nTabCount] = new ScTable(this, nTabCount, rName);
330 pTab[nTabCount]->SetCodeName( rName );
331 ++nMaxTableNumber;
332 if ( bExternalDocument )
333 pTab[nTabCount]->SetVisible( sal_False );
334 }
335 else
336 {
337 if (VALIDTAB(nPos) && (nPos < nTabCount))
338 {
339 ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
340 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
341 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
342 pRangeName->UpdateTabRef( nPos, 1 );
343 pDBCollection->UpdateReference(
344 URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
345 if (pDPCollection)
346 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
347 if (pDetOpList)
348 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
349 UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
350 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 );
351 if ( pUnoBroadcaster )
352 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
353
354 SCTAB i;
355 for (i = 0; i <= MAXTAB; i++)
356 if (pTab[i])
357 pTab[i]->UpdateInsertTab(nPos);
358
359 for (i = nTabCount; i > nPos; i--)
360 {
361 pTab[i] = pTab[i - 1];
362 }
363
364 pTab[nPos] = new ScTable(this, nPos, rName);
365 pTab[nPos]->SetCodeName( rName );
366 ++nMaxTableNumber;
367
368 // UpdateBroadcastAreas must be called between UpdateInsertTab,
369 // which ends listening, and StartAllListeners, to not modify
370 // areas that are to be inserted by starting listeners.
371 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,1);
372 for (i = 0; i <= MAXTAB; i++)
373 if (pTab[i])
374 pTab[i]->UpdateCompile();
375 for (i = 0; i <= MAXTAB; i++)
376 if (pTab[i])
377 pTab[i]->StartAllListeners();
378
379 // update conditional formats after table is inserted
380 if ( pCondFormList )
381 pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
382 if ( pValidationList )
383 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
384 // #81844# sheet names of references are not valid until sheet is inserted
385 if ( pChartListenerCollection )
386 pChartListenerCollection->UpdateScheduledSeriesRanges();
387
388 SetDirty();
389 bValid = sal_True;
390 }
391 else
392 bValid = sal_False;
393 }
394 }
395 return bValid;
396 }
397
398
DeleteTab(SCTAB nTab,ScDocument * pRefUndoDoc)399 sal_Bool ScDocument::DeleteTab( SCTAB nTab, ScDocument* pRefUndoDoc )
400 {
401 sal_Bool bValid = sal_False;
402 if (VALIDTAB(nTab))
403 {
404 if (pTab[nTab])
405 {
406 SCTAB nTabCount = GetTableCount();
407 if (nTabCount > 1)
408 {
409 sal_Bool bOldAutoCalc = GetAutoCalc();
410 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
411 ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab );
412 DelBroadcastAreasInRange( aRange );
413
414 // #i8180# remove database ranges etc. that are on the deleted tab
415 // (restored in undo with ScRefUndoData)
416
417 xColNameRanges->DeleteOnTab( nTab );
418 xRowNameRanges->DeleteOnTab( nTab );
419 pDBCollection->DeleteOnTab( nTab );
420 if (pDPCollection)
421 pDPCollection->DeleteOnTab( nTab );
422 if (pDetOpList)
423 pDetOpList->DeleteOnTab( nTab );
424 DeleteAreaLinksOnTab( nTab );
425
426 // normal reference update
427
428 aRange.aEnd.SetTab( MAXTAB );
429 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
430 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
431 pRangeName->UpdateTabRef( nTab, 2 );
432 pDBCollection->UpdateReference(
433 URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
434 if (pDPCollection)
435 pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
436 if (pDetOpList)
437 pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1 );
438 UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
439 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1 );
440 if ( pCondFormList )
441 pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
442 if ( pValidationList )
443 pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
444 if ( pUnoBroadcaster )
445 pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1 ) );
446
447 SCTAB i;
448 for (i=0; i<=MAXTAB; i++)
449 if (pTab[i])
450 pTab[i]->UpdateDeleteTab(nTab,sal_False,
451 pRefUndoDoc ? pRefUndoDoc->pTab[i] : 0);
452 delete pTab[nTab];
453 for (i=nTab + 1; i < nTabCount; i++)
454 pTab[i - 1] = pTab[i];
455 pTab[nTabCount - 1] = NULL;
456 --nMaxTableNumber;
457 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
458 // which ends listening, and StartAllListeners, to not modify
459 // areas that are to be inserted by starting listeners.
460 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1);
461 for (i = 0; i <= MAXTAB; i++)
462 if (pTab[i])
463 pTab[i]->UpdateCompile();
464 // Excel-Filter loescht einige Tables waehrend des Ladens,
465 // Listener werden erst nach dem Laden aufgesetzt
466 if ( !bInsertingFromOtherDoc )
467 {
468 for (i = 0; i <= MAXTAB; i++)
469 if (pTab[i])
470 pTab[i]->StartAllListeners();
471 SetDirty();
472 }
473 // #81844# sheet names of references are not valid until sheet is deleted
474 pChartListenerCollection->UpdateScheduledSeriesRanges();
475
476 SetAutoCalc( bOldAutoCalc );
477 bValid = sal_True;
478 }
479 }
480 }
481 return bValid;
482 }
483
484
RenameTab(SCTAB nTab,const String & rName,sal_Bool,sal_Bool bExternalDocument)485 sal_Bool ScDocument::RenameTab( SCTAB nTab, const String& rName, sal_Bool /* bUpdateRef */,
486 sal_Bool bExternalDocument )
487 {
488 sal_Bool bValid = sal_False;
489 SCTAB i;
490 if VALIDTAB(nTab)
491 if (pTab[nTab])
492 {
493 if ( bExternalDocument )
494 bValid = sal_True; // zusammengesetzter Name
495 else
496 bValid = ValidTabName(rName);
497 for (i=0; (i<=MAXTAB) && bValid; i++)
498 if (pTab[i] && (i != nTab))
499 {
500 String aOldName;
501 pTab[i]->GetName(aOldName);
502 bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
503 }
504 if (bValid)
505 {
506 // #i75258# update charts before renaming, so they can get their live data objects.
507 // Once the charts are live, the sheet can be renamed without problems.
508 if ( pChartListenerCollection )
509 pChartListenerCollection->UpdateChartsContainingTab( nTab );
510 pTab[nTab]->SetName(rName);
511
512 // If formulas refer to the renamed sheet, the TokenArray remains valid,
513 // but the XML stream must be re-generated.
514 for (i=0; i<=MAXTAB; ++i)
515 if (pTab[i] && pTab[i]->IsStreamValid())
516 pTab[i]->SetStreamValid( sal_False );
517 }
518 }
519 return bValid;
520 }
521
522
SetVisible(SCTAB nTab,sal_Bool bVisible)523 void ScDocument::SetVisible( SCTAB nTab, sal_Bool bVisible )
524 {
525 if (VALIDTAB(nTab))
526 if (pTab[nTab])
527 pTab[nTab]->SetVisible(bVisible);
528 }
529
530
IsVisible(SCTAB nTab) const531 sal_Bool ScDocument::IsVisible( SCTAB nTab ) const
532 {
533 if (VALIDTAB(nTab))
534 if (pTab[nTab])
535 return pTab[nTab]->IsVisible();
536
537 return sal_False;
538 }
539
540
IsStreamValid(SCTAB nTab) const541 sal_Bool ScDocument::IsStreamValid( SCTAB nTab ) const
542 {
543 if ( ValidTab(nTab) && pTab[nTab] )
544 return pTab[nTab]->IsStreamValid();
545
546 return sal_False;
547 }
548
549
SetStreamValid(SCTAB nTab,sal_Bool bSet,sal_Bool bIgnoreLock)550 void ScDocument::SetStreamValid( SCTAB nTab, sal_Bool bSet, sal_Bool bIgnoreLock )
551 {
552 if ( ValidTab(nTab) && pTab[nTab] )
553 pTab[nTab]->SetStreamValid( bSet, bIgnoreLock );
554 }
555
556
LockStreamValid(bool bLock)557 void ScDocument::LockStreamValid( bool bLock )
558 {
559 mbStreamValidLocked = bLock;
560 }
561
562
IsPendingRowHeights(SCTAB nTab) const563 sal_Bool ScDocument::IsPendingRowHeights( SCTAB nTab ) const
564 {
565 if ( ValidTab(nTab) && pTab[nTab] )
566 return pTab[nTab]->IsPendingRowHeights();
567
568 return sal_False;
569 }
570
571
SetPendingRowHeights(SCTAB nTab,sal_Bool bSet)572 void ScDocument::SetPendingRowHeights( SCTAB nTab, sal_Bool bSet )
573 {
574 if ( ValidTab(nTab) && pTab[nTab] )
575 pTab[nTab]->SetPendingRowHeights( bSet );
576 }
577
578
SetLayoutRTL(SCTAB nTab,sal_Bool bRTL)579 void ScDocument::SetLayoutRTL( SCTAB nTab, sal_Bool bRTL )
580 {
581 if ( ValidTab(nTab) && pTab[nTab] )
582 {
583 if ( bImportingXML )
584 {
585 // #i57869# only set the LoadingRTL flag, the real setting (including mirroring)
586 // is applied in SetImportingXML(sal_False). This is so the shapes can be loaded in
587 // normal LTR mode.
588
589 pTab[nTab]->SetLoadingRTL( bRTL );
590 return;
591 }
592
593 pTab[nTab]->SetLayoutRTL( bRTL ); // only sets the flag
594 pTab[nTab]->SetDrawPageSize();
595
596 // mirror existing objects:
597
598 if (pDrawLayer)
599 {
600 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
601 DBG_ASSERT(pPage,"Page ?");
602 if (pPage)
603 {
604 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
605 SdrObject* pObject = aIter.Next();
606 while (pObject)
607 {
608 // objects with ScDrawObjData are re-positioned in SetPageSize,
609 // don't mirror again
610 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
611 if ( !pData )
612 pDrawLayer->MirrorRTL( pObject );
613
614 pObject->SetContextWritingMode( bRTL ? WritingMode2::RL_TB : WritingMode2::LR_TB );
615
616 pObject = aIter.Next();
617 }
618 }
619 }
620 }
621 }
622
623
IsLayoutRTL(SCTAB nTab) const624 sal_Bool ScDocument::IsLayoutRTL( SCTAB nTab ) const
625 {
626 if ( ValidTab(nTab) && pTab[nTab] )
627 return pTab[nTab]->IsLayoutRTL();
628
629 return sal_False;
630 }
631
632
IsNegativePage(SCTAB nTab) const633 sal_Bool ScDocument::IsNegativePage( SCTAB nTab ) const
634 {
635 // Negative page area is always used for RTL layout.
636 // The separate method is used to find all RTL handling of drawing objects.
637 return IsLayoutRTL( nTab );
638 }
639
640
641 /* ----------------------------------------------------------------------------
642 benutzten Bereich suchen:
643
644 GetCellArea - nur Daten
645 GetTableArea - Daten / Attribute
646 GetPrintArea - beruecksichtigt auch Zeichenobjekte,
647 streicht Attribute bis ganz rechts / unten
648 ---------------------------------------------------------------------------- */
649
650
GetCellArea(SCTAB nTab,SCCOL & rEndCol,SCROW & rEndRow) const651 sal_Bool ScDocument::GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
652 {
653 if (VALIDTAB(nTab))
654 if (pTab[nTab])
655 return pTab[nTab]->GetCellArea( rEndCol, rEndRow );
656
657 rEndCol = 0;
658 rEndRow = 0;
659 return sal_False;
660 }
661
662
GetTableArea(SCTAB nTab,SCCOL & rEndCol,SCROW & rEndRow) const663 sal_Bool ScDocument::GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
664 {
665 if (VALIDTAB(nTab))
666 if (pTab[nTab])
667 return pTab[nTab]->GetTableArea( rEndCol, rEndRow );
668
669 rEndCol = 0;
670 rEndRow = 0;
671 return sal_False;
672 }
673
ShrinkToDataArea(SCTAB nTab,SCCOL & rStartCol,SCROW & rStartRow,SCCOL & rEndCol,SCROW & rEndRow) const674 bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow) const
675 {
676 if (!ValidTab(nTab) || !pTab[nTab])
677 return false;
678
679 SCCOL nCol1, nCol2;
680 SCROW nRow1, nRow2;
681 pTab[nTab]->GetFirstDataPos(nCol1, nRow1);
682 pTab[nTab]->GetLastDataPos(nCol2, nRow2);
683
684 if (nCol1 > nCol2 || nRow1 > nRow2)
685 // invalid range.
686 return false;
687
688 // Make sure the area only shrinks, and doesn't grow.
689 if (rStartCol < nCol1)
690 rStartCol = nCol1;
691 if (nCol2 < rEndCol)
692 rEndCol = nCol2;
693 if (rStartRow < nRow1)
694 rStartRow = nRow1;
695 if (nRow2 < rEndRow)
696 rEndRow = nRow2;
697
698 if (rStartCol > rEndCol || rStartRow > rEndRow)
699 // invalid range.
700 return false;
701
702 return true; // success!
703 }
704
ShrinkToUsedDataArea(bool & o_bShrunk,SCTAB nTab,SCCOL & rStartCol,SCROW & rStartRow,SCCOL & rEndCol,SCROW & rEndRow,bool bColumnsOnly) const705 bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol,
706 SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
707 {
708 if (!ValidTab(nTab) || !pTab[nTab])
709 {
710 o_bShrunk = false;
711 return false;
712 }
713 return pTab[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly);
714 }
715
716 // zusammenhaengender Bereich
717
GetDataArea(SCTAB nTab,SCCOL & rStartCol,SCROW & rStartRow,SCCOL & rEndCol,SCROW & rEndRow,sal_Bool bIncludeOld,bool bOnlyDown) const718 void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
719 SCCOL& rEndCol, SCROW& rEndRow, sal_Bool bIncludeOld, bool bOnlyDown ) const
720 {
721 if (ValidTab(nTab) && pTab[nTab])
722 pTab[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown );
723 }
724
725
LimitChartArea(SCTAB nTab,SCCOL & rStartCol,SCROW & rStartRow,SCCOL & rEndCol,SCROW & rEndRow)726 void ScDocument::LimitChartArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
727 SCCOL& rEndCol, SCROW& rEndRow )
728 {
729 if (VALIDTAB(nTab))
730 if (pTab[nTab])
731 pTab[nTab]->LimitChartArea( rStartCol, rStartRow, rEndCol, rEndRow );
732 }
733
734
LimitChartIfAll(ScRangeListRef & rRangeList)735 void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList )
736 {
737 ScRangeListRef aNew = new ScRangeList;
738 if (rRangeList.Is())
739 {
740 sal_uLong nCount = rRangeList->Count();
741 for (sal_uLong i=0; i<nCount; i++)
742 {
743 ScRange aRange(*rRangeList->GetObject( i ));
744 if ( ( aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL ) ||
745 ( aRange.aStart.Row() == 0 && aRange.aEnd.Row() == MAXROW ) )
746 {
747 SCCOL nStartCol = aRange.aStart.Col();
748 SCROW nStartRow = aRange.aStart.Row();
749 SCCOL nEndCol = aRange.aEnd.Col();
750 SCROW nEndRow = aRange.aEnd.Row();
751 SCTAB nTab = aRange.aStart.Tab();
752 if (pTab[nTab])
753 pTab[nTab]->LimitChartArea(nStartCol, nStartRow, nEndCol, nEndRow);
754 aRange.aStart.SetCol( nStartCol );
755 aRange.aStart.SetRow( nStartRow );
756 aRange.aEnd.SetCol( nEndCol );
757 aRange.aEnd.SetRow( nEndRow );
758 }
759 aNew->Append(aRange);
760 }
761 }
762 else
763 {
764 DBG_ERROR("LimitChartIfAll: Ref==0");
765 }
766 rRangeList = aNew;
767 }
768
769
lcl_GetFirstTabRange(SCTAB & rTabRangeStart,SCTAB & rTabRangeEnd,const ScMarkData * pTabMark)770 void lcl_GetFirstTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark )
771 {
772 // without ScMarkData, leave start/end unchanged
773 if ( pTabMark )
774 {
775 for (SCTAB nTab=0; nTab<=MAXTAB; ++nTab)
776 if (pTabMark->GetTableSelect(nTab))
777 {
778 // find first range of consecutive selected sheets
779 rTabRangeStart = nTab;
780 while ( nTab+1 <= MAXTAB && pTabMark->GetTableSelect(nTab+1) )
781 ++nTab;
782 rTabRangeEnd = nTab;
783 return;
784 }
785 }
786 }
787
lcl_GetNextTabRange(SCTAB & rTabRangeStart,SCTAB & rTabRangeEnd,const ScMarkData * pTabMark)788 bool lcl_GetNextTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark )
789 {
790 if ( pTabMark )
791 {
792 // find next range of consecutive selected sheets after rTabRangeEnd
793 for (SCTAB nTab=rTabRangeEnd+1; nTab<=MAXTAB; ++nTab)
794 if (pTabMark->GetTableSelect(nTab))
795 {
796 rTabRangeStart = nTab;
797 while ( nTab+1 <= MAXTAB && pTabMark->GetTableSelect(nTab+1) )
798 ++nTab;
799 rTabRangeEnd = nTab;
800 return true;
801 }
802 }
803 return false;
804 }
805
806
CanInsertRow(const ScRange & rRange) const807 sal_Bool ScDocument::CanInsertRow( const ScRange& rRange ) const
808 {
809 SCCOL nStartCol = rRange.aStart.Col();
810 SCROW nStartRow = rRange.aStart.Row();
811 SCTAB nStartTab = rRange.aStart.Tab();
812 SCCOL nEndCol = rRange.aEnd.Col();
813 SCROW nEndRow = rRange.aEnd.Row();
814 SCTAB nEndTab = rRange.aEnd.Tab();
815 PutInOrder( nStartCol, nEndCol );
816 PutInOrder( nStartRow, nEndRow );
817 PutInOrder( nStartTab, nEndTab );
818 SCSIZE nSize = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
819
820 sal_Bool bTest = sal_True;
821 for (SCTAB i=nStartTab; i<=nEndTab && bTest; i++)
822 if (pTab[i])
823 bTest &= pTab[i]->TestInsertRow( nStartCol, nEndCol, nSize );
824
825 return bTest;
826 }
827
828
InsertRow(SCCOL nStartCol,SCTAB nStartTab,SCCOL nEndCol,SCTAB nEndTab,SCROW nStartRow,SCSIZE nSize,ScDocument * pRefUndoDoc,const ScMarkData * pTabMark)829 sal_Bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
830 SCCOL nEndCol, SCTAB nEndTab,
831 SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc,
832 const ScMarkData* pTabMark )
833 {
834 SCTAB i;
835
836 PutInOrder( nStartCol, nEndCol );
837 PutInOrder( nStartTab, nEndTab );
838 if ( pTabMark )
839 {
840 nStartTab = 0;
841 nEndTab = MAXTAB;
842 }
843
844 sal_Bool bTest = sal_True;
845 sal_Bool bRet = sal_False;
846 sal_Bool bOldAutoCalc = GetAutoCalc();
847 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
848 for ( i = nStartTab; i <= nEndTab && bTest; i++)
849 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
850 bTest &= pTab[i]->TestInsertRow( nStartCol, nEndCol, nSize );
851 if (bTest)
852 {
853 // UpdateBroadcastAreas muss vor UpdateReference gerufen werden, damit nicht
854 // Eintraege verschoben werden, die erst bei UpdateReference neu erzeugt werden
855
856 // handle chunks of consecutive selected sheets together
857 SCTAB nTabRangeStart = nStartTab;
858 SCTAB nTabRangeEnd = nEndTab;
859 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
860 do
861 {
862 UpdateBroadcastAreas( URM_INSDEL, ScRange(
863 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
864 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, static_cast<SCsROW>(nSize), 0 );
865 }
866 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
867
868 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
869 do
870 {
871 UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart,
872 nEndCol, MAXROW, nTabRangeEnd,
873 0, static_cast<SCsROW>(nSize), 0, pRefUndoDoc, sal_False ); // without drawing objects
874 }
875 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
876
877 for (i=nStartTab; i<=nEndTab; i++)
878 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
879 pTab[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize );
880
881 // #82991# UpdateRef for drawing layer must be after inserting,
882 // when the new row heights are known.
883 for (i=nStartTab; i<=nEndTab; i++)
884 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
885 pTab[i]->UpdateDrawRef( URM_INSDEL,
886 nStartCol, nStartRow, nStartTab, nEndCol, MAXROW, nEndTab,
887 0, static_cast<SCsROW>(nSize), 0 );
888
889 if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
890 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
891 // ein neues Listening faellig, bisherige Listener wurden in
892 // FormulaCell UpdateReference abgehaengt
893 StartAllListeners();
894 }
895 else
896 { // Listeners have been removed in UpdateReference
897 for (i=0; i<=MAXTAB; i++)
898 if (pTab[i])
899 pTab[i]->StartNeededListeners();
900 // #69592# at least all cells using range names pointing relative
901 // to the moved range must recalculate
902 for (i=0; i<=MAXTAB; i++)
903 if (pTab[i])
904 pTab[i]->SetRelNameDirty();
905 }
906 bRet = sal_True;
907 }
908 SetAutoCalc( bOldAutoCalc );
909 if ( bRet )
910 pChartListenerCollection->UpdateDirtyCharts();
911 return bRet;
912 }
913
914
InsertRow(const ScRange & rRange,ScDocument * pRefUndoDoc)915 sal_Bool ScDocument::InsertRow( const ScRange& rRange, ScDocument* pRefUndoDoc )
916 {
917 return InsertRow( rRange.aStart.Col(), rRange.aStart.Tab(),
918 rRange.aEnd.Col(), rRange.aEnd.Tab(),
919 rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
920 pRefUndoDoc );
921 }
922
923
DeleteRow(SCCOL nStartCol,SCTAB nStartTab,SCCOL nEndCol,SCTAB nEndTab,SCROW nStartRow,SCSIZE nSize,ScDocument * pRefUndoDoc,sal_Bool * pUndoOutline,const ScMarkData * pTabMark)924 void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
925 SCCOL nEndCol, SCTAB nEndTab,
926 SCROW nStartRow, SCSIZE nSize,
927 ScDocument* pRefUndoDoc, sal_Bool* pUndoOutline,
928 const ScMarkData* pTabMark )
929 {
930 SCTAB i;
931
932 PutInOrder( nStartCol, nEndCol );
933 PutInOrder( nStartTab, nEndTab );
934 if ( pTabMark )
935 {
936 nStartTab = 0;
937 nEndTab = MAXTAB;
938 }
939
940 sal_Bool bOldAutoCalc = GetAutoCalc();
941 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
942
943 // handle chunks of consecutive selected sheets together
944 SCTAB nTabRangeStart = nStartTab;
945 SCTAB nTabRangeEnd = nEndTab;
946 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
947 do
948 {
949 if ( ValidRow(nStartRow+nSize) )
950 {
951 DelBroadcastAreasInRange( ScRange(
952 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
953 ScAddress( nEndCol, nStartRow+nSize-1, nTabRangeEnd ) ) );
954 UpdateBroadcastAreas( URM_INSDEL, ScRange(
955 ScAddress( nStartCol, nStartRow+nSize, nTabRangeStart ),
956 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, -(static_cast<SCsROW>(nSize)), 0 );
957 }
958 else
959 DelBroadcastAreasInRange( ScRange(
960 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
961 ScAddress( nEndCol, MAXROW, nTabRangeEnd ) ) );
962 }
963 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
964
965 if ( ValidRow(nStartRow+nSize) )
966 {
967 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
968 do
969 {
970 UpdateReference( URM_INSDEL, nStartCol, nStartRow+nSize, nTabRangeStart,
971 nEndCol, MAXROW, nTabRangeEnd,
972 0, -(static_cast<SCsROW>(nSize)), 0, pRefUndoDoc, sal_True, false );
973 }
974 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
975 }
976
977 if (pUndoOutline)
978 *pUndoOutline = sal_False;
979
980 for ( i = nStartTab; i <= nEndTab; i++)
981 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
982 pTab[i]->DeleteRow( nStartCol, nEndCol, nStartRow, nSize, pUndoOutline );
983
984 if ( ValidRow(nStartRow+nSize) )
985 { // Listeners have been removed in UpdateReference
986 for (i=0; i<=MAXTAB; i++)
987 if (pTab[i])
988 pTab[i]->StartNeededListeners();
989 // #69592# at least all cells using range names pointing relative to
990 // the moved range must recalculate
991 for (i=0; i<=MAXTAB; i++)
992 if (pTab[i])
993 pTab[i]->SetRelNameDirty();
994 }
995
996 SetAutoCalc( bOldAutoCalc );
997 pChartListenerCollection->UpdateDirtyCharts();
998 }
999
1000
DeleteRow(const ScRange & rRange,ScDocument * pRefUndoDoc,sal_Bool * pUndoOutline)1001 void ScDocument::DeleteRow( const ScRange& rRange, ScDocument* pRefUndoDoc, sal_Bool* pUndoOutline )
1002 {
1003 DeleteRow( rRange.aStart.Col(), rRange.aStart.Tab(),
1004 rRange.aEnd.Col(), rRange.aEnd.Tab(),
1005 rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
1006 pRefUndoDoc, pUndoOutline );
1007 }
1008
1009
CanInsertCol(const ScRange & rRange) const1010 sal_Bool ScDocument::CanInsertCol( const ScRange& rRange ) const
1011 {
1012 SCCOL nStartCol = rRange.aStart.Col();
1013 SCROW nStartRow = rRange.aStart.Row();
1014 SCTAB nStartTab = rRange.aStart.Tab();
1015 SCCOL nEndCol = rRange.aEnd.Col();
1016 SCROW nEndRow = rRange.aEnd.Row();
1017 SCTAB nEndTab = rRange.aEnd.Tab();
1018 PutInOrder( nStartCol, nEndCol );
1019 PutInOrder( nStartRow, nEndRow );
1020 PutInOrder( nStartTab, nEndTab );
1021 SCSIZE nSize = static_cast<SCSIZE>(nEndCol - nStartCol + 1);
1022
1023 sal_Bool bTest = sal_True;
1024 for (SCTAB i=nStartTab; i<=nEndTab && bTest; i++)
1025 if (pTab[i])
1026 bTest &= pTab[i]->TestInsertCol( nStartRow, nEndRow, nSize );
1027
1028 return bTest;
1029 }
1030
1031
InsertCol(SCROW nStartRow,SCTAB nStartTab,SCROW nEndRow,SCTAB nEndTab,SCCOL nStartCol,SCSIZE nSize,ScDocument * pRefUndoDoc,const ScMarkData * pTabMark)1032 sal_Bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
1033 SCROW nEndRow, SCTAB nEndTab,
1034 SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
1035 const ScMarkData* pTabMark )
1036 {
1037 SCTAB i;
1038
1039 PutInOrder( nStartRow, nEndRow );
1040 PutInOrder( nStartTab, nEndTab );
1041 if ( pTabMark )
1042 {
1043 nStartTab = 0;
1044 nEndTab = MAXTAB;
1045 }
1046
1047 sal_Bool bTest = sal_True;
1048 sal_Bool bRet = sal_False;
1049 sal_Bool bOldAutoCalc = GetAutoCalc();
1050 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1051 for ( i = nStartTab; i <= nEndTab && bTest; i++)
1052 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1053 bTest &= pTab[i]->TestInsertCol( nStartRow, nEndRow, nSize );
1054 if (bTest)
1055 {
1056 // handle chunks of consecutive selected sheets together
1057 SCTAB nTabRangeStart = nStartTab;
1058 SCTAB nTabRangeEnd = nEndTab;
1059 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
1060 do
1061 {
1062 UpdateBroadcastAreas( URM_INSDEL, ScRange(
1063 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1064 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), static_cast<SCsCOL>(nSize), 0, 0 );
1065 }
1066 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
1067
1068 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
1069 do
1070 {
1071 UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart,
1072 MAXCOL, nEndRow, nTabRangeEnd,
1073 static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc, sal_True, false );
1074 }
1075 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
1076
1077 for (i=nStartTab; i<=nEndTab; i++)
1078 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1079 pTab[i]->InsertCol( nStartCol, nStartRow, nEndRow, nSize );
1080
1081 if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
1082 { // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
1083 // ein neues Listening faellig, bisherige Listener wurden in
1084 // FormulaCell UpdateReference abgehaengt
1085 StartAllListeners();
1086 }
1087 else
1088 { // Listeners have been removed in UpdateReference
1089 for (i=0; i<=MAXTAB; i++)
1090 if (pTab[i])
1091 pTab[i]->StartNeededListeners();
1092 // #69592# at least all cells using range names pointing relative
1093 // to the moved range must recalculate
1094 for (i=0; i<=MAXTAB; i++)
1095 if (pTab[i])
1096 pTab[i]->SetRelNameDirty();
1097 }
1098 bRet = sal_True;
1099 }
1100 SetAutoCalc( bOldAutoCalc );
1101 if ( bRet )
1102 pChartListenerCollection->UpdateDirtyCharts();
1103 return bRet;
1104 }
1105
1106
InsertCol(const ScRange & rRange,ScDocument * pRefUndoDoc)1107 sal_Bool ScDocument::InsertCol( const ScRange& rRange, ScDocument* pRefUndoDoc )
1108 {
1109 return InsertCol( rRange.aStart.Row(), rRange.aStart.Tab(),
1110 rRange.aEnd.Row(), rRange.aEnd.Tab(),
1111 rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
1112 pRefUndoDoc );
1113 }
1114
1115
DeleteCol(SCROW nStartRow,SCTAB nStartTab,SCROW nEndRow,SCTAB nEndTab,SCCOL nStartCol,SCSIZE nSize,ScDocument * pRefUndoDoc,sal_Bool * pUndoOutline,const ScMarkData * pTabMark)1116 void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab,
1117 SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
1118 sal_Bool* pUndoOutline, const ScMarkData* pTabMark )
1119 {
1120 SCTAB i;
1121
1122 PutInOrder( nStartRow, nEndRow );
1123 PutInOrder( nStartTab, nEndTab );
1124 if ( pTabMark )
1125 {
1126 nStartTab = 0;
1127 nEndTab = MAXTAB;
1128 }
1129
1130 sal_Bool bOldAutoCalc = GetAutoCalc();
1131 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1132
1133 // handle chunks of consecutive selected sheets together
1134 SCTAB nTabRangeStart = nStartTab;
1135 SCTAB nTabRangeEnd = nEndTab;
1136 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
1137 do
1138 {
1139 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1140 {
1141 DelBroadcastAreasInRange( ScRange(
1142 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1143 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nTabRangeEnd ) ) );
1144 UpdateBroadcastAreas( URM_INSDEL, ScRange(
1145 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart ),
1146 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), -static_cast<SCsCOL>(nSize), 0, 0 );
1147 }
1148 else
1149 DelBroadcastAreasInRange( ScRange(
1150 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1151 ScAddress( MAXCOL, nEndRow, nTabRangeEnd ) ) );
1152 }
1153 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
1154
1155 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1156 {
1157 lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark );
1158 do
1159 {
1160 UpdateReference( URM_INSDEL, sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart,
1161 MAXCOL, nEndRow, nTabRangeEnd,
1162 -static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc, sal_True, false );
1163 }
1164 while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) );
1165 }
1166
1167 if (pUndoOutline)
1168 *pUndoOutline = sal_False;
1169
1170 for ( i = nStartTab; i <= nEndTab; i++)
1171 if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1172 pTab[i]->DeleteCol( nStartCol, nStartRow, nEndRow, nSize, pUndoOutline );
1173
1174 if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1175 { // Listeners have been removed in UpdateReference
1176 for (i=0; i<=MAXTAB; i++)
1177 if (pTab[i])
1178 pTab[i]->StartNeededListeners();
1179 // #69592# at least all cells using range names pointing relative to
1180 // the moved range must recalculate
1181 for (i=0; i<=MAXTAB; i++)
1182 if (pTab[i])
1183 pTab[i]->SetRelNameDirty();
1184 }
1185
1186 SetAutoCalc( bOldAutoCalc );
1187 pChartListenerCollection->UpdateDirtyCharts();
1188 }
1189
1190
DeleteCol(const ScRange & rRange,ScDocument * pRefUndoDoc,sal_Bool * pUndoOutline)1191 void ScDocument::DeleteCol( const ScRange& rRange, ScDocument* pRefUndoDoc, sal_Bool* pUndoOutline )
1192 {
1193 DeleteCol( rRange.aStart.Row(), rRange.aStart.Tab(),
1194 rRange.aEnd.Row(), rRange.aEnd.Tab(),
1195 rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
1196 pRefUndoDoc, pUndoOutline );
1197 }
1198
1199
1200 // fuer Area-Links: Zellen einuegen/loeschen, wenn sich der Bereich veraendert
1201 // (ohne Paint)
1202
1203
lcl_GetInsDelRanges(const ScRange & rOld,const ScRange & rNew,ScRange & rColRange,sal_Bool & rInsCol,sal_Bool & rDelCol,ScRange & rRowRange,sal_Bool & rInsRow,sal_Bool & rDelRow)1204 void lcl_GetInsDelRanges( const ScRange& rOld, const ScRange& rNew,
1205 ScRange& rColRange, sal_Bool& rInsCol, sal_Bool& rDelCol,
1206 ScRange& rRowRange, sal_Bool& rInsRow, sal_Bool& rDelRow )
1207 {
1208 DBG_ASSERT( rOld.aStart == rNew.aStart, "FitBlock: Anfang unterschiedlich" );
1209
1210 rInsCol = rDelCol = rInsRow = rDelRow = sal_False;
1211
1212 SCCOL nStartX = rOld.aStart.Col();
1213 SCROW nStartY = rOld.aStart.Row();
1214 SCCOL nOldEndX = rOld.aEnd.Col();
1215 SCROW nOldEndY = rOld.aEnd.Row();
1216 SCCOL nNewEndX = rNew.aEnd.Col();
1217 SCROW nNewEndY = rNew.aEnd.Row();
1218 SCTAB nTab = rOld.aStart.Tab();
1219
1220 // wenn es mehr Zeilen werden, werden Spalten auf der alten Hoehe eingefuegt/geloescht
1221 sal_Bool bGrowY = ( nNewEndY > nOldEndY );
1222 SCROW nColEndY = bGrowY ? nOldEndY : nNewEndY;
1223 SCCOL nRowEndX = bGrowY ? nNewEndX : nOldEndX;
1224
1225 // Spalten
1226
1227 if ( nNewEndX > nOldEndX ) // Spalten einfuegen
1228 {
1229 rColRange = ScRange( nOldEndX+1, nStartY, nTab, nNewEndX, nColEndY, nTab );
1230 rInsCol = sal_True;
1231 }
1232 else if ( nNewEndX < nOldEndX ) // Spalten loeschen
1233 {
1234 rColRange = ScRange( nNewEndX+1, nStartY, nTab, nOldEndX, nColEndY, nTab );
1235 rDelCol = sal_True;
1236 }
1237
1238 // Zeilen
1239
1240 if ( nNewEndY > nOldEndY ) // Zeilen einfuegen
1241 {
1242 rRowRange = ScRange( nStartX, nOldEndY+1, nTab, nRowEndX, nNewEndY, nTab );
1243 rInsRow = sal_True;
1244 }
1245 else if ( nNewEndY < nOldEndY ) // Zeilen loeschen
1246 {
1247 rRowRange = ScRange( nStartX, nNewEndY+1, nTab, nRowEndX, nOldEndY, nTab );
1248 rDelRow = sal_True;
1249 }
1250 }
1251
1252
HasPartOfMerged(const ScRange & rRange)1253 sal_Bool ScDocument::HasPartOfMerged( const ScRange& rRange )
1254 {
1255 sal_Bool bPart = sal_False;
1256 SCTAB nTab = rRange.aStart.Tab();
1257
1258 SCCOL nStartX = rRange.aStart.Col();
1259 SCROW nStartY = rRange.aStart.Row();
1260 SCCOL nEndX = rRange.aEnd.Col();
1261 SCROW nEndY = rRange.aEnd.Row();
1262
1263 if (HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab,
1264 HASATTR_MERGED | HASATTR_OVERLAPPED ))
1265 {
1266 ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
1267 ExtendOverlapped( nStartX, nStartY, nEndX, nEndY, nTab );
1268
1269 bPart = ( nStartX != rRange.aStart.Col() || nEndX != rRange.aEnd.Col() ||
1270 nStartY != rRange.aStart.Row() || nEndY != rRange.aEnd.Row() );
1271 }
1272 return bPart;
1273 }
1274
1275
CanFitBlock(const ScRange & rOld,const ScRange & rNew)1276 sal_Bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
1277 {
1278 if ( rOld == rNew )
1279 return sal_True;
1280
1281 sal_Bool bOk = sal_True;
1282 sal_Bool bInsCol,bDelCol,bInsRow,bDelRow;
1283 ScRange aColRange,aRowRange;
1284 lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
1285
1286 if ( bInsCol && !CanInsertCol( aColRange ) ) // Zellen am Rand ?
1287 bOk = sal_False;
1288 if ( bInsRow && !CanInsertRow( aRowRange ) ) // Zellen am Rand ?
1289 bOk = sal_False;
1290
1291 if ( bInsCol || bDelCol )
1292 {
1293 aColRange.aEnd.SetCol(MAXCOL);
1294 if ( HasPartOfMerged(aColRange) )
1295 bOk = sal_False;
1296 }
1297 if ( bInsRow || bDelRow )
1298 {
1299 aRowRange.aEnd.SetRow(MAXROW);
1300 if ( HasPartOfMerged(aRowRange) )
1301 bOk = sal_False;
1302 }
1303
1304 return bOk;
1305 }
1306
1307
FitBlock(const ScRange & rOld,const ScRange & rNew,sal_Bool bClear)1308 void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, sal_Bool bClear )
1309 {
1310 if (bClear)
1311 DeleteAreaTab( rOld, IDF_ALL );
1312
1313 sal_Bool bInsCol,bDelCol,bInsRow,bDelRow;
1314 ScRange aColRange,aRowRange;
1315 lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
1316
1317 if ( bInsCol )
1318 InsertCol( aColRange ); // Spalten zuerst einfuegen
1319 if ( bInsRow )
1320 InsertRow( aRowRange );
1321
1322 if ( bDelRow )
1323 DeleteRow( aRowRange ); // Zeilen zuerst loeschen
1324 if ( bDelCol )
1325 DeleteCol( aColRange );
1326
1327 // Referenzen um eingefuegte Zeilen erweitern
1328
1329 if ( bInsCol || bInsRow )
1330 {
1331 ScRange aGrowSource = rOld;
1332 aGrowSource.aEnd.SetCol(Min( rOld.aEnd.Col(), rNew.aEnd.Col() ));
1333 aGrowSource.aEnd.SetRow(Min( rOld.aEnd.Row(), rNew.aEnd.Row() ));
1334 SCCOL nGrowX = bInsCol ? ( rNew.aEnd.Col() - rOld.aEnd.Col() ) : 0;
1335 SCROW nGrowY = bInsRow ? ( rNew.aEnd.Row() - rOld.aEnd.Row() ) : 0;
1336 UpdateGrow( aGrowSource, nGrowX, nGrowY );
1337 }
1338 }
1339
1340
DeleteArea(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark,sal_uInt16 nDelFlag)1341 void ScDocument::DeleteArea(SCCOL nCol1, SCROW nRow1,
1342 SCCOL nCol2, SCROW nRow2,
1343 const ScMarkData& rMark, sal_uInt16 nDelFlag)
1344 {
1345 PutInOrder( nCol1, nCol2 );
1346 PutInOrder( nRow1, nRow2 );
1347 sal_Bool bOldAutoCalc = GetAutoCalc();
1348 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1349 for (SCTAB i = 0; i <= MAXTAB; i++)
1350 if (pTab[i])
1351 if ( rMark.GetTableSelect(i) || bIsUndo )
1352 pTab[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
1353 SetAutoCalc( bOldAutoCalc );
1354 }
1355
1356
DeleteAreaTab(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,SCTAB nTab,sal_uInt16 nDelFlag)1357 void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1,
1358 SCCOL nCol2, SCROW nRow2,
1359 SCTAB nTab, sal_uInt16 nDelFlag)
1360 {
1361 PutInOrder( nCol1, nCol2 );
1362 PutInOrder( nRow1, nRow2 );
1363 if ( VALIDTAB(nTab) && pTab[nTab] )
1364 {
1365 sal_Bool bOldAutoCalc = GetAutoCalc();
1366 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1367 pTab[nTab]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
1368 SetAutoCalc( bOldAutoCalc );
1369 }
1370 }
1371
1372
DeleteAreaTab(const ScRange & rRange,sal_uInt16 nDelFlag)1373 void ScDocument::DeleteAreaTab( const ScRange& rRange, sal_uInt16 nDelFlag )
1374 {
1375 for ( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); nTab++ )
1376 DeleteAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
1377 rRange.aEnd.Col(), rRange.aEnd.Row(),
1378 nTab, nDelFlag );
1379 }
1380
1381
InitUndoSelected(ScDocument * pSrcDoc,const ScMarkData & rTabSelection,sal_Bool bColInfo,sal_Bool bRowInfo)1382 void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSelection,
1383 sal_Bool bColInfo, sal_Bool bRowInfo )
1384 {
1385 if (bIsUndo)
1386 {
1387 Clear();
1388
1389 xPoolHelper = pSrcDoc->xPoolHelper;
1390
1391 String aString;
1392 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++)
1393 if ( rTabSelection.GetTableSelect( nTab ) )
1394 {
1395 pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1396 nMaxTableNumber = nTab + 1;
1397 }
1398 }
1399 else
1400 {
1401 DBG_ERROR("InitUndo");
1402 }
1403 }
1404
1405
InitUndo(ScDocument * pSrcDoc,SCTAB nTab1,SCTAB nTab2,sal_Bool bColInfo,sal_Bool bRowInfo)1406 void ScDocument::InitUndo( ScDocument* pSrcDoc, SCTAB nTab1, SCTAB nTab2,
1407 sal_Bool bColInfo, sal_Bool bRowInfo )
1408 {
1409 if (bIsUndo)
1410 {
1411 Clear();
1412
1413 xPoolHelper = pSrcDoc->xPoolHelper;
1414
1415 String aString;
1416 for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
1417 pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1418
1419 nMaxTableNumber = nTab2 + 1;
1420 }
1421 else
1422 {
1423 DBG_ERROR("InitUndo");
1424 }
1425 }
1426
1427
AddUndoTab(SCTAB nTab1,SCTAB nTab2,sal_Bool bColInfo,sal_Bool bRowInfo)1428 void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, sal_Bool bColInfo, sal_Bool bRowInfo )
1429 {
1430 if (bIsUndo)
1431 {
1432 String aString;
1433 for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
1434 if (!pTab[nTab])
1435 pTab[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1436
1437 if ( nMaxTableNumber <= nTab2 )
1438 nMaxTableNumber = nTab2 + 1;
1439 }
1440 else
1441 {
1442 DBG_ERROR("InitUndo");
1443 }
1444 }
1445
1446
SetCutMode(sal_Bool bVal)1447 void ScDocument::SetCutMode( sal_Bool bVal )
1448 {
1449 if (bIsClip)
1450 GetClipParam().mbCutMode = bVal;
1451 else
1452 {
1453 DBG_ERROR("SetCutMode without bIsClip");
1454 }
1455 }
1456
1457
IsCutMode()1458 sal_Bool ScDocument::IsCutMode()
1459 {
1460 if (bIsClip)
1461 return GetClipParam().mbCutMode;
1462 else
1463 {
1464 DBG_ERROR("IsCutMode ohne bIsClip");
1465 return sal_False;
1466 }
1467 }
1468
1469
CopyToDocument(SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2,sal_uInt16 nFlags,sal_Bool bOnlyMarked,ScDocument * pDestDoc,const ScMarkData * pMarks,sal_Bool bColRowFlags)1470 void ScDocument::CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1471 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1472 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc,
1473 const ScMarkData* pMarks, sal_Bool bColRowFlags )
1474 {
1475 PutInOrder( nCol1, nCol2 );
1476 PutInOrder( nRow1, nRow2 );
1477 PutInOrder( nTab1, nTab2 );
1478 if( !pDestDoc->aDocName.Len() )
1479 pDestDoc->aDocName = aDocName;
1480 if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
1481 {
1482 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1483 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1484 for (SCTAB i = nTab1; i <= nTab2; i++)
1485 {
1486 if (pTab[i] && pDestDoc->pTab[i])
1487 pTab[i]->CopyToTable( nCol1, nRow1, nCol2, nRow2, nFlags,
1488 bOnlyMarked, pDestDoc->pTab[i], pMarks,
1489 sal_False, bColRowFlags );
1490 }
1491 pDestDoc->SetAutoCalc( bOldAutoCalc );
1492 }
1493 }
1494
1495
UndoToDocument(SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2,sal_uInt16 nFlags,sal_Bool bOnlyMarked,ScDocument * pDestDoc,const ScMarkData * pMarks)1496 void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1497 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1498 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc,
1499 const ScMarkData* pMarks)
1500 {
1501 PutInOrder( nCol1, nCol2 );
1502 PutInOrder( nRow1, nRow2 );
1503 PutInOrder( nTab1, nTab2 );
1504 if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
1505 {
1506 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1507 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1508 if (nTab1 > 0)
1509 CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, sal_False, pDestDoc, pMarks );
1510
1511 for (SCTAB i = nTab1; i <= nTab2; i++)
1512 {
1513 if (pTab[i] && pDestDoc->pTab[i])
1514 pTab[i]->UndoToTable(nCol1, nRow1, nCol2, nRow2, nFlags,
1515 bOnlyMarked, pDestDoc->pTab[i], pMarks);
1516 }
1517
1518 if (nTab2 < MAXTAB)
1519 CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, sal_False, pDestDoc, pMarks );
1520 pDestDoc->SetAutoCalc( bOldAutoCalc );
1521 }
1522 }
1523
1524
CopyToDocument(const ScRange & rRange,sal_uInt16 nFlags,sal_Bool bOnlyMarked,ScDocument * pDestDoc,const ScMarkData * pMarks,sal_Bool bColRowFlags)1525 void ScDocument::CopyToDocument(const ScRange& rRange,
1526 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc,
1527 const ScMarkData* pMarks, sal_Bool bColRowFlags)
1528 {
1529 ScRange aNewRange = rRange;
1530 aNewRange.Justify();
1531
1532 if( !pDestDoc->aDocName.Len() )
1533 pDestDoc->aDocName = aDocName;
1534 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1535 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1536 for (SCTAB i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab(); i++)
1537 if (pTab[i] && pDestDoc->pTab[i])
1538 pTab[i]->CopyToTable(aNewRange.aStart.Col(), aNewRange.aStart.Row(),
1539 aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
1540 nFlags, bOnlyMarked, pDestDoc->pTab[i],
1541 pMarks, sal_False, bColRowFlags);
1542 pDestDoc->SetAutoCalc( bOldAutoCalc );
1543 }
1544
1545
UndoToDocument(const ScRange & rRange,sal_uInt16 nFlags,sal_Bool bOnlyMarked,ScDocument * pDestDoc,const ScMarkData * pMarks)1546 void ScDocument::UndoToDocument(const ScRange& rRange,
1547 sal_uInt16 nFlags, sal_Bool bOnlyMarked, ScDocument* pDestDoc,
1548 const ScMarkData* pMarks)
1549 {
1550 ScRange aNewRange = rRange;
1551 aNewRange.Justify();
1552 SCTAB nTab1 = aNewRange.aStart.Tab();
1553 SCTAB nTab2 = aNewRange.aEnd.Tab();
1554
1555 sal_Bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1556 pDestDoc->SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
1557 if (nTab1 > 0)
1558 CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, sal_False, pDestDoc, pMarks );
1559
1560 for (SCTAB i = nTab1; i <= nTab2; i++)
1561 {
1562 if (pTab[i] && pDestDoc->pTab[i])
1563 pTab[i]->UndoToTable(aNewRange.aStart.Col(), aNewRange.aStart.Row(),
1564 aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
1565 nFlags, bOnlyMarked, pDestDoc->pTab[i], pMarks);
1566 }
1567
1568 if (nTab2 < MAXTAB)
1569 CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, sal_False, pDestDoc, pMarks );
1570 pDestDoc->SetAutoCalc( bOldAutoCalc );
1571 }
1572
CopyToClip(const ScClipParam & rClipParam,ScDocument * pClipDoc,const ScMarkData * pMarks,bool bAllTabs,bool bKeepScenarioFlags,bool bIncludeObjects,bool bCloneNoteCaptions)1573 void ScDocument::CopyToClip(const ScClipParam& rClipParam,
1574 ScDocument* pClipDoc, const ScMarkData* pMarks,
1575 bool bAllTabs, bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions)
1576 {
1577 DBG_ASSERT( bAllTabs || pMarks, "CopyToClip: ScMarkData fehlt" );
1578
1579 if (bIsClip)
1580 return;
1581
1582 if (!pClipDoc)
1583 {
1584 DBG_ERROR("CopyToClip: no ClipDoc");
1585 pClipDoc = SC_MOD()->GetClipDoc();
1586 }
1587
1588 pClipDoc->aDocName = aDocName;
1589 pClipDoc->SetClipParam(rClipParam);
1590 pClipDoc->ResetClip(this, pMarks);
1591
1592 ScRange aClipRange = rClipParam.getWholeRange();
1593 CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
1594
1595 for (SCTAB i = 0; i <= MAXTAB; ++i)
1596 {
1597 if (!pTab[i] || !pClipDoc->pTab[i])
1598 continue;
1599
1600 if (pMarks && !pMarks->GetTableSelect(i))
1601 continue;
1602
1603 pTab[i]->CopyToClip(rClipParam.maRanges, pClipDoc->pTab[i], bKeepScenarioFlags, bCloneNoteCaptions);
1604
1605 if (pDrawLayer && bIncludeObjects)
1606 {
1607 // also copy drawing objects
1608 Rectangle aObjRect = GetMMRect(
1609 aClipRange.aStart.Col(), aClipRange.aStart.Row(), aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i);
1610 pDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
1611 }
1612 }
1613
1614 // Make sure to mark overlapped cells.
1615 pClipDoc->ExtendMerge(aClipRange, true);
1616 }
1617
CopyTabToClip(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,SCTAB nTab,ScDocument * pClipDoc)1618 void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
1619 SCCOL nCol2, SCROW nRow2,
1620 SCTAB nTab, ScDocument* pClipDoc)
1621 {
1622 if (!bIsClip)
1623 {
1624 PutInOrder( nCol1, nCol2 );
1625 PutInOrder( nRow1, nRow2 );
1626 if (!pClipDoc)
1627 {
1628 DBG_ERROR("CopyTabToClip: no ClipDoc");
1629 pClipDoc = SC_MOD()->GetClipDoc();
1630 }
1631
1632 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1633 pClipDoc->aDocName = aDocName;
1634 rClipParam.maRanges.RemoveAll();
1635 rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
1636 pClipDoc->ResetClip( this, nTab );
1637
1638 if (pTab[nTab] && pClipDoc->pTab[nTab])
1639 pTab[nTab]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[nTab], sal_False, sal_True);
1640
1641 pClipDoc->GetClipParam().mbCutMode = false;
1642 }
1643 }
1644
1645
TransposeClip(ScDocument * pTransClip,sal_uInt16 nFlags,sal_Bool bAsLink)1646 void ScDocument::TransposeClip( ScDocument* pTransClip, sal_uInt16 nFlags, sal_Bool bAsLink )
1647 {
1648 DBG_ASSERT( bIsClip && pTransClip && pTransClip->bIsClip,
1649 "TransposeClip mit falschem Dokument" );
1650
1651 // initialisieren
1652 // -> pTransClip muss vor dem Original-Dokument geloescht werden!
1653
1654 pTransClip->ResetClip(this, (ScMarkData*)NULL); // alle
1655
1656 // Bereiche uebernehmen
1657
1658 pTransClip->pRangeName->FreeAll();
1659 for (sal_uInt16 i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
1660 {
1661 sal_uInt16 nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
1662 ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
1663 if (!pTransClip->pRangeName->Insert(pData))
1664 delete pData;
1665 else
1666 pData->SetIndex(nIndex);
1667 }
1668
1669 // Daten
1670
1671 ScRange aClipRange = GetClipParam().getWholeRange();
1672 if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
1673 {
1674 for (SCTAB i=0; i<=MAXTAB; i++)
1675 if (pTab[i])
1676 {
1677 DBG_ASSERT( pTransClip->pTab[i], "TransposeClip: Tabelle nicht da" );
1678 pTab[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
1679 aClipRange.aEnd.Col(), aClipRange.aEnd.Row(),
1680 pTransClip->pTab[i], nFlags, bAsLink );
1681
1682 if ( pDrawLayer && ( nFlags & IDF_OBJECTS ) )
1683 {
1684 // Drawing objects are copied to the new area without transposing.
1685 // CopyFromClip is used to adjust the objects to the transposed block's
1686 // cell range area.
1687 // (pDrawLayer in the original clipboard document is set only if there
1688 // are drawing objects to copy)
1689
1690 pTransClip->InitDrawLayer();
1691 Rectangle aSourceRect = GetMMRect( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
1692 aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i );
1693 Rectangle aDestRect = pTransClip->GetMMRect( 0, 0,
1694 static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()),
1695 static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()), i );
1696 pTransClip->pDrawLayer->CopyFromClip( pDrawLayer, i, aSourceRect, ScAddress(0,0,i), aDestRect );
1697 }
1698 }
1699
1700 pTransClip->SetClipParam(GetClipParam());
1701 pTransClip->GetClipParam().transpose();
1702 }
1703 else
1704 {
1705 DBG_ERROR("TransposeClip: zu gross");
1706 }
1707
1708 // Dies passiert erst beim Einfuegen...
1709
1710 GetClipParam().mbCutMode = false;
1711 }
1712
CopyRangeNamesToClip(ScDocument * pClipDoc,const ScRange & rClipRange,const ScMarkData * pMarks,bool bAllTabs)1713 void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs)
1714 {
1715 std::set<sal_uInt16> aUsedNames; // indexes of named ranges that are used in the copied cells
1716 for (SCTAB i = 0; i <= MAXTAB; ++i)
1717 if (pTab[i] && pClipDoc->pTab[i])
1718 if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
1719 pTab[i]->FindRangeNamesInUse(
1720 rClipRange.aStart.Col(), rClipRange.aStart.Row(),
1721 rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames);
1722
1723 pClipDoc->pRangeName->FreeAll();
1724 for (sal_uInt16 i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
1725 {
1726 sal_uInt16 nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
1727 bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() );
1728 if (bInUse)
1729 {
1730 ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
1731 if (!pClipDoc->pRangeName->Insert(pData))
1732 delete pData;
1733 else
1734 pData->SetIndex(nIndex);
1735 }
1736 }
1737 }
1738
NumFmtMergeHandler(ScDocument * pDoc,ScDocument * pSrcDoc)1739 ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) :
1740 mpDoc(pDoc)
1741 {
1742 mpDoc->MergeNumberFormatter(pSrcDoc);
1743 }
1744
~NumFmtMergeHandler()1745 ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
1746 {
1747 mpDoc->pFormatExchangeList = NULL;
1748 }
1749
MergeNumberFormatter(ScDocument * pSrcDoc)1750 void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
1751 {
1752 SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
1753 SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
1754 if (pOtherFormatter && pOtherFormatter != pThisFormatter)
1755 {
1756 SvNumberFormatterIndexTable* pExchangeList =
1757 pThisFormatter->MergeFormatter(*(pOtherFormatter));
1758 if (pExchangeList->Count() > 0)
1759 pFormatExchangeList = pExchangeList;
1760 }
1761 }
1762
CopyRangeNamesFromClip(ScDocument * pClipDoc,ScClipRangeNameData & rRangeNames)1763 void ScDocument::CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames)
1764 {
1765 sal_uInt16 nClipRangeNameCount = pClipDoc->pRangeName->GetCount();
1766 ScClipRangeNameData aClipRangeNames;
1767
1768 // array containing range names which might need update of indices
1769 aClipRangeNames.mpRangeNames.resize(nClipRangeNameCount, NULL);
1770
1771 for (sal_uInt16 i = 0; i < nClipRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
1772 {
1773 /* Copy only if the name doesn't exist in this document.
1774 If it exists we use the already existing name instead,
1775 another possibility could be to create new names if
1776 documents differ.
1777 A proper solution would ask the user how to proceed.
1778 The adjustment of the indices in the formulas is done later.
1779 */
1780 ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i];
1781 sal_uInt16 k;
1782 if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) )
1783 {
1784 aClipRangeNames.mpRangeNames[i] = NULL; // range name not inserted
1785 sal_uInt16 nOldIndex = pClipRangeData->GetIndex();
1786 sal_uInt16 nNewIndex = ((*pRangeName)[k])->GetIndex();
1787 aClipRangeNames.insert(nOldIndex, nNewIndex);
1788 if ( !aClipRangeNames.mbReplace )
1789 aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
1790 }
1791 else
1792 {
1793 ScRangeData* pData = new ScRangeData( *pClipRangeData );
1794 pData->SetDocument(this);
1795 if ( pRangeName->FindIndex( pData->GetIndex() ) )
1796 pData->SetIndex(0); // need new index, done in Insert
1797 if ( pRangeName->Insert( pData ) )
1798 {
1799 aClipRangeNames.mpRangeNames[i] = pData;
1800 sal_uInt16 nOldIndex = pClipRangeData->GetIndex();
1801 sal_uInt16 nNewIndex = pData->GetIndex();
1802 aClipRangeNames.insert(nOldIndex, nNewIndex);
1803 if ( !aClipRangeNames.mbReplace )
1804 aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
1805 }
1806 else
1807 { // must be an overflow
1808 delete pData;
1809 aClipRangeNames.mpRangeNames[i] = NULL;
1810 aClipRangeNames.insert(pClipRangeData->GetIndex(), 0);
1811 aClipRangeNames.mbReplace = true;
1812 }
1813 }
1814 }
1815 rRangeNames = aClipRangeNames;
1816 }
1817
UpdateRangeNamesInFormulas(ScClipRangeNameData & rRangeNames,const ScRangeList & rDestRanges,const ScMarkData & rMark,SCCOL nXw,SCROW nYw)1818 void ScDocument::UpdateRangeNamesInFormulas(
1819 ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
1820 SCCOL nXw, SCROW nYw)
1821 {
1822 // nXw and nYw are the extra width and height of the destination range
1823 // extended due to presence of merged cell(s).
1824
1825 if (!rRangeNames.mbReplace)
1826 return;
1827
1828 // first update all inserted named formulas if they contain other
1829 // range names and used indices changed
1830 size_t nRangeNameCount = rRangeNames.mpRangeNames.size();
1831 for (size_t i = 0; i < nRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
1832 {
1833 if ( rRangeNames.mpRangeNames[i] )
1834 rRangeNames.mpRangeNames[i]->ReplaceRangeNamesInUse(rRangeNames.maRangeMap);
1835 }
1836 // then update the formulas, they might need just the updated range names
1837 for (sal_uLong nRange = 0; nRange < rDestRanges.Count(); ++nRange)
1838 {
1839 const ScRange* pRange = rDestRanges.GetObject( nRange);
1840 SCCOL nCol1 = pRange->aStart.Col();
1841 SCROW nRow1 = pRange->aStart.Row();
1842 SCCOL nCol2 = pRange->aEnd.Col();
1843 SCROW nRow2 = pRange->aEnd.Row();
1844
1845 SCCOL nC1 = nCol1;
1846 SCROW nR1 = nRow1;
1847 SCCOL nC2 = nC1 + nXw;
1848 if (nC2 > nCol2)
1849 nC2 = nCol2;
1850 SCROW nR2 = nR1 + nYw;
1851 if (nR2 > nRow2)
1852 nR2 = nRow2;
1853 do
1854 {
1855 do
1856 {
1857 for (SCTAB k = 0; k <= MAXTAB; k++)
1858 {
1859 if ( pTab[k] && rMark.GetTableSelect(k) )
1860 pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
1861 nC2, nR2, rRangeNames.maRangeMap);
1862 }
1863 nC1 = nC2 + 1;
1864 nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
1865 } while (nC1 <= nCol2);
1866 nC1 = nCol1;
1867 nC2 = nC1 + nXw;
1868 if (nC2 > nCol2)
1869 nC2 = nCol2;
1870 nR1 = nR2 + 1;
1871 nR2 = Min((SCROW)(nR1 + nYw), nRow2);
1872 } while (nR1 <= nRow2);
1873 }
1874 }
1875
GetClipParam()1876 ScClipParam& ScDocument::GetClipParam()
1877 {
1878 if (!mpClipParam.get())
1879 mpClipParam.reset(new ScClipParam);
1880
1881 return *mpClipParam;
1882 }
1883
SetClipParam(const ScClipParam & rParam)1884 void ScDocument::SetClipParam(const ScClipParam& rParam)
1885 {
1886 mpClipParam.reset(new ScClipParam(rParam));
1887 }
1888
IsClipboardSource() const1889 sal_Bool ScDocument::IsClipboardSource() const
1890 {
1891 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
1892 return pClipDoc && pClipDoc->xPoolHelper.isValid() &&
1893 xPoolHelper->GetDocPool() == pClipDoc->xPoolHelper->GetDocPool();
1894 }
1895
1896
StartListeningFromClip(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark,sal_uInt16 nInsFlag)1897 void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
1898 SCCOL nCol2, SCROW nRow2,
1899 const ScMarkData& rMark, sal_uInt16 nInsFlag )
1900 {
1901 if (nInsFlag & IDF_CONTENTS)
1902 {
1903 for (SCTAB i = 0; i <= MAXTAB; i++)
1904 if (pTab[i])
1905 if (rMark.GetTableSelect(i))
1906 pTab[i]->StartListeningInArea( nCol1, nRow1, nCol2, nRow2 );
1907 }
1908 }
1909
1910
BroadcastFromClip(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark,sal_uInt16 nInsFlag)1911 void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
1912 SCCOL nCol2, SCROW nRow2,
1913 const ScMarkData& rMark, sal_uInt16 nInsFlag )
1914 {
1915 if (nInsFlag & IDF_CONTENTS)
1916 {
1917 ScBulkBroadcast aBulkBroadcast( GetBASM());
1918 for (SCTAB i = 0; i <= MAXTAB; i++)
1919 if (pTab[i])
1920 if (rMark.GetTableSelect(i))
1921 pTab[i]->BroadcastInArea( nCol1, nRow1, nCol2, nRow2 );
1922 }
1923 }
1924
1925
CopyBlockFromClip(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark,SCsCOL nDx,SCsROW nDy,const ScCopyBlockFromClipParams * pCBFCP)1926 void ScDocument::CopyBlockFromClip( SCCOL nCol1, SCROW nRow1,
1927 SCCOL nCol2, SCROW nRow2,
1928 const ScMarkData& rMark,
1929 SCsCOL nDx, SCsROW nDy,
1930 const ScCopyBlockFromClipParams* pCBFCP )
1931 {
1932 ScTable** ppClipTab = pCBFCP->pClipDoc->pTab;
1933 SCTAB nTabEnd = pCBFCP->nTabEnd;
1934 SCTAB nClipTab = 0;
1935 for (SCTAB i = pCBFCP->nTabStart; i <= nTabEnd; i++)
1936 {
1937 if (pTab[i] && rMark.GetTableSelect(i) )
1938 {
1939 while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
1940
1941 pTab[i]->CopyFromClip( nCol1, nRow1, nCol2, nRow2, nDx, nDy,
1942 pCBFCP->nInsFlag, pCBFCP->bAsLink, pCBFCP->bSkipAttrForEmpty, ppClipTab[nClipTab] );
1943
1944 if ( pCBFCP->pClipDoc->pDrawLayer && ( pCBFCP->nInsFlag & IDF_OBJECTS ) )
1945 {
1946 // also copy drawing objects
1947
1948 // drawing layer must be created before calling CopyFromClip
1949 // (ScDocShell::MakeDrawLayer also does InitItems etc.)
1950 DBG_ASSERT( pDrawLayer, "CopyBlockFromClip: No drawing layer" );
1951 if ( pDrawLayer )
1952 {
1953 // For GetMMRect, the row heights in the target document must already be valid
1954 // (copied in an extra step before pasting, or updated after pasting cells, but
1955 // before pasting objects).
1956
1957 Rectangle aSourceRect = pCBFCP->pClipDoc->GetMMRect(
1958 nCol1-nDx, nRow1-nDy, nCol2-nDx, nRow2-nDy, nClipTab );
1959 Rectangle aDestRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, i );
1960 pDrawLayer->CopyFromClip( pCBFCP->pClipDoc->pDrawLayer, nClipTab, aSourceRect,
1961 ScAddress( nCol1, nRow1, i ), aDestRect );
1962 }
1963 }
1964
1965 nClipTab = (nClipTab+1) % (MAXTAB+1);
1966 }
1967 }
1968 if ( (pCBFCP->nInsFlag & IDF_CONTENTS) &&
1969 (pCBFCP->pClipDoc->GetClipParam().getSourceDocID() == 0 ||
1970 pCBFCP->pClipDoc->GetClipParam().getSourceDocID() == GetDocumentID()) ) // #118023# only update references for *intra-document* cut and paste
1971 {
1972 nClipTab = 0;
1973 for (SCTAB i = pCBFCP->nTabStart; i <= nTabEnd; i++)
1974 {
1975 if (pTab[i] && rMark.GetTableSelect(i) )
1976 {
1977 while (!ppClipTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
1978 SCsTAB nDz = ((SCsTAB)i) - nClipTab;
1979
1980 // #89081# ranges of consecutive selected tables (in clipboard and dest. doc)
1981 // must be handled in one UpdateReference call
1982 SCTAB nFollow = 0;
1983 while ( i + nFollow < nTabEnd
1984 && rMark.GetTableSelect( i + nFollow + 1 )
1985 && nClipTab + nFollow < MAXTAB
1986 && ppClipTab[nClipTab + nFollow + 1] )
1987 ++nFollow;
1988
1989 if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode )
1990 {
1991 sal_Bool bOldInserting = IsInsertingFromOtherDoc();
1992 SetInsertingFromOtherDoc( sal_True);
1993 UpdateReference( URM_MOVE,
1994 nCol1, nRow1, i, nCol2, nRow2, i+nFollow,
1995 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False );
1996 SetInsertingFromOtherDoc( bOldInserting);
1997 }
1998 else
1999 UpdateReference( URM_COPY,
2000 nCol1, nRow1, i, nCol2, nRow2, i+nFollow,
2001 nDx, nDy, nDz, pCBFCP->pRefUndoDoc, sal_False );
2002
2003 nClipTab = (nClipTab+nFollow+1) % (MAXTAB+1);
2004 i = sal::static_int_cast<SCTAB>( i + nFollow );
2005 }
2006 }
2007 }
2008 }
2009
2010
CopyNonFilteredFromClip(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark,SCsCOL nDx,SCsROW,const ScCopyBlockFromClipParams * pCBFCP,SCROW & rClipStartRow)2011 void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1,
2012 SCCOL nCol2, SCROW nRow2,
2013 const ScMarkData& rMark,
2014 SCsCOL nDx, SCsROW /* nDy */,
2015 const ScCopyBlockFromClipParams* pCBFCP,
2016 SCROW & rClipStartRow )
2017 {
2018 // call CopyBlockFromClip for ranges of consecutive non-filtered rows
2019 // nCol1/nRow1 etc. is in target doc
2020
2021 // filtered state is taken from first used table in clipboard (as in GetClipArea)
2022 SCTAB nFlagTab = 0;
2023 ScTable** ppClipTab = pCBFCP->pClipDoc->pTab;
2024 while ( nFlagTab < MAXTAB && !ppClipTab[nFlagTab] )
2025 ++nFlagTab;
2026
2027 SCROW nSourceRow = rClipStartRow;
2028 SCROW nSourceEnd = 0;
2029 if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count())
2030 nSourceEnd = pCBFCP->pClipDoc->GetClipParam().maRanges.First()->aEnd.Row();
2031 SCROW nDestRow = nRow1;
2032
2033 while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
2034 {
2035 // skip filtered rows
2036 nSourceRow = pCBFCP->pClipDoc->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab);
2037
2038 if ( nSourceRow <= nSourceEnd )
2039 {
2040 // look for more non-filtered rows following
2041 SCROW nLastRow = nSourceRow;
2042 pCBFCP->pClipDoc->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow);
2043 SCROW nFollow = nLastRow - nSourceRow;
2044
2045 if (nFollow > nSourceEnd - nSourceRow)
2046 nFollow = nSourceEnd - nSourceRow;
2047 if (nFollow > nRow2 - nDestRow)
2048 nFollow = nRow2 - nDestRow;
2049
2050 SCsROW nNewDy = ((SCsROW)nDestRow) - nSourceRow;
2051 CopyBlockFromClip( nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy, pCBFCP );
2052
2053 nSourceRow += nFollow + 1;
2054 nDestRow += nFollow + 1;
2055 }
2056 }
2057 rClipStartRow = nSourceRow;
2058 }
2059
2060
CopyFromClip(const ScRange & rDestRange,const ScMarkData & rMark,sal_uInt16 nInsFlag,ScDocument * pRefUndoDoc,ScDocument * pClipDoc,sal_Bool bResetCut,sal_Bool bAsLink,sal_Bool bIncludeFiltered,sal_Bool bSkipAttrForEmpty,const ScRangeList * pDestRanges)2061 void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
2062 sal_uInt16 nInsFlag,
2063 ScDocument* pRefUndoDoc, ScDocument* pClipDoc, sal_Bool bResetCut,
2064 sal_Bool bAsLink, sal_Bool bIncludeFiltered, sal_Bool bSkipAttrForEmpty,
2065 const ScRangeList * pDestRanges )
2066 {
2067 if (!bIsClip)
2068 {
2069 if (!pClipDoc)
2070 {
2071 DBG_ERROR("CopyFromClip: no ClipDoc");
2072 pClipDoc = SC_MOD()->GetClipDoc();
2073 }
2074 if (pClipDoc->bIsClip && pClipDoc->GetTableCount())
2075 {
2076 sal_Bool bOldAutoCalc = GetAutoCalc();
2077 SetAutoCalc( sal_False ); // avoid multiple recalculations
2078
2079 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2080
2081 ScClipRangeNameData aClipRangeNames;
2082 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
2083
2084 SCCOL nAllCol1 = rDestRange.aStart.Col();
2085 SCROW nAllRow1 = rDestRange.aStart.Row();
2086 SCCOL nAllCol2 = rDestRange.aEnd.Col();
2087 SCROW nAllRow2 = rDestRange.aEnd.Row();
2088
2089 SCCOL nXw = 0;
2090 SCROW nYw = 0;
2091 ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
2092 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) // find largest merge overlap
2093 if (pClipDoc->pTab[nTab]) // all sheets of the clipboard content
2094 {
2095 SCCOL nThisEndX = aClipRange.aEnd.Col();
2096 SCROW nThisEndY = aClipRange.aEnd.Row();
2097 pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
2098 aClipRange.aStart.Row(),
2099 nThisEndX, nThisEndY, nTab );
2100 // only extra value from ExtendMerge
2101 nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
2102 nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
2103 if ( nThisEndX > nXw )
2104 nXw = nThisEndX;
2105 if ( nThisEndY > nYw )
2106 nYw = nThisEndY;
2107 }
2108
2109 SCCOL nDestAddX;
2110 SCROW nDestAddY;
2111 pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered );
2112 nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX );
2113 nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value
2114
2115 /* Decide which contents to delete before copying. Delete all
2116 contents if nInsFlag contains any real content flag.
2117 #i102056# Notes are pasted from clipboard in a second pass,
2118 together with the special flag IDF_ADDNOTES that states to not
2119 overwrite/delete existing cells but to insert the notes into
2120 these cells. In this case, just delete old notes from the
2121 destination area. */
2122 sal_uInt16 nDelFlag = IDF_NONE;
2123 if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) )
2124 nDelFlag |= IDF_NOTE;
2125 else if ( nInsFlag & IDF_CONTENTS )
2126 nDelFlag |= IDF_CONTENTS;
2127 // With bSkipAttrForEmpty, don't remove attributes, copy
2128 // on top of existing attributes instead.
2129 if ( ( nInsFlag & IDF_ATTRIB ) && !bSkipAttrForEmpty )
2130 nDelFlag |= IDF_ATTRIB;
2131
2132 ScCopyBlockFromClipParams aCBFCP;
2133 aCBFCP.pRefUndoDoc = pRefUndoDoc;
2134 aCBFCP.pClipDoc = pClipDoc;
2135 aCBFCP.nInsFlag = nInsFlag;
2136 aCBFCP.bAsLink = bAsLink;
2137 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty;
2138 aCBFCP.nTabStart = MAXTAB; // wird in der Schleife angepasst
2139 aCBFCP.nTabEnd = 0; // wird in der Schleife angepasst
2140
2141 // Inc/DecRecalcLevel einmal aussen, damit nicht fuer jeden Block
2142 // die Draw-Seitengroesse neu berechnet werden muss
2143 //! nur wenn ganze Zeilen/Spalten kopiert werden?
2144
2145 for (SCTAB j = 0; j <= MAXTAB; j++)
2146 if (pTab[j] && rMark.GetTableSelect(j))
2147 {
2148 if ( j < aCBFCP.nTabStart )
2149 aCBFCP.nTabStart = j;
2150 aCBFCP.nTabEnd = j;
2151 pTab[j]->IncRecalcLevel();
2152 }
2153
2154 ScRangeList aLocalRangeList;
2155 if (!pDestRanges)
2156 {
2157 aLocalRangeList.Append( rDestRange);
2158 pDestRanges = &aLocalRangeList;
2159 }
2160
2161 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert
2162
2163 // bei mindestens 64 Zeilen wird in ScColumn::CopyFromClip voralloziert
2164 sal_Bool bDoDouble = ( nYw < 64 && nAllRow2 - nAllRow1 > 64);
2165 sal_Bool bOldDouble = ScColumn::bDoubleAlloc;
2166 if (bDoDouble)
2167 ScColumn::bDoubleAlloc = sal_True;
2168
2169 SCCOL nClipStartCol = aClipRange.aStart.Col();
2170 SCROW nClipStartRow = aClipRange.aStart.Row();
2171 // WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col();
2172 SCROW nClipEndRow = aClipRange.aEnd.Row();
2173 for (sal_uLong nRange = 0; nRange < pDestRanges->Count(); ++nRange)
2174 {
2175 const ScRange* pRange = pDestRanges->GetObject( nRange);
2176 SCCOL nCol1 = pRange->aStart.Col();
2177 SCROW nRow1 = pRange->aStart.Row();
2178 SCCOL nCol2 = pRange->aEnd.Col();
2179 SCROW nRow2 = pRange->aEnd.Row();
2180
2181 DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
2182
2183 SCCOL nC1 = nCol1;
2184 SCROW nR1 = nRow1;
2185 SCCOL nC2 = nC1 + nXw;
2186 if (nC2 > nCol2)
2187 nC2 = nCol2;
2188 SCROW nR2 = nR1 + nYw;
2189 if (nR2 > nRow2)
2190 nR2 = nRow2;
2191
2192 const unsigned PERFORMANCEOPTIMIZATION4PATTERNTHRESHOLD = 8192;
2193 bool bNeedPerformanceOptimization4Pattern = nRow2 - nRow1 > PERFORMANCEOPTIMIZATION4PATTERNTHRESHOLD;
2194 std::vector< std::vector< SCSIZE > > vvPatternCount( bNeedPerformanceOptimization4Pattern ? nCol2 - nCol1 + 1 : 0 );
2195 std::vector< SCTAB > vTables;
2196
2197 if( bNeedPerformanceOptimization4Pattern )
2198 {
2199 for (SCTAB i = aCBFCP.nTabStart; i <= aCBFCP.nTabEnd; i++)
2200 if (pTab[i] && rMark.GetTableSelect( i ) )
2201 vTables.push_back( i );
2202
2203 for( SCSIZE i = 0; i < vvPatternCount.size(); i++ )
2204 {
2205 vvPatternCount[i].resize( vTables.size() );
2206
2207 for( std::vector< SCTAB >::size_type j = 0; j<vTables.size(); j++ )
2208 vvPatternCount[i][j] = this->GetPatternCount( vTables[j], nCol1+i );
2209 }
2210 }
2211
2212 do
2213 {
2214 // Pasting is done column-wise, when pasting to a filtered
2215 // area this results in partitioning and we have to
2216 // remember and reset the start row for each column until
2217 // it can be advanced for the next chunk of unfiltered
2218 // rows.
2219 SCROW nSaveClipStartRow = nClipStartRow;
2220 do
2221 {
2222 nClipStartRow = nSaveClipStartRow;
2223 SCsCOL nDx = ((SCsCOL)nC1) - nClipStartCol;
2224 SCsROW nDy = ((SCsROW)nR1) - nClipStartRow;
2225 if ( bIncludeFiltered )
2226 {
2227 CopyBlockFromClip( nC1, nR1, nC2, nR2, rMark, nDx,
2228 nDy, &aCBFCP );
2229 nClipStartRow += nR2 - nR1 + 1;
2230 }
2231 else
2232 {
2233 CopyNonFilteredFromClip( nC1, nR1, nC2, nR2, rMark,
2234 nDx, nDy, &aCBFCP, nClipStartRow );
2235 }
2236 // Not needed for columns, but if it was this would be how to.
2237 //if (nClipStartCol > nClipEndCol)
2238 // nClipStartCol = pClipDoc->aClipRange.aStart.Col();
2239 nC1 = nC2 + 1;
2240 nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
2241 } while (nC1 <= nCol2);
2242 if (nClipStartRow > nClipEndRow)
2243 nClipStartRow = aClipRange.aStart.Row();
2244 nC1 = nCol1;
2245 nC2 = nC1 + nXw;
2246 if (nC2 > nCol2)
2247 nC2 = nCol2;
2248
2249 if( bNeedPerformanceOptimization4Pattern && vvPatternCount.size() )
2250 {
2251 for( SCSIZE i = 0; i < vvPatternCount.size(); i++ )
2252 {
2253 vvPatternCount[i].resize( vTables.size() );
2254
2255 for( std::vector< SCTAB >::size_type j = 0; j<vTables.size(); j++ )
2256 this->ReservedPatternCount( vTables[j], nCol1+i, vvPatternCount[i][j] + ( this->GetPatternCount( vTables[j], nCol1+i, nR1, nR2 ) ) * ( ( nRow2 - nRow1 + 1 ) / ( nYw + 1 ) ) );
2257 }
2258
2259 bNeedPerformanceOptimization4Pattern = false;
2260 vvPatternCount.clear();
2261 }
2262
2263 nR1 = nR2 + 1;
2264 nR2 = Min((SCROW)(nR1 + nYw), nRow2);
2265 } while (nR1 <= nRow2);
2266 }
2267
2268 ScColumn::bDoubleAlloc = bOldDouble;
2269
2270 for (SCTAB k = 0; k <= MAXTAB; k++)
2271 if (pTab[k] && rMark.GetTableSelect(k))
2272 pTab[k]->DecRecalcLevel();
2273
2274 bInsertingFromOtherDoc = sal_False;
2275
2276 UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw);
2277
2278 // Listener aufbauen nachdem alles inserted wurde
2279 StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
2280 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2281 BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
2282 if (bResetCut)
2283 pClipDoc->GetClipParam().mbCutMode = false;
2284 SetAutoCalc( bOldAutoCalc );
2285 }
2286 }
2287 }
2288
lcl_getLastNonFilteredRow(const ScBitMaskCompressedArray<SCROW,sal_uInt8> & rFlags,SCROW nBegRow,SCROW nEndRow,SCROW nRowCount)2289 static SCROW lcl_getLastNonFilteredRow(
2290 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags, SCROW nBegRow, SCROW nEndRow,
2291 SCROW nRowCount)
2292 {
2293 SCROW nFilteredRow = rFlags.GetFirstForCondition(
2294 nBegRow, nEndRow, CR_FILTERED, CR_FILTERED);
2295
2296 SCROW nRow = nFilteredRow - 1;
2297 if (nRow - nBegRow + 1 > nRowCount)
2298 // make sure the row range stays within the data size.
2299 nRow = nBegRow + nRowCount - 1;
2300
2301 return nRow;
2302 }
2303
CopyMultiRangeFromClip(const ScAddress & rDestPos,const ScMarkData & rMark,sal_uInt16 nInsFlag,ScDocument * pClipDoc,bool bResetCut,bool bAsLink,bool,bool bSkipAttrForEmpty)2304 void ScDocument::CopyMultiRangeFromClip(
2305 const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
2306 bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
2307 {
2308 if (bIsClip)
2309 return;
2310
2311 if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
2312 // There is nothing in the clip doc to copy.
2313 return;
2314
2315 sal_Bool bOldAutoCalc = GetAutoCalc();
2316 SetAutoCalc( sal_False ); // avoid multiple recalculations
2317
2318 NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2319
2320 ScClipRangeNameData aClipRangeNames;
2321 CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
2322
2323 SCCOL nCol1 = rDestPos.Col();
2324 SCROW nRow1 = rDestPos.Row();
2325 ScClipParam& rClipParam = pClipDoc->GetClipParam();
2326
2327 ScCopyBlockFromClipParams aCBFCP;
2328 aCBFCP.pRefUndoDoc = NULL;
2329 aCBFCP.pClipDoc = pClipDoc;
2330 aCBFCP.nInsFlag = nInsFlag;
2331 aCBFCP.bAsLink = bAsLink;
2332 aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty;
2333 aCBFCP.nTabStart = MAXTAB;
2334 aCBFCP.nTabEnd = 0;
2335
2336 for (SCTAB j = 0; j <= MAXTAB; ++j)
2337 {
2338 if (pTab[j] && rMark.GetTableSelect(j))
2339 {
2340 if ( j < aCBFCP.nTabStart )
2341 aCBFCP.nTabStart = j;
2342 aCBFCP.nTabEnd = j;
2343 pTab[j]->IncRecalcLevel();
2344 }
2345 }
2346
2347 ScRange aDestRange;
2348 rMark.GetMarkArea(aDestRange);
2349 SCROW nLastMarkedRow = aDestRange.aEnd.Row();
2350
2351 bInsertingFromOtherDoc = sal_True; // kein Broadcast/Listener aufbauen bei Insert
2352
2353 SCROW nBegRow = nRow1;
2354 sal_uInt16 nDelFlag = IDF_CONTENTS;
2355 const ScBitMaskCompressedArray<SCROW, sal_uInt8>& rFlags = GetRowFlagsArray(aCBFCP.nTabStart);
2356
2357 for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next())
2358 {
2359 // The begin row must not be filtered.
2360
2361 SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1;
2362
2363 SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
2364 SCsROW nDy = static_cast<SCsROW>(nBegRow - p->aStart.Row());
2365 SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
2366
2367 SCROW nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
2368
2369 if (!bSkipAttrForEmpty)
2370 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
2371
2372 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP);
2373 nRowCount -= nEndRow - nBegRow + 1;
2374
2375 while (nRowCount > 0)
2376 {
2377 // Get the first non-filtered row.
2378 SCROW nNonFilteredRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
2379 if (nNonFilteredRow > nLastMarkedRow)
2380 return;
2381
2382 SCROW nRowsSkipped = nNonFilteredRow - nEndRow - 1;
2383 nDy += nRowsSkipped;
2384
2385 nBegRow = nNonFilteredRow;
2386 nEndRow = lcl_getLastNonFilteredRow(rFlags, nBegRow, nLastMarkedRow, nRowCount);
2387
2388 if (!bSkipAttrForEmpty)
2389 DeleteArea(nCol1, nBegRow, nCol2, nEndRow, rMark, nDelFlag);
2390
2391 CopyBlockFromClip(nCol1, nBegRow, nCol2, nEndRow, rMark, nDx, nDy, &aCBFCP);
2392 nRowCount -= nEndRow - nBegRow + 1;
2393 }
2394
2395 if (rClipParam.meDirection == ScClipParam::Row)
2396 // Begin row for the next range being pasted.
2397 nBegRow = rFlags.GetFirstForCondition(nEndRow+1, nLastMarkedRow, CR_FILTERED, 0);
2398 else
2399 nBegRow = nRow1;
2400
2401 if (rClipParam.meDirection == ScClipParam::Column)
2402 nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
2403 }
2404
2405 for (SCTAB i = 0; i <= MAXTAB; i++)
2406 if (pTab[i] && rMark.GetTableSelect(i))
2407 pTab[i]->DecRecalcLevel();
2408
2409 bInsertingFromOtherDoc = sal_False;
2410
2411 ScRangeList aRanges;
2412 aRanges.Append(aDestRange);
2413 SCCOL nCols = aDestRange.aEnd.Col() - aDestRange.aStart.Col() + 1;
2414 SCROW nRows = aDestRange.aEnd.Row() - aDestRange.aStart.Row() + 1;
2415 UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1);
2416
2417 // Listener aufbauen nachdem alles inserted wurde
2418 StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
2419 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
2420 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
2421 BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
2422 aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
2423
2424 if (bResetCut)
2425 pClipDoc->GetClipParam().mbCutMode = false;
2426 SetAutoCalc( bOldAutoCalc );
2427 }
2428
SetClipArea(const ScRange & rArea,sal_Bool bCut)2429 void ScDocument::SetClipArea( const ScRange& rArea, sal_Bool bCut )
2430 {
2431 if (bIsClip)
2432 {
2433 ScClipParam& rClipParam = GetClipParam();
2434 rClipParam.maRanges.RemoveAll();
2435 rClipParam.maRanges.Append(rArea);
2436 rClipParam.mbCutMode = bCut;
2437 }
2438 else
2439 {
2440 DBG_ERROR("SetClipArea: kein Clip");
2441 }
2442 }
2443
2444
GetClipArea(SCCOL & nClipX,SCROW & nClipY,sal_Bool bIncludeFiltered)2445 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, sal_Bool bIncludeFiltered)
2446 {
2447 if (!bIsClip)
2448 {
2449 DBG_ERROR("GetClipArea: kein Clip");
2450 return;
2451 }
2452
2453 ScRangeList& rClipRanges = GetClipParam().maRanges;
2454 if (!rClipRanges.Count())
2455 // No clip range. Bail out.
2456 return;
2457
2458 ScRangePtr p = rClipRanges.First();
2459 SCCOL nStartCol = p->aStart.Col();
2460 SCCOL nEndCol = p->aEnd.Col();
2461 SCROW nStartRow = p->aStart.Row();
2462 SCROW nEndRow = p->aEnd.Row();
2463 for (p = rClipRanges.Next(); p; p = rClipRanges.Next())
2464 {
2465 if (p->aStart.Col() < nStartCol)
2466 nStartCol = p->aStart.Col();
2467 if (p->aStart.Row() < nStartRow)
2468 nStartRow = p->aStart.Row();
2469 if (p->aEnd.Col() > nEndCol)
2470 nEndCol = p->aEnd.Col();
2471 if (p->aEnd.Row() < nEndRow)
2472 nEndRow = p->aEnd.Row();
2473 }
2474
2475 nClipX = nEndCol - nStartCol;
2476
2477 if ( bIncludeFiltered )
2478 nClipY = nEndRow - nStartRow;
2479 else
2480 {
2481 // count non-filtered rows
2482 // count on first used table in clipboard
2483 SCTAB nCountTab = 0;
2484 while ( nCountTab < MAXTAB && !pTab[nCountTab] )
2485 ++nCountTab;
2486
2487 SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab);
2488
2489 if ( nResult > 0 )
2490 nClipY = nResult - 1;
2491 else
2492 nClipY = 0; // always return at least 1 row
2493 }
2494 }
2495
2496
GetClipStart(SCCOL & nClipX,SCROW & nClipY)2497 void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
2498 {
2499 if (bIsClip)
2500 {
2501 ScRangeList& rClipRanges = GetClipParam().maRanges;
2502 if (rClipRanges.Count())
2503 {
2504 nClipX = rClipRanges.First()->aStart.Col();
2505 nClipY = rClipRanges.First()->aStart.Row();
2506 }
2507 }
2508 else
2509 {
2510 DBG_ERROR("GetClipStart: kein Clip");
2511 }
2512 }
2513
2514
HasClipFilteredRows()2515 sal_Bool ScDocument::HasClipFilteredRows()
2516 {
2517 // count on first used table in clipboard
2518 SCTAB nCountTab = 0;
2519 while ( nCountTab < MAXTAB && !pTab[nCountTab] )
2520 ++nCountTab;
2521
2522 ScRangeList& rClipRanges = GetClipParam().maRanges;
2523 if (!rClipRanges.Count())
2524 return false;
2525
2526 for (ScRange* p = rClipRanges.First(); p; p = rClipRanges.Next())
2527 {
2528 bool bAnswer = pTab[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row());
2529 if (bAnswer)
2530 return true;
2531 }
2532 return false;
2533 }
2534
2535
MixDocument(const ScRange & rRange,sal_uInt16 nFunction,sal_Bool bSkipEmpty,ScDocument * pSrcDoc)2536 void ScDocument::MixDocument( const ScRange& rRange, sal_uInt16 nFunction, sal_Bool bSkipEmpty,
2537 ScDocument* pSrcDoc )
2538 {
2539 SCTAB nTab1 = rRange.aStart.Tab();
2540 SCTAB nTab2 = rRange.aEnd.Tab();
2541 for (SCTAB i = nTab1; i <= nTab2; i++)
2542 if (pTab[i] && pSrcDoc->pTab[i])
2543 pTab[i]->MixData( rRange.aStart.Col(), rRange.aStart.Row(),
2544 rRange.aEnd.Col(), rRange.aEnd.Row(),
2545 nFunction, bSkipEmpty, pSrcDoc->pTab[i] );
2546 }
2547
2548
FillTab(const ScRange & rSrcArea,const ScMarkData & rMark,sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty,sal_Bool bAsLink)2549 void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark,
2550 sal_uInt16 nFlags, sal_uInt16 nFunction,
2551 sal_Bool bSkipEmpty, sal_Bool bAsLink )
2552 {
2553 sal_uInt16 nDelFlags = nFlags;
2554 if (nDelFlags & IDF_CONTENTS)
2555 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
2556
2557 SCTAB nSrcTab = rSrcArea.aStart.Tab();
2558
2559 if (ValidTab(nSrcTab) && pTab[nSrcTab])
2560 {
2561 SCCOL nStartCol = rSrcArea.aStart.Col();
2562 SCROW nStartRow = rSrcArea.aStart.Row();
2563 SCCOL nEndCol = rSrcArea.aEnd.Col();
2564 SCROW nEndRow = rSrcArea.aEnd.Row();
2565 ScDocument* pMixDoc = NULL;
2566 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
2567
2568 sal_Bool bOldAutoCalc = GetAutoCalc();
2569 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
2570
2571 SCTAB nCount = GetTableCount();
2572 for (SCTAB i=0; i<nCount; i++)
2573 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) )
2574 {
2575 if (bDoMix)
2576 {
2577 if (!pMixDoc)
2578 {
2579 pMixDoc = new ScDocument( SCDOCMODE_UNDO );
2580 pMixDoc->InitUndo( this, i, i );
2581 }
2582 else
2583 pMixDoc->AddUndoTab( i, i );
2584 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2585 IDF_CONTENTS, sal_False, pMixDoc->pTab[i] );
2586 }
2587 pTab[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags);
2588 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2589 nFlags, sal_False, pTab[i], NULL, bAsLink );
2590
2591 if (bDoMix)
2592 pTab[i]->MixData( nStartCol,nStartRow, nEndCol,nEndRow,
2593 nFunction, bSkipEmpty, pMixDoc->pTab[i] );
2594 }
2595
2596 delete pMixDoc;
2597
2598 SetAutoCalc( bOldAutoCalc );
2599 }
2600 else
2601 {
2602 DBG_ERROR("falsche Tabelle");
2603 }
2604 }
2605
2606
FillTabMarked(SCTAB nSrcTab,const ScMarkData & rMark,sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty,sal_Bool bAsLink)2607 void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark,
2608 sal_uInt16 nFlags, sal_uInt16 nFunction,
2609 sal_Bool bSkipEmpty, sal_Bool bAsLink )
2610 {
2611 sal_uInt16 nDelFlags = nFlags;
2612 if (nDelFlags & IDF_CONTENTS)
2613 nDelFlags |= IDF_CONTENTS; // immer alle Inhalte oder keine loeschen!
2614
2615 if (ValidTab(nSrcTab) && pTab[nSrcTab])
2616 {
2617 ScDocument* pMixDoc = NULL;
2618 sal_Bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
2619
2620 sal_Bool bOldAutoCalc = GetAutoCalc();
2621 SetAutoCalc( sal_False ); // Mehrfachberechnungen vermeiden
2622
2623 ScRange aArea;
2624 rMark.GetMultiMarkArea( aArea );
2625 SCCOL nStartCol = aArea.aStart.Col();
2626 SCROW nStartRow = aArea.aStart.Row();
2627 SCCOL nEndCol = aArea.aEnd.Col();
2628 SCROW nEndRow = aArea.aEnd.Row();
2629
2630 SCTAB nCount = GetTableCount();
2631 for (SCTAB i=0; i<nCount; i++)
2632 if ( i!=nSrcTab && pTab[i] && rMark.GetTableSelect(i) )
2633 {
2634 if (bDoMix)
2635 {
2636 if (!pMixDoc)
2637 {
2638 pMixDoc = new ScDocument( SCDOCMODE_UNDO );
2639 pMixDoc->InitUndo( this, i, i );
2640 }
2641 else
2642 pMixDoc->AddUndoTab( i, i );
2643 pTab[i]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2644 IDF_CONTENTS, sal_True, pMixDoc->pTab[i], &rMark );
2645 }
2646
2647 pTab[i]->DeleteSelection( nDelFlags, rMark );
2648 pTab[nSrcTab]->CopyToTable( nStartCol,nStartRow, nEndCol,nEndRow,
2649 nFlags, sal_True, pTab[i], &rMark, bAsLink );
2650
2651 if (bDoMix)
2652 pTab[i]->MixMarked( rMark, nFunction, bSkipEmpty, pMixDoc->pTab[i] );
2653 }
2654
2655 delete pMixDoc;
2656
2657 SetAutoCalc( bOldAutoCalc );
2658 }
2659 else
2660 {
2661 DBG_ERROR("falsche Tabelle");
2662 }
2663 }
2664
2665
PutCell(SCCOL nCol,SCROW nRow,SCTAB nTab,ScBaseCell * pCell,sal_Bool bForceTab)2666 void ScDocument::PutCell( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* pCell, sal_Bool bForceTab )
2667 {
2668 if (VALIDTAB(nTab))
2669 {
2670 if ( bForceTab && !pTab[nTab] )
2671 {
2672 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
2673
2674 pTab[nTab] = new ScTable(this, nTab,
2675 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
2676 bExtras, bExtras);
2677 ++nMaxTableNumber;
2678 }
2679
2680 if (pTab[nTab])
2681 pTab[nTab]->PutCell( nCol, nRow, pCell );
2682 }
2683 }
2684
2685
PutCell(const ScAddress & rPos,ScBaseCell * pCell,sal_Bool bForceTab)2686 void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell, sal_Bool bForceTab )
2687 {
2688 SCTAB nTab = rPos.Tab();
2689 if ( bForceTab && !pTab[nTab] )
2690 {
2691 sal_Bool bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
2692
2693 pTab[nTab] = new ScTable(this, nTab,
2694 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
2695 bExtras, bExtras);
2696 ++nMaxTableNumber;
2697 }
2698
2699 if (pTab[nTab])
2700 pTab[nTab]->PutCell( rPos, pCell );
2701 }
2702
2703
SetString(SCCOL nCol,SCROW nRow,SCTAB nTab,const String & rString,SvNumberFormatter * pFormatter,bool bDetectNumberFormat)2704 sal_Bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString,
2705 SvNumberFormatter* pFormatter, bool bDetectNumberFormat )
2706 {
2707 if ( ValidTab(nTab) && pTab[nTab] )
2708 return pTab[nTab]->SetString( nCol, nRow, nTab, rString, pFormatter, bDetectNumberFormat );
2709 else
2710 return sal_False;
2711 }
2712
2713
SetValue(SCCOL nCol,SCROW nRow,SCTAB nTab,const double & rVal)2714 void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal )
2715 {
2716 if (VALIDTAB(nTab))
2717 if (pTab[nTab])
2718 pTab[nTab]->SetValue( nCol, nRow, rVal );
2719 }
2720
2721
GetString(SCCOL nCol,SCROW nRow,SCTAB nTab,String & rString)2722 void ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString )
2723 {
2724 if ( VALIDTAB(nTab) && pTab[nTab] )
2725 pTab[nTab]->GetString( nCol, nRow, rString );
2726 else
2727 rString.Erase();
2728 }
2729
FillDPCache(ScDPTableDataCache * pCache,SCTAB nTab,SCCOL nStartCol,SCCOL nEndCol,SCROW nStartRow,SCROW nEndRow)2730 void ScDocument::FillDPCache( ScDPTableDataCache * pCache, SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
2731 {
2732 if ( VALIDTAB(nTab) && pTab[nTab] )
2733 pTab[nTab]->FillDPCache( pCache, nStartCol, nEndCol, nStartRow, nEndRow );
2734 }
2735
GetInputString(SCCOL nCol,SCROW nRow,SCTAB nTab,String & rString)2736 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString )
2737 {
2738 if ( VALIDTAB(nTab) && pTab[nTab] )
2739 pTab[nTab]->GetInputString( nCol, nRow, rString );
2740 else
2741 rString.Erase();
2742 }
2743
2744
GetStringForFormula(const ScAddress & rPos,rtl::OUString & rString)2745 sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, rtl::OUString& rString )
2746 {
2747 // Used in formulas (add-in parameters etc), so it must use the same semantics as
2748 // ScInterpreter::GetCellString: always format values as numbers.
2749 // The return value is the error code.
2750
2751 sal_uInt16 nErr = 0;
2752 String aStr;
2753 ScBaseCell* pCell = GetCell( rPos );
2754 if (pCell)
2755 {
2756 SvNumberFormatter* pFormatter = GetFormatTable();
2757 switch (pCell->GetCellType())
2758 {
2759 case CELLTYPE_STRING:
2760 static_cast<ScStringCell*>(pCell)->GetString(aStr);
2761 break;
2762 case CELLTYPE_EDIT:
2763 static_cast<ScEditCell*>(pCell)->GetString(aStr);
2764 break;
2765 case CELLTYPE_FORMULA:
2766 {
2767 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
2768 nErr = pFCell->GetErrCode();
2769 if (pFCell->IsValue())
2770 {
2771 double fVal = pFCell->GetValue();
2772 sal_uInt32 nIndex = pFormatter->GetStandardFormat(
2773 NUMBERFORMAT_NUMBER,
2774 ScGlobal::eLnge);
2775 pFormatter->GetInputLineString(fVal, nIndex, aStr);
2776 }
2777 else
2778 pFCell->GetString(aStr);
2779 }
2780 break;
2781 case CELLTYPE_VALUE:
2782 {
2783 double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
2784 sal_uInt32 nIndex = pFormatter->GetStandardFormat(
2785 NUMBERFORMAT_NUMBER,
2786 ScGlobal::eLnge);
2787 pFormatter->GetInputLineString(fVal, nIndex, aStr);
2788 }
2789 break;
2790 default:
2791 ;
2792 }
2793 }
2794 rString = aStr;
2795 return nErr;
2796 }
2797
2798
GetValue(SCCOL nCol,SCROW nRow,SCTAB nTab,double & rValue)2799 void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue )
2800 {
2801 if ( VALIDTAB(nTab) && pTab[nTab] )
2802 rValue = pTab[nTab]->GetValue( nCol, nRow );
2803 else
2804 rValue = 0.0;
2805 }
2806
2807
GetValue(const ScAddress & rPos)2808 double ScDocument::GetValue( const ScAddress& rPos )
2809 {
2810 SCTAB nTab = rPos.Tab();
2811 if ( pTab[nTab] )
2812 return pTab[nTab]->GetValue( rPos );
2813 return 0.0;
2814 }
2815
2816
GetNumberFormat(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_uInt32 & rFormat)2817 void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
2818 sal_uInt32& rFormat )
2819 {
2820 if (VALIDTAB(nTab))
2821 if (pTab[nTab])
2822 {
2823 rFormat = pTab[nTab]->GetNumberFormat( nCol, nRow );
2824 return ;
2825 }
2826 rFormat = 0;
2827 }
2828
2829
GetNumberFormat(const ScAddress & rPos) const2830 sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const
2831 {
2832 SCTAB nTab = rPos.Tab();
2833 if ( pTab[nTab] )
2834 return pTab[nTab]->GetNumberFormat( rPos );
2835 return 0;
2836 }
2837
2838
GetNumberFormatInfo(short & nType,sal_uLong & nIndex,const ScAddress & rPos,const ScBaseCell * pCell) const2839 void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex,
2840 const ScAddress& rPos, const ScBaseCell* pCell ) const
2841 {
2842 SCTAB nTab = rPos.Tab();
2843 if ( pTab[nTab] )
2844 {
2845 nIndex = pTab[nTab]->GetNumberFormat( rPos );
2846 if ( (nIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && pCell &&
2847 pCell->GetCellType() == CELLTYPE_FORMULA )
2848 static_cast<const ScFormulaCell*>(pCell)->GetFormatInfo( nType, nIndex );
2849 else
2850 nType = GetFormatTable()->GetType( nIndex );
2851 }
2852 else
2853 {
2854 nType = NUMBERFORMAT_UNDEFINED;
2855 nIndex = 0;
2856 }
2857 }
2858
2859
GetFormula(SCCOL nCol,SCROW nRow,SCTAB nTab,String & rFormula,sal_Bool bAsciiExport) const2860 void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rFormula,
2861 sal_Bool bAsciiExport ) const
2862 {
2863 if ( VALIDTAB(nTab) && pTab[nTab] )
2864 pTab[nTab]->GetFormula( nCol, nRow, rFormula, bAsciiExport );
2865 else
2866 rFormula.Erase();
2867 }
2868
2869
GetCellType(const ScAddress & rPos) const2870 CellType ScDocument::GetCellType( const ScAddress& rPos ) const
2871 {
2872 SCTAB nTab = rPos.Tab();
2873 if ( pTab[nTab] )
2874 return pTab[nTab]->GetCellType( rPos );
2875 return CELLTYPE_NONE;
2876 }
2877
2878
GetCellType(SCCOL nCol,SCROW nRow,SCTAB nTab,CellType & rCellType) const2879 void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab,
2880 CellType& rCellType ) const
2881 {
2882 if (ValidTab(nTab) && pTab[nTab])
2883 rCellType = pTab[nTab]->GetCellType( nCol, nRow );
2884 else
2885 rCellType = CELLTYPE_NONE;
2886 }
2887
2888
GetCell(SCCOL nCol,SCROW nRow,SCTAB nTab,ScBaseCell * & rpCell) const2889 void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
2890 ScBaseCell*& rpCell ) const
2891 {
2892 if (ValidTab(nTab) && pTab[nTab])
2893 rpCell = pTab[nTab]->GetCell( nCol, nRow );
2894 else
2895 {
2896 DBG_ERROR("GetCell ohne Tabelle");
2897 rpCell = NULL;
2898 }
2899 }
2900
2901
GetCell(const ScAddress & rPos) const2902 ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const
2903 {
2904 SCTAB nTab = rPos.Tab();
2905 if (ValidTab(nTab) && pTab[nTab])
2906 return pTab[nTab]->GetCell( rPos );
2907
2908 DBG_ERROR("GetCell ohne Tabelle");
2909 return NULL;
2910 }
2911
2912
HasStringData(SCCOL nCol,SCROW nRow,SCTAB nTab) const2913 sal_Bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
2914 {
2915 if ( VALIDTAB(nTab) && pTab[nTab] )
2916 return pTab[nTab]->HasStringData( nCol, nRow );
2917 else
2918 return sal_False;
2919 }
2920
2921
HasValueData(SCCOL nCol,SCROW nRow,SCTAB nTab) const2922 sal_Bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
2923 {
2924 if ( VALIDTAB(nTab) && pTab[nTab] )
2925 return pTab[nTab]->HasValueData( nCol, nRow );
2926 else
2927 return sal_False;
2928 }
2929
2930
HasStringCells(const ScRange & rRange) const2931 sal_Bool ScDocument::HasStringCells( const ScRange& rRange ) const
2932 {
2933 // sal_True, wenn String- oder Editzellen im Bereich
2934
2935 SCCOL nStartCol = rRange.aStart.Col();
2936 SCROW nStartRow = rRange.aStart.Row();
2937 SCTAB nStartTab = rRange.aStart.Tab();
2938 SCCOL nEndCol = rRange.aEnd.Col();
2939 SCROW nEndRow = rRange.aEnd.Row();
2940 SCTAB nEndTab = rRange.aEnd.Tab();
2941
2942 for ( SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++ )
2943 if ( pTab[nTab] && pTab[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) )
2944 return sal_True;
2945
2946 return sal_False;
2947 }
2948
2949
HasSelectionData(SCCOL nCol,SCROW nRow,SCTAB nTab) const2950 sal_Bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
2951 {
2952 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
2953 if( nValidation )
2954 {
2955 const ScValidationData* pData = GetValidationEntry( nValidation );
2956 if( pData && pData->HasSelectionList() )
2957 return sal_True;
2958 }
2959 return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) );
2960 }
2961
2962
GetNote(const ScAddress & rPos)2963 ScPostIt* ScDocument::GetNote( const ScAddress& rPos )
2964 {
2965 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0;
2966 return pTable ? pTable->GetNote( rPos.Col(), rPos.Row() ) : 0;
2967 }
2968
2969
TakeNote(const ScAddress & rPos,ScPostIt * & rpNote)2970 void ScDocument::TakeNote( const ScAddress& rPos, ScPostIt*& rpNote )
2971 {
2972 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] )
2973 pTab[ rPos.Tab() ]->TakeNote( rPos.Col(), rPos.Row(), rpNote );
2974 else
2975 DELETEZ( rpNote );
2976 }
2977
2978
ReleaseNote(const ScAddress & rPos)2979 ScPostIt* ScDocument::ReleaseNote( const ScAddress& rPos )
2980 {
2981 ScTable* pTable = ValidTab( rPos.Tab() ) ? pTab[ rPos.Tab() ] : 0;
2982 return pTable ? pTable->ReleaseNote( rPos.Col(), rPos.Row() ) : 0;
2983 }
2984
2985
GetOrCreateNote(const ScAddress & rPos)2986 ScPostIt* ScDocument::GetOrCreateNote( const ScAddress& rPos )
2987 {
2988 ScPostIt* pNote = GetNote( rPos );
2989 if( !pNote )
2990 {
2991 pNote = new ScPostIt( *this, rPos, false );
2992 TakeNote( rPos, pNote );
2993 }
2994 return pNote;
2995 }
2996
2997
DeleteNote(const ScAddress & rPos)2998 void ScDocument::DeleteNote( const ScAddress& rPos )
2999 {
3000 if( ValidTab( rPos.Tab() ) && pTab[ rPos.Tab() ] )
3001 pTab[ rPos.Tab() ]->DeleteNote( rPos.Col(), rPos.Row() );
3002 }
3003
3004
InitializeNoteCaptions(SCTAB nTab,bool bForced)3005 void ScDocument::InitializeNoteCaptions( SCTAB nTab, bool bForced )
3006 {
3007 if( ValidTab( nTab ) && pTab[ nTab ] )
3008 pTab[ nTab ]->InitializeNoteCaptions( bForced );
3009 }
3010
InitializeAllNoteCaptions(bool bForced)3011 void ScDocument::InitializeAllNoteCaptions( bool bForced )
3012 {
3013 for( SCTAB nTab = 0; nTab < GetTableCount(); ++nTab )
3014 InitializeNoteCaptions( nTab, bForced );
3015 }
3016
SetDirty()3017 void ScDocument::SetDirty()
3018 {
3019 sal_Bool bOldAutoCalc = GetAutoCalc();
3020 bAutoCalc = sal_False; // keine Mehrfachberechnung
3021 { // scope for bulk broadcast
3022 ScBulkBroadcast aBulkBroadcast( GetBASM());
3023 for (SCTAB i=0; i<=MAXTAB; i++)
3024 if (pTab[i]) pTab[i]->SetDirty();
3025 }
3026
3027 // Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt,
3028 // wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt
3029 // (#45205#) - darum alle Charts nochmal explizit
3030 if (pChartListenerCollection)
3031 pChartListenerCollection->SetDirty();
3032
3033 SetAutoCalc( bOldAutoCalc );
3034 }
3035
3036
SetDirty(const ScRange & rRange)3037 void ScDocument::SetDirty( const ScRange& rRange )
3038 {
3039 sal_Bool bOldAutoCalc = GetAutoCalc();
3040 bAutoCalc = sal_False; // keine Mehrfachberechnung
3041 { // scope for bulk broadcast
3042 ScBulkBroadcast aBulkBroadcast( GetBASM());
3043 SCTAB nTab2 = rRange.aEnd.Tab();
3044 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++)
3045 if (pTab[i]) pTab[i]->SetDirty( rRange );
3046 }
3047 SetAutoCalc( bOldAutoCalc );
3048 }
3049
3050
SetTableOpDirty(const ScRange & rRange)3051 void ScDocument::SetTableOpDirty( const ScRange& rRange )
3052 {
3053 sal_Bool bOldAutoCalc = GetAutoCalc();
3054 bAutoCalc = sal_False; // no multiple recalculation
3055 SCTAB nTab2 = rRange.aEnd.Tab();
3056 for (SCTAB i=rRange.aStart.Tab(); i<=nTab2; i++)
3057 if (pTab[i]) pTab[i]->SetTableOpDirty( rRange );
3058 SetAutoCalc( bOldAutoCalc );
3059 }
3060
3061
InterpretDirtyCells(const ScRangeList & rRanges)3062 void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
3063 {
3064 sal_uLong nRangeCount = rRanges.Count();
3065 for (sal_uLong nPos=0; nPos<nRangeCount; nPos++)
3066 {
3067 ScCellIterator aIter( this, *rRanges.GetObject(nPos) );
3068 ScBaseCell* pCell = aIter.GetFirst();
3069 while (pCell)
3070 {
3071 if (pCell->GetCellType() == CELLTYPE_FORMULA)
3072 {
3073 if ( static_cast<ScFormulaCell*>(pCell)->GetDirty() && GetAutoCalc() )
3074 static_cast<ScFormulaCell*>(pCell)->Interpret();
3075 }
3076 pCell = aIter.GetNext();
3077 }
3078 }
3079 }
3080
3081
AddTableOpFormulaCell(ScFormulaCell * pCell)3082 void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
3083 {
3084 ScInterpreterTableOpParams* p = aTableOpList.Last();
3085 if ( p && p->bCollectNotifications )
3086 {
3087 if ( p->bRefresh )
3088 { // refresh pointers only
3089 p->aNotifiedFormulaCells.push_back( pCell );
3090 }
3091 else
3092 { // init both, address and pointer
3093 p->aNotifiedFormulaCells.push_back( pCell );
3094 p->aNotifiedFormulaPos.push_back( pCell->aPos );
3095 }
3096 }
3097 }
3098
3099
CalcAll()3100 void ScDocument::CalcAll()
3101 {
3102 ClearLookupCaches(); // Ensure we don't deliver zombie data.
3103 sal_Bool bOldAutoCalc = GetAutoCalc();
3104 SetAutoCalc( sal_True );
3105 SCTAB i;
3106 for (i=0; i<=MAXTAB; i++)
3107 if (pTab[i]) pTab[i]->SetDirtyVar();
3108 for (i=0; i<=MAXTAB; i++)
3109 if (pTab[i]) pTab[i]->CalcAll();
3110 ClearFormulaTree();
3111 SetAutoCalc( bOldAutoCalc );
3112 }
3113
3114
CompileAll()3115 void ScDocument::CompileAll()
3116 {
3117 if ( pCondFormList )
3118 pCondFormList->CompileAll();
3119
3120 for (SCTAB i=0; i<=MAXTAB; i++)
3121 if (pTab[i]) pTab[i]->CompileAll();
3122 SetDirty();
3123 }
3124
3125
CompileXML()3126 void ScDocument::CompileXML()
3127 {
3128 sal_Bool bOldAutoCalc = GetAutoCalc();
3129 SetAutoCalc( sal_False );
3130 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(
3131 STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() );
3132
3133 // #b6355215# set AutoNameCache to speed up automatic name lookup
3134 DBG_ASSERT( !pAutoNameCache, "AutoNameCache already set" );
3135 pAutoNameCache = new ScAutoNameCache( this );
3136
3137 for (SCTAB i=0; i<=MAXTAB; i++)
3138 if (pTab[i]) pTab[i]->CompileXML( aProgress );
3139
3140 DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change
3141
3142 if ( pCondFormList )
3143 pCondFormList->CompileXML();
3144 if ( pValidationList )
3145 pValidationList->CompileXML();
3146
3147 SetDirty();
3148 SetAutoCalc( bOldAutoCalc );
3149 }
3150
3151
CalcAfterLoad()3152 void ScDocument::CalcAfterLoad()
3153 {
3154 SCTAB i;
3155
3156 if (bIsClip) // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen
3157 return; // dann wird erst beim Einfuegen in das richtige Doc berechnet
3158
3159 bCalcingAfterLoad = sal_True;
3160 for ( i = 0; i <= MAXTAB; i++)
3161 if (pTab[i]) pTab[i]->CalcAfterLoad();
3162 for (i=0; i<=MAXTAB; i++)
3163 if (pTab[i]) pTab[i]->SetDirtyAfterLoad();
3164 bCalcingAfterLoad = sal_False;
3165
3166 SetDetectiveDirty(sal_False); // noch keine wirklichen Aenderungen
3167
3168 // #i112436# If formula cells are already dirty, they don't broadcast further changes.
3169 // So the source ranges of charts must be interpreted even if they are not visible,
3170 // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899).
3171 if (pChartListenerCollection)
3172 {
3173 sal_uInt16 nChartCount = pChartListenerCollection->GetCount();
3174 for ( sal_uInt16 nIndex = 0; nIndex < nChartCount; nIndex++ )
3175 {
3176 ScChartListener* pChartListener = static_cast<ScChartListener*>(pChartListenerCollection->At(nIndex));
3177 InterpretDirtyCells(*pChartListener->GetRangeList());
3178 }
3179 }
3180 }
3181
3182
GetErrCode(const ScAddress & rPos) const3183 sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const
3184 {
3185 SCTAB nTab = rPos.Tab();
3186 if ( pTab[nTab] )
3187 return pTab[nTab]->GetErrCode( rPos );
3188 return 0;
3189 }
3190
3191
ResetChanged(const ScRange & rRange)3192 void ScDocument::ResetChanged( const ScRange& rRange )
3193 {
3194 SCTAB nStartTab = rRange.aStart.Tab();
3195 SCTAB nEndTab = rRange.aEnd.Tab();
3196 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3197 if (pTab[nTab])
3198 pTab[nTab]->ResetChanged( rRange );
3199 }
3200
3201 //
3202 // Spaltenbreiten / Zeilenhoehen --------------------------------------
3203 //
3204
3205
SetColWidth(SCCOL nCol,SCTAB nTab,sal_uInt16 nNewWidth)3206 void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3207 {
3208 if ( ValidTab(nTab) && pTab[nTab] )
3209 pTab[nTab]->SetColWidth( nCol, nNewWidth );
3210 }
3211
SetColWidthOnly(SCCOL nCol,SCTAB nTab,sal_uInt16 nNewWidth)3212 void ScDocument::SetColWidthOnly( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3213 {
3214 if ( ValidTab(nTab) && pTab[nTab] )
3215 pTab[nTab]->SetColWidthOnly( nCol, nNewWidth );
3216 }
3217
SetRowHeight(SCROW nRow,SCTAB nTab,sal_uInt16 nNewHeight)3218 void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight )
3219 {
3220 if ( ValidTab(nTab) && pTab[nTab] )
3221 pTab[nTab]->SetRowHeight( nRow, nNewHeight );
3222 }
3223
3224
SetRowHeightRange(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_uInt16 nNewHeight)3225 void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3226 {
3227 if ( ValidTab(nTab) && pTab[nTab] )
3228 pTab[nTab]->SetRowHeightRange
3229 ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 );
3230 }
3231
SetRowHeightOnly(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_uInt16 nNewHeight)3232 void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3233 {
3234 if ( ValidTab(nTab) && pTab[nTab] )
3235 pTab[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight );
3236 }
3237
SetManualHeight(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_Bool bManual)3238 void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_Bool bManual )
3239 {
3240 if ( ValidTab(nTab) && pTab[nTab] )
3241 pTab[nTab]->SetManualHeight( nStartRow, nEndRow, bManual );
3242 }
3243
3244
GetColWidth(SCCOL nCol,SCTAB nTab) const3245 sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab ) const
3246 {
3247 if ( ValidTab(nTab) && pTab[nTab] )
3248 return pTab[nTab]->GetColWidth( nCol );
3249 DBG_ERROR("Falsche Tabellennummer");
3250 return 0;
3251 }
3252
3253
GetOriginalWidth(SCCOL nCol,SCTAB nTab) const3254 sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const
3255 {
3256 if ( ValidTab(nTab) && pTab[nTab] )
3257 return pTab[nTab]->GetOriginalWidth( nCol );
3258 DBG_ERROR("Falsche Tabellennummer");
3259 return 0;
3260 }
3261
3262
GetCommonWidth(SCCOL nEndCol,SCTAB nTab) const3263 sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const
3264 {
3265 if ( ValidTab(nTab) && pTab[nTab] )
3266 return pTab[nTab]->GetCommonWidth( nEndCol );
3267 DBG_ERROR("Wrong table number");
3268 return 0;
3269 }
3270
3271
GetOriginalHeight(SCROW nRow,SCTAB nTab) const3272 sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const
3273 {
3274 if ( ValidTab(nTab) && pTab[nTab] )
3275 return pTab[nTab]->GetOriginalHeight( nRow );
3276 DBG_ERROR("Wrong table number");
3277 return 0;
3278 }
3279
3280
GetRowHeight(SCROW nRow,SCTAB nTab,bool bHiddenAsZero) const3281 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
3282 {
3283 if ( ValidTab(nTab) && pTab[nTab] )
3284 return pTab[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero );
3285 DBG_ERROR("Wrong sheet number");
3286 return 0;
3287 }
3288
3289
GetRowHeight(SCROW nRow,SCTAB nTab,SCROW * pStartRow,SCROW * pEndRow,bool bHiddenAsZero) const3290 sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
3291 {
3292 if ( ValidTab(nTab) && pTab[nTab] )
3293 return pTab[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero );
3294 DBG_ERROR("Wrong sheet number");
3295 return 0;
3296 }
3297
3298
GetRowHeight(SCROW nStartRow,SCROW nEndRow,SCTAB nTab) const3299 sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const
3300 {
3301 if (nStartRow == nEndRow)
3302 return GetRowHeight( nStartRow, nTab); // faster for a single row
3303
3304 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3305 if (nStartRow > nEndRow)
3306 return 0;
3307
3308 if ( ValidTab(nTab) && pTab[nTab] )
3309 return pTab[nTab]->GetRowHeight( nStartRow, nEndRow);
3310
3311 DBG_ERROR("wrong sheet number");
3312 return 0;
3313 }
3314
GetRowForHeight(SCTAB nTab,sal_uLong nHeight) const3315 SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const
3316 {
3317 return pTab[nTab]->GetRowForHeight(nHeight);
3318 }
3319
GetScaledRowHeight(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,double fScale) const3320 sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow,
3321 SCTAB nTab, double fScale ) const
3322 {
3323 // faster for a single row
3324 if (nStartRow == nEndRow)
3325 return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale);
3326
3327 // check bounds because this method replaces former for(i=start;i<=end;++i) loops
3328 if (nStartRow > nEndRow)
3329 return 0;
3330
3331 if ( ValidTab(nTab) && pTab[nTab] )
3332 return pTab[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale);
3333
3334 DBG_ERROR("wrong sheet number");
3335 return 0;
3336 }
3337
GetHiddenRowCount(SCROW nRow,SCTAB nTab) const3338 SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const
3339 {
3340 if ( ValidTab(nTab) && pTab[nTab] )
3341 return pTab[nTab]->GetHiddenRowCount( nRow );
3342 DBG_ERROR("Falsche Tabellennummer");
3343 return 0;
3344 }
3345
3346
GetColOffset(SCCOL nCol,SCTAB nTab) const3347 sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab ) const
3348 {
3349 if ( ValidTab(nTab) && pTab[nTab] )
3350 return pTab[nTab]->GetColOffset( nCol );
3351 DBG_ERROR("Falsche Tabellennummer");
3352 return 0;
3353 }
3354
3355
GetRowOffset(SCROW nRow,SCTAB nTab) const3356 sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab ) const
3357 {
3358 if ( ValidTab(nTab) && pTab[nTab] )
3359 return pTab[nTab]->GetRowOffset( nRow );
3360 DBG_ERROR("Falsche Tabellennummer");
3361 return 0;
3362 }
3363
3364
GetOptimalColWidth(SCCOL nCol,SCTAB nTab,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bFormula,const ScMarkData * pMarkData,sal_Bool bSimpleTextImport)3365 sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev,
3366 double nPPTX, double nPPTY,
3367 const Fraction& rZoomX, const Fraction& rZoomY,
3368 sal_Bool bFormula, const ScMarkData* pMarkData,
3369 sal_Bool bSimpleTextImport )
3370 {
3371 if ( ValidTab(nTab) && pTab[nTab] )
3372 return pTab[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY,
3373 rZoomX, rZoomY, bFormula, pMarkData, bSimpleTextImport );
3374 DBG_ERROR("Falsche Tabellennummer");
3375 return 0;
3376 }
3377
3378
GetNeededSize(SCCOL nCol,SCROW nRow,SCTAB nTab,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bWidth,sal_Bool bTotalSize)3379 long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab,
3380 OutputDevice* pDev,
3381 double nPPTX, double nPPTY,
3382 const Fraction& rZoomX, const Fraction& rZoomY,
3383 sal_Bool bWidth, sal_Bool bTotalSize )
3384 {
3385 if ( ValidTab(nTab) && pTab[nTab] )
3386 return pTab[nTab]->GetNeededSize
3387 ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize );
3388 DBG_ERROR("Falsche Tabellennummer");
3389 return 0;
3390 }
3391
3392
SetOptimalHeight(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_uInt16 nExtra,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bShrink)3393 sal_Bool ScDocument::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nExtra,
3394 OutputDevice* pDev,
3395 double nPPTX, double nPPTY,
3396 const Fraction& rZoomX, const Fraction& rZoomY,
3397 sal_Bool bShrink )
3398 {
3399 //! MarkToMulti();
3400 if ( ValidTab(nTab) && pTab[nTab] )
3401 return pTab[nTab]->SetOptimalHeight( nStartRow, nEndRow, nExtra,
3402 pDev, nPPTX, nPPTY, rZoomX, rZoomY, bShrink );
3403 DBG_ERROR("Falsche Tabellennummer");
3404 return sal_False;
3405 }
3406
3407
UpdateAllRowHeights(OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,const ScMarkData * pTabMark)3408 void ScDocument::UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY,
3409 const Fraction& rZoomX, const Fraction& rZoomY, const ScMarkData* pTabMark )
3410 {
3411 // one progress across all (selected) sheets
3412
3413 sal_uLong nCellCount = 0;
3414 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
3415 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
3416 nCellCount += pTab[nTab]->GetWeightedCount();
3417
3418 ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount );
3419
3420 sal_uLong nProgressStart = 0;
3421 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
3422 if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
3423 {
3424 pTab[nTab]->SetOptimalHeight( 0, MAXROW, 0,
3425 pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False, &aProgress, nProgressStart );
3426 nProgressStart += pTab[nTab]->GetWeightedCount();
3427 }
3428 }
3429
3430
3431 //
3432 // Spalten-/Zeilen-Flags ----------------------------------------------
3433 //
3434
ShowCol(SCCOL nCol,SCTAB nTab,sal_Bool bShow)3435 void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, sal_Bool bShow)
3436 {
3437 if ( ValidTab(nTab) && pTab[nTab] )
3438 pTab[nTab]->ShowCol( nCol, bShow );
3439 }
3440
3441
ShowRow(SCROW nRow,SCTAB nTab,sal_Bool bShow)3442 void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, sal_Bool bShow)
3443 {
3444 if ( ValidTab(nTab) && pTab[nTab] )
3445 pTab[nTab]->ShowRow( nRow, bShow );
3446 }
3447
3448
ShowRows(SCROW nRow1,SCROW nRow2,SCTAB nTab,sal_Bool bShow)3449 void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, sal_Bool bShow)
3450 {
3451 if ( ValidTab(nTab) && pTab[nTab] )
3452 pTab[nTab]->ShowRows( nRow1, nRow2, bShow );
3453 }
3454
3455
SetColFlags(SCCOL nCol,SCTAB nTab,sal_uInt8 nNewFlags)3456 void ScDocument::SetColFlags( SCCOL nCol, SCTAB nTab, sal_uInt8 nNewFlags )
3457 {
3458 if ( ValidTab(nTab) && pTab[nTab] )
3459 pTab[nTab]->SetColFlags( nCol, nNewFlags );
3460 }
3461
3462
SetRowFlags(SCROW nRow,SCTAB nTab,sal_uInt8 nNewFlags)3463 void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags )
3464 {
3465 if ( ValidTab(nTab) && pTab[nTab] )
3466 pTab[nTab]->SetRowFlags( nRow, nNewFlags );
3467 }
3468
3469
SetRowFlags(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,sal_uInt8 nNewFlags)3470 void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags )
3471 {
3472 if ( ValidTab(nTab) && pTab[nTab] )
3473 pTab[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags );
3474 }
3475
3476
GetColFlags(SCCOL nCol,SCTAB nTab) const3477 sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const
3478 {
3479 if ( ValidTab(nTab) && pTab[nTab] )
3480 return pTab[nTab]->GetColFlags( nCol );
3481 DBG_ERROR("Falsche Tabellennummer");
3482 return 0;
3483 }
3484
GetRowFlags(SCROW nRow,SCTAB nTab) const3485 sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const
3486 {
3487 if ( ValidTab(nTab) && pTab[nTab] )
3488 return pTab[nTab]->GetRowFlags( nRow );
3489 DBG_ERROR("Falsche Tabellennummer");
3490 return 0;
3491 }
3492
GetRowFlagsArrayModifiable(SCTAB nTab)3493 ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArrayModifiable(
3494 SCTAB nTab )
3495 {
3496 return const_cast< ScBitMaskCompressedArray< SCROW, sal_uInt8> & >(
3497 GetRowFlagsArray( nTab));
3498 }
3499
GetRowFlagsArray(SCTAB nTab) const3500 const ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArray(
3501 SCTAB nTab ) const
3502 {
3503 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pFlags;
3504 if ( ValidTab(nTab) && pTab[nTab] )
3505 pFlags = pTab[nTab]->GetRowFlagsArray();
3506 else
3507 {
3508 DBG_ERROR("wrong sheet number");
3509 pFlags = 0;
3510 }
3511 if (!pFlags)
3512 {
3513 DBG_ERROR("no row flags at sheet");
3514 static ScBitMaskCompressedArray< SCROW, sal_uInt8> aDummy( MAXROW, 0);
3515 pFlags = &aDummy;
3516 }
3517 return *pFlags;
3518 }
3519
GetAllRowBreaks(set<SCROW> & rBreaks,SCTAB nTab,bool bPage,bool bManual) const3520 void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
3521 {
3522 if (!ValidTab(nTab) || !pTab[nTab])
3523 return;
3524
3525 pTab[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual);
3526 }
3527
GetAllColBreaks(set<SCCOL> & rBreaks,SCTAB nTab,bool bPage,bool bManual) const3528 void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
3529 {
3530 if (!ValidTab(nTab) || !pTab[nTab])
3531 return;
3532
3533 pTab[nTab]->GetAllColBreaks(rBreaks, bPage, bManual);
3534 }
3535
HasRowBreak(SCROW nRow,SCTAB nTab) const3536 ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const
3537 {
3538 ScBreakType nType = BREAK_NONE;
3539 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow))
3540 return nType;
3541
3542 if (pTab[nTab]->HasRowPageBreak(nRow))
3543 nType |= BREAK_PAGE;
3544
3545 if (pTab[nTab]->HasRowManualBreak(nRow))
3546 nType |= BREAK_MANUAL;
3547
3548 return nType;
3549 }
3550
HasColBreak(SCCOL nCol,SCTAB nTab) const3551 ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const
3552 {
3553 ScBreakType nType = BREAK_NONE;
3554 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol))
3555 return nType;
3556
3557 if (pTab[nTab]->HasColPageBreak(nCol))
3558 nType |= BREAK_PAGE;
3559
3560 if (pTab[nTab]->HasColManualBreak(nCol))
3561 nType |= BREAK_MANUAL;
3562
3563 return nType;
3564 }
3565
SetRowBreak(SCROW nRow,SCTAB nTab,bool bPage,bool bManual)3566 void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
3567 {
3568 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow))
3569 return;
3570
3571 pTab[nTab]->SetRowBreak(nRow, bPage, bManual);
3572 }
3573
SetColBreak(SCCOL nCol,SCTAB nTab,bool bPage,bool bManual)3574 void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
3575 {
3576 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol))
3577 return;
3578
3579 pTab[nTab]->SetColBreak(nCol, bPage, bManual);
3580 }
3581
RemoveRowBreak(SCROW nRow,SCTAB nTab,bool bPage,bool bManual)3582 void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
3583 {
3584 if (!ValidTab(nTab) || !pTab[nTab] || !ValidRow(nRow))
3585 return;
3586
3587 pTab[nTab]->RemoveRowBreak(nRow, bPage, bManual);
3588 }
3589
RemoveColBreak(SCCOL nCol,SCTAB nTab,bool bPage,bool bManual)3590 void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
3591 {
3592 if (!ValidTab(nTab) || !pTab[nTab] || !ValidCol(nCol))
3593 return;
3594
3595 pTab[nTab]->RemoveColBreak(nCol, bPage, bManual);
3596 }
3597
GetRowBreakData(SCTAB nTab) const3598 Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const
3599 {
3600 if (!ValidTab(nTab) || !pTab[nTab])
3601 return Sequence<TablePageBreakData>();
3602
3603 return pTab[nTab]->GetRowBreakData();
3604 }
3605
RowHidden(SCROW nRow,SCTAB nTab,SCROW * pFirstRow,SCROW * pLastRow)3606 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow)
3607 {
3608 if (!ValidTab(nTab) || !pTab[nTab])
3609 return false;
3610
3611 return pTab[nTab]->RowHidden(nRow, pFirstRow, pLastRow);
3612 }
3613
RowHidden(SCROW nRow,SCTAB nTab,SCROW & rLastRow)3614 bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW& rLastRow)
3615 {
3616 if (!ValidTab(nTab) || !pTab[nTab])
3617 {
3618 rLastRow = nRow;
3619 return false;
3620 }
3621
3622 return pTab[nTab]->RowHidden(nRow, rLastRow);
3623 }
3624
3625
HasHiddenRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3626 bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3627 {
3628 if (!ValidTab(nTab) || !pTab[nTab])
3629 return false;
3630
3631 return pTab[nTab]->HasHiddenRows(nStartRow, nEndRow);
3632 }
3633
ColHidden(SCCOL nCol,SCTAB nTab,SCCOL & rLastCol)3634 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL& rLastCol)
3635 {
3636 if (!ValidTab(nTab) || !pTab[nTab])
3637 {
3638 rLastCol = nCol;
3639 return false;
3640 }
3641
3642 return pTab[nTab]->ColHidden(nCol, rLastCol);
3643 }
3644
ColHidden(SCCOL nCol,SCTAB nTab,SCCOL * pFirstCol,SCCOL * pLastCol)3645 bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol)
3646 {
3647 if (!ValidTab(nTab) || !pTab[nTab])
3648 {
3649 if (pFirstCol)
3650 *pFirstCol = nCol;
3651 if (pLastCol)
3652 *pLastCol = nCol;
3653 return false;
3654 }
3655
3656 return pTab[nTab]->ColHidden(nCol, pFirstCol, pLastCol);
3657 }
3658
SetRowHidden(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,bool bHidden)3659 void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden)
3660 {
3661 if (!ValidTab(nTab) || !pTab[nTab])
3662 return;
3663
3664 pTab[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden);
3665 }
3666
SetColHidden(SCCOL nStartCol,SCCOL nEndCol,SCTAB nTab,bool bHidden)3667 void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden)
3668 {
3669 if (!ValidTab(nTab) || !pTab[nTab])
3670 return;
3671
3672 pTab[nTab]->SetColHidden(nStartCol, nEndCol, bHidden);
3673 }
3674
FirstVisibleRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3675 SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3676 {
3677 if (!ValidTab(nTab) || !pTab[nTab])
3678 return ::std::numeric_limits<SCROW>::max();;
3679
3680 return pTab[nTab]->FirstVisibleRow(nStartRow, nEndRow);
3681 }
3682
LastVisibleRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3683 SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3684 {
3685 if (!ValidTab(nTab) || !pTab[nTab])
3686 return ::std::numeric_limits<SCROW>::max();;
3687
3688 return pTab[nTab]->LastVisibleRow(nStartRow, nEndRow);
3689 }
3690
CountVisibleRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3691 SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3692 {
3693 if (!ValidTab(nTab) || !pTab[nTab])
3694 return 0;
3695
3696 return pTab[nTab]->CountVisibleRows(nStartRow, nEndRow);
3697 }
3698
RowFiltered(SCROW nRow,SCTAB nTab,SCROW * pFirstRow,SCROW * pLastRow)3699 bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow)
3700 {
3701 if (!ValidTab(nTab) || !pTab[nTab])
3702 return false;
3703
3704 return pTab[nTab]->RowFiltered(nRow, pFirstRow, pLastRow);
3705 }
3706
HasFilteredRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3707 bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3708 {
3709 if (!ValidTab(nTab) || !pTab[nTab])
3710 return false;
3711
3712 return pTab[nTab]->HasFilteredRows(nStartRow, nEndRow);
3713 }
3714
ColFiltered(SCCOL nCol,SCTAB nTab,SCCOL * pFirstCol,SCCOL * pLastCol)3715 bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol)
3716 {
3717 if (!ValidTab(nTab) || !pTab[nTab])
3718 return false;
3719
3720 return pTab[nTab]->ColFiltered(nCol, pFirstCol, pLastCol);
3721 }
3722
SetRowFiltered(SCROW nStartRow,SCROW nEndRow,SCTAB nTab,bool bFiltered)3723 void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered)
3724 {
3725 if (!ValidTab(nTab) || !pTab[nTab])
3726 return;
3727
3728 pTab[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered);
3729 }
3730
SetColFiltered(SCCOL nStartCol,SCCOL nEndCol,SCTAB nTab,bool bFiltered)3731 void ScDocument::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bFiltered)
3732 {
3733 if (!ValidTab(nTab) || !pTab[nTab])
3734 return;
3735
3736 pTab[nTab]->SetColFiltered(nStartCol, nEndCol, bFiltered);
3737 }
3738
FirstNonFilteredRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3739 SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3740 {
3741 if (!ValidTab(nTab) || !pTab[nTab])
3742 return ::std::numeric_limits<SCROW>::max();;
3743
3744 return pTab[nTab]->FirstNonFilteredRow(nStartRow, nEndRow);
3745 }
3746
LastNonFilteredRow(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3747 SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3748 {
3749 if (!ValidTab(nTab) || !pTab[nTab])
3750 return ::std::numeric_limits<SCROW>::max();;
3751
3752 return pTab[nTab]->LastNonFilteredRow(nStartRow, nEndRow);
3753 }
3754
CountNonFilteredRows(SCROW nStartRow,SCROW nEndRow,SCTAB nTab)3755 SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
3756 {
3757 if (!ValidTab(nTab) || !pTab[nTab])
3758 return 0;
3759
3760 return pTab[nTab]->CountNonFilteredRows(nStartRow, nEndRow);
3761 }
3762
SyncColRowFlags()3763 void ScDocument::SyncColRowFlags()
3764 {
3765 for (SCTAB i = 0; i <= nMaxTableNumber; ++i)
3766 {
3767 if (!ValidTab(i) || !pTab[i])
3768 continue;
3769
3770 pTab[i]->SyncColRowFlags();
3771 }
3772 }
3773
GetLastFlaggedRow(SCTAB nTab) const3774 SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const
3775 {
3776 if ( ValidTab(nTab) && pTab[nTab] )
3777 return pTab[nTab]->GetLastFlaggedRow();
3778 return 0;
3779 }
3780
3781
GetLastChangedCol(SCTAB nTab) const3782 SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const
3783 {
3784 if ( ValidTab(nTab) && pTab[nTab] )
3785 return pTab[nTab]->GetLastChangedCol();
3786 return 0;
3787 }
3788
GetLastChangedRow(SCTAB nTab) const3789 SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const
3790 {
3791 if ( ValidTab(nTab) && pTab[nTab] )
3792 return pTab[nTab]->GetLastChangedRow();
3793 return 0;
3794 }
3795
3796
GetNextDifferentChangedCol(SCTAB nTab,SCCOL nStart) const3797 SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const
3798 {
3799 if ( ValidTab(nTab) && pTab[nTab] )
3800 {
3801 sal_uInt8 nStartFlags = pTab[nTab]->GetColFlags(nStart);
3802 sal_uInt16 nStartWidth = pTab[nTab]->GetOriginalWidth(nStart);
3803 for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++)
3804 {
3805 if (((nStartFlags & CR_MANUALBREAK) != (pTab[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) ||
3806 (nStartWidth != pTab[nTab]->GetOriginalWidth(nCol)) ||
3807 ((nStartFlags & CR_HIDDEN) != (pTab[nTab]->GetColFlags(nCol) & CR_HIDDEN)) )
3808 return nCol;
3809 }
3810 return MAXCOL+1;
3811 }
3812 return 0;
3813 }
3814
GetNextDifferentChangedRow(SCTAB nTab,SCROW nStart,bool bCareManualSize) const3815 SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const
3816 {
3817 const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pRowFlagsArray;
3818 if ( ValidTab(nTab) && pTab[nTab] && ((pRowFlagsArray = pTab[nTab]->GetRowFlagsArray()) != NULL) &&
3819 pTab[nTab]->mpRowHeights && pTab[nTab]->mpHiddenRows )
3820 {
3821 size_t nIndex; // ignored
3822 SCROW nFlagsEndRow;
3823 SCROW nHiddenEndRow;
3824 SCROW nHeightEndRow;
3825 sal_uInt8 nFlags;
3826 bool bHidden;
3827 sal_uInt16 nHeight;
3828 sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow);
3829 bool bStartHidden = bHidden = pTab[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow);
3830 sal_uInt16 nStartHeight = nHeight = pTab[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false);
3831 SCROW nRow;
3832 while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW)
3833 {
3834 if (nFlagsEndRow < nRow)
3835 nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow);
3836 if (nHiddenEndRow < nRow)
3837 bHidden = pTab[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow);
3838 if (nHeightEndRow < nRow)
3839 nHeight = pTab[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false);
3840 if ( ((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) ||
3841 ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) ||
3842 (bStartHidden != bHidden) ||
3843 (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) ||
3844 (!bCareManualSize && ((nStartHeight != nHeight))))
3845 return nRow;
3846 }
3847 return MAXROW+1;
3848 }
3849 return 0;
3850 }
3851
GetColDefault(SCTAB nTab,SCCOL nCol,SCROW nLastRow,SCROW & nDefault)3852 sal_Bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault)
3853 {
3854 sal_Bool bRet(sal_False);
3855 nDefault = 0;
3856 ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow);
3857 SCCOL nColumn;
3858 SCROW nStartRow;
3859 SCROW nEndRow;
3860 const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
3861 if (nEndRow < nLastRow)
3862 {
3863 ScDefaultAttrSet aSet;
3864 ScDefaultAttrSet::iterator aItr = aSet.end();
3865 while (pAttr)
3866 {
3867 ScDefaultAttr aAttr(pAttr);
3868 aItr = aSet.find(aAttr);
3869 if (aItr == aSet.end())
3870 {
3871 aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
3872 aAttr.nFirst = nStartRow;
3873 aSet.insert(aAttr);
3874 }
3875 else
3876 {
3877 aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1);
3878 aAttr.nFirst = aItr->nFirst;
3879 aSet.erase(aItr);
3880 aSet.insert(aAttr);
3881 }
3882 pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
3883 }
3884 ScDefaultAttrSet::iterator aDefaultItr = aSet.begin();
3885 aItr = aDefaultItr;
3886 aItr++;
3887 while (aItr != aSet.end())
3888 {
3889 // for entries with equal count, use the one with the lowest start row,
3890 // don't use the random order of pointer comparisons
3891 if ( aItr->nCount > aDefaultItr->nCount ||
3892 ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) )
3893 aDefaultItr = aItr;
3894 aItr++;
3895 }
3896 nDefault = aDefaultItr->nFirst;
3897 bRet = sal_True;
3898 }
3899 else
3900 bRet = sal_True;
3901 return bRet;
3902 }
3903
GetRowDefault(SCTAB,SCROW,SCCOL,SCCOL &)3904 sal_Bool ScDocument::GetRowDefault( SCTAB /* nTab */, SCROW /* nRow */, SCCOL /* nLastCol */, SCCOL& /* nDefault */ )
3905 {
3906 sal_Bool bRet(sal_False);
3907 return bRet;
3908 }
3909
StripHidden(SCCOL & rX1,SCROW & rY1,SCCOL & rX2,SCROW & rY2,SCTAB nTab)3910 void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
3911 {
3912 if ( ValidTab(nTab) && pTab[nTab] )
3913 pTab[nTab]->StripHidden( rX1, rY1, rX2, rY2 );
3914 }
3915
3916
ExtendHidden(SCCOL & rX1,SCROW & rY1,SCCOL & rX2,SCROW & rY2,SCTAB nTab)3917 void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
3918 {
3919 if ( ValidTab(nTab) && pTab[nTab] )
3920 pTab[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 );
3921 }
3922
3923 //
3924 // Attribute ----------------------------------------------------------
3925 //
3926
GetAttr(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_uInt16 nWhich) const3927 const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
3928 {
3929 if ( ValidTab(nTab) && pTab[nTab] )
3930 {
3931 const SfxPoolItem* pTemp = pTab[nTab]->GetAttr( nCol, nRow, nWhich );
3932 if (pTemp)
3933 return pTemp;
3934 else
3935 {
3936 DBG_ERROR( "Attribut Null" );
3937 }
3938 }
3939 return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich );
3940 }
3941
3942
GetPattern(SCCOL nCol,SCROW nRow,SCTAB nTab) const3943 const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3944 {
3945 if ( ValidTab(nTab) && pTab[nTab] )
3946 return pTab[nTab]->GetPattern( nCol, nRow );
3947 return NULL;
3948 }
3949
3950
GetMostUsedPattern(SCCOL nCol,SCROW nStartRow,SCROW nEndRow,SCTAB nTab) const3951 const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const
3952 {
3953 if ( ValidTab(nTab) && pTab[nTab] )
3954 return pTab[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow );
3955 return NULL;
3956 }
3957
3958
ApplyAttr(SCCOL nCol,SCROW nRow,SCTAB nTab,const SfxPoolItem & rAttr)3959 void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr )
3960 {
3961 if ( ValidTab(nTab) && pTab[nTab] )
3962 pTab[nTab]->ApplyAttr( nCol, nRow, rAttr );
3963 }
3964
3965
ApplyPattern(SCCOL nCol,SCROW nRow,SCTAB nTab,const ScPatternAttr & rAttr)3966 void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr )
3967 {
3968 if ( ValidTab(nTab) && pTab[nTab] )
3969 pTab[nTab]->ApplyPattern( nCol, nRow, rAttr );
3970 }
3971
3972
ApplyPatternArea(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScMarkData & rMark,const ScPatternAttr & rAttr)3973 void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow,
3974 SCCOL nEndCol, SCROW nEndRow,
3975 const ScMarkData& rMark,
3976 const ScPatternAttr& rAttr )
3977 {
3978 for (SCTAB i=0; i <= MAXTAB; i++)
3979 if (pTab[i])
3980 if (rMark.GetTableSelect(i))
3981 pTab[i]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
3982 }
3983
3984
ApplyPatternAreaTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,const ScPatternAttr & rAttr)3985 void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow,
3986 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr )
3987 {
3988 if (VALIDTAB(nTab))
3989 if (pTab[nTab])
3990 pTab[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
3991 }
3992
ApplyPooledPatternAreaTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,const ScPatternAttr & rPooledAttr,const ScPatternAttr & rAttr)3993 void ScDocument::ApplyPooledPatternAreaTab( SCCOL nStartCol, SCROW nStartRow,
3994 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rPooledAttr, const ScPatternAttr& rAttr )
3995 {
3996 if (VALIDTAB(nTab))
3997 if (pTab[nTab])
3998 pTab[nTab]->ApplyPooledPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rPooledAttr, rAttr );
3999 }
4000
ApplyPatternIfNumberformatIncompatible(const ScRange & rRange,const ScMarkData & rMark,const ScPatternAttr & rPattern,short nNewType)4001 void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
4002 const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType )
4003 {
4004 for (SCTAB i=0; i <= MAXTAB; i++)
4005 if (pTab[i])
4006 if (rMark.GetTableSelect(i))
4007 pTab[i]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
4008 }
4009
4010
ApplyStyle(SCCOL nCol,SCROW nRow,SCTAB nTab,const ScStyleSheet & rStyle)4011 void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle)
4012 {
4013 if (VALIDTAB(nTab))
4014 if (pTab[nTab])
4015 pTab[nTab]->ApplyStyle( nCol, nRow, rStyle );
4016 }
4017
4018
ApplyStyleArea(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScMarkData & rMark,const ScStyleSheet & rStyle)4019 void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow,
4020 SCCOL nEndCol, SCROW nEndRow,
4021 const ScMarkData& rMark,
4022 const ScStyleSheet& rStyle)
4023 {
4024 for (SCTAB i=0; i <= MAXTAB; i++)
4025 if (pTab[i])
4026 if (rMark.GetTableSelect(i))
4027 pTab[i]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4028 }
4029
4030
ApplyStyleAreaTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,const ScStyleSheet & rStyle)4031 void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow,
4032 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle)
4033 {
4034 if (VALIDTAB(nTab))
4035 if (pTab[nTab])
4036 pTab[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4037 }
4038
4039
ApplySelectionStyle(const ScStyleSheet & rStyle,const ScMarkData & rMark)4040 void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
4041 {
4042 // ApplySelectionStyle needs multi mark
4043 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
4044 {
4045 ScRange aRange;
4046 rMark.GetMarkArea( aRange );
4047 ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(),
4048 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle );
4049 }
4050 else
4051 {
4052 for (SCTAB i=0; i<=MAXTAB; i++)
4053 if ( pTab[i] && rMark.GetTableSelect(i) )
4054 pTab[i]->ApplySelectionStyle( rStyle, rMark );
4055 }
4056 }
4057
4058
ApplySelectionLineStyle(const ScMarkData & rMark,const SvxBorderLine * pLine,sal_Bool bColorOnly)4059 void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark,
4060 const SvxBorderLine* pLine, sal_Bool bColorOnly )
4061 {
4062 if ( bColorOnly && !pLine )
4063 return;
4064
4065 for (SCTAB i=0; i<=MAXTAB; i++)
4066 if (pTab[i])
4067 if (rMark.GetTableSelect(i))
4068 pTab[i]->ApplySelectionLineStyle( rMark, pLine, bColorOnly );
4069 }
4070
4071
GetStyle(SCCOL nCol,SCROW nRow,SCTAB nTab) const4072 const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4073 {
4074 if ( VALIDTAB(nTab) && pTab[nTab] )
4075 return pTab[nTab]->GetStyle(nCol, nRow);
4076 else
4077 return NULL;
4078 }
4079
4080
GetSelectionStyle(const ScMarkData & rMark) const4081 const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const
4082 {
4083 sal_Bool bEqual = sal_True;
4084 sal_Bool bFound;
4085
4086 const ScStyleSheet* pStyle = NULL;
4087 const ScStyleSheet* pNewStyle;
4088
4089 if ( rMark.IsMultiMarked() )
4090 for (SCTAB i=0; i<=MAXTAB && bEqual; i++)
4091 if (pTab[i] && rMark.GetTableSelect(i))
4092 {
4093 pNewStyle = pTab[i]->GetSelectionStyle( rMark, bFound );
4094 if (bFound)
4095 {
4096 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4097 bEqual = sal_False; // unterschiedliche
4098 pStyle = pNewStyle;
4099 }
4100 }
4101 if ( rMark.IsMarked() )
4102 {
4103 ScRange aRange;
4104 rMark.GetMarkArea( aRange );
4105 for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual; i++)
4106 if (pTab[i] && rMark.GetTableSelect(i))
4107 {
4108 pNewStyle = pTab[i]->GetAreaStyle( bFound,
4109 aRange.aStart.Col(), aRange.aStart.Row(),
4110 aRange.aEnd.Col(), aRange.aEnd.Row() );
4111 if (bFound)
4112 {
4113 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4114 bEqual = sal_False; // unterschiedliche
4115 pStyle = pNewStyle;
4116 }
4117 }
4118 }
4119
4120 return bEqual ? pStyle : NULL;
4121 }
4122
4123
StyleSheetChanged(const SfxStyleSheetBase * pStyleSheet,sal_Bool bRemoved,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY)4124 void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved,
4125 OutputDevice* pDev,
4126 double nPPTX, double nPPTY,
4127 const Fraction& rZoomX, const Fraction& rZoomY )
4128 {
4129 for (SCTAB i=0; i <= MAXTAB; i++)
4130 if (pTab[i])
4131 pTab[i]->StyleSheetChanged
4132 ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY );
4133
4134 if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
4135 {
4136 // update attributes for all note objects
4137 ScDetectiveFunc::UpdateAllComments( *this );
4138 }
4139 }
4140
4141
IsStyleSheetUsed(const ScStyleSheet & rStyle,sal_Bool bGatherAllStyles) const4142 sal_Bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const
4143 {
4144 if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN )
4145 {
4146 if ( bGatherAllStyles )
4147 {
4148 SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(),
4149 SFX_STYLE_FAMILY_PARA );
4150 for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle;
4151 pStyle = aIter.Next() )
4152 {
4153 const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle );
4154 if ( pScStyle )
4155 pScStyle->SetUsage( ScStyleSheet::NOTUSED );
4156 }
4157 }
4158
4159 sal_Bool bIsUsed = sal_False;
4160
4161 for ( SCTAB i=0; i<=MAXTAB; i++ )
4162 {
4163 if ( pTab[i] )
4164 {
4165 if ( pTab[i]->IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
4166 {
4167 if ( !bGatherAllStyles )
4168 return sal_True;
4169 bIsUsed = sal_True;
4170 }
4171 }
4172 }
4173
4174 if ( bGatherAllStyles )
4175 bStyleSheetUsageInvalid = sal_False;
4176
4177 return bIsUsed;
4178 }
4179
4180 return rStyle.GetUsage() == ScStyleSheet::USED;
4181 }
4182
4183
ApplyFlagsTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,sal_Int16 nFlags)4184 sal_Bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4185 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4186 {
4187 if (VALIDTAB(nTab))
4188 if (pTab[nTab])
4189 return pTab[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4190
4191 DBG_ERROR("ApplyFlags: falsche Tabelle");
4192 return sal_False;
4193 }
4194
4195
RemoveFlagsTab(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab,sal_Int16 nFlags)4196 sal_Bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4197 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4198 {
4199 if (VALIDTAB(nTab))
4200 if (pTab[nTab])
4201 return pTab[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4202
4203 DBG_ERROR("RemoveFlags: falsche Tabelle");
4204 return sal_False;
4205 }
4206
4207
SetPattern(SCCOL nCol,SCROW nRow,SCTAB nTab,const ScPatternAttr & rAttr,sal_Bool bPutToPool)4208 void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr,
4209 sal_Bool bPutToPool )
4210 {
4211 if (VALIDTAB(nTab))
4212 if (pTab[nTab])
4213 pTab[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool );
4214 }
4215
4216
SetPattern(const ScAddress & rPos,const ScPatternAttr & rAttr,sal_Bool bPutToPool)4217 void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr,
4218 sal_Bool bPutToPool )
4219 {
4220 SCTAB nTab = rPos.Tab();
4221 if (pTab[nTab])
4222 pTab[nTab]->SetPattern( rPos, rAttr, bPutToPool );
4223 }
4224
4225
CreateSelectionPattern(const ScMarkData & rMark,sal_Bool bDeep)4226 ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep )
4227 {
4228 ScMergePatternState aState;
4229
4230 if ( rMark.IsMultiMarked() ) // multi selection
4231 {
4232 for (SCTAB i=0; i<=MAXTAB; i++)
4233 if (pTab[i] && rMark.GetTableSelect(i))
4234 pTab[i]->MergeSelectionPattern( aState, rMark, bDeep );
4235 }
4236 if ( rMark.IsMarked() ) // simle selection
4237 {
4238 ScRange aRange;
4239 rMark.GetMarkArea(aRange);
4240 for (SCTAB i=0; i<=MAXTAB; i++)
4241 if (pTab[i] && rMark.GetTableSelect(i))
4242 pTab[i]->MergePatternArea( aState,
4243 aRange.aStart.Col(), aRange.aStart.Row(),
4244 aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep );
4245 }
4246
4247 DBG_ASSERT( aState.pItemSet, "SelectionPattern Null" );
4248 if (aState.pItemSet)
4249 return new ScPatternAttr( aState.pItemSet );
4250 else
4251 return new ScPatternAttr( GetPool() ); // empty
4252 }
4253
4254
GetSelectionPattern(const ScMarkData & rMark,sal_Bool bDeep)4255 const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, sal_Bool bDeep )
4256 {
4257 delete pSelectionAttr;
4258 pSelectionAttr = CreateSelectionPattern( rMark, bDeep );
4259 return pSelectionAttr;
4260 }
4261
4262
GetSelectionFrame(const ScMarkData & rMark,SvxBoxItem & rLineOuter,SvxBoxInfoItem & rLineInner)4263 void ScDocument::GetSelectionFrame( const ScMarkData& rMark,
4264 SvxBoxItem& rLineOuter,
4265 SvxBoxInfoItem& rLineInner )
4266 {
4267 rLineOuter.SetLine(NULL, BOX_LINE_TOP);
4268 rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM);
4269 rLineOuter.SetLine(NULL, BOX_LINE_LEFT);
4270 rLineOuter.SetLine(NULL, BOX_LINE_RIGHT);
4271 rLineOuter.SetDistance(0);
4272
4273 rLineInner.SetLine(NULL, BOXINFO_LINE_HORI);
4274 rLineInner.SetLine(NULL, BOXINFO_LINE_VERT);
4275 rLineInner.SetTable(sal_True);
4276 rLineInner.SetDist(sal_True);
4277 rLineInner.SetMinDist(sal_False);
4278
4279 ScLineFlags aFlags;
4280
4281 if (rMark.IsMarked())
4282 {
4283 ScRange aRange;
4284 rMark.GetMarkArea(aRange);
4285 rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() );
4286 rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() );
4287 for (SCTAB i=0; i<=MAXTAB; i++)
4288 if (pTab[i] && rMark.GetTableSelect(i))
4289 pTab[i]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags,
4290 aRange.aStart.Col(), aRange.aStart.Row(),
4291 aRange.aEnd.Col(), aRange.aEnd.Row() );
4292 }
4293
4294 // Don't care Status auswerten
4295
4296 rLineInner.SetValid( VALID_LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) );
4297 rLineInner.SetValid( VALID_RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) );
4298 rLineInner.SetValid( VALID_TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) );
4299 rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) );
4300 rLineInner.SetValid( VALID_HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) );
4301 rLineInner.SetValid( VALID_VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) );
4302 }
4303
4304
HasAttrib(SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2,sal_uInt16 nMask)4305 bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
4306 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask )
4307 {
4308 if ( nMask & HASATTR_ROTATE )
4309 {
4310 // Attribut im Dokument ueberhaupt verwendet?
4311 // (wie in fillinfo)
4312
4313 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4314
4315 sal_Bool bAnyItem = sal_False;
4316 sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE );
4317 for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++)
4318 {
4319 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem );
4320 if ( pItem )
4321 {
4322 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
4323 // (see ScPatternAttr::GetCellOrientation)
4324 sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue();
4325 if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
4326 {
4327 bAnyItem = sal_True;
4328 break;
4329 }
4330 }
4331 }
4332 if (!bAnyItem)
4333 nMask &= ~HASATTR_ROTATE;
4334 }
4335
4336 if ( nMask & HASATTR_RTL )
4337 {
4338 // first check if right-to left is in the pool at all
4339 // (the same item is used in cell and page format)
4340
4341 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4342
4343 sal_Bool bHasRtl = sal_False;
4344 sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR );
4345 for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++)
4346 {
4347 const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem );
4348 if ( pItem && ((const SvxFrameDirectionItem*)pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP )
4349 {
4350 bHasRtl = sal_True;
4351 break;
4352 }
4353 }
4354 if (!bHasRtl)
4355 nMask &= ~HASATTR_RTL;
4356 }
4357
4358 if (!nMask)
4359 return false;
4360
4361 bool bFound = false;
4362 for (SCTAB i=nTab1; i<=nTab2 && !bFound; i++)
4363 if (pTab[i])
4364 {
4365 if ( nMask & HASATTR_RTL )
4366 {
4367 if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L ) // sheet default
4368 bFound = true;
4369 }
4370 if ( nMask & HASATTR_RIGHTORCENTER )
4371 {
4372 // On a RTL sheet, don't start to look for the default left value
4373 // (which is then logically right), instead always assume sal_True.
4374 // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets.
4375
4376 if ( IsLayoutRTL(i) )
4377 bFound = true;
4378 }
4379
4380 if ( !bFound )
4381 bFound = pTab[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask );
4382 }
4383
4384 return bFound;
4385 }
4386
HasAttrib(const ScRange & rRange,sal_uInt16 nMask)4387 bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask )
4388 {
4389 return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
4390 rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(),
4391 nMask );
4392 }
4393
FindMaxRotCol(SCTAB nTab,RowInfo * pRowInfo,SCSIZE nArrCount,SCCOL nX1,SCCOL nX2) const4394 void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
4395 SCCOL nX1, SCCOL nX2 ) const
4396 {
4397 if ( ValidTab(nTab) && pTab[nTab] )
4398 pTab[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 );
4399 else
4400 {
4401 DBG_ERRORFILE("FindMaxRotCol: falsche Tabelle");
4402 }
4403 }
4404
GetBorderLines(SCCOL nCol,SCROW nRow,SCTAB nTab,const SvxBorderLine ** ppLeft,const SvxBorderLine ** ppTop,const SvxBorderLine ** ppRight,const SvxBorderLine ** ppBottom) const4405 void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab,
4406 const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop,
4407 const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const
4408 {
4409 //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
4410
4411 const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER );
4412 DBG_ASSERT(pThisAttr,"wo ist das Attribut?");
4413
4414 const SvxBorderLine* pLeftLine = pThisAttr->GetLeft();
4415 const SvxBorderLine* pTopLine = pThisAttr->GetTop();
4416 const SvxBorderLine* pRightLine = pThisAttr->GetRight();
4417 const SvxBorderLine* pBottomLine = pThisAttr->GetBottom();
4418
4419 if ( nCol > 0 )
4420 {
4421 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4422 GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight();
4423 if ( ScHasPriority( pOther, pLeftLine ) )
4424 pLeftLine = pOther;
4425 }
4426 if ( nRow > 0 )
4427 {
4428 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4429 GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom();
4430 if ( ScHasPriority( pOther, pTopLine ) )
4431 pTopLine = pOther;
4432 }
4433 if ( nCol < MAXCOL )
4434 {
4435 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4436 GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft();
4437 if ( ScHasPriority( pOther, pRightLine ) )
4438 pRightLine = pOther;
4439 }
4440 if ( nRow < MAXROW )
4441 {
4442 const SvxBorderLine* pOther = ((const SvxBoxItem*)
4443 GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
4444 if ( ScHasPriority( pOther, pBottomLine ) )
4445 pBottomLine = pOther;
4446 }
4447
4448 if (ppLeft)
4449 *ppLeft = pLeftLine;
4450 if (ppTop)
4451 *ppTop = pTopLine;
4452 if (ppRight)
4453 *ppRight = pRightLine;
4454 if (ppBottom)
4455 *ppBottom = pBottomLine;
4456 }
4457
IsBlockEmpty(SCTAB nTab,SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,bool bIgnoreNotes) const4458 sal_Bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
4459 SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const
4460 {
4461 if (VALIDTAB(nTab))
4462 if (pTab[nTab])
4463 return pTab[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes );
4464
4465 DBG_ERROR("Falsche Tabellennummer");
4466 return sal_False;
4467 }
4468
4469
LockTable(SCTAB nTab)4470 void ScDocument::LockTable(SCTAB nTab)
4471 {
4472 if ( ValidTab(nTab) && pTab[nTab] )
4473 pTab[nTab]->LockTable();
4474 else
4475 {
4476 DBG_ERROR("Falsche Tabellennummer");
4477 }
4478 }
4479
4480
UnlockTable(SCTAB nTab)4481 void ScDocument::UnlockTable(SCTAB nTab)
4482 {
4483 if ( ValidTab(nTab) && pTab[nTab] )
4484 pTab[nTab]->UnlockTable();
4485 else
4486 {
4487 DBG_ERROR("Falsche Tabellennummer");
4488 }
4489 }
4490
4491
IsBlockEditable(SCTAB nTab,SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,sal_Bool * pOnlyNotBecauseOfMatrix) const4492 sal_Bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
4493 SCCOL nEndCol, SCROW nEndRow,
4494 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
4495 {
4496 // import into read-only document is possible
4497 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() )
4498 {
4499 if ( pOnlyNotBecauseOfMatrix )
4500 *pOnlyNotBecauseOfMatrix = sal_False;
4501 return sal_False;
4502 }
4503
4504 if (VALIDTAB(nTab))
4505 if (pTab[nTab])
4506 return pTab[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol,
4507 nEndRow, pOnlyNotBecauseOfMatrix );
4508
4509 DBG_ERROR("Falsche Tabellennummer");
4510 if ( pOnlyNotBecauseOfMatrix )
4511 *pOnlyNotBecauseOfMatrix = sal_False;
4512 return sal_False;
4513 }
4514
4515
IsSelectionEditable(const ScMarkData & rMark,sal_Bool * pOnlyNotBecauseOfMatrix) const4516 sal_Bool ScDocument::IsSelectionEditable( const ScMarkData& rMark,
4517 sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
4518 {
4519 // import into read-only document is possible
4520 if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() )
4521 {
4522 if ( pOnlyNotBecauseOfMatrix )
4523 *pOnlyNotBecauseOfMatrix = sal_False;
4524 return sal_False;
4525 }
4526
4527 ScRange aRange;
4528 rMark.GetMarkArea(aRange);
4529
4530 sal_Bool bOk = sal_True;
4531 sal_Bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL );
4532 for ( SCTAB i=0; i<=MAXTAB && (bOk || bMatrix); i++ )
4533 {
4534 if ( pTab[i] && rMark.GetTableSelect(i) )
4535 {
4536 if (rMark.IsMarked())
4537 {
4538 if ( !pTab[i]->IsBlockEditable( aRange.aStart.Col(),
4539 aRange.aStart.Row(), aRange.aEnd.Col(),
4540 aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) )
4541 {
4542 bOk = sal_False;
4543 if ( pOnlyNotBecauseOfMatrix )
4544 bMatrix = *pOnlyNotBecauseOfMatrix;
4545 }
4546 }
4547 if (rMark.IsMultiMarked())
4548 {
4549 if ( !pTab[i]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) )
4550 {
4551 bOk = sal_False;
4552 if ( pOnlyNotBecauseOfMatrix )
4553 bMatrix = *pOnlyNotBecauseOfMatrix;
4554 }
4555 }
4556 }
4557 }
4558
4559 if ( pOnlyNotBecauseOfMatrix )
4560 *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix );
4561
4562 return bOk;
4563 }
4564
4565
HasSelectedBlockMatrixFragment(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScMarkData & rMark) const4566 sal_Bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow,
4567 SCCOL nEndCol, SCROW nEndRow,
4568 const ScMarkData& rMark ) const
4569 {
4570 sal_Bool bOk = sal_True;
4571 for (SCTAB i=0; i<=MAXTAB && bOk; i++)
4572 if (pTab[i])
4573 if (rMark.GetTableSelect(i))
4574 if (pTab[i]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow ))
4575 bOk = sal_False;
4576
4577 return !bOk;
4578 }
4579
4580
GetMatrixFormulaRange(const ScAddress & rCellPos,ScRange & rMatrix)4581 sal_Bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix )
4582 {
4583 // if rCell is part of a matrix formula, return its complete range
4584
4585 sal_Bool bRet = sal_False;
4586 ScBaseCell* pCell = GetCell( rCellPos );
4587 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
4588 {
4589 ScAddress aOrigin = rCellPos;
4590 if ( ((ScFormulaCell*)pCell)->GetMatrixOrigin( aOrigin ) )
4591 {
4592 if ( aOrigin != rCellPos )
4593 pCell = GetCell( aOrigin );
4594 if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
4595 {
4596 SCCOL nSizeX;
4597 SCROW nSizeY;
4598 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY);
4599 if ( !(nSizeX > 0 && nSizeY > 0) )
4600 {
4601 // GetMatrixEdge computes also dimensions of the matrix
4602 // if not already done (may occur if document is loaded
4603 // from old file format).
4604 // Needs an "invalid" initialized address.
4605 aOrigin.SetInvalid();
4606 ((ScFormulaCell*)pCell)->GetMatrixEdge(aOrigin);
4607 ((ScFormulaCell*)pCell)->GetMatColsRows(nSizeX,nSizeY);
4608 }
4609 if ( nSizeX > 0 && nSizeY > 0 )
4610 {
4611 ScAddress aEnd( aOrigin.Col() + nSizeX - 1,
4612 aOrigin.Row() + nSizeY - 1,
4613 aOrigin.Tab() );
4614
4615 rMatrix.aStart = aOrigin;
4616 rMatrix.aEnd = aEnd;
4617 bRet = sal_True;
4618 }
4619 }
4620 }
4621 }
4622 return bRet;
4623 }
4624
4625
ExtendOverlapped(SCCOL & rStartCol,SCROW & rStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab)4626 sal_Bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
4627 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
4628 {
4629 sal_Bool bFound = sal_False;
4630 if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) )
4631 {
4632 if (pTab[nTab])
4633 {
4634 SCCOL nCol;
4635 SCCOL nOldCol = rStartCol;
4636 SCROW nOldRow = rStartRow;
4637 for (nCol=nOldCol; nCol<=nEndCol; nCol++)
4638 while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))->
4639 IsVerOverlapped())
4640 --rStartRow;
4641
4642 //! weiterreichen ?
4643
4644 ScAttrArray* pAttrArray = pTab[nTab]->aCol[nOldCol].pAttrArray;
4645 SCSIZE nIndex;
4646 pAttrArray->Search( nOldRow, nIndex );
4647 SCROW nAttrPos = nOldRow;
4648 while (nAttrPos<=nEndRow)
4649 {
4650 DBG_ASSERT( nIndex < pAttrArray->nCount, "Falscher Index im AttrArray" );
4651
4652 if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern->
4653 GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped())
4654 {
4655 SCROW nLoopEndRow = Min( nEndRow, pAttrArray->pData[nIndex].nRow );
4656 for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++)
4657 {
4658 SCCOL nTempCol = nOldCol;
4659 do
4660 --nTempCol;
4661 while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG))
4662 ->IsHorOverlapped());
4663 if (nTempCol < rStartCol)
4664 rStartCol = nTempCol;
4665 }
4666 }
4667 nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
4668 ++nIndex;
4669 }
4670 }
4671 }
4672 else
4673 {
4674 DBG_ERROR("ExtendOverlapped: falscher Bereich");
4675 }
4676
4677 return bFound;
4678 }
4679
4680
ExtendMergeSel(SCCOL nStartCol,SCROW nStartRow,SCCOL & rEndCol,SCROW & rEndRow,const ScMarkData & rMark,sal_Bool bRefresh,sal_Bool bAttrs)4681 sal_Bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow,
4682 SCCOL& rEndCol, SCROW& rEndRow,
4683 const ScMarkData& rMark, sal_Bool bRefresh, sal_Bool bAttrs )
4684 {
4685 // use all selected sheets from rMark
4686
4687 sal_Bool bFound = sal_False;
4688 SCCOL nOldEndCol = rEndCol;
4689 SCROW nOldEndRow = rEndRow;
4690
4691 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++)
4692 if ( pTab[nTab] && rMark.GetTableSelect(nTab) )
4693 {
4694 SCCOL nThisEndCol = nOldEndCol;
4695 SCROW nThisEndRow = nOldEndRow;
4696 if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, nTab, bRefresh, bAttrs ) )
4697 bFound = sal_True;
4698 if ( nThisEndCol > rEndCol )
4699 rEndCol = nThisEndCol;
4700 if ( nThisEndRow > rEndRow )
4701 rEndRow = nThisEndRow;
4702 }
4703
4704 return bFound;
4705 }
4706
4707
ExtendMerge(SCCOL nStartCol,SCROW nStartRow,SCCOL & rEndCol,SCROW & rEndRow,SCTAB nTab,sal_Bool bRefresh,sal_Bool bAttrs)4708 sal_Bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
4709 SCCOL& rEndCol, SCROW& rEndRow,
4710 SCTAB nTab, sal_Bool bRefresh, sal_Bool bAttrs )
4711 {
4712 sal_Bool bFound = sal_False;
4713 if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) )
4714 {
4715 if (pTab[nTab])
4716 bFound = pTab[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh, bAttrs );
4717
4718 if (bRefresh)
4719 RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab );
4720 }
4721 else
4722 {
4723 DBG_ERROR("ExtendMerge: falscher Bereich");
4724 }
4725
4726 return bFound;
4727 }
4728
4729
ExtendMerge(ScRange & rRange,sal_Bool bRefresh,sal_Bool bAttrs)4730 sal_Bool ScDocument::ExtendMerge( ScRange& rRange, sal_Bool bRefresh, sal_Bool bAttrs )
4731 {
4732 sal_Bool bFound = sal_False;
4733 SCTAB nStartTab = rRange.aStart.Tab();
4734 SCTAB nEndTab = rRange.aEnd.Tab();
4735 SCCOL nEndCol = rRange.aEnd.Col();
4736 SCROW nEndRow = rRange.aEnd.Row();
4737
4738 PutInOrder( nStartTab, nEndTab );
4739 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ )
4740 {
4741 SCCOL nExtendCol = rRange.aEnd.Col();
4742 SCROW nExtendRow = rRange.aEnd.Row();
4743 if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(),
4744 nExtendCol, nExtendRow,
4745 nTab, bRefresh, bAttrs ) )
4746 {
4747 bFound = sal_True;
4748 if (nExtendCol > nEndCol) nEndCol = nExtendCol;
4749 if (nExtendRow > nEndRow) nEndRow = nExtendRow;
4750 }
4751 }
4752
4753 rRange.aEnd.SetCol(nEndCol);
4754 rRange.aEnd.SetRow(nEndRow);
4755
4756 return bFound;
4757 }
4758
ExtendTotalMerge(ScRange & rRange)4759 sal_Bool ScDocument::ExtendTotalMerge( ScRange& rRange )
4760 {
4761 // Bereich genau dann auf zusammengefasste Zellen erweitern, wenn
4762 // dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden
4763
4764 sal_Bool bRet = sal_False;
4765 ScRange aExt = rRange;
4766 if (ExtendMerge(aExt))
4767 {
4768 if ( aExt.aEnd.Row() > rRange.aEnd.Row() )
4769 {
4770 ScRange aTest = aExt;
4771 aTest.aStart.SetRow( rRange.aEnd.Row() + 1 );
4772 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
4773 aExt.aEnd.SetRow(rRange.aEnd.Row());
4774 }
4775 if ( aExt.aEnd.Col() > rRange.aEnd.Col() )
4776 {
4777 ScRange aTest = aExt;
4778 aTest.aStart.SetCol( rRange.aEnd.Col() + 1 );
4779 if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
4780 aExt.aEnd.SetCol(rRange.aEnd.Col());
4781 }
4782
4783 bRet = ( aExt.aEnd != rRange.aEnd );
4784 rRange = aExt;
4785 }
4786 return bRet;
4787 }
4788
ExtendOverlapped(ScRange & rRange)4789 sal_Bool ScDocument::ExtendOverlapped( ScRange& rRange )
4790 {
4791 sal_Bool bFound = sal_False;
4792 SCTAB nStartTab = rRange.aStart.Tab();
4793 SCTAB nEndTab = rRange.aEnd.Tab();
4794 SCCOL nStartCol = rRange.aStart.Col();
4795 SCROW nStartRow = rRange.aStart.Row();
4796
4797 PutInOrder( nStartTab, nEndTab );
4798 for (SCTAB nTab = nStartTab; nTab <= nEndTab; nTab++ )
4799 {
4800 SCCOL nExtendCol = rRange.aStart.Col();
4801 SCROW nExtendRow = rRange.aStart.Row();
4802 ExtendOverlapped( nExtendCol, nExtendRow,
4803 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab );
4804 if (nExtendCol < nStartCol)
4805 {
4806 nStartCol = nExtendCol;
4807 bFound = sal_True;
4808 }
4809 if (nExtendRow < nStartRow)
4810 {
4811 nStartRow = nExtendRow;
4812 bFound = sal_True;
4813 }
4814 }
4815
4816 rRange.aStart.SetCol(nStartCol);
4817 rRange.aStart.SetRow(nStartRow);
4818
4819 return bFound;
4820 }
4821
RefreshAutoFilter(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,SCTAB nTab)4822 sal_Bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow,
4823 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
4824 {
4825 sal_uInt16 nCount = pDBCollection->GetCount();
4826 sal_uInt16 i;
4827 ScDBData* pData;
4828 SCTAB nDBTab;
4829 SCCOL nDBStartCol;
4830 SCROW nDBStartRow;
4831 SCCOL nDBEndCol;
4832 SCROW nDBEndRow;
4833
4834 // Autofilter loeschen
4835
4836 sal_Bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO );
4837
4838 // Autofilter setzen
4839
4840 for (i=0; i<nCount; i++)
4841 {
4842 pData = (*pDBCollection)[i];
4843 if (pData->HasAutoFilter())
4844 {
4845 pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
4846 if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
4847 nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
4848 {
4849 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
4850 nDBTab, SC_MF_AUTO ))
4851 bChange = sal_True;
4852 }
4853 }
4854 }
4855 return bChange;
4856 }
4857
4858
IsHorOverlapped(SCCOL nCol,SCROW nRow,SCTAB nTab) const4859 sal_Bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4860 {
4861 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
4862 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
4863 if (pAttr)
4864 return pAttr->IsHorOverlapped();
4865 else
4866 {
4867 DBG_ERROR("Overlapped: Attr==0");
4868 return sal_False;
4869 }
4870 }
4871
4872
IsVerOverlapped(SCCOL nCol,SCROW nRow,SCTAB nTab) const4873 sal_Bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4874 {
4875 const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
4876 GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
4877 if (pAttr)
4878 return pAttr->IsVerOverlapped();
4879 else
4880 {
4881 DBG_ERROR("Overlapped: Attr==0");
4882 return sal_False;
4883 }
4884 }
4885
4886
ApplySelectionFrame(const ScMarkData & rMark,const SvxBoxItem * pLineOuter,const SvxBoxInfoItem * pLineInner)4887 void ScDocument::ApplySelectionFrame( const ScMarkData& rMark,
4888 const SvxBoxItem* pLineOuter,
4889 const SvxBoxInfoItem* pLineInner )
4890 {
4891 ScRangeList aRangeList;
4892 rMark.FillRangeListWithMarks( &aRangeList, sal_False );
4893 sal_uLong nRangeCount = aRangeList.Count();
4894 for (SCTAB i=0; i<=MAXTAB; i++)
4895 {
4896 if (pTab[i] && rMark.GetTableSelect(i))
4897 {
4898 for (sal_uLong j=0; j<nRangeCount; j++)
4899 {
4900 ScRange aRange = *aRangeList.GetObject(j);
4901 pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner,
4902 aRange.aStart.Col(), aRange.aStart.Row(),
4903 aRange.aEnd.Col(), aRange.aEnd.Row() );
4904 }
4905 }
4906 }
4907 }
4908
4909
ApplyFrameAreaTab(const ScRange & rRange,const SvxBoxItem * pLineOuter,const SvxBoxInfoItem * pLineInner)4910 void ScDocument::ApplyFrameAreaTab( const ScRange& rRange,
4911 const SvxBoxItem* pLineOuter,
4912 const SvxBoxInfoItem* pLineInner )
4913 {
4914 SCTAB nStartTab = rRange.aStart.Tab();
4915 SCTAB nEndTab = rRange.aStart.Tab();
4916 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4917 if (pTab[nTab])
4918 pTab[nTab]->ApplyBlockFrame( pLineOuter, pLineInner,
4919 rRange.aStart.Col(), rRange.aStart.Row(),
4920 rRange.aEnd.Col(), rRange.aEnd.Row() );
4921 }
4922
4923
ApplySelectionPattern(const ScPatternAttr & rAttr,const ScMarkData & rMark)4924 void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark )
4925 {
4926 const SfxItemSet* pSet = &rAttr.GetItemSet();
4927 sal_Bool bSet = sal_False;
4928 sal_uInt16 i;
4929 for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++)
4930 if (pSet->GetItemState(i) == SFX_ITEM_SET)
4931 bSet = sal_True;
4932
4933 if (bSet)
4934 {
4935 // ApplySelectionCache needs multi mark
4936 if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
4937 {
4938 ScRange aRange;
4939 rMark.GetMarkArea( aRange );
4940 ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(),
4941 aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr );
4942 }
4943 else
4944 {
4945 SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet );
4946 for (SCTAB nTab=0; nTab<=MAXTAB; nTab++)
4947 if (pTab[nTab])
4948 if (rMark.GetTableSelect(nTab))
4949 pTab[nTab]->ApplySelectionCache( &aCache, rMark );
4950 }
4951 }
4952 }
4953
4954
ChangeSelectionIndent(sal_Bool bIncrement,const ScMarkData & rMark)4955 void ScDocument::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark )
4956 {
4957 for (SCTAB i=0; i<=MAXTAB; i++)
4958 if (pTab[i] && rMark.GetTableSelect(i))
4959 pTab[i]->ChangeSelectionIndent( bIncrement, rMark );
4960 }
4961
4962
ClearSelectionItems(const sal_uInt16 * pWhich,const ScMarkData & rMark)4963 void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
4964 {
4965 for (SCTAB i=0; i<=MAXTAB; i++)
4966 if (pTab[i] && rMark.GetTableSelect(i))
4967 pTab[i]->ClearSelectionItems( pWhich, rMark );
4968 }
4969
4970
DeleteSelection(sal_uInt16 nDelFlag,const ScMarkData & rMark)4971 void ScDocument::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
4972 {
4973 for (SCTAB i=0; i<=MAXTAB; i++)
4974 if (pTab[i] && rMark.GetTableSelect(i))
4975 pTab[i]->DeleteSelection( nDelFlag, rMark );
4976 }
4977
4978
DeleteSelectionTab(SCTAB nTab,sal_uInt16 nDelFlag,const ScMarkData & rMark)4979 void ScDocument::DeleteSelectionTab( SCTAB nTab, sal_uInt16 nDelFlag, const ScMarkData& rMark )
4980 {
4981 if (ValidTab(nTab) && pTab[nTab])
4982 pTab[nTab]->DeleteSelection( nDelFlag, rMark );
4983 else
4984 {
4985 DBG_ERROR("Falsche Tabelle");
4986 }
4987 }
4988
4989
GetDefPattern() const4990 ScPatternAttr* ScDocument::GetDefPattern() const
4991 {
4992 return (ScPatternAttr*) &xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN);
4993 }
4994
4995
GetPool()4996 ScDocumentPool* ScDocument::GetPool()
4997 {
4998 return xPoolHelper->GetDocPool();
4999 }
5000
5001
5002
GetStyleSheetPool() const5003 ScStyleSheetPool* ScDocument::GetStyleSheetPool() const
5004 {
5005 return xPoolHelper->GetStylePool();
5006 }
5007
5008
GetEmptyLinesInBlock(SCCOL nStartCol,SCROW nStartRow,SCTAB nStartTab,SCCOL nEndCol,SCROW nEndRow,SCTAB nEndTab,ScDirection eDir)5009 SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
5010 SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir )
5011 {
5012 PutInOrder(nStartCol, nEndCol);
5013 PutInOrder(nStartRow, nEndRow);
5014 PutInOrder(nStartTab, nEndTab);
5015 if (VALIDTAB(nStartTab))
5016 {
5017 if (pTab[nStartTab])
5018 return pTab[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir);
5019 else
5020 return 0;
5021 }
5022 else
5023 return 0;
5024 }
5025
5026
FindAreaPos(SCCOL & rCol,SCROW & rRow,SCTAB nTab,SCsCOL nMovX,SCsROW nMovY)5027 void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY )
5028 {
5029 if (ValidTab(nTab) && pTab[nTab])
5030 pTab[nTab]->FindAreaPos( rCol, rRow, nMovX, nMovY );
5031 }
5032
5033
GetNextPos(SCCOL & rCol,SCROW & rRow,SCTAB nTab,SCsCOL nMovX,SCsROW nMovY,sal_Bool bMarked,sal_Bool bUnprotected,const ScMarkData & rMark)5034 void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
5035 sal_Bool bMarked, sal_Bool bUnprotected, const ScMarkData& rMark )
5036 {
5037 DBG_ASSERT( !nMovX || !nMovY, "GetNextPos: nur X oder Y" );
5038
5039 ScMarkData aCopyMark = rMark;
5040 aCopyMark.SetMarking(sal_False);
5041 aCopyMark.MarkToMulti();
5042
5043 if (ValidTab(nTab) && pTab[nTab])
5044 pTab[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
5045 }
5046
5047 //
5048 // Datei-Operationen
5049 //
5050
5051
UpdStlShtPtrsFrmNms()5052 void ScDocument::UpdStlShtPtrsFrmNms()
5053 {
5054 ScPatternAttr::pDoc = this;
5055
5056 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5057
5058 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5059 ScPatternAttr* pPattern;
5060 for (sal_uInt32 i=0; i<nCount; i++)
5061 {
5062 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
5063 if (pPattern)
5064 pPattern->UpdateStyleSheet();
5065 }
5066 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet();
5067 }
5068
5069
StylesToNames()5070 void ScDocument::StylesToNames()
5071 {
5072 ScPatternAttr::pDoc = this;
5073
5074 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5075
5076 sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5077 ScPatternAttr* pPattern;
5078 for (sal_uInt32 i=0; i<nCount; i++)
5079 {
5080 pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
5081 if (pPattern)
5082 pPattern->StyleToName();
5083 }
5084 ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName();
5085 }
5086
5087
GetCellCount() const5088 sal_uLong ScDocument::GetCellCount() const
5089 {
5090 sal_uLong nCellCount = 0L;
5091
5092 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
5093 if ( pTab[nTab] )
5094 nCellCount += pTab[nTab]->GetCellCount();
5095
5096 return nCellCount;
5097 }
5098
GetCellCount(SCTAB nTab,SCCOL nCol) const5099 SCSIZE ScDocument::GetCellCount(SCTAB nTab, SCCOL nCol) const
5100 {
5101 if (!ValidTab(nTab) || !pTab[nTab])
5102 return 0;
5103
5104 return pTab[nTab]->GetCellCount(nCol);
5105 }
5106
GetCodeCount() const5107 sal_uLong ScDocument::GetCodeCount() const
5108 {
5109 sal_uLong nCodeCount = 0;
5110
5111 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
5112 if ( pTab[nTab] )
5113 nCodeCount += pTab[nTab]->GetCodeCount();
5114
5115 return nCodeCount;
5116 }
5117
5118
GetWeightedCount() const5119 sal_uLong ScDocument::GetWeightedCount() const
5120 {
5121 sal_uLong nCellCount = 0L;
5122
5123 for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ )
5124 if ( pTab[nTab] )
5125 nCellCount += pTab[nTab]->GetWeightedCount();
5126
5127 return nCellCount;
5128 }
5129
5130
PageStyleModified(SCTAB nTab,const String & rNewName)5131 void ScDocument::PageStyleModified( SCTAB nTab, const String& rNewName )
5132 {
5133 if ( ValidTab(nTab) && pTab[nTab] )
5134 pTab[nTab]->PageStyleModified( rNewName );
5135 }
5136
5137
SetPageStyle(SCTAB nTab,const String & rName)5138 void ScDocument::SetPageStyle( SCTAB nTab, const String& rName )
5139 {
5140 if ( ValidTab(nTab) && pTab[nTab] )
5141 pTab[nTab]->SetPageStyle( rName );
5142 }
5143
5144
GetPageStyle(SCTAB nTab) const5145 const String& ScDocument::GetPageStyle( SCTAB nTab ) const
5146 {
5147 if ( ValidTab(nTab) && pTab[nTab] )
5148 return pTab[nTab]->GetPageStyle();
5149
5150 return EMPTY_STRING;
5151 }
5152
5153
SetPageSize(SCTAB nTab,const Size & rSize)5154 void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize )
5155 {
5156 if ( ValidTab(nTab) && pTab[nTab] )
5157 pTab[nTab]->SetPageSize( rSize );
5158 }
5159
GetPageSize(SCTAB nTab) const5160 Size ScDocument::GetPageSize( SCTAB nTab ) const
5161 {
5162 if ( ValidTab(nTab) && pTab[nTab] )
5163 return pTab[nTab]->GetPageSize();
5164
5165 DBG_ERROR("falsche Tab");
5166 return Size();
5167 }
5168
5169
SetRepeatArea(SCTAB nTab,SCCOL nStartCol,SCCOL nEndCol,SCROW nStartRow,SCROW nEndRow)5170 void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
5171 {
5172 if ( ValidTab(nTab) && pTab[nTab] )
5173 pTab[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow );
5174 }
5175
InvalidatePageBreaks(SCTAB nTab)5176 void ScDocument::InvalidatePageBreaks(SCTAB nTab)
5177 {
5178 if (ValidTab(nTab) && pTab[nTab])
5179 pTab[nTab]->InvalidatePageBreaks();
5180 }
5181
UpdatePageBreaks(SCTAB nTab,const ScRange * pUserArea)5182 void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea )
5183 {
5184 if ( ValidTab(nTab) && pTab[nTab] )
5185 pTab[nTab]->UpdatePageBreaks( pUserArea );
5186 }
5187
RemoveManualBreaks(SCTAB nTab)5188 void ScDocument::RemoveManualBreaks( SCTAB nTab )
5189 {
5190 if ( ValidTab(nTab) && pTab[nTab] )
5191 pTab[nTab]->RemoveManualBreaks();
5192 }
5193
HasManualBreaks(SCTAB nTab) const5194 sal_Bool ScDocument::HasManualBreaks( SCTAB nTab ) const
5195 {
5196 if ( ValidTab(nTab) && pTab[nTab] )
5197 return pTab[nTab]->HasManualBreaks();
5198
5199 DBG_ERROR("falsche Tab");
5200 return sal_False;
5201 }
5202
5203
GetDocStat(ScDocStat & rDocStat)5204 void ScDocument::GetDocStat( ScDocStat& rDocStat )
5205 {
5206 rDocStat.nTableCount = GetTableCount();
5207 rDocStat.aDocName = aDocName;
5208 rDocStat.nCellCount = GetCellCount();
5209 }
5210
5211
HasPrintRange()5212 sal_Bool ScDocument::HasPrintRange()
5213 {
5214 sal_Bool bResult = sal_False;
5215
5216 for ( SCTAB i=0; !bResult && i<nMaxTableNumber; i++ )
5217 if ( pTab[i] )
5218 bResult = pTab[i]->IsPrintEntireSheet() || (pTab[i]->GetPrintRangeCount() > 0);
5219
5220 return bResult;
5221 }
5222
5223
IsPrintEntireSheet(SCTAB nTab) const5224 sal_Bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const
5225 {
5226 return (ValidTab(nTab) ) && pTab[nTab] && pTab[nTab]->IsPrintEntireSheet();
5227 }
5228
5229
GetPrintRangeCount(SCTAB nTab)5230 sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab )
5231 {
5232 if (ValidTab(nTab) && pTab[nTab])
5233 return pTab[nTab]->GetPrintRangeCount();
5234
5235 return 0;
5236 }
5237
5238
GetPrintRange(SCTAB nTab,sal_uInt16 nPos)5239 const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos )
5240 {
5241 if (ValidTab(nTab) && pTab[nTab])
5242 return pTab[nTab]->GetPrintRange(nPos);
5243
5244 return NULL;
5245 }
5246
5247
GetRepeatColRange(SCTAB nTab)5248 const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab )
5249 {
5250 if (ValidTab(nTab) && pTab[nTab])
5251 return pTab[nTab]->GetRepeatColRange();
5252
5253 return NULL;
5254 }
5255
5256
GetRepeatRowRange(SCTAB nTab)5257 const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab )
5258 {
5259 if (ValidTab(nTab) && pTab[nTab])
5260 return pTab[nTab]->GetRepeatRowRange();
5261
5262 return NULL;
5263 }
5264
5265
ClearPrintRanges(SCTAB nTab)5266 void ScDocument::ClearPrintRanges( SCTAB nTab )
5267 {
5268 if (ValidTab(nTab) && pTab[nTab])
5269 pTab[nTab]->ClearPrintRanges();
5270 }
5271
5272
AddPrintRange(SCTAB nTab,const ScRange & rNew)5273 void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew )
5274 {
5275 if (ValidTab(nTab) && pTab[nTab])
5276 pTab[nTab]->AddPrintRange( rNew );
5277 }
5278
5279
5280 //UNUSED2009-05 void ScDocument::SetPrintRange( SCTAB nTab, const ScRange& rNew )
5281 //UNUSED2009-05 {
5282 //UNUSED2009-05 if (ValidTab(nTab) && pTab[nTab])
5283 //UNUSED2009-05 pTab[nTab]->SetPrintRange( rNew );
5284 //UNUSED2009-05 }
5285
5286
SetPrintEntireSheet(SCTAB nTab)5287 void ScDocument::SetPrintEntireSheet( SCTAB nTab )
5288 {
5289 if (ValidTab(nTab) && pTab[nTab])
5290 pTab[nTab]->SetPrintEntireSheet();
5291 }
5292
5293
SetRepeatColRange(SCTAB nTab,const ScRange * pNew)5294 void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew )
5295 {
5296 if (ValidTab(nTab) && pTab[nTab])
5297 pTab[nTab]->SetRepeatColRange( pNew );
5298 }
5299
5300
SetRepeatRowRange(SCTAB nTab,const ScRange * pNew)5301 void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew )
5302 {
5303 if (ValidTab(nTab) && pTab[nTab])
5304 pTab[nTab]->SetRepeatRowRange( pNew );
5305 }
5306
5307
CreatePrintRangeSaver() const5308 ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const
5309 {
5310 SCTAB nCount = GetTableCount();
5311 ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount );
5312 for (SCTAB i=0; i<nCount; i++)
5313 if (pTab[i])
5314 pTab[i]->FillPrintSaver( pNew->GetTabData(i) );
5315 return pNew;
5316 }
5317
5318
RestorePrintRanges(const ScPrintRangeSaver & rSaver)5319 void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver )
5320 {
5321 SCTAB nCount = rSaver.GetTabCount();
5322 for (SCTAB i=0; i<nCount; i++)
5323 if (pTab[i])
5324 pTab[i]->RestorePrintRanges( rSaver.GetTabData(i) );
5325 }
5326
5327
NeedPageResetAfterTab(SCTAB nTab) const5328 sal_Bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const
5329 {
5330 // Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine
5331 // andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen)
5332 // und eine Seitennummer angegeben ist (nicht 0)
5333
5334 if ( nTab < MAXTAB && pTab[nTab] && pTab[nTab+1] )
5335 {
5336 String aNew = pTab[nTab+1]->GetPageStyle();
5337 if ( aNew != pTab[nTab]->GetPageStyle() )
5338 {
5339 SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE );
5340 if ( pStyle )
5341 {
5342 const SfxItemSet& rSet = pStyle->GetItemSet();
5343 sal_uInt16 nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue();
5344 if ( nFirst != 0 )
5345 return sal_True; // Seitennummer in neuer Vorlage angegeben
5346 }
5347 }
5348 }
5349
5350 return sal_False; // sonst nicht
5351 }
5352
GetUndoManager()5353 SfxUndoManager* ScDocument::GetUndoManager()
5354 {
5355 if (!mpUndoManager)
5356 {
5357 // to support enhanced text edit for draw objects, use an SdrUndoManager
5358 mpUndoManager = new SdrUndoManager;
5359 }
5360
5361 return mpUndoManager;
5362 }
5363
GetRowBreakIterator(SCTAB nTab) const5364 ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const
5365 {
5366 if (ValidTab(nTab) && pTab[nTab])
5367 return new ScRowBreakIterator(pTab[nTab]->maRowPageBreaks);
5368 return NULL;
5369 }
5370
EnableUndo(bool bVal)5371 void ScDocument::EnableUndo( bool bVal )
5372 {
5373 GetUndoManager()->EnableUndo(bVal);
5374 if( pDrawLayer ) pDrawLayer->EnableUndo(bVal);
5375 mbUndoEnabled = bVal;
5376 }
5377
IsInVBAMode() const5378 bool ScDocument::IsInVBAMode() const
5379 {
5380 bool bResult = false;
5381 if ( pShell )
5382 {
5383 com::sun::star::uno::Reference< com::sun::star::script::vba::XVBACompatibility > xVBA( pShell->GetBasicContainer(), com::sun::star::uno::UNO_QUERY );
5384 bResult = xVBA.is() && xVBA->getVBACompatibilityMode();
5385 }
5386 return bResult;
5387 }
5388